thunderbolt: Explicitly enable lane adapter hotplug events at startup
authorMario Limonciello <mario.limonciello@amd.com>
Mon, 26 Sep 2022 14:33:50 +0000 (09:33 -0500)
committerMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 26 Sep 2022 17:18:25 +0000 (20:18 +0300)
Software that has run before the USB4 CM in Linux runs may have disabled
hotplug events for a given lane adapter.

Other CMs such as that one distributed with Windows 11 will enable hotplug
events. Do the same thing in the Linux CM which fixes hotplug events on
"AMD Pink Sardine".

Cc: stable@vger.kernel.org
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
drivers/thunderbolt/switch.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/tb_regs.h
drivers/thunderbolt/usb4.c

index 72bc03249490a10a1a0a9204b778fe37125589b2..59f786a47b56ad121d04b3b13fff468b99025987 100644 (file)
@@ -2900,6 +2900,26 @@ static void tb_switch_credits_init(struct tb_switch *sw)
                tb_sw_info(sw, "failed to determine preferred buffer allocation, using defaults\n");
 }
 
+static int tb_switch_port_hotplug_enable(struct tb_switch *sw)
+{
+       struct tb_port *port;
+
+       if (tb_switch_is_icm(sw))
+               return 0;
+
+       tb_switch_for_each_port(sw, port) {
+               int res;
+
+               if (!port->cap_usb4)
+                       continue;
+
+               res = usb4_port_hotplug_enable(port);
+               if (res)
+                       return res;
+       }
+       return 0;
+}
+
 /**
  * tb_switch_add() - Add a switch to the domain
  * @sw: Switch to add
@@ -2969,6 +2989,10 @@ int tb_switch_add(struct tb_switch *sw)
                        return ret;
        }
 
+       ret = tb_switch_port_hotplug_enable(sw);
+       if (ret)
+               return ret;
+
        ret = device_add(&sw->dev);
        if (ret) {
                dev_err(&sw->dev, "failed to add device: %d\n", ret);
index 33524503a422192e545bdbc724b23564a68d534e..32843e64482fd6e00e2cd69ed850590a3712ab7f 100644 (file)
@@ -1194,6 +1194,7 @@ int usb4_switch_add_ports(struct tb_switch *sw);
 void usb4_switch_remove_ports(struct tb_switch *sw);
 
 int usb4_port_unlock(struct tb_port *port);
+int usb4_port_hotplug_enable(struct tb_port *port);
 int usb4_port_configure(struct tb_port *port);
 void usb4_port_unconfigure(struct tb_port *port);
 int usb4_port_configure_xdomain(struct tb_port *port);
index 0fe1daa21423a5ded88ffa74a020037efad55c48..86319dca0f8ca90585879dbd6e7b3f4c489f85d0 100644 (file)
@@ -308,6 +308,7 @@ struct tb_regs_port_header {
 #define ADP_CS_5                               0x05
 #define ADP_CS_5_LCA_MASK                      GENMASK(28, 22)
 #define ADP_CS_5_LCA_SHIFT                     22
+#define ADP_CS_5_DHP                           BIT(31)
 
 /* TMU adapter registers */
 #define TMU_ADP_CS_3                           0x03
index 70036f3e37a57cb3763069b688c40d4c9f006e06..38c10c30e6cffca705b4f3f4b5b37ce03be3f3c1 100644 (file)
@@ -1046,6 +1046,26 @@ int usb4_port_unlock(struct tb_port *port)
        return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_4, 1);
 }
 
+/**
+ * usb4_port_hotplug_enable() - Enables hotplug for a port
+ * @port: USB4 port to operate on
+ *
+ * Enables hot plug events on a given port. This is only intended
+ * to be used on lane, DP-IN, and DP-OUT adapters.
+ */
+int usb4_port_hotplug_enable(struct tb_port *port)
+{
+       int ret;
+       u32 val;
+
+       ret = tb_port_read(port, &val, TB_CFG_PORT, ADP_CS_5, 1);
+       if (ret)
+               return ret;
+
+       val &= ~ADP_CS_5_DHP;
+       return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1);
+}
+
 static int usb4_port_set_configured(struct tb_port *port, bool configured)
 {
        int ret;