Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thunderbolt: Make tb_switch_alloc() return ERR_PTR()

In order to detect possible connections to other domains we need to be
able to find out why tb_switch_alloc() fails so make it return ERR_PTR()
instead. This allows the caller to differentiate between errors such as
-ENOMEM which comes from the kernel and for instance -EIO which comes
from the hardware when trying to access the possible switch.

Convert all the current call sites to handle this properly.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

+26 -22
+3 -3
drivers/thunderbolt/icm.c
··· 468 468 pm_runtime_get_sync(&parent_sw->dev); 469 469 470 470 sw = tb_switch_alloc(parent_sw->tb, &parent_sw->dev, route); 471 - if (!sw) 471 + if (IS_ERR(sw)) 472 472 goto out; 473 473 474 474 sw->uuid = kmemdup(uuid, sizeof(*uuid), GFP_KERNEL); ··· 1848 1848 tb->root_switch = tb_switch_alloc_safe_mode(tb, &tb->dev, 0); 1849 1849 else 1850 1850 tb->root_switch = tb_switch_alloc(tb, &tb->dev, 0); 1851 - if (!tb->root_switch) 1852 - return -ENODEV; 1851 + if (IS_ERR(tb->root_switch)) 1852 + return PTR_ERR(tb->root_switch); 1853 1853 1854 1854 /* 1855 1855 * NVM upgrade has not been tested on Apple systems and they
+20 -16
drivers/thunderbolt/switch.c
··· 1450 1450 * separately. The returned switch should be released by calling 1451 1451 * tb_switch_put(). 1452 1452 * 1453 - * Return: Pointer to the allocated switch or %NULL in case of failure 1453 + * Return: Pointer to the allocated switch or ERR_PTR() in case of 1454 + * failure. 1454 1455 */ 1455 1456 struct tb_switch *tb_switch_alloc(struct tb *tb, struct device *parent, 1456 1457 u64 route) 1457 1458 { 1458 1459 struct tb_switch *sw; 1459 1460 int upstream_port; 1460 - int i, cap, depth; 1461 + int i, ret, depth; 1461 1462 1462 1463 /* Make sure we do not exceed maximum topology limit */ 1463 1464 depth = tb_route_length(route); 1464 1465 if (depth > TB_SWITCH_MAX_DEPTH) 1465 - return NULL; 1466 + return ERR_PTR(-EADDRNOTAVAIL); 1466 1467 1467 1468 upstream_port = tb_cfg_get_upstream_port(tb->ctl, route); 1468 1469 if (upstream_port < 0) 1469 - return NULL; 1470 + return ERR_PTR(upstream_port); 1470 1471 1471 1472 sw = kzalloc(sizeof(*sw), GFP_KERNEL); 1472 1473 if (!sw) 1473 - return NULL; 1474 + return ERR_PTR(-ENOMEM); 1474 1475 1475 1476 sw->tb = tb; 1476 - if (tb_cfg_read(tb->ctl, &sw->config, route, 0, TB_CFG_SWITCH, 0, 5)) 1477 + ret = tb_cfg_read(tb->ctl, &sw->config, route, 0, TB_CFG_SWITCH, 0, 5); 1478 + if (ret) 1477 1479 goto err_free_sw_ports; 1478 1480 1479 1481 tb_dbg(tb, "current switch config:\n"); ··· 1491 1489 /* initialize ports */ 1492 1490 sw->ports = kcalloc(sw->config.max_port_number + 1, sizeof(*sw->ports), 1493 1491 GFP_KERNEL); 1494 - if (!sw->ports) 1492 + if (!sw->ports) { 1493 + ret = -ENOMEM; 1495 1494 goto err_free_sw_ports; 1495 + } 1496 1496 1497 1497 for (i = 0; i <= sw->config.max_port_number; i++) { 1498 1498 /* minimum setup for tb_find_cap and tb_drom_read to work */ ··· 1504 1500 1505 1501 sw->generation = tb_switch_get_generation(sw); 1506 1502 1507 - cap = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS); 1508 - if (cap < 0) { 1503 + ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_PLUG_EVENTS); 1504 + if (ret < 0) { 1509 1505 tb_sw_warn(sw, "cannot find TB_VSE_CAP_PLUG_EVENTS aborting\n"); 1510 1506 goto err_free_sw_ports; 1511 1507 } 1512 - sw->cap_plug_events = cap; 1508 + sw->cap_plug_events = ret; 1513 1509 1514 - cap = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER); 1515 - if (cap > 0) 1516 - sw->cap_lc = cap; 1510 + ret = tb_switch_find_vse_cap(sw, TB_VSE_CAP_LINK_CONTROLLER); 1511 + if (ret > 0) 1512 + sw->cap_lc = ret; 1517 1513 1518 1514 /* Root switch is always authorized */ 1519 1515 if (!route) ··· 1532 1528 kfree(sw->ports); 1533 1529 kfree(sw); 1534 1530 1535 - return NULL; 1531 + return ERR_PTR(ret); 1536 1532 } 1537 1533 1538 1534 /** ··· 1547 1543 * 1548 1544 * The returned switch must be released by calling tb_switch_put(). 1549 1545 * 1550 - * Return: Pointer to the allocated switch or %NULL in case of failure 1546 + * Return: Pointer to the allocated switch or ERR_PTR() in case of failure 1551 1547 */ 1552 1548 struct tb_switch * 1553 1549 tb_switch_alloc_safe_mode(struct tb *tb, struct device *parent, u64 route) ··· 1556 1552 1557 1553 sw = kzalloc(sizeof(*sw), GFP_KERNEL); 1558 1554 if (!sw) 1559 - return NULL; 1555 + return ERR_PTR(-ENOMEM); 1560 1556 1561 1557 sw->tb = tb; 1562 1558 sw->config.depth = tb_route_length(route);
+3 -3
drivers/thunderbolt/tb.c
··· 148 148 } 149 149 sw = tb_switch_alloc(port->sw->tb, &port->sw->dev, 150 150 tb_downstream_route(port)); 151 - if (!sw) 151 + if (IS_ERR(sw)) 152 152 return; 153 153 154 154 if (tb_switch_configure(sw)) { ··· 533 533 int ret; 534 534 535 535 tb->root_switch = tb_switch_alloc(tb, &tb->dev, 0); 536 - if (!tb->root_switch) 537 - return -ENOMEM; 536 + if (IS_ERR(tb->root_switch)) 537 + return PTR_ERR(tb->root_switch); 538 538 539 539 /* 540 540 * ICM firmware upgrade needs running firmware and in native