* [PATCH 1/7] xhci-pci: set the dma max_seg_size
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 14:22 ` [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it Mathias Nyman
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Ricardo Ribalda, stable, Takashi Iwai, Mathias Nyman
From: Ricardo Ribalda <ribalda@chromium.org>
Allow devices to have dma operations beyond 64K, and avoid warnings such
as:
xhci_hcd 0000:00:14.0: mapping sg segment longer than device claims to support [len=98304] [max=65536]
Cc: stable@vger.kernel.org
Cc: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci-pci.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 79d679b3e076..2c0d7038f040 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -455,6 +455,8 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
pm_runtime_allow(&dev->dev);
+ dma_set_max_seg_size(&dev->dev, UINT_MAX);
+
return 0;
put_usb3_hcd:
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
2023-01-16 14:22 ` [PATCH 1/7] xhci-pci: set the dma max_seg_size Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 16:59 ` Ladislav Michl
2023-02-23 16:26 ` youling257
2023-01-16 14:22 ` [PATCH 3/7] xhci: Fix null pointer dereference when host dies Mathias Nyman
` (4 subsequent siblings)
6 siblings, 2 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Jimmy Hu, stable, Mathias Nyman
From: Jimmy Hu <hhhuuu@google.com>
When the host controller is not responding, all URBs queued to all
endpoints need to be killed. This can cause a kernel panic if we
dereference an invalid endpoint.
Fix this by using xhci_get_virt_ep() helper to find the endpoint and
checking if the endpoint is valid before dereferencing it.
[233311.853271] xhci-hcd xhci-hcd.1.auto: xHCI host controller not responding, assume dead
[233311.853393] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000e8
[233311.853964] pc : xhci_hc_died+0x10c/0x270
[233311.853971] lr : xhci_hc_died+0x1ac/0x270
[233311.854077] Call trace:
[233311.854085] xhci_hc_died+0x10c/0x270
[233311.854093] xhci_stop_endpoint_command_watchdog+0x100/0x1a4
[233311.854105] call_timer_fn+0x50/0x2d4
[233311.854112] expire_timers+0xac/0x2e4
[233311.854118] run_timer_softirq+0x300/0xabc
[233311.854127] __do_softirq+0x148/0x528
[233311.854135] irq_exit+0x194/0x1a8
[233311.854143] __handle_domain_irq+0x164/0x1d0
[233311.854149] gic_handle_irq.22273+0x10c/0x188
[233311.854156] el1_irq+0xfc/0x1a8
[233311.854175] lpm_cpuidle_enter+0x25c/0x418 [msm_pm]
[233311.854185] cpuidle_enter_state+0x1f0/0x764
[233311.854194] do_idle+0x594/0x6ac
[233311.854201] cpu_startup_entry+0x7c/0x80
[233311.854209] secondary_start_kernel+0x170/0x198
Fixes: 50e8725e7c42 ("xhci: Refactor command watchdog and fix split string.")
Cc: stable@vger.kernel.org
Signed-off-by: Jimmy Hu <hhhuuu@google.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci-ring.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index ddc30037f9ce..f5b0e1ce22af 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1169,7 +1169,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
struct xhci_virt_ep *ep;
struct xhci_ring *ring;
- ep = &xhci->devs[slot_id]->eps[ep_index];
+ ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
+ if (!ep)
+ return;
+
if ((ep->ep_state & EP_HAS_STREAMS) ||
(ep->ep_state & EP_GETTING_NO_STREAMS)) {
int stream_id;
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-01-16 14:22 ` [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it Mathias Nyman
@ 2023-01-16 16:59 ` Ladislav Michl
2023-01-17 10:02 ` Mathias Nyman
2023-02-23 16:26 ` youling257
1 sibling, 1 reply; 14+ messages in thread
From: Ladislav Michl @ 2023-01-16 16:59 UTC (permalink / raw)
To: Mathias Nyman; +Cc: gregkh, linux-usb, Jimmy Hu, stable
Hi Mathias,
On Mon, Jan 16, 2023 at 04:22:11PM +0200, Mathias Nyman wrote:
> From: Jimmy Hu <hhhuuu@google.com>
>
> When the host controller is not responding, all URBs queued to all
> endpoints need to be killed. This can cause a kernel panic if we
> dereference an invalid endpoint.
>
> Fix this by using xhci_get_virt_ep() helper to find the endpoint and
> checking if the endpoint is valid before dereferencing it.
I'm a bit confused this goes in and even to stable. Let me quote your
own analysis from
Message-ID: <0fe978ed-8269-9774-1c40-f8a98c17e838@linux.intel.com>
On Thu, Dec 22, 2022 at 03:18:53PM +0200, Mathias Nyman wrote:
> I think root cause is that freeing xhci->devs[i] and including rings isn't
> protected by the lock, this happens in xhci_free_virt_device() called by
> xhci_free_dev(), which in turn may be called by usbcore at any time
>
> So xhci->devs[i] might just suddenly disappear
>
> Patch just checks more often if xhci->devs[i] is valid, between every endpoint.
> So the race between xhci_free_virt_device() and xhci_kill_endpoint_urbs()
> doesn't trigger null pointer deref as easily.
I believe the above is correct and even Jimmy was unable to verify your
later patch (3rd in this serie), which brings a question how could be this
patch tested. It just burns a bug a bit deeper and I do not think it is the
right approach.
ladis
> [233311.853271] xhci-hcd xhci-hcd.1.auto: xHCI host controller not responding, assume dead
> [233311.853393] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000e8
>
> [233311.853964] pc : xhci_hc_died+0x10c/0x270
> [233311.853971] lr : xhci_hc_died+0x1ac/0x270
>
> [233311.854077] Call trace:
> [233311.854085] xhci_hc_died+0x10c/0x270
> [233311.854093] xhci_stop_endpoint_command_watchdog+0x100/0x1a4
> [233311.854105] call_timer_fn+0x50/0x2d4
> [233311.854112] expire_timers+0xac/0x2e4
> [233311.854118] run_timer_softirq+0x300/0xabc
> [233311.854127] __do_softirq+0x148/0x528
> [233311.854135] irq_exit+0x194/0x1a8
> [233311.854143] __handle_domain_irq+0x164/0x1d0
> [233311.854149] gic_handle_irq.22273+0x10c/0x188
> [233311.854156] el1_irq+0xfc/0x1a8
> [233311.854175] lpm_cpuidle_enter+0x25c/0x418 [msm_pm]
> [233311.854185] cpuidle_enter_state+0x1f0/0x764
> [233311.854194] do_idle+0x594/0x6ac
> [233311.854201] cpu_startup_entry+0x7c/0x80
> [233311.854209] secondary_start_kernel+0x170/0x198
>
> Fixes: 50e8725e7c42 ("xhci: Refactor command watchdog and fix split string.")
> Cc: stable@vger.kernel.org
> Signed-off-by: Jimmy Hu <hhhuuu@google.com>
> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
> ---
> drivers/usb/host/xhci-ring.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index ddc30037f9ce..f5b0e1ce22af 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1169,7 +1169,10 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
> struct xhci_virt_ep *ep;
> struct xhci_ring *ring;
>
> - ep = &xhci->devs[slot_id]->eps[ep_index];
> + ep = xhci_get_virt_ep(xhci, slot_id, ep_index);
> + if (!ep)
> + return;
> +
> if ((ep->ep_state & EP_HAS_STREAMS) ||
> (ep->ep_state & EP_GETTING_NO_STREAMS)) {
> int stream_id;
> --
> 2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-01-16 16:59 ` Ladislav Michl
@ 2023-01-17 10:02 ` Mathias Nyman
0 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-17 10:02 UTC (permalink / raw)
To: Ladislav Michl; +Cc: gregkh, linux-usb, Jimmy Hu, stable
On 16.1.2023 18.59, Ladislav Michl wrote:
> Hi Mathias,
>
> On Mon, Jan 16, 2023 at 04:22:11PM +0200, Mathias Nyman wrote:
>> From: Jimmy Hu <hhhuuu@google.com>
>>
>> When the host controller is not responding, all URBs queued to all
>> endpoints need to be killed. This can cause a kernel panic if we
>> dereference an invalid endpoint.
>>
>> Fix this by using xhci_get_virt_ep() helper to find the endpoint and
>> checking if the endpoint is valid before dereferencing it.
>
> I'm a bit confused this goes in and even to stable. Let me quote your
> own analysis from
> Message-ID: <0fe978ed-8269-9774-1c40-f8a98c17e838@linux.intel.com>
> On Thu, Dec 22, 2022 at 03:18:53PM +0200, Mathias Nyman wrote:
>> I think root cause is that freeing xhci->devs[i] and including rings isn't
>> protected by the lock, this happens in xhci_free_virt_device() called by
>> xhci_free_dev(), which in turn may be called by usbcore at any time
>>
>> So xhci->devs[i] might just suddenly disappear
>>
>> Patch just checks more often if xhci->devs[i] is valid, between every endpoint.
>> So the race between xhci_free_virt_device() and xhci_kill_endpoint_urbs()
>> doesn't trigger null pointer deref as easily.>
> I believe the above is correct and even Jimmy was unable to verify your
> later patch (3rd in this serie), which brings a question how could be this
> patch tested. It just burns a bug a bit deeper and I do not think it is the
> right approach.
As I said in a direct response to the original patch I think this is a valid fix
for older kernels where we used to unlock xhci->lock while giving back
URBs. Together with PATCH 3/7 the issue should be completely resolved.
For later kernels PATCH 3/7 should be enough by itself, but no harm in keeping this.
See Message-ID: <379b395f-b65c-96fe-7ecc-f18e3740b990@linux.intel.com>
Older kernels are all before v5.5 that lack commit
36dc01657b49 usb: host: xhci: Support running urb giveback in tasklet context.
I haven't been able to trigger this issue myself, but based on the report and finding in
the code I still think this the right approach. The internal testing this has been
through could only prove these patches (2/7 and 3/7) don't cause any additional issues.
If you think the analysis or solution is incorrect let me know, and we can come up with a
better one.
Thanks
Mathias
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-01-16 14:22 ` [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it Mathias Nyman
2023-01-16 16:59 ` Ladislav Michl
@ 2023-02-23 16:26 ` youling257
2023-02-24 10:29 ` Mathias Nyman
1 sibling, 1 reply; 14+ messages in thread
From: youling257 @ 2023-02-23 16:26 UTC (permalink / raw)
To: mathias.nyman; +Cc: gregkh, hhhuuu, linux-usb, stable
I used type-c 20Gbps USB3.2 GEN2x2 PCIe Expansion Card, may be this patch cause USB3.2 GEN2x2 PCIe Expansion Card not work.
[ 0.285088] xhci_hcd 0000:09:00.0: hcc params 0x0200ef80 hci version 0x110 quirks 0x0000000000800010
[ 0.285334] usb usb7: We don't know the algorithms for LPM for this host, disabling LPM.
[ 0.285347] xhci_hcd 0000:09:00.0: xHCI Host Controller
[ 0.285407] hub 7-0:1.0: USB hub found
[ 0.285415] hub 7-0:1.0: 4 ports detected
[ 0.285783] xhci_hcd 0000:09:00.0: new USB bus registered, assigned bus number 8
[ 0.285787] xhci_hcd 0000:09:00.0: Host supports USB 3.2 Enhanced SuperSpeed
[ 0.285889] hub 4-0:1.0: USB hub found
[ 0.285901] hub 4-0:1.0: 1 port detected
[ 0.285988] usb usb8: We don't know the algorithms for LPM for this host, disabling LPM.
[ 3277.156054] xhci_hcd 0000:09:00.0: Abort failed to stop command ring: -110
[ 3277.156091] xhci_hcd 0000:09:00.0: xHCI host controller not responding, assume dead
[ 3277.156103] xhci_hcd 0000:09:00.0: HC died; cleaning up
may be this patch cause "xhci_hcd 0000:09:00.0: HC died; cleaning up" problem.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-02-23 16:26 ` youling257
@ 2023-02-24 10:29 ` Mathias Nyman
2023-02-24 15:58 ` youling 257
0 siblings, 1 reply; 14+ messages in thread
From: Mathias Nyman @ 2023-02-24 10:29 UTC (permalink / raw)
To: youling257; +Cc: gregkh, hhhuuu, linux-usb, stable
On 23.2.2023 18.26, youling257 wrote:
> I used type-c 20Gbps USB3.2 GEN2x2 PCIe Expansion Card, may be this patch cause USB3.2 GEN2x2 PCIe Expansion Card not work.
>
> [ 0.285088] xhci_hcd 0000:09:00.0: hcc params 0x0200ef80 hci version 0x110 quirks 0x0000000000800010
> [ 0.285334] usb usb7: We don't know the algorithms for LPM for this host, disabling LPM.
> [ 0.285347] xhci_hcd 0000:09:00.0: xHCI Host Controller
> [ 0.285407] hub 7-0:1.0: USB hub found
> [ 0.285415] hub 7-0:1.0: 4 ports detected
> [ 0.285783] xhci_hcd 0000:09:00.0: new USB bus registered, assigned bus number 8
> [ 0.285787] xhci_hcd 0000:09:00.0: Host supports USB 3.2 Enhanced SuperSpeed
> [ 0.285889] hub 4-0:1.0: USB hub found
> [ 0.285901] hub 4-0:1.0: 1 port detected
> [ 0.285988] usb usb8: We don't know the algorithms for LPM for this host, disabling LPM.
> [ 3277.156054] xhci_hcd 0000:09:00.0: Abort failed to stop command ring: -110
> [ 3277.156091] xhci_hcd 0000:09:00.0: xHCI host controller not responding, assume dead
> [ 3277.156103] xhci_hcd 0000:09:00.0: HC died; cleaning up
>
> may be this patch cause "xhci_hcd 0000:09:00.0: HC died; cleaning up" problem.
Unlikely, this patch only touches code called after HC already died.
Does reverting this patch fix the issue?
Thanks
Mathias
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-02-24 10:29 ` Mathias Nyman
@ 2023-02-24 15:58 ` youling 257
2023-02-24 16:03 ` youling 257
0 siblings, 1 reply; 14+ messages in thread
From: youling 257 @ 2023-02-24 15:58 UTC (permalink / raw)
To: Mathias Nyman; +Cc: gregkh, hhhuuu, linux-usb, stable
February 17, when i used linux 6.2-rc8, happen "Abort failed to stop
command ring: -110", google search history February 17 search "Abort
failed to stop command ring: -110" and "Usbreset No such device
found".
Date: Fri, 17 Feb 2023 23:59:29 +0800
Subject: [PATCH] Revert "usb: xhci: Check endpoint is valid before
dereferencing it"
This reverts commit e8fb5bc76eb86437ab87002d4a36d6da02165654.
a week never see usb not work.
may be revert it fix my problem.
2023-02-24 18:29 GMT+08:00, Mathias Nyman <mathias.nyman@linux.intel.com>:
> On 23.2.2023 18.26, youling257 wrote:
>> I used type-c 20Gbps USB3.2 GEN2x2 PCIe Expansion Card, may be this patch
>> cause USB3.2 GEN2x2 PCIe Expansion Card not work.
>>
>> [ 0.285088] xhci_hcd 0000:09:00.0: hcc params 0x0200ef80 hci version
>> 0x110 quirks 0x0000000000800010
>> [ 0.285334] usb usb7: We don't know the algorithms for LPM for this
>> host, disabling LPM.
>> [ 0.285347] xhci_hcd 0000:09:00.0: xHCI Host Controller
>> [ 0.285407] hub 7-0:1.0: USB hub found
>> [ 0.285415] hub 7-0:1.0: 4 ports detected
>> [ 0.285783] xhci_hcd 0000:09:00.0: new USB bus registered, assigned bus
>> number 8
>> [ 0.285787] xhci_hcd 0000:09:00.0: Host supports USB 3.2 Enhanced
>> SuperSpeed
>> [ 0.285889] hub 4-0:1.0: USB hub found
>> [ 0.285901] hub 4-0:1.0: 1 port detected
>> [ 0.285988] usb usb8: We don't know the algorithms for LPM for this
>> host, disabling LPM.
>> [ 3277.156054] xhci_hcd 0000:09:00.0: Abort failed to stop command ring:
>> -110
>> [ 3277.156091] xhci_hcd 0000:09:00.0: xHCI host controller not responding,
>> assume dead
>> [ 3277.156103] xhci_hcd 0000:09:00.0: HC died; cleaning up
>>
>> may be this patch cause "xhci_hcd 0000:09:00.0: HC died; cleaning up"
>> problem.
>
> Unlikely, this patch only touches code called after HC already died.
>
> Does reverting this patch fix the issue?
>
> Thanks
> Mathias
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it
2023-02-24 15:58 ` youling 257
@ 2023-02-24 16:03 ` youling 257
0 siblings, 0 replies; 14+ messages in thread
From: youling 257 @ 2023-02-24 16:03 UTC (permalink / raw)
To: Mathias Nyman; +Cc: gregkh, hhhuuu, linux-usb, stable
By the way, i used this patch on linux kernel has been a year,
https://lore.kernel.org/all/6908aa69-469b-8f92-8e19-60685f524f9c@synopsys.com/
2023-02-24 23:58 GMT+08:00, youling 257 <youling257@gmail.com>:
> February 17, when i used linux 6.2-rc8, happen "Abort failed to stop
> command ring: -110", google search history February 17 search "Abort
> failed to stop command ring: -110" and "Usbreset No such device
> found".
>
> Date: Fri, 17 Feb 2023 23:59:29 +0800
> Subject: [PATCH] Revert "usb: xhci: Check endpoint is valid before
> dereferencing it"
> This reverts commit e8fb5bc76eb86437ab87002d4a36d6da02165654.
>
> a week never see usb not work.
> may be revert it fix my problem.
>
> 2023-02-24 18:29 GMT+08:00, Mathias Nyman <mathias.nyman@linux.intel.com>:
>> On 23.2.2023 18.26, youling257 wrote:
>>> I used type-c 20Gbps USB3.2 GEN2x2 PCIe Expansion Card, may be this
>>> patch
>>> cause USB3.2 GEN2x2 PCIe Expansion Card not work.
>>>
>>> [ 0.285088] xhci_hcd 0000:09:00.0: hcc params 0x0200ef80 hci version
>>> 0x110 quirks 0x0000000000800010
>>> [ 0.285334] usb usb7: We don't know the algorithms for LPM for this
>>> host, disabling LPM.
>>> [ 0.285347] xhci_hcd 0000:09:00.0: xHCI Host Controller
>>> [ 0.285407] hub 7-0:1.0: USB hub found
>>> [ 0.285415] hub 7-0:1.0: 4 ports detected
>>> [ 0.285783] xhci_hcd 0000:09:00.0: new USB bus registered, assigned
>>> bus
>>> number 8
>>> [ 0.285787] xhci_hcd 0000:09:00.0: Host supports USB 3.2 Enhanced
>>> SuperSpeed
>>> [ 0.285889] hub 4-0:1.0: USB hub found
>>> [ 0.285901] hub 4-0:1.0: 1 port detected
>>> [ 0.285988] usb usb8: We don't know the algorithms for LPM for this
>>> host, disabling LPM.
>>> [ 3277.156054] xhci_hcd 0000:09:00.0: Abort failed to stop command ring:
>>> -110
>>> [ 3277.156091] xhci_hcd 0000:09:00.0: xHCI host controller not
>>> responding,
>>> assume dead
>>> [ 3277.156103] xhci_hcd 0000:09:00.0: HC died; cleaning up
>>>
>>> may be this patch cause "xhci_hcd 0000:09:00.0: HC died; cleaning up"
>>> problem.
>>
>> Unlikely, this patch only touches code called after HC already died.
>>
>> Does reverting this patch fix the issue?
>>
>> Thanks
>> Mathias
>>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/7] xhci: Fix null pointer dereference when host dies
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
2023-01-16 14:22 ` [PATCH 1/7] xhci-pci: set the dma max_seg_size Mathias Nyman
2023-01-16 14:22 ` [PATCH 2/7] usb: xhci: Check endpoint is valid before dereferencing it Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 14:22 ` [PATCH 4/7] xhci: Add update_hub_device override for PCI xHCI hosts Mathias Nyman
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Mathias Nyman, stable
Make sure xhci_free_dev() and xhci_kill_endpoint_urbs() do not race
and cause null pointer dereference when host suddenly dies.
Usb core may call xhci_free_dev() which frees the xhci->devs[slot_id]
virt device at the same time that xhci_kill_endpoint_urbs() tries to
loop through all the device's endpoints, checking if there are any
cancelled urbs left to give back.
hold the xhci spinlock while freeing the virt device
Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 79d7931c048a..50b41213e827 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3974,6 +3974,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev;
struct xhci_slot_ctx *slot_ctx;
+ unsigned long flags;
int i, ret;
/*
@@ -4000,7 +4001,11 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
virt_dev->udev = NULL;
xhci_disable_slot(xhci, udev->slot_id);
+
+ spin_lock_irqsave(&xhci->lock, flags);
xhci_free_virt_device(xhci, udev->slot_id);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
}
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 4/7] xhci: Add update_hub_device override for PCI xHCI hosts
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
` (2 preceding siblings ...)
2023-01-16 14:22 ` [PATCH 3/7] xhci: Fix null pointer dereference when host dies Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 14:22 ` [PATCH 5/7] xhci: Add a flag to disable USB3 lpm on a xhci root port level Mathias Nyman
` (2 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Mathias Nyman, stable
Allow PCI hosts to check and tune roothub and port settings
before the hub is up and running.
This override is needed to turn off U1 and U2 LPM for some ports
based on per port ACPI _DSM, _UPC, or possibly vendor specific mmio
values for Intel xHC hosts.
Usb core calls the host update_hub_device once it creates a hub.
Entering U1 or U2 link power save state on ports with this limitation
will cause link to fail, turning the usb device unusable in that setup.
Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci-pci.c | 9 +++++++++
drivers/usb/host/xhci.c | 5 ++++-
drivers/usb/host/xhci.h | 4 ++++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 2c0d7038f040..b5016709b26f 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -78,9 +78,12 @@ static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
static int xhci_pci_setup(struct usb_hcd *hcd);
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+ struct usb_tt *tt, gfp_t mem_flags);
static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
.reset = xhci_pci_setup,
+ .update_hub_device = xhci_pci_update_hub_device,
};
/* called after powerup, by probe or system-pm "wakeup" */
@@ -386,6 +389,12 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
return xhci_pci_reinit(xhci, pdev);
}
+static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+ struct usb_tt *tt, gfp_t mem_flags)
+{
+ return xhci_update_hub_device(hcd, hdev, tt, mem_flags);
+}
+
/*
* We need to register our own PCI probe function (instead of the USB core's
* function) in order to create a second roothub under xHCI.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 50b41213e827..89f92fc78bb1 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5124,7 +5124,7 @@ static int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd,
/* Once a hub descriptor is fetched for a device, we need to update the xHC's
* internal data structures for the device.
*/
-static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -5224,6 +5224,7 @@ static int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
xhci_free_command(xhci, config_cmd);
return ret;
}
+EXPORT_SYMBOL_GPL(xhci_update_hub_device);
static int xhci_get_frame(struct usb_hcd *hcd)
{
@@ -5507,6 +5508,8 @@ void xhci_init_driver(struct hc_driver *drv,
drv->check_bandwidth = over->check_bandwidth;
if (over->reset_bandwidth)
drv->reset_bandwidth = over->reset_bandwidth;
+ if (over->update_hub_device)
+ drv->update_hub_device = over->update_hub_device;
}
}
EXPORT_SYMBOL_GPL(xhci_init_driver);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c9f06c5e4e9d..3edfacb93817 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1943,6 +1943,8 @@ struct xhci_driver_overrides {
struct usb_host_endpoint *ep);
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+ int (*update_hub_device)(struct usb_hcd *hcd, struct usb_device *hdev,
+ struct usb_tt *tt, gfp_t mem_flags);
};
#define XHCI_CFC_DELAY 10
@@ -2122,6 +2124,8 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint *ep);
int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
+int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
+ struct usb_tt *tt, gfp_t mem_flags);
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
int xhci_ext_cap_init(struct xhci_hcd *xhci);
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 5/7] xhci: Add a flag to disable USB3 lpm on a xhci root port level.
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
` (3 preceding siblings ...)
2023-01-16 14:22 ` [PATCH 4/7] xhci: Add update_hub_device override for PCI xHCI hosts Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 14:22 ` [PATCH 6/7] usb: acpi: add helper to check port lpm capability using acpi _DSM Mathias Nyman
2023-01-16 14:22 ` [PATCH 7/7] xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables Mathias Nyman
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Mathias Nyman, stable
One USB3 roothub port may support link power management, while another
root port on the same xHC can't due to different retimers used for
the ports.
This is the case with Intel Alder Lake, and possible future platforms
where retimers used for USB4 ports cause too long exit latecy to
enable native USB3 lpm U1 and U2 states.
Add a flag in the xhci port structure to indicate if the port is
lpm_incapable, and check it while calculating exit latency.
Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci.c | 8 ++++++++
drivers/usb/host/xhci.h | 1 +
2 files changed, 9 insertions(+)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 89f92fc78bb1..2b280beb0011 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5049,6 +5049,7 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
struct usb_device *udev, enum usb3_link_state state)
{
struct xhci_hcd *xhci;
+ struct xhci_port *port;
u16 hub_encoded_timeout;
int mel;
int ret;
@@ -5065,6 +5066,13 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd,
if (xhci_check_tier_policy(xhci, udev, state) < 0)
return USB3_LPM_DISABLED;
+ /* If connected to root port then check port can handle lpm */
+ if (udev->parent && !udev->parent->parent) {
+ port = xhci->usb3_rhub.ports[udev->portnum - 1];
+ if (port->lpm_incapable)
+ return USB3_LPM_DISABLED;
+ }
+
hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state);
mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout);
if (mel < 0) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 3edfacb93817..dcee7f3207ad 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1735,6 +1735,7 @@ struct xhci_port {
int hcd_portnum;
struct xhci_hub *rhub;
struct xhci_port_cap *port_cap;
+ unsigned int lpm_incapable:1;
};
struct xhci_hub {
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 6/7] usb: acpi: add helper to check port lpm capability using acpi _DSM
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
` (4 preceding siblings ...)
2023-01-16 14:22 ` [PATCH 5/7] xhci: Add a flag to disable USB3 lpm on a xhci root port level Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
2023-01-16 14:22 ` [PATCH 7/7] xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables Mathias Nyman
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Mathias Nyman, stable, Ron Lee
Add a helper to evaluate ACPI usb device specific method (_DSM) provided
in case the USB3 port shouldn't enter U1 and U2 link states.
This _DSM was added as port specific retimer configuration may lead to
exit latencies growing beyond U1/U2 exit limits, and OS needs a way to
find which ports can't support U1/U2 link power management states.
This _DSM is also used by windows:
Link: https://docs.microsoft.com/en-us/windows-hardware/drivers/bringup/usb-device-specific-method---dsm-
Some patch issues found in testing resolved by Ron Lee
Cc: stable@vger.kernel.org
Tested-by: Ron Lee <ron.lee@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/core/usb-acpi.c | 65 +++++++++++++++++++++++++++++++++++++
include/linux/usb.h | 3 ++
2 files changed, 68 insertions(+)
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 6d93428432f1..533baa85083c 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -37,6 +37,71 @@ bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
}
EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
+#define UUID_USB_CONTROLLER_DSM "ce2ee385-00e6-48cb-9f05-2edb927c4899"
+#define USB_DSM_DISABLE_U1_U2_FOR_PORT 5
+
+/**
+ * usb_acpi_port_lpm_incapable - check if lpm should be disabled for a port.
+ * @hdev: USB device belonging to the usb hub
+ * @index: zero based port index
+ *
+ * Some USB3 ports may not support USB3 link power management U1/U2 states
+ * due to different retimer setup. ACPI provides _DSM method which returns 0x01
+ * if U1 and U2 states should be disabled. Evaluate _DSM with:
+ * Arg0: UUID = ce2ee385-00e6-48cb-9f05-2edb927c4899
+ * Arg1: Revision ID = 0
+ * Arg2: Function Index = 5
+ * Arg3: (empty)
+ *
+ * Return 1 if USB3 port is LPM incapable, negative on error, otherwise 0
+ */
+
+int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+{
+ union acpi_object *obj;
+ acpi_handle port_handle;
+ int port1 = index + 1;
+ guid_t guid;
+ int ret;
+
+ ret = guid_parse(UUID_USB_CONTROLLER_DSM, &guid);
+ if (ret)
+ return ret;
+
+ port_handle = usb_get_hub_port_acpi_handle(hdev, port1);
+ if (!port_handle) {
+ dev_dbg(&hdev->dev, "port-%d no acpi handle\n", port1);
+ return -ENODEV;
+ }
+
+ if (!acpi_check_dsm(port_handle, &guid, 0,
+ BIT(USB_DSM_DISABLE_U1_U2_FOR_PORT))) {
+ dev_dbg(&hdev->dev, "port-%d no _DSM function %d\n",
+ port1, USB_DSM_DISABLE_U1_U2_FOR_PORT);
+ return -ENODEV;
+ }
+
+ obj = acpi_evaluate_dsm(port_handle, &guid, 0,
+ USB_DSM_DISABLE_U1_U2_FOR_PORT, NULL);
+
+ if (!obj)
+ return -ENODEV;
+
+ if (obj->type != ACPI_TYPE_INTEGER) {
+ dev_dbg(&hdev->dev, "evaluate port-%d _DSM failed\n", port1);
+ ACPI_FREE(obj);
+ return -EINVAL;
+ }
+
+ if (obj->integer.value == 0x01)
+ ret = 1;
+
+ ACPI_FREE(obj);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usb_acpi_port_lpm_incapable);
+
/**
* usb_acpi_set_power_state - control usb port's power via acpi power
* resource
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7d5325d47c45..04a7e94fb772 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -774,11 +774,14 @@ extern struct device *usb_intf_get_dma_device(struct usb_interface *intf);
extern int usb_acpi_set_power_state(struct usb_device *hdev, int index,
bool enable);
extern bool usb_acpi_power_manageable(struct usb_device *hdev, int index);
+extern int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index);
#else
static inline int usb_acpi_set_power_state(struct usb_device *hdev, int index,
bool enable) { return 0; }
static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
{ return true; }
+static inline int usb_acpi_port_lpm_incapable(struct usb_device *hdev, int index)
+ { return 0; }
#endif
/* USB autosuspend and autoresume */
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* [PATCH 7/7] xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables
2023-01-16 14:22 [PATCH 0/7] usb and xhci fixes for usb-linus Mathias Nyman
` (5 preceding siblings ...)
2023-01-16 14:22 ` [PATCH 6/7] usb: acpi: add helper to check port lpm capability using acpi _DSM Mathias Nyman
@ 2023-01-16 14:22 ` Mathias Nyman
6 siblings, 0 replies; 14+ messages in thread
From: Mathias Nyman @ 2023-01-16 14:22 UTC (permalink / raw)
To: gregkh; +Cc: linux-usb, Mathias Nyman, stable
USB3 ports on xHC hosts may have retimers that cause too long
exit latency to work with native USB3 U1/U2 link power management states.
For now only use usb_acpi_port_lpm_incapable() to evaluate if port lpm
should be disabled while setting up the USB3 roothub.
Other ways to identify lpm incapable ports can be added here later if
ACPI _DSM does not exist.
Limit this to Intel hosts for now, this is to my knowledge only
an Intel issue.
Cc: stable@vger.kernel.org
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
---
drivers/usb/host/xhci-pci.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index b5016709b26f..fb988e4ea924 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -355,8 +355,38 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
NULL);
ACPI_FREE(obj);
}
+
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev)
+{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct xhci_hub *rhub = &xhci->usb3_rhub;
+ int ret;
+ int i;
+
+ /* This is not the usb3 roothub we are looking for */
+ if (hcd != rhub->hcd)
+ return;
+
+ if (hdev->maxchild > rhub->num_ports) {
+ dev_err(&hdev->dev, "USB3 roothub port number mismatch\n");
+ return;
+ }
+
+ for (i = 0; i < hdev->maxchild; i++) {
+ ret = usb_acpi_port_lpm_incapable(hdev, i);
+
+ dev_dbg(&hdev->dev, "port-%d disable U1/U2 _DSM: %d\n", i + 1, ret);
+
+ if (ret >= 0) {
+ rhub->ports[i]->lpm_incapable = ret;
+ continue;
+ }
+ }
+}
+
#else
static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+static void xhci_find_lpm_incapable_ports(struct usb_hcd *hcd, struct usb_device *hdev) { }
#endif /* CONFIG_ACPI */
/* called during probe() after chip reset completes */
@@ -392,6 +422,10 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
static int xhci_pci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
struct usb_tt *tt, gfp_t mem_flags)
{
+ /* Check if acpi claims some USB3 roothub ports are lpm incapable */
+ if (!hdev->parent)
+ xhci_find_lpm_incapable_ports(hcd, hdev);
+
return xhci_update_hub_device(hcd, hdev, tt, mem_flags);
}
--
2.25.1
^ permalink raw reply related [flat|nested] 14+ messages in thread