@@ -1538,29 +1538,124 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw)
1538
1538
regs -> __unknown1 , regs -> __unknown4 );
1539
1539
}
1540
1540
1541
+ static int tb_switch_reset_host (struct tb_switch * sw )
1542
+ {
1543
+ if (sw -> generation > 1 ) {
1544
+ struct tb_port * port ;
1545
+
1546
+ tb_switch_for_each_port (sw , port ) {
1547
+ int i , ret ;
1548
+
1549
+ /*
1550
+ * For lane adapters we issue downstream port
1551
+ * reset and clear up path config spaces.
1552
+ *
1553
+ * For protocol adapters we disable the path and
1554
+ * clear path config space one by one (from 8 to
1555
+ * Max Input HopID of the adapter).
1556
+ */
1557
+ if (tb_port_is_null (port ) && !tb_is_upstream_port (port )) {
1558
+ ret = tb_port_reset (port );
1559
+ if (ret )
1560
+ return ret ;
1561
+ } else if (tb_port_is_usb3_down (port ) ||
1562
+ tb_port_is_usb3_up (port )) {
1563
+ tb_usb3_port_enable (port , false);
1564
+ } else if (tb_port_is_dpin (port ) ||
1565
+ tb_port_is_dpout (port )) {
1566
+ tb_dp_port_enable (port , false);
1567
+ } else if (tb_port_is_pcie_down (port ) ||
1568
+ tb_port_is_pcie_up (port )) {
1569
+ tb_pci_port_enable (port , false);
1570
+ } else {
1571
+ continue ;
1572
+ }
1573
+
1574
+ /* Cleanup path config space of protocol adapter */
1575
+ for (i = TB_PATH_MIN_HOPID ;
1576
+ i <= port -> config .max_in_hop_id ; i ++ ) {
1577
+ ret = tb_path_deactivate_hop (port , i );
1578
+ if (ret )
1579
+ return ret ;
1580
+ }
1581
+ }
1582
+ } else {
1583
+ struct tb_cfg_result res ;
1584
+
1585
+ /* Thunderbolt 1 uses the "reset" config space packet */
1586
+ res .err = tb_sw_write (sw , ((u32 * ) & sw -> config ) + 2 ,
1587
+ TB_CFG_SWITCH , 2 , 2 );
1588
+ if (res .err )
1589
+ return res .err ;
1590
+ res = tb_cfg_reset (sw -> tb -> ctl , tb_route (sw ));
1591
+ if (res .err > 0 )
1592
+ return - EIO ;
1593
+ else if (res .err < 0 )
1594
+ return res .err ;
1595
+ }
1596
+
1597
+ return 0 ;
1598
+ }
1599
+
1600
+ static int tb_switch_reset_device (struct tb_switch * sw )
1601
+ {
1602
+ return tb_port_reset (tb_switch_downstream_port (sw ));
1603
+ }
1604
+
1605
+ static bool tb_switch_enumerated (struct tb_switch * sw )
1606
+ {
1607
+ u32 val ;
1608
+ int ret ;
1609
+
1610
+ /*
1611
+ * Read directly from the hardware because we use this also
1612
+ * during system sleep where sw->config.enabled is already set
1613
+ * by us.
1614
+ */
1615
+ ret = tb_sw_read (sw , & val , TB_CFG_SWITCH , ROUTER_CS_3 , 1 );
1616
+ if (ret )
1617
+ return false;
1618
+
1619
+ return !!(val & ROUTER_CS_3_V );
1620
+ }
1621
+
1541
1622
/**
1542
- * tb_switch_reset() - reconfigure route, enable and send TB_CFG_PKG_RESET
1543
- * @sw: Switch to reset
1623
+ * tb_switch_reset() - Perform reset to the router
1624
+ * @sw: Router to reset
1544
1625
*
1545
- * Return: Returns 0 on success or an error code on failure.
1626
+ * Issues reset to the router @sw. Can be used for any router. For host
1627
+ * routers, resets all the downstream ports and cleans up path config
1628
+ * spaces accordingly. For device routers issues downstream port reset
1629
+ * through the parent router, so as side effect there will be unplug
1630
+ * soon after this is finished.
1631
+ *
1632
+ * If the router is not enumerated does nothing.
1633
+ *
1634
+ * Returns %0 on success or negative errno in case of failure.
1546
1635
*/
1547
1636
int tb_switch_reset (struct tb_switch * sw )
1548
1637
{
1549
- struct tb_cfg_result res ;
1638
+ int ret ;
1550
1639
1551
- if (sw -> generation > 1 )
1640
+ /*
1641
+ * We cannot access the port config spaces unless the router is
1642
+ * already enumerated. If the router is not enumerated it is
1643
+ * equal to being reset so we can skip that here.
1644
+ */
1645
+ if (!tb_switch_enumerated (sw ))
1552
1646
return 0 ;
1553
1647
1554
- tb_sw_dbg (sw , "resetting switch \n" );
1648
+ tb_sw_dbg (sw , "resetting\n" );
1555
1649
1556
- res .err = tb_sw_write (sw , ((u32 * ) & sw -> config ) + 2 ,
1557
- TB_CFG_SWITCH , 2 , 2 );
1558
- if (res .err )
1559
- return res .err ;
1560
- res = tb_cfg_reset (sw -> tb -> ctl , tb_route (sw ));
1561
- if (res .err > 0 )
1562
- return - EIO ;
1563
- return res .err ;
1650
+ if (tb_route (sw ))
1651
+ ret = tb_switch_reset_device (sw );
1652
+ else
1653
+ ret = tb_switch_reset_host (sw );
1654
+
1655
+ if (ret )
1656
+ tb_sw_warn (sw , "failed to reset\n" );
1657
+
1658
+ return ret ;
1564
1659
}
1565
1660
1566
1661
/**
0 commit comments