From: Greg Kroah-Hartman Date: Mon, 1 Apr 2024 10:00:52 +0000 (+0200) Subject: 6.8-stable patches X-Git-Tag: v6.7.12~66 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3b61e080681d52f238f70e271235b4ec9e1d8b29;p=thirdparty%2Fkernel%2Fstable-queue.git 6.8-stable patches added patches: genirq-introduce-irqf_cond_oneshot-and-use-it-in-pinctrl-amd.patch usb-core-add-hub_get-and-hub_put-routines.patch usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch usb-core-fix-deadlock-in-usb_deauthorize_interface.patch usb-dwc3-properly-set-system-wakeup.patch --- diff --git a/queue-6.8/genirq-introduce-irqf_cond_oneshot-and-use-it-in-pinctrl-amd.patch b/queue-6.8/genirq-introduce-irqf_cond_oneshot-and-use-it-in-pinctrl-amd.patch new file mode 100644 index 00000000000..852c90def01 --- /dev/null +++ b/queue-6.8/genirq-introduce-irqf_cond_oneshot-and-use-it-in-pinctrl-amd.patch @@ -0,0 +1,110 @@ +From c2ddeb29612f7ca84ed10c6d4f3ac99705135447 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Mon, 25 Mar 2024 13:58:08 +0100 +Subject: genirq: Introduce IRQF_COND_ONESHOT and use it in pinctrl-amd + +From: Rafael J. Wysocki + +commit c2ddeb29612f7ca84ed10c6d4f3ac99705135447 upstream. + +There is a problem when a driver requests a shared interrupt line to run a +threaded handler on it without IRQF_ONESHOT set if that flag has been set +already for the IRQ in question by somebody else. Namely, the request +fails which usually leads to a probe failure even though the driver might +have worked just fine with IRQF_ONESHOT, but it does not want to use it by +default. Currently, the only way to handle this is to try to request the +IRQ without IRQF_ONESHOT, but with IRQF_PROBE_SHARED set and if this fails, +try again with IRQF_ONESHOT set. However, this is a bit cumbersome and not +very clean. + +When commit 7a36b901a6eb ("ACPI: OSL: Use a threaded interrupt handler for +SCI") switched the ACPI subsystem over to using a threaded interrupt +handler for the SCI, it had to use IRQF_ONESHOT for it because that's +required due to the way the SCI handler works (it needs to walk all of the +enabled GPEs before the interrupt line can be unmasked). The SCI interrupt +line is not shared with other users very often due to the SCI handling +overhead, but on sone systems it is shared and when the other user of it +attempts to install a threaded handler, a flags mismatch related to +IRQF_ONESHOT may occur. + +As it turned out, that happened to the pinctrl-amd driver and so commit +4451e8e8415e ("pinctrl: amd: Add IRQF_ONESHOT to the interrupt request") +attempted to address the issue by adding IRQF_ONESHOT to the interrupt +flags in that driver, but this is now causing an IRQF_ONESHOT-related +mismatch to occur on another system which cannot boot as a result of it. + +Clearly, pinctrl-amd can work with IRQF_ONESHOT if need be, but it should +not set that flag by default, so it needs a way to indicate that to the +interrupt subsystem. + +To that end, introdcuce a new interrupt flag, IRQF_COND_ONESHOT, which will +only have effect when the IRQ line is shared and IRQF_ONESHOT has been set +for it already, in which case it will be promoted to the latter. + +This is sufficient for drivers sharing the interrupt line with the SCI as +it is requested by the ACPI subsystem before any drivers are probed, so +they will always see IRQF_ONESHOT set for the interrupt in question. + +Fixes: 4451e8e8415e ("pinctrl: amd: Add IRQF_ONESHOT to the interrupt request") +Reported-by: Francisco Ayala Le Brun +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Thomas Gleixner +Reviewed-by: Linus Walleij +Cc: 6.8+ # 6.8+ +Closes: https://lore.kernel.org/lkml/CAN-StX1HqWqi+YW=t+V52-38Mfp5fAz7YHx4aH-CQjgyNiKx3g@mail.gmail.com/ +Link: https://lore.kernel.org/r/12417336.O9o76ZdvQC@kreacher +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pinctrl/pinctrl-amd.c | 2 +- + include/linux/interrupt.h | 3 +++ + kernel/irq/manage.c | 9 +++++++-- + 3 files changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/pinctrl/pinctrl-amd.c ++++ b/drivers/pinctrl/pinctrl-amd.c +@@ -1159,7 +1159,7 @@ static int amd_gpio_probe(struct platfor + } + + ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler, +- IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, gpio_dev); ++ IRQF_SHARED | IRQF_COND_ONESHOT, KBUILD_MODNAME, gpio_dev); + if (ret) + goto out2; + +--- a/include/linux/interrupt.h ++++ b/include/linux/interrupt.h +@@ -67,6 +67,8 @@ + * later. + * IRQF_NO_DEBUG - Exclude from runnaway detection for IPI and similar handlers, + * depends on IRQF_PERCPU. ++ * IRQF_COND_ONESHOT - Agree to do IRQF_ONESHOT if already set for a shared ++ * interrupt. + */ + #define IRQF_SHARED 0x00000080 + #define IRQF_PROBE_SHARED 0x00000100 +@@ -82,6 +84,7 @@ + #define IRQF_COND_SUSPEND 0x00040000 + #define IRQF_NO_AUTOEN 0x00080000 + #define IRQF_NO_DEBUG 0x00100000 ++#define IRQF_COND_ONESHOT 0x00200000 + + #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD) + +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -1642,8 +1642,13 @@ __setup_irq(unsigned int irq, struct irq + } + + if (!((old->flags & new->flags) & IRQF_SHARED) || +- (oldtype != (new->flags & IRQF_TRIGGER_MASK)) || +- ((old->flags ^ new->flags) & IRQF_ONESHOT)) ++ (oldtype != (new->flags & IRQF_TRIGGER_MASK))) ++ goto mismatch; ++ ++ if ((old->flags & IRQF_ONESHOT) && ++ (new->flags & IRQF_COND_ONESHOT)) ++ new->flags |= IRQF_ONESHOT; ++ else if ((old->flags ^ new->flags) & IRQF_ONESHOT) + goto mismatch; + + /* All handlers must agree on per-cpuness */ diff --git a/queue-6.8/series b/queue-6.8/series index af0c0b1e6c7..56559cd5532 100644 --- a/queue-6.8/series +++ b/queue-6.8/series @@ -353,3 +353,8 @@ scsi-sg-avoid-sg-device-teardown-race.patch scsi-core-fix-unremoved-procfs-host-directory-regression.patch staging-vc04_services-changen-strncpy-to-strscpy_pad.patch staging-vc04_services-fix-information-leak-in-create_component.patch +genirq-introduce-irqf_cond_oneshot-and-use-it-in-pinctrl-amd.patch +usb-dwc3-properly-set-system-wakeup.patch +usb-core-fix-deadlock-in-usb_deauthorize_interface.patch +usb-core-add-hub_get-and-hub_put-routines.patch +usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch diff --git a/queue-6.8/usb-core-add-hub_get-and-hub_put-routines.patch b/queue-6.8/usb-core-add-hub_get-and-hub_put-routines.patch new file mode 100644 index 00000000000..d0ff4a24bde --- /dev/null +++ b/queue-6.8/usb-core-add-hub_get-and-hub_put-routines.patch @@ -0,0 +1,113 @@ +From ee113b860aa169e9a4d2c167c95d0f1961c6e1b8 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 15 Mar 2024 13:04:50 -0400 +Subject: USB: core: Add hub_get() and hub_put() routines + +From: Alan Stern + +commit ee113b860aa169e9a4d2c167c95d0f1961c6e1b8 upstream. + +Create hub_get() and hub_put() routines to encapsulate the kref_get() +and kref_put() calls in hub.c. The new routines will be used by the +next patch in this series. + +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/r/604da420-ae8a-4a9e-91a4-2d511ff404fb@rowland.harvard.edu +Cc: stable +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hub.c | 23 ++++++++++++++++------- + drivers/usb/core/hub.h | 2 ++ + 2 files changed, 18 insertions(+), 7 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -129,7 +129,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rws + #define HUB_DEBOUNCE_STEP 25 + #define HUB_DEBOUNCE_STABLE 100 + +-static void hub_release(struct kref *kref); + static int usb_reset_and_verify_device(struct usb_device *udev); + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); + static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, +@@ -691,14 +690,14 @@ static void kick_hub_wq(struct usb_hub * + */ + intf = to_usb_interface(hub->intfdev); + usb_autopm_get_interface_no_resume(intf); +- kref_get(&hub->kref); ++ hub_get(hub); + + if (queue_work(hub_wq, &hub->events)) + return; + + /* the work has already been scheduled */ + usb_autopm_put_interface_async(intf); +- kref_put(&hub->kref, hub_release); ++ hub_put(hub); + } + + void usb_kick_hub_wq(struct usb_device *hdev) +@@ -1066,7 +1065,7 @@ static void hub_activate(struct usb_hub + goto init2; + goto init3; + } +- kref_get(&hub->kref); ++ hub_get(hub); + + /* The superspeed hub except for root hub has to use Hub Depth + * value as an offset into the route string to locate the bits +@@ -1314,7 +1313,7 @@ static void hub_activate(struct usb_hub + device_unlock(&hdev->dev); + } + +- kref_put(&hub->kref, hub_release); ++ hub_put(hub); + } + + /* Implement the continuations for the delays above */ +@@ -1730,6 +1729,16 @@ static void hub_release(struct kref *kre + kfree(hub); + } + ++void hub_get(struct usb_hub *hub) ++{ ++ kref_get(&hub->kref); ++} ++ ++void hub_put(struct usb_hub *hub) ++{ ++ kref_put(&hub->kref, hub_release); ++} ++ + static unsigned highspeed_hubs; + + static void hub_disconnect(struct usb_interface *intf) +@@ -1778,7 +1787,7 @@ static void hub_disconnect(struct usb_in + + onboard_hub_destroy_pdevs(&hub->onboard_hub_devs); + +- kref_put(&hub->kref, hub_release); ++ hub_put(hub); + } + + static bool hub_descriptor_is_sane(struct usb_host_interface *desc) +@@ -5905,7 +5914,7 @@ out_hdev_lock: + + /* Balance the stuff in kick_hub_wq() and allow autosuspend */ + usb_autopm_put_interface(intf); +- kref_put(&hub->kref, hub_release); ++ hub_put(hub); + + kcov_remote_stop(); + } +--- a/drivers/usb/core/hub.h ++++ b/drivers/usb/core/hub.h +@@ -129,6 +129,8 @@ extern void usb_hub_remove_port_device(s + extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, + int port1, bool set); + extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev); ++extern void hub_get(struct usb_hub *hub); ++extern void hub_put(struct usb_hub *hub); + extern int hub_port_debounce(struct usb_hub *hub, int port1, + bool must_be_connected); + extern int usb_clear_port_feature(struct usb_device *hdev, diff --git a/queue-6.8/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch b/queue-6.8/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch new file mode 100644 index 00000000000..15514434729 --- /dev/null +++ b/queue-6.8/usb-core-fix-deadlock-in-port-disable-sysfs-attribute.patch @@ -0,0 +1,123 @@ +From f4d1960764d8a70318b02f15203a1be2b2554ca1 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 15 Mar 2024 13:06:33 -0400 +Subject: USB: core: Fix deadlock in port "disable" sysfs attribute + +From: Alan Stern + +commit f4d1960764d8a70318b02f15203a1be2b2554ca1 upstream. + +The show and store callback routines for the "disable" sysfs attribute +file in port.c acquire the device lock for the port's parent hub +device. This can cause problems if another process has locked the hub +to remove it or change its configuration: + + Removing the hub or changing its configuration requires the + hub interface to be removed, which requires the port device + to be removed, and device_del() waits until all outstanding + sysfs attribute callbacks for the ports have returned. The + lock can't be released until then. + + But the disable_show() or disable_store() routine can't return + until after it has acquired the lock. + +The resulting deadlock can be avoided by calling +sysfs_break_active_protection(). This will cause the sysfs core not +to wait for the attribute's callback routine to return, allowing the +removal to proceed. The disadvantage is that after making this call, +there is no guarantee that the hub structure won't be deallocated at +any moment. To prevent this, we have to acquire a reference to it +first by calling hub_get(). + +Signed-off-by: Alan Stern +Cc: stable +Link: https://lore.kernel.org/r/f7a8c135-a495-4ce6-bd49-405a45e7ea9a@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/port.c | 38 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) + +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -55,11 +55,22 @@ static ssize_t disable_show(struct devic + u16 portstatus, unused; + bool disabled; + int rc; ++ struct kernfs_node *kn; + ++ hub_get(hub); + rc = usb_autopm_get_interface(intf); + if (rc < 0) +- return rc; ++ goto out_hub_get; + ++ /* ++ * Prevent deadlock if another process is concurrently ++ * trying to unregister hdev. ++ */ ++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); ++ if (!kn) { ++ rc = -ENODEV; ++ goto out_autopm; ++ } + usb_lock_device(hdev); + if (hub->disconnected) { + rc = -ENODEV; +@@ -69,9 +80,13 @@ static ssize_t disable_show(struct devic + usb_hub_port_status(hub, port1, &portstatus, &unused); + disabled = !usb_port_is_power_on(hub, portstatus); + +-out_hdev_lock: ++ out_hdev_lock: + usb_unlock_device(hdev); ++ sysfs_unbreak_active_protection(kn); ++ out_autopm: + usb_autopm_put_interface(intf); ++ out_hub_get: ++ hub_put(hub); + + if (rc) + return rc; +@@ -89,15 +104,26 @@ static ssize_t disable_store(struct devi + int port1 = port_dev->portnum; + bool disabled; + int rc; ++ struct kernfs_node *kn; + + rc = kstrtobool(buf, &disabled); + if (rc) + return rc; + ++ hub_get(hub); + rc = usb_autopm_get_interface(intf); + if (rc < 0) +- return rc; ++ goto out_hub_get; + ++ /* ++ * Prevent deadlock if another process is concurrently ++ * trying to unregister hdev. ++ */ ++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); ++ if (!kn) { ++ rc = -ENODEV; ++ goto out_autopm; ++ } + usb_lock_device(hdev); + if (hub->disconnected) { + rc = -ENODEV; +@@ -118,9 +144,13 @@ static ssize_t disable_store(struct devi + if (!rc) + rc = count; + +-out_hdev_lock: ++ out_hdev_lock: + usb_unlock_device(hdev); ++ sysfs_unbreak_active_protection(kn); ++ out_autopm: + usb_autopm_put_interface(intf); ++ out_hub_get: ++ hub_put(hub); + + return rc; + } diff --git a/queue-6.8/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch b/queue-6.8/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch new file mode 100644 index 00000000000..62aa8e32c6b --- /dev/null +++ b/queue-6.8/usb-core-fix-deadlock-in-usb_deauthorize_interface.patch @@ -0,0 +1,70 @@ +From 80ba43e9f799cbdd83842fc27db667289b3150f5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 12 Mar 2024 11:48:23 -0400 +Subject: USB: core: Fix deadlock in usb_deauthorize_interface() + +From: Alan Stern + +commit 80ba43e9f799cbdd83842fc27db667289b3150f5 upstream. + +Among the attribute file callback routines in +drivers/usb/core/sysfs.c, the interface_authorized_store() function is +the only one which acquires a device lock on an ancestor device: It +calls usb_deauthorize_interface(), which locks the interface's parent +USB device. + +The will lead to deadlock if another process already owns that lock +and tries to remove the interface, whether through a configuration +change or because the device has been disconnected. As part of the +removal procedure, device_del() waits for all ongoing sysfs attribute +callbacks to complete. But usb_deauthorize_interface() can't complete +until the device lock has been released, and the lock won't be +released until the removal has finished. + +The mechanism provided by sysfs to prevent this kind of deadlock is +to use the sysfs_break_active_protection() function, which tells sysfs +not to wait for the attribute callback. + +Reported-and-tested by: Yue Sun +Reported by: xingwei lee + +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/linux-usb/CAEkJfYO6jRVC8Tfrd_R=cjO0hguhrV31fDPrLrNOOHocDkPoAA@mail.gmail.com/#r +Fixes: 310d2b4124c0 ("usb: interface authorization: SysFS part of USB interface authorization") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/1c37eea1-9f56-4534-b9d8-b443438dc869@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/sysfs.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +--- a/drivers/usb/core/sysfs.c ++++ b/drivers/usb/core/sysfs.c +@@ -1168,14 +1168,24 @@ static ssize_t interface_authorized_stor + { + struct usb_interface *intf = to_usb_interface(dev); + bool val; ++ struct kernfs_node *kn; + + if (kstrtobool(buf, &val) != 0) + return -EINVAL; + +- if (val) ++ if (val) { + usb_authorize_interface(intf); +- else +- usb_deauthorize_interface(intf); ++ } else { ++ /* ++ * Prevent deadlock if another process is concurrently ++ * trying to unregister intf. ++ */ ++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); ++ if (kn) { ++ usb_deauthorize_interface(intf); ++ sysfs_unbreak_active_protection(kn); ++ } ++ } + + return count; + } diff --git a/queue-6.8/usb-dwc3-properly-set-system-wakeup.patch b/queue-6.8/usb-dwc3-properly-set-system-wakeup.patch new file mode 100644 index 00000000000..b2bb4970e39 --- /dev/null +++ b/queue-6.8/usb-dwc3-properly-set-system-wakeup.patch @@ -0,0 +1,128 @@ +From f9aa41130ac69d13a53ce2a153ca79c70d43f39c Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Fri, 8 Mar 2024 02:40:25 +0000 +Subject: usb: dwc3: Properly set system wakeup + +From: Thinh Nguyen + +commit f9aa41130ac69d13a53ce2a153ca79c70d43f39c upstream. + +If the device is configured for system wakeup, then make sure that the +xHCI driver knows about it and make sure to permit wakeup only at the +appropriate time. + +For host mode, if the controller goes through the dwc3 code path, then a +child xHCI platform device is created. Make sure the platform device +also inherits the wakeup setting for xHCI to enable remote wakeup. + +For device mode, make sure to disable system wakeup if no gadget driver +is bound. We may experience unwanted system wakeup due to the wakeup +signal from the controller PMU detecting connection/disconnection when +in low power (D3). E.g. In the case of Steam Deck, the PCI PME prevents +the system staying in suspend. + +Cc: stable@vger.kernel.org +Reported-by: Guilherme G. Piccoli +Closes: https://lore.kernel.org/linux-usb/70a7692d-647c-9be7-00a6-06fc60f77294@igalia.com/T/#mf00d6669c2eff7b308d1162acd1d66c09f0853c7 +Fixes: d07e8819a03d ("usb: dwc3: add xHCI Host support") +Signed-off-by: Thinh Nguyen +Tested-by: Sanath S +Tested-by: Guilherme G. Piccoli # Steam Deck +Link: https://lore.kernel.org/r/667cfda7009b502e08462c8fb3f65841d103cc0a.1709865476.git.Thinh.Nguyen@synopsys.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/core.c | 2 ++ + drivers/usb/dwc3/core.h | 2 ++ + drivers/usb/dwc3/gadget.c | 10 ++++++++++ + drivers/usb/dwc3/host.c | 11 +++++++++++ + 4 files changed, 25 insertions(+) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1519,6 +1519,8 @@ static void dwc3_get_properties(struct d + else + dwc->sysdev = dwc->dev; + ++ dwc->sys_wakeup = device_may_wakeup(dwc->sysdev); ++ + ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name); + if (ret >= 0) { + dwc->usb_psy = power_supply_get_by_name(usb_psy_name); +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1132,6 +1132,7 @@ struct dwc3_scratchpad_array { + * 3 - Reserved + * @dis_metastability_quirk: set to disable metastability quirk. + * @dis_split_quirk: set to disable split boundary. ++ * @sys_wakeup: set if the device may do system wakeup. + * @wakeup_configured: set if the device is configured for remote wakeup. + * @suspended: set to track suspend event due to U3/L2. + * @imod_interval: set the interrupt moderation interval in 250ns +@@ -1355,6 +1356,7 @@ struct dwc3 { + + unsigned dis_split_quirk:1; + unsigned async_callbacks:1; ++ unsigned sys_wakeup:1; + unsigned wakeup_configured:1; + unsigned suspended:1; + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2968,6 +2968,9 @@ static int dwc3_gadget_start(struct usb_ + dwc->gadget_driver = driver; + spin_unlock_irqrestore(&dwc->lock, flags); + ++ if (dwc->sys_wakeup) ++ device_wakeup_enable(dwc->sysdev); ++ + return 0; + } + +@@ -2983,6 +2986,9 @@ static int dwc3_gadget_stop(struct usb_g + struct dwc3 *dwc = gadget_to_dwc(g); + unsigned long flags; + ++ if (dwc->sys_wakeup) ++ device_wakeup_disable(dwc->sysdev); ++ + spin_lock_irqsave(&dwc->lock, flags); + dwc->gadget_driver = NULL; + dwc->max_cfg_eps = 0; +@@ -4664,6 +4670,10 @@ int dwc3_gadget_init(struct dwc3 *dwc) + else + dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed); + ++ /* No system wakeup if no gadget driver bound */ ++ if (dwc->sys_wakeup) ++ device_wakeup_disable(dwc->sysdev); ++ + return 0; + + err5: +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -123,6 +123,14 @@ int dwc3_host_init(struct dwc3 *dwc) + goto err; + } + ++ if (dwc->sys_wakeup) { ++ /* Restore wakeup setting if switched from device */ ++ device_wakeup_enable(dwc->sysdev); ++ ++ /* Pass on wakeup setting to the new xhci platform device */ ++ device_init_wakeup(&xhci->dev, true); ++ } ++ + return 0; + err: + platform_device_put(xhci); +@@ -131,6 +139,9 @@ err: + + void dwc3_host_exit(struct dwc3 *dwc) + { ++ if (dwc->sys_wakeup) ++ device_init_wakeup(&dwc->xhci->dev, false); ++ + platform_device_unregister(dwc->xhci); + dwc->xhci = NULL; + }