in xdomain.c [1055:1148]
static void tb_xdomain_get_properties(struct work_struct *work)
{
struct tb_xdomain *xd = container_of(work, typeof(*xd),
get_properties_work.work);
struct tb_property_dir *dir;
struct tb *tb = xd->tb;
bool update = false;
u32 *block = NULL;
u32 gen = 0;
int ret;
dev_dbg(&xd->dev, "requesting remote properties\n");
ret = tb_xdp_properties_request(tb->ctl, xd->route, xd->local_uuid,
xd->remote_uuid, xd->properties_retries,
&block, &gen);
if (ret < 0) {
if (xd->properties_retries-- > 0) {
dev_dbg(&xd->dev,
"failed to request remote properties, retrying\n");
queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
msecs_to_jiffies(1000));
} else {
/* Give up now */
dev_err(&xd->dev,
"failed read XDomain properties from %pUb\n",
xd->remote_uuid);
}
return;
}
xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;
mutex_lock(&xd->lock);
/* Only accept newer generation properties */
if (xd->remote_properties && gen <= xd->remote_property_block_gen)
goto err_free_block;
dir = tb_property_parse_dir(block, ret);
if (!dir) {
dev_err(&xd->dev, "failed to parse XDomain properties\n");
goto err_free_block;
}
ret = populate_properties(xd, dir);
if (ret) {
dev_err(&xd->dev, "missing XDomain properties in response\n");
goto err_free_dir;
}
/* Release the existing one */
if (xd->remote_properties) {
tb_property_free_dir(xd->remote_properties);
update = true;
}
xd->remote_properties = dir;
xd->remote_property_block_gen = gen;
tb_xdomain_update_link_attributes(xd);
mutex_unlock(&xd->lock);
kfree(block);
/*
* Now the device should be ready enough so we can add it to the
* bus and let userspace know about it. If the device is already
* registered, we notify the userspace that it has changed.
*/
if (!update) {
if (device_add(&xd->dev)) {
dev_err(&xd->dev, "failed to add XDomain device\n");
return;
}
dev_info(&xd->dev, "new host found, vendor=%#x device=%#x\n",
xd->vendor, xd->device);
if (xd->vendor_name && xd->device_name)
dev_info(&xd->dev, "%s %s\n", xd->vendor_name,
xd->device_name);
} else {
kobject_uevent(&xd->dev.kobj, KOBJ_CHANGE);
}
enumerate_services(xd);
return;
err_free_dir:
tb_property_free_dir(dir);
err_free_block:
kfree(block);
mutex_unlock(&xd->lock);
}