in switch.c [2759:2869]
int tb_switch_add(struct tb_switch *sw)
{
int i, ret;
/*
* Initialize DMA control port now before we read DROM. Recent
* host controllers have more complete DROM on NVM that includes
* vendor and model identification strings which we then expose
* to the userspace. NVM can be accessed through DMA
* configuration based mailbox.
*/
ret = tb_switch_add_dma_port(sw);
if (ret) {
dev_err(&sw->dev, "failed to add DMA port\n");
return ret;
}
if (!sw->safe_mode) {
tb_switch_credits_init(sw);
/* read drom */
ret = tb_drom_read(sw);
if (ret) {
dev_err(&sw->dev, "reading DROM failed\n");
return ret;
}
tb_sw_dbg(sw, "uid: %#llx\n", sw->uid);
tb_check_quirks(sw);
ret = tb_switch_set_uuid(sw);
if (ret) {
dev_err(&sw->dev, "failed to set UUID\n");
return ret;
}
for (i = 0; i <= sw->config.max_port_number; i++) {
if (sw->ports[i].disabled) {
tb_port_dbg(&sw->ports[i], "disabled by eeprom\n");
continue;
}
ret = tb_init_port(&sw->ports[i]);
if (ret) {
dev_err(&sw->dev, "failed to initialize port %d\n", i);
return ret;
}
}
tb_switch_default_link_ports(sw);
ret = tb_switch_update_link_attributes(sw);
if (ret)
return ret;
ret = tb_switch_tmu_init(sw);
if (ret)
return ret;
}
ret = device_add(&sw->dev);
if (ret) {
dev_err(&sw->dev, "failed to add device: %d\n", ret);
return ret;
}
if (tb_route(sw)) {
dev_info(&sw->dev, "new device found, vendor=%#x device=%#x\n",
sw->vendor, sw->device);
if (sw->vendor_name && sw->device_name)
dev_info(&sw->dev, "%s %s\n", sw->vendor_name,
sw->device_name);
}
ret = usb4_switch_add_ports(sw);
if (ret) {
dev_err(&sw->dev, "failed to add USB4 ports\n");
goto err_del;
}
ret = tb_switch_nvm_add(sw);
if (ret) {
dev_err(&sw->dev, "failed to add NVM devices\n");
goto err_ports;
}
/*
* Thunderbolt routers do not generate wakeups themselves but
* they forward wakeups from tunneled protocols, so enable it
* here.
*/
device_init_wakeup(&sw->dev, true);
pm_runtime_set_active(&sw->dev);
if (sw->rpm) {
pm_runtime_set_autosuspend_delay(&sw->dev, TB_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(&sw->dev);
pm_runtime_mark_last_busy(&sw->dev);
pm_runtime_enable(&sw->dev);
pm_request_autosuspend(&sw->dev);
}
tb_switch_debugfs_init(sw);
return 0;
err_ports:
usb4_switch_remove_ports(sw);
err_del:
device_del(&sw->dev);
return ret;
}