diff options
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r-- | drivers/thunderbolt/switch.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 9dfb8e18cdf7..0d50e7e7b29b 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c | |||
@@ -180,20 +180,17 @@ int tb_port_clear_counter(struct tb_port *port, int counter) | |||
180 | * | 180 | * |
181 | * Return: Returns 0 on success or an error code on failure. | 181 | * Return: Returns 0 on success or an error code on failure. |
182 | */ | 182 | */ |
183 | static int tb_init_port(struct tb_switch *sw, u8 port_nr) | 183 | static int tb_init_port(struct tb_port *port) |
184 | { | 184 | { |
185 | int res; | 185 | int res; |
186 | int cap; | 186 | int cap; |
187 | struct tb_port *port = &sw->ports[port_nr]; | 187 | |
188 | port->sw = sw; | ||
189 | port->port = port_nr; | ||
190 | port->remote = NULL; | ||
191 | res = tb_port_read(port, &port->config, TB_CFG_PORT, 0, 8); | 188 | res = tb_port_read(port, &port->config, TB_CFG_PORT, 0, 8); |
192 | if (res) | 189 | if (res) |
193 | return res; | 190 | return res; |
194 | 191 | ||
195 | /* Port 0 is the switch itself and has no PHY. */ | 192 | /* Port 0 is the switch itself and has no PHY. */ |
196 | if (port->config.type == TB_TYPE_PORT && port_nr != 0) { | 193 | if (port->config.type == TB_TYPE_PORT && port->port != 0) { |
197 | cap = tb_find_cap(port, TB_CFG_PORT, TB_CAP_PHY); | 194 | cap = tb_find_cap(port, TB_CFG_PORT, TB_CAP_PHY); |
198 | 195 | ||
199 | if (cap > 0) | 196 | if (cap > 0) |
@@ -202,7 +199,7 @@ static int tb_init_port(struct tb_switch *sw, u8 port_nr) | |||
202 | tb_port_WARN(port, "non switch port without a PHY\n"); | 199 | tb_port_WARN(port, "non switch port without a PHY\n"); |
203 | } | 200 | } |
204 | 201 | ||
205 | tb_dump_port(sw->tb, &port->config); | 202 | tb_dump_port(port->sw->tb, &port->config); |
206 | 203 | ||
207 | /* TODO: Read dual link port, DP port and more from EEPROM. */ | 204 | /* TODO: Read dual link port, DP port and more from EEPROM. */ |
208 | return 0; | 205 | return 0; |
@@ -329,6 +326,7 @@ void tb_switch_free(struct tb_switch *sw) | |||
329 | tb_plug_events_active(sw, false); | 326 | tb_plug_events_active(sw, false); |
330 | 327 | ||
331 | kfree(sw->ports); | 328 | kfree(sw->ports); |
329 | kfree(sw->drom); | ||
332 | kfree(sw); | 330 | kfree(sw); |
333 | } | 331 | } |
334 | 332 | ||
@@ -381,18 +379,16 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) | |||
381 | 379 | ||
382 | /* initialize ports */ | 380 | /* initialize ports */ |
383 | sw->ports = kcalloc(sw->config.max_port_number + 1, sizeof(*sw->ports), | 381 | sw->ports = kcalloc(sw->config.max_port_number + 1, sizeof(*sw->ports), |
384 | GFP_KERNEL); | 382 | GFP_KERNEL); |
385 | if (!sw->ports) | 383 | if (!sw->ports) |
386 | goto err; | 384 | goto err; |
387 | 385 | ||
388 | for (i = 0; i <= sw->config.max_port_number; i++) { | 386 | for (i = 0; i <= sw->config.max_port_number; i++) { |
389 | if (tb_init_port(sw, i)) | 387 | /* minimum setup for tb_find_cap and tb_drom_read to work */ |
390 | goto err; | 388 | sw->ports[i].sw = sw; |
391 | /* TODO: check if port is disabled (EEPROM) */ | 389 | sw->ports[i].port = i; |
392 | } | 390 | } |
393 | 391 | ||
394 | /* TODO: I2C, IECS, EEPROM, link controller */ | ||
395 | |||
396 | cap = tb_find_cap(&sw->ports[0], TB_CFG_SWITCH, TB_CAP_PLUG_EVENTS); | 392 | cap = tb_find_cap(&sw->ports[0], TB_CFG_SWITCH, TB_CAP_PLUG_EVENTS); |
397 | if (cap < 0) { | 393 | if (cap < 0) { |
398 | tb_sw_warn(sw, "cannot find TB_CAP_PLUG_EVENTS aborting\n"); | 394 | tb_sw_warn(sw, "cannot find TB_CAP_PLUG_EVENTS aborting\n"); |
@@ -400,10 +396,21 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) | |||
400 | } | 396 | } |
401 | sw->cap_plug_events = cap; | 397 | sw->cap_plug_events = cap; |
402 | 398 | ||
403 | if (tb_drom_read_uid_only(sw, &sw->uid)) | 399 | /* read drom */ |
404 | tb_sw_warn(sw, "could not read uid from eeprom\n"); | 400 | if (tb_drom_read(sw)) |
405 | else | 401 | tb_sw_warn(sw, "tb_eeprom_read_rom failed, continuing\n"); |
406 | tb_sw_info(sw, "uid: %#llx\n", sw->uid); | 402 | tb_sw_info(sw, "uid: %#llx\n", sw->uid); |
403 | |||
404 | for (i = 0; i <= sw->config.max_port_number; i++) { | ||
405 | if (sw->ports[i].disabled) { | ||
406 | tb_port_info(&sw->ports[i], "disabled by eeprom\n"); | ||
407 | continue; | ||
408 | } | ||
409 | if (tb_init_port(&sw->ports[i])) | ||
410 | goto err; | ||
411 | } | ||
412 | |||
413 | /* TODO: I2C, IECS, link controller */ | ||
407 | 414 | ||
408 | if (tb_plug_events_active(sw, true)) | 415 | if (tb_plug_events_active(sw, true)) |
409 | goto err; | 416 | goto err; |
@@ -411,6 +418,7 @@ struct tb_switch *tb_switch_alloc(struct tb *tb, u64 route) | |||
411 | return sw; | 418 | return sw; |
412 | err: | 419 | err: |
413 | kfree(sw->ports); | 420 | kfree(sw->ports); |
421 | kfree(sw->drom); | ||
414 | kfree(sw); | 422 | kfree(sw); |
415 | return NULL; | 423 | return NULL; |
416 | } | 424 | } |