From: Greg Kroah-Hartman Date: Mon, 27 Jun 2022 08:23:58 +0000 (+0200) Subject: 5.18-stable patches X-Git-Tag: v5.4.202~36 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da35a271239891dcb63e5a936d318cdbff77bcd5;p=thirdparty%2Fkernel%2Fstable-queue.git 5.18-stable patches added patches: usb-gadget-fix-double-free-bug-in-raw_gadget-driver.patch usb-gadget-fix-non-unique-driver-names-in-raw-gadget-driver.patch usb-gadget-uvc-fix-list-double-add-in-uvcg_video_pump.patch xhci-pci-allow-host-runtime-pm-as-default-for-intel-meteor-lake-xhci.patch xhci-pci-allow-host-runtime-pm-as-default-for-intel-raptor-lake-xhci.patch xhci-turn-off-port-power-in-shutdown.patch --- diff --git a/queue-5.18/s390-crash-make-copy_oldmem_page-return-number-of-by.patch b/queue-5.18/s390-crash-make-copy_oldmem_page-return-number-of-by.patch index 2881465c1c5..b17712c4960 100644 --- a/queue-5.18/s390-crash-make-copy_oldmem_page-return-number-of-by.patch +++ b/queue-5.18/s390-crash-make-copy_oldmem_page-return-number-of-by.patch @@ -15,15 +15,14 @@ Reviewed-by: Alexander Egorenkov Tested-by: Alexander Egorenkov Signed-off-by: Alexander Gordeev Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman --- - arch/s390/kernel/crash_dump.c | 7 ++++--- + arch/s390/kernel/crash_dump.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) -diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c -index 2534a31d2550..28124d0fa1d5 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c -@@ -233,9 +233,10 @@ ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, size_t csize, +@@ -233,9 +233,10 @@ ssize_t copy_oldmem_page(struct iov_iter rc = copy_oldmem_user(iter->iov->iov_base, src, csize); else rc = copy_oldmem_kernel(iter->kvec->iov_base, src, csize); @@ -37,6 +36,3 @@ index 2534a31d2550..28124d0fa1d5 100644 } /* --- -2.35.1 - diff --git a/queue-5.18/series b/queue-5.18/series index 6e82cb5def0..cb0f74911fd 100644 --- a/queue-5.18/series +++ b/queue-5.18/series @@ -112,3 +112,9 @@ io_uring-fix-wrong-arm_poll-error-handling.patch vmcore-convert-copy_oldmem_page-to-take-an-iov_iter.patch s390-crash-add-missing-iterator-advance-in-copy_oldm.patch s390-crash-make-copy_oldmem_page-return-number-of-by.patch +xhci-turn-off-port-power-in-shutdown.patch +xhci-pci-allow-host-runtime-pm-as-default-for-intel-raptor-lake-xhci.patch +xhci-pci-allow-host-runtime-pm-as-default-for-intel-meteor-lake-xhci.patch +usb-gadget-uvc-fix-list-double-add-in-uvcg_video_pump.patch +usb-gadget-fix-non-unique-driver-names-in-raw-gadget-driver.patch +usb-gadget-fix-double-free-bug-in-raw_gadget-driver.patch diff --git a/queue-5.18/usb-gadget-fix-double-free-bug-in-raw_gadget-driver.patch b/queue-5.18/usb-gadget-fix-double-free-bug-in-raw_gadget-driver.patch new file mode 100644 index 00000000000..57cdb79b14c --- /dev/null +++ b/queue-5.18/usb-gadget-fix-double-free-bug-in-raw_gadget-driver.patch @@ -0,0 +1,86 @@ +From 90bc2af24638659da56397ff835f3c95a948f991 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 22 Jun 2022 10:46:31 -0400 +Subject: USB: gadget: Fix double-free bug in raw_gadget driver + +From: Alan Stern + +commit 90bc2af24638659da56397ff835f3c95a948f991 upstream. + +Re-reading a recently merged fix to the raw_gadget driver showed that +it inadvertently introduced a double-free bug in a failure pathway. +If raw_ioctl_init() encounters an error after the driver ID number has +been allocated, it deallocates the ID number before returning. But +when dev_free() runs later on, it will then try to deallocate the ID +number a second time. + +Closely related to this issue is another error in the recent fix: The +ID number is stored in the raw_dev structure before the code checks to +see whether the structure has already been initialized, in which case +the new ID number would overwrite the earlier value. + +The solution to both bugs is to keep the new ID number in a local +variable, and store it in the raw_dev structure only after the check +for prior initialization. No errors can occur after that point, so +the double-free will never happen. + +Fixes: f2d8c2606825 ("usb: gadget: Fix non-unique driver names in raw-gadget driver") +CC: Andrey Konovalov +CC: +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/r/YrMrRw5AyIZghN0v@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/legacy/raw_gadget.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/usb/gadget/legacy/raw_gadget.c ++++ b/drivers/usb/gadget/legacy/raw_gadget.c +@@ -430,6 +430,7 @@ out_put: + static int raw_ioctl_init(struct raw_dev *dev, unsigned long value) + { + int ret = 0; ++ int driver_id_number; + struct usb_raw_init arg; + char *udc_driver_name; + char *udc_device_name; +@@ -452,10 +453,9 @@ static int raw_ioctl_init(struct raw_dev + return -EINVAL; + } + +- ret = ida_alloc(&driver_id_numbers, GFP_KERNEL); +- if (ret < 0) +- return ret; +- dev->driver_id_number = ret; ++ driver_id_number = ida_alloc(&driver_id_numbers, GFP_KERNEL); ++ if (driver_id_number < 0) ++ return driver_id_number; + + driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL); + if (!driver_driver_name) { +@@ -463,7 +463,7 @@ static int raw_ioctl_init(struct raw_dev + goto out_free_driver_id_number; + } + snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX, +- DRIVER_NAME ".%d", dev->driver_id_number); ++ DRIVER_NAME ".%d", driver_id_number); + + udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); + if (!udc_driver_name) { +@@ -507,6 +507,7 @@ static int raw_ioctl_init(struct raw_dev + dev->driver.driver.name = driver_driver_name; + dev->driver.udc_name = udc_device_name; + dev->driver.match_existing_only = 1; ++ dev->driver_id_number = driver_id_number; + + dev->state = STATE_DEV_INITIALIZED; + spin_unlock_irqrestore(&dev->lock, flags); +@@ -521,7 +522,7 @@ out_free_udc_driver_name: + out_free_driver_driver_name: + kfree(driver_driver_name); + out_free_driver_id_number: +- ida_free(&driver_id_numbers, dev->driver_id_number); ++ ida_free(&driver_id_numbers, driver_id_number); + return ret; + } + diff --git a/queue-5.18/usb-gadget-fix-non-unique-driver-names-in-raw-gadget-driver.patch b/queue-5.18/usb-gadget-fix-non-unique-driver-names-in-raw-gadget-driver.patch new file mode 100644 index 00000000000..d0eaa1038d5 --- /dev/null +++ b/queue-5.18/usb-gadget-fix-non-unique-driver-names-in-raw-gadget-driver.patch @@ -0,0 +1,192 @@ +From f2d8c2606825317b77db1f9ba0fc26ef26160b30 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 13 Jun 2022 10:17:03 -0400 +Subject: usb: gadget: Fix non-unique driver names in raw-gadget driver + +From: Alan Stern + +commit f2d8c2606825317b77db1f9ba0fc26ef26160b30 upstream. + +In a report for a separate bug (which has already been fixed by commit +5f0b5f4d50fa "usb: gadget: fix race when gadget driver register via +ioctl") in the raw-gadget driver, the syzbot console log included +error messages caused by attempted registration of a new driver with +the same name as an existing driver: + +> kobject_add_internal failed for raw-gadget with -EEXIST, don't try to register things with the same name in the same directory. +> UDC core: USB Raw Gadget: driver registration failed: -17 +> misc raw-gadget: fail, usb_gadget_register_driver returned -17 + +These errors arise because raw_gadget.c registers a separate UDC +driver for each of the UDC instances it creates, but these drivers all +have the same name: "raw-gadget". Until recently this wasn't a +problem, but when the "gadget" bus was added and UDC drivers were +registered on this bus, it became possible for name conflicts to cause +the registrations to fail. The reason is simply that the bus code in +the driver core uses the driver name as a sysfs directory name (e.g., +/sys/bus/gadget/drivers/raw-gadget/), and you can't create two +directories with the same pathname. + +To fix this problem, the driver names used by raw-gadget are made +distinct by appending a unique ID number: "raw-gadget.N", with a +different value of N for each driver instance. And to avoid the +proliferation of error handling code in the raw_ioctl_init() routine, +the error return paths are refactored into the common pattern (goto +statements leading to cleanup code at the end of the routine). + +Link: https://lore.kernel.org/all/0000000000008c664105dffae2eb@google.com/ +Fixes: fc274c1e9973 "USB: gadget: Add a new bus for gadgets" +CC: Andrey Konovalov +CC: +Reported-and-tested-by: syzbot+02b16343704b3af1667e@syzkaller.appspotmail.com +Reviewed-by: Andrey Konovalov +Acked-by: Hillf Danton +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/r/YqdG32w+3h8c1s7z@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/legacy/raw_gadget.c | 62 ++++++++++++++++++++++++--------- + 1 file changed, 46 insertions(+), 16 deletions(-) + +--- a/drivers/usb/gadget/legacy/raw_gadget.c ++++ b/drivers/usb/gadget/legacy/raw_gadget.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -36,6 +37,9 @@ MODULE_LICENSE("GPL"); + + /*----------------------------------------------------------------------*/ + ++static DEFINE_IDA(driver_id_numbers); ++#define DRIVER_DRIVER_NAME_LENGTH_MAX 32 ++ + #define RAW_EVENT_QUEUE_SIZE 16 + + struct raw_event_queue { +@@ -161,6 +165,9 @@ struct raw_dev { + /* Reference to misc device: */ + struct device *dev; + ++ /* Make driver names unique */ ++ int driver_id_number; ++ + /* Protected by lock: */ + enum dev_state state; + bool gadget_registered; +@@ -189,6 +196,7 @@ static struct raw_dev *dev_new(void) + spin_lock_init(&dev->lock); + init_completion(&dev->ep0_done); + raw_event_queue_init(&dev->queue); ++ dev->driver_id_number = -1; + return dev; + } + +@@ -199,6 +207,9 @@ static void dev_free(struct kref *kref) + + kfree(dev->udc_name); + kfree(dev->driver.udc_name); ++ kfree(dev->driver.driver.name); ++ if (dev->driver_id_number >= 0) ++ ida_free(&driver_id_numbers, dev->driver_id_number); + if (dev->req) { + if (dev->ep0_urb_queued) + usb_ep_dequeue(dev->gadget->ep0, dev->req); +@@ -422,6 +433,7 @@ static int raw_ioctl_init(struct raw_dev + struct usb_raw_init arg; + char *udc_driver_name; + char *udc_device_name; ++ char *driver_driver_name; + unsigned long flags; + + if (copy_from_user(&arg, (void __user *)value, sizeof(arg))) +@@ -440,36 +452,44 @@ static int raw_ioctl_init(struct raw_dev + return -EINVAL; + } + ++ ret = ida_alloc(&driver_id_numbers, GFP_KERNEL); ++ if (ret < 0) ++ return ret; ++ dev->driver_id_number = ret; ++ ++ driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL); ++ if (!driver_driver_name) { ++ ret = -ENOMEM; ++ goto out_free_driver_id_number; ++ } ++ snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX, ++ DRIVER_NAME ".%d", dev->driver_id_number); ++ + udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); +- if (!udc_driver_name) +- return -ENOMEM; ++ if (!udc_driver_name) { ++ ret = -ENOMEM; ++ goto out_free_driver_driver_name; ++ } + ret = strscpy(udc_driver_name, &arg.driver_name[0], + UDC_NAME_LENGTH_MAX); +- if (ret < 0) { +- kfree(udc_driver_name); +- return ret; +- } ++ if (ret < 0) ++ goto out_free_udc_driver_name; + ret = 0; + + udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); + if (!udc_device_name) { +- kfree(udc_driver_name); +- return -ENOMEM; ++ ret = -ENOMEM; ++ goto out_free_udc_driver_name; + } + ret = strscpy(udc_device_name, &arg.device_name[0], + UDC_NAME_LENGTH_MAX); +- if (ret < 0) { +- kfree(udc_driver_name); +- kfree(udc_device_name); +- return ret; +- } ++ if (ret < 0) ++ goto out_free_udc_device_name; + ret = 0; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->state != STATE_DEV_OPENED) { + dev_dbg(dev->dev, "fail, device is not opened\n"); +- kfree(udc_driver_name); +- kfree(udc_device_name); + ret = -EINVAL; + goto out_unlock; + } +@@ -484,14 +504,24 @@ static int raw_ioctl_init(struct raw_dev + dev->driver.suspend = gadget_suspend; + dev->driver.resume = gadget_resume; + dev->driver.reset = gadget_reset; +- dev->driver.driver.name = DRIVER_NAME; ++ dev->driver.driver.name = driver_driver_name; + dev->driver.udc_name = udc_device_name; + dev->driver.match_existing_only = 1; + + dev->state = STATE_DEV_INITIALIZED; ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return ret; + + out_unlock: + spin_unlock_irqrestore(&dev->lock, flags); ++out_free_udc_device_name: ++ kfree(udc_device_name); ++out_free_udc_driver_name: ++ kfree(udc_driver_name); ++out_free_driver_driver_name: ++ kfree(driver_driver_name); ++out_free_driver_id_number: ++ ida_free(&driver_id_numbers, dev->driver_id_number); + return ret; + } + diff --git a/queue-5.18/usb-gadget-uvc-fix-list-double-add-in-uvcg_video_pump.patch b/queue-5.18/usb-gadget-uvc-fix-list-double-add-in-uvcg_video_pump.patch new file mode 100644 index 00000000000..8fcbf17544f --- /dev/null +++ b/queue-5.18/usb-gadget-uvc-fix-list-double-add-in-uvcg_video_pump.patch @@ -0,0 +1,47 @@ +From 96163f835e65f8c9897487fac965819f0651d671 Mon Sep 17 00:00:00 2001 +From: Dan Vacura +Date: Fri, 17 Jun 2022 11:31:53 -0500 +Subject: usb: gadget: uvc: fix list double add in uvcg_video_pump + +From: Dan Vacura + +commit 96163f835e65f8c9897487fac965819f0651d671 upstream. + +A panic can occur if the endpoint becomes disabled and the +uvcg_video_pump adds the request back to the req_free list after it has +already been queued to the endpoint. The endpoint complete will add the +request back to the req_free list. Invalidate the local request handle +once it's been queued. + +<6>[ 246.796704][T13726] configfs-gadget gadget: uvc: uvc_function_set_alt(1, 0) +<3>[ 246.797078][ T26] list_add double add: new=ffffff878bee5c40, prev=ffffff878bee5c40, next=ffffff878b0f0a90. +<6>[ 246.797213][ T26] ------------[ cut here ]------------ +<2>[ 246.797224][ T26] kernel BUG at lib/list_debug.c:31! +<6>[ 246.807073][ T26] Call trace: +<6>[ 246.807180][ T26] uvcg_video_pump+0x364/0x38c +<6>[ 246.807366][ T26] process_one_work+0x2a4/0x544 +<6>[ 246.807394][ T26] worker_thread+0x350/0x784 +<6>[ 246.807442][ T26] kthread+0x2ac/0x320 + +Fixes: f9897ec0f6d3 ("usb: gadget: uvc: only pump video data if necessary") +Cc: stable@vger.kernel.org +Reviewed-by: Laurent Pinchart +Signed-off-by: Dan Vacura +Link: https://lore.kernel.org/r/20220617163154.16621-1-w36195@motorola.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/uvc_video.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/gadget/function/uvc_video.c ++++ b/drivers/usb/gadget/function/uvc_video.c +@@ -415,6 +415,9 @@ static void uvcg_video_pump(struct work_ + uvcg_queue_cancel(queue, 0); + break; + } ++ ++ /* Endpoint now owns the request */ ++ req = NULL; + video->req_int_count++; + } + diff --git a/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-meteor-lake-xhci.patch b/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-meteor-lake-xhci.patch new file mode 100644 index 00000000000..a144d6a0381 --- /dev/null +++ b/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-meteor-lake-xhci.patch @@ -0,0 +1,42 @@ +From 8ffdc53a60049f3930afe161dc51c67959c8d83d Mon Sep 17 00:00:00 2001 +From: Utkarsh Patel +Date: Thu, 23 Jun 2022 14:19:45 +0300 +Subject: xhci-pci: Allow host runtime PM as default for Intel Meteor Lake xHCI + +From: Utkarsh Patel + +commit 8ffdc53a60049f3930afe161dc51c67959c8d83d upstream. + +Meteor Lake TCSS(Type-C Subsystem) xHCI needs to be runtime suspended +whenever possible to allow the TCSS hardware block to enter D3cold and +thus save energy. + +Cc: stable@kernel.org +Signed-off-by: Utkarsh Patel +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220623111945.1557702-5-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-pci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -62,6 +62,7 @@ + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed + #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e ++#define PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI 0x7ec0 + + #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 + #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 +@@ -272,7 +273,8 @@ static void xhci_pci_quirks(struct devic + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || +- pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI)) ++ pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_METEOR_LAKE_XHCI)) + xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; + + if (pdev->vendor == PCI_VENDOR_ID_ETRON && diff --git a/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-raptor-lake-xhci.patch b/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-raptor-lake-xhci.patch new file mode 100644 index 00000000000..69ea3651642 --- /dev/null +++ b/queue-5.18/xhci-pci-allow-host-runtime-pm-as-default-for-intel-raptor-lake-xhci.patch @@ -0,0 +1,42 @@ +From 7516da47a349e74de623243a27f9b8a91446bf4f Mon Sep 17 00:00:00 2001 +From: Tanveer Alam +Date: Thu, 23 Jun 2022 14:19:44 +0300 +Subject: xhci-pci: Allow host runtime PM as default for Intel Raptor Lake xHCI + +From: Tanveer Alam + +commit 7516da47a349e74de623243a27f9b8a91446bf4f upstream. + +In the same way as Intel Alder Lake TCSS (Type-C Subsystem) the Raptor +Lake TCSS xHCI needs to be runtime suspended whenever possible to +allow the TCSS hardware block to enter D3cold and thus save energy. + +Cc: stable@kernel.org +Signed-off-by: Tanveer Alam +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220623111945.1557702-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-pci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -61,6 +61,7 @@ + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI 0x464e + #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI 0x51ed ++#define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI 0xa71e + + #define PCI_DEVICE_ID_AMD_RENOIR_XHCI 0x1639 + #define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 +@@ -270,7 +271,8 @@ static void xhci_pci_quirks(struct devic + pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_N_XHCI || +- pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI)) ++ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_PCH_XHCI || ++ pdev->device == PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_XHCI)) + xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; + + if (pdev->vendor == PCI_VENDOR_ID_ETRON && diff --git a/queue-5.18/xhci-turn-off-port-power-in-shutdown.patch b/queue-5.18/xhci-turn-off-port-power-in-shutdown.patch new file mode 100644 index 00000000000..ab61a5defeb --- /dev/null +++ b/queue-5.18/xhci-turn-off-port-power-in-shutdown.patch @@ -0,0 +1,86 @@ +From 83810f84ecf11dfc5a9414a8b762c3501b328185 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 23 Jun 2022 14:19:43 +0300 +Subject: xhci: turn off port power in shutdown + +From: Mathias Nyman + +commit 83810f84ecf11dfc5a9414a8b762c3501b328185 upstream. + +If ports are not turned off in shutdown then runtime suspended +self-powered USB devices may survive in U3 link state over S5. + +During subsequent boot, if firmware sends an IPC command to program +the port in DISCONNECT state, it will time out, causing significant +delay in the boot time. + +Turning off roothub port power is also recommended in xhci +specification 4.19.4 "Port Power" in the additional note. + +Cc: stable@vger.kernel.org +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220623111945.1557702-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-hub.c | 2 +- + drivers/usb/host/xhci.c | 15 +++++++++++++-- + drivers/usb/host/xhci.h | 2 ++ + 3 files changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -652,7 +652,7 @@ struct xhci_hub *xhci_get_rhub(struct us + * It will release and re-aquire the lock while calling ACPI + * method. + */ +-static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, ++void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, + u16 index, bool on, unsigned long *flags) + __must_hold(&xhci->lock) + { +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -779,6 +779,8 @@ static void xhci_stop(struct usb_hcd *hc + void xhci_shutdown(struct usb_hcd *hcd) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); ++ unsigned long flags; ++ int i; + + if (xhci->quirks & XHCI_SPURIOUS_REBOOT) + usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); +@@ -794,12 +796,21 @@ void xhci_shutdown(struct usb_hcd *hcd) + del_timer_sync(&xhci->shared_hcd->rh_timer); + } + +- spin_lock_irq(&xhci->lock); ++ spin_lock_irqsave(&xhci->lock, flags); + xhci_halt(xhci); ++ ++ /* Power off USB2 ports*/ ++ for (i = 0; i < xhci->usb2_rhub.num_ports; i++) ++ xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags); ++ ++ /* Power off USB3 ports*/ ++ for (i = 0; i < xhci->usb3_rhub.num_ports; i++) ++ xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags); ++ + /* Workaround for spurious wakeups at shutdown with HSW */ + if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) + xhci_reset(xhci, XHCI_RESET_SHORT_USEC); +- spin_unlock_irq(&xhci->lock); ++ spin_unlock_irqrestore(&xhci->lock, flags); + + xhci_cleanup_msix(xhci); + +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -2172,6 +2172,8 @@ int xhci_hub_control(struct usb_hcd *hcd + int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); + int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); + struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); ++void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index, ++ bool on, unsigned long *flags); + + void xhci_hc_died(struct xhci_hcd *xhci); +