aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thunderbolt/switch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thunderbolt/switch.c')
-rw-r--r--drivers/thunderbolt/switch.c42
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 */
183static int tb_init_port(struct tb_switch *sw, u8 port_nr) 183static 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;
412err: 419err:
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}