From 772f89e77f1dd19ddea9c0c490b027c2ece2c3c4 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 6 Dec 2022 07:44:13 +0100 Subject: [PATCH] linux.port: xhci patch to fix "unknown event type 37" Issue #4678 --- .../dde_linux/patches/xhci_fix_event_37.patch | 59 +++++++++++++++++++ repos/dde_linux/ports/linux.hash | 2 +- repos/dde_linux/ports/linux.port | 4 +- 3 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 repos/dde_linux/patches/xhci_fix_event_37.patch diff --git a/repos/dde_linux/patches/xhci_fix_event_37.patch b/repos/dde_linux/patches/xhci_fix_event_37.patch new file mode 100644 index 0000000000..27198b8c99 --- /dev/null +++ b/repos/dde_linux/patches/xhci_fix_event_37.patch @@ -0,0 +1,59 @@ +From e91ac20889d1a26d077cc511365cd7ff4346a6f3 Mon Sep 17 00:00:00 2001 +From: Weitao Wang +Date: Fri, 8 Apr 2022 16:48:21 +0300 +Subject: [PATCH] USB: Fix xhci event ring dequeue pointer ERDP update issue + +In some situations software handles TRB events slower than adding TRBs. +If the number of TRB events to be processed in a given interrupt is exactly +the same as the event ring size 256, then the local variable +"event_ring_deq" that holds the initial dequeue position is equal to +software_dequeue after handling all 256 interrupts. + +It will cause driver to not update ERDP to hardware, + +Software dequeue pointer is out of sync with ERDP on interrupt exit. +On the next interrupt, the event ring may full but driver will not +update ERDP as software_dequeue is equal to ERDP. + +[ 536.377115] xhci_hcd 0000:00:12.0: ERROR unknown event type 37 +[ 566.933173] sd 8:0:0:0: [sdb] tag#27 uas_eh_abort_handler 0 uas-tag 7 inflight: CMD OUT +[ 566.933181] sd 8:0:0:0: [sdb] tag#27 CDB: Write(10) 2a 00 17 71 e6 78 00 00 08 00 +[ 572.041186] xhci_hcd On some situataions,the0000:00:12.0: xHCI host not responding to stop endpoint command. +[ 572.057193] xhci_hcd 0000:00:12.0: Host halt failed, -110 +[ 572.057196] xhci_hcd 0000:00:12.0: xHCI host controller not responding, assume dead +[ 572.057236] sd 8:0:0:0: [sdb] tag#26 uas_eh_abort_handler 0 uas-tag 6 inflight: CMD +[ 572.057240] sd 8:0:0:0: [sdb] tag#26 CDB: Write(10) 2a 00 38 eb cc d8 00 00 08 00 +[ 572.057244] sd 8:0:0:0: [sdb] tag#25 uas_eh_abort_handler 0 uas-tag 5 inflight: CMD + +Hardware ERDP is updated mid event handling if there are more than 128 +events in an interrupt (half of ring size). +Fix this by updating the software local variable at the same time as +hardware ERDP. + +[commit message rewording -Mathias] + +Fixes: dc0ffbea5729 ("usb: host: xhci: update event ring dequeue pointer on purpose") +Reviewed-by: Peter Chen +Signed-off-by: Weitao Wang +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220408134823.2527272-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-ring.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c +index d0b6806275e0..f9707997969d 100644 +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -3141,6 +3141,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) + if (event_loop++ < TRBS_PER_SEGMENT / 2) + continue; + xhci_update_erst_dequeue(xhci, event_ring_deq); ++ event_ring_deq = xhci->event_ring->dequeue; + + /* ring is half-full, force isoc trbs to interrupt more often */ + if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN) +-- +2.25.1 + diff --git a/repos/dde_linux/ports/linux.hash b/repos/dde_linux/ports/linux.hash index d39912c7bf..c514d17c2d 100644 --- a/repos/dde_linux/ports/linux.hash +++ b/repos/dde_linux/ports/linux.hash @@ -1 +1 @@ -3258c9b6efca7364b55b34139f0f4333c3eab88d +dccfc6e02b4f279be801444242ba5ee37e9b8082 diff --git a/repos/dde_linux/ports/linux.port b/repos/dde_linux/ports/linux.port index 3d8dc55c4c..9815d7a7bb 100644 --- a/repos/dde_linux/ports/linux.port +++ b/repos/dde_linux/ports/linux.port @@ -9,9 +9,11 @@ DIR(linux) := src/linux # # Patches # -PATCH_FILES := i915_irq.patch i915_alderlake.patch xhci_abort_ring.patch iwlwifi_enable_irq_before_pnvm.patch +PATCH_FILES := i915_irq.patch i915_alderlake.patch xhci_fix_event_37.patch \ + xhci_abort_ring.patch iwlwifi_enable_irq_before_pnvm.patch PATCHES += $(addprefix patches/,$(PATCH_FILES)) # i915 PATCH_OPT(patches/i915_irq.patch) := -p1 -d${DIR(linux)} PATCH_OPT(patches/xhci_abort_ring.patch) := -p1 -d${DIR(linux)} +PATCH_OPT(patches/xhci_fix_event_37.patch) := -p1 -d${DIR(linux)}