diff options
-rw-r--r-- | drivers/thunderbolt/acpi.c | 12 | ||||
-rw-r--r-- | drivers/thunderbolt/switch.c | 5 | ||||
-rw-r--r-- | drivers/thunderbolt/tb_regs.h | 2 | ||||
-rw-r--r-- | drivers/thunderbolt/usb4.c | 33 | ||||
-rw-r--r-- | drivers/thunderbolt/usb4_port.c | 3 | ||||
-rw-r--r-- | drivers/thunderbolt/xdomain.c | 4 |
6 files changed, 39 insertions, 20 deletions
diff --git a/drivers/thunderbolt/acpi.c b/drivers/thunderbolt/acpi.c index 7a8adf5ad5a0..317e4f5fdb97 100644 --- a/drivers/thunderbolt/acpi.c +++ b/drivers/thunderbolt/acpi.c @@ -15,24 +15,20 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, void **return_value) { struct acpi_device *adev = acpi_fetch_acpi_dev(handle); - struct fwnode_reference_args args; struct fwnode_handle *fwnode; struct tb_nhi *nhi = data; struct pci_dev *pdev; struct device *dev; - int ret; if (!adev) return AE_OK; - fwnode = acpi_fwnode_handle(adev); - ret = fwnode_property_get_reference_args(fwnode, "usb4-host-interface", - NULL, 0, 0, &args); - if (ret) + fwnode = fwnode_find_reference(acpi_fwnode_handle(adev), "usb4-host-interface", 0); + if (IS_ERR(fwnode)) return AE_OK; /* It needs to reference this NHI */ - if (dev_fwnode(&nhi->pdev->dev) != args.fwnode) + if (dev_fwnode(&nhi->pdev->dev) != fwnode) goto out_put; /* @@ -100,7 +96,7 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data, } out_put: - fwnode_handle_put(args.fwnode); + fwnode_handle_put(fwnode); return AE_OK; } diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 60da5c23ccaf..363d712aa364 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -8,12 +8,13 @@ #include <linux/delay.h> #include <linux/idr.h> +#include <linux/module.h> #include <linux/nvmem-provider.h> #include <linux/pm_runtime.h> #include <linux/sched/signal.h> #include <linux/sizes.h> #include <linux/slab.h> -#include <linux/module.h> +#include <linux/string_helpers.h> #include "tb.h" @@ -644,7 +645,7 @@ static int __tb_port_enable(struct tb_port *port, bool enable) if (ret) return ret; - tb_port_dbg(port, "lane %sabled\n", enable ? "en" : "dis"); + tb_port_dbg(port, "lane %s\n", str_enabled_disabled(enable)); return 0; } diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h index 86319dca0f8c..3c38b0cb8f74 100644 --- a/drivers/thunderbolt/tb_regs.h +++ b/drivers/thunderbolt/tb_regs.h @@ -361,6 +361,8 @@ struct tb_regs_port_header { #define PORT_CS_18_BE BIT(8) #define PORT_CS_18_TCM BIT(9) #define PORT_CS_18_CPS BIT(10) +#define PORT_CS_18_WOCS BIT(16) +#define PORT_CS_18_WODS BIT(17) #define PORT_CS_18_WOU4S BIT(18) #define PORT_CS_19 0x13 #define PORT_CS_19_PC BIT(3) diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index f986854aa207..2ed50fcbcca7 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -155,6 +155,8 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode, static void usb4_switch_check_wakes(struct tb_switch *sw) { + bool wakeup_usb4 = false; + struct usb4_port *usb4; struct tb_port *port; bool wakeup = false; u32 val; @@ -173,20 +175,31 @@ static void usb4_switch_check_wakes(struct tb_switch *sw) wakeup = val & (ROUTER_CS_6_WOPS | ROUTER_CS_6_WOUS); } - /* Check for any connected downstream ports for USB4 wake */ + /* + * Check for any downstream ports for USB4 wake, + * connection wake and disconnection wake. + */ tb_switch_for_each_port(sw, port) { - if (!tb_port_has_remote(port)) + if (!port->cap_usb4) continue; if (tb_port_read(port, &val, TB_CFG_PORT, port->cap_usb4 + PORT_CS_18, 1)) break; - tb_port_dbg(port, "USB4 wake: %s\n", - (val & PORT_CS_18_WOU4S) ? "yes" : "no"); + tb_port_dbg(port, "USB4 wake: %s, connection wake: %s, disconnection wake: %s\n", + (val & PORT_CS_18_WOU4S) ? "yes" : "no", + (val & PORT_CS_18_WOCS) ? "yes" : "no", + (val & PORT_CS_18_WODS) ? "yes" : "no"); + + wakeup_usb4 = val & (PORT_CS_18_WOU4S | PORT_CS_18_WOCS | + PORT_CS_18_WODS); + + usb4 = port->usb4; + if (device_may_wakeup(&usb4->dev) && wakeup_usb4) + pm_wakeup_event(&usb4->dev, 0); - if (val & PORT_CS_18_WOU4S) - wakeup = true; + wakeup |= wakeup_usb4; } if (wakeup) @@ -366,6 +379,7 @@ bool usb4_switch_lane_bonding_possible(struct tb_switch *sw) */ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) { + struct usb4_port *usb4; struct tb_port *port; u64 route = tb_route(sw); u32 val; @@ -395,10 +409,13 @@ int usb4_switch_set_wake(struct tb_switch *sw, unsigned int flags) val |= PORT_CS_19_WOU4; } else { bool configured = val & PORT_CS_19_PC; + usb4 = port->usb4; - if ((flags & TB_WAKE_ON_CONNECT) && !configured) + if (((flags & TB_WAKE_ON_CONNECT) | + device_may_wakeup(&usb4->dev)) && !configured) val |= PORT_CS_19_WOC; - if ((flags & TB_WAKE_ON_DISCONNECT) && configured) + if (((flags & TB_WAKE_ON_DISCONNECT) | + device_may_wakeup(&usb4->dev)) && configured) val |= PORT_CS_19_WOD; if ((flags & TB_WAKE_ON_USB4) && configured) val |= PORT_CS_19_WOU4; diff --git a/drivers/thunderbolt/usb4_port.c b/drivers/thunderbolt/usb4_port.c index 1a30c0a23286..e355bfd6343f 100644 --- a/drivers/thunderbolt/usb4_port.c +++ b/drivers/thunderbolt/usb4_port.c @@ -284,6 +284,9 @@ struct usb4_port *usb4_port_device_add(struct tb_port *port) } } + if (!tb_is_upstream_port(port)) + device_set_wakeup_capable(&usb4->dev, true); + pm_runtime_no_callbacks(&usb4->dev); pm_runtime_set_active(&usb4->dev); pm_runtime_enable(&usb4->dev); diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index f00b2f62d8e3..cfa83486c9da 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -13,6 +13,7 @@ #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/prandom.h> +#include <linux/string_helpers.h> #include <linux/utsname.h> #include <linux/uuid.h> #include <linux/workqueue.h> @@ -341,7 +342,6 @@ static int tb_xdp_properties_request(struct tb_ctl *ctl, u64 route, memcpy(&req.src_uuid, src_uuid, sizeof(*src_uuid)); memcpy(&req.dst_uuid, dst_uuid, sizeof(*dst_uuid)); - len = 0; data_len = 0; do { @@ -1344,7 +1344,7 @@ static int tb_xdomain_bond_lanes_uuid_high(struct tb_xdomain *xd) tb_port_update_credits(port); tb_xdomain_update_link_attributes(xd); - dev_dbg(&xd->dev, "lane bonding %sabled\n", width == 2 ? "en" : "dis"); + dev_dbg(&xd->dev, "lane bonding %s\n", str_enabled_disabled(width == 2)); return 0; } |