From bdb1b10bd47b09dd99935df09d7e47b404d11859 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 13 May 2024 15:27:52 +0200 Subject: [PATCH] 6.8-stable patches added patches: alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch usb-core-fix-access-violation-during-port-device-removal.patch usb-dwc3-core-prevent-phy-suspend-during-init.patch usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch usb-gadget-composite-fix-os-descriptors-w_value-logic.patch usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch usb-ohci-prevent-missed-ohci-interrupts.patch usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch usb-xhci-plat-don-t-include-xhci.h.patch --- ...d-17aa-386f-for-lenovo-legion-models.patch | 82 ++++++ ...ix-mute-led-of-hp-laptop-15-da3001tu.patch | 31 +++ ...-some-local-asynchronous-transaction.patch | 62 +++++ queue-6.8/series | 15 + ...violation-during-port-device-removal.patch | 69 +++++ ...core-prevent-phy-suspend-during-init.patch | 262 ++++++++++++++++++ ...xpacket-in-virtual-superspeed-device.patch | 46 +++ ...ite-fix-os-descriptors-w_value-logic.patch | 78 ++++++ ...dition-when-processing-setup-packets.patch | 34 +++ ...-aio_cancel-and-aio-request-complete.patch | 88 ++++++ ...fer-size-when-parsing-configfs-lists.patch | 51 ++++ ...-ohci-prevent-missed-ohci-interrupts.patch | 60 ++++ ...partner-validity-before-consuming-it.patch | 114 ++++++++ ...m-clear-pd_event-queue-in-port_reset.patch | 43 +++ ...g-source-caps-before-re-registration.patch | 66 +++++ .../usb-xhci-plat-don-t-include-xhci.h.patch | 46 +++ 16 files changed, 1147 insertions(+) create mode 100644 queue-6.8/alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch create mode 100644 queue-6.8/alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch create mode 100644 queue-6.8/firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch create mode 100644 queue-6.8/usb-core-fix-access-violation-during-port-device-removal.patch create mode 100644 queue-6.8/usb-dwc3-core-prevent-phy-suspend-during-init.patch create mode 100644 queue-6.8/usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch create mode 100644 queue-6.8/usb-gadget-composite-fix-os-descriptors-w_value-logic.patch create mode 100644 queue-6.8/usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch create mode 100644 queue-6.8/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch create mode 100644 queue-6.8/usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch create mode 100644 queue-6.8/usb-ohci-prevent-missed-ohci-interrupts.patch create mode 100644 queue-6.8/usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch create mode 100644 queue-6.8/usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch create mode 100644 queue-6.8/usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch create mode 100644 queue-6.8/usb-xhci-plat-don-t-include-xhci.h.patch diff --git a/queue-6.8/alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch b/queue-6.8/alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch new file mode 100644 index 00000000000..9d9ffbf72a5 --- /dev/null +++ b/queue-6.8/alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch @@ -0,0 +1,82 @@ +From 39815cdfc8d46ce2c72cbf2aa3d991c4bfb0024f Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 30 Apr 2024 18:32:04 +0200 +Subject: ALSA: hda/realtek: Fix conflicting PCI SSID 17aa:386f for Lenovo Legion models + +From: Takashi Iwai + +commit 39815cdfc8d46ce2c72cbf2aa3d991c4bfb0024f upstream. + +Unfortunately both Lenovo Legion Pro 7 16ARX8H and Legion 7i 16IAX7 +got the very same PCI SSID while the hardware implementations are +completely different (the former is with TI TAS2781 codec while the +latter is with Cirrus CS35L41 codec). The former model got broken by +the recent fix for the latter model. + +For addressing the regression, check the codec SSID and apply the +proper quirk for each model now. + +Fixes: 24b6332c2d4f ("ALSA: hda: Add Lenovo Legion 7i gen7 sound quirk") +Cc: +Link: https://bugzilla.suse.com/show_bug.cgi?id=1223462 +Message-ID: <20240430163206.5200-1-tiwai@suse.de> +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/patch_realtek.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -7502,6 +7502,7 @@ enum { + ALC287_FIXUP_YOGA7_14ITL_SPEAKERS, + ALC298_FIXUP_LENOVO_C940_DUET7, + ALC287_FIXUP_LENOVO_14IRP8_DUETITL, ++ ALC287_FIXUP_LENOVO_LEGION_7, + ALC287_FIXUP_13S_GEN2_SPEAKERS, + ALC256_FIXUP_SET_COEF_DEFAULTS, + ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE, +@@ -7574,6 +7575,23 @@ static void alc287_fixup_lenovo_14irp8_d + __snd_hda_apply_fixup(codec, id, action, 0); + } + ++/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with ++ * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec); ++ * we apply a corresponding fixup depending on the codec SSID instead ++ */ ++static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec, ++ const struct hda_fixup *fix, ++ int action) ++{ ++ int id; ++ ++ if (codec->core.subsystem_id == 0x17aa38a8) ++ id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */ ++ else ++ id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */ ++ __snd_hda_apply_fixup(codec, id, action, 0); ++} ++ + static const struct hda_fixup alc269_fixups[] = { + [ALC269_FIXUP_GPIO2] = { + .type = HDA_FIXUP_FUNC, +@@ -9468,6 +9486,10 @@ static const struct hda_fixup alc269_fix + .type = HDA_FIXUP_FUNC, + .v.func = alc287_fixup_lenovo_14irp8_duetitl, + }, ++ [ALC287_FIXUP_LENOVO_LEGION_7] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc287_fixup_lenovo_legion_7, ++ }, + [ALC287_FIXUP_13S_GEN2_SPEAKERS] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { +@@ -10372,7 +10394,7 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS), + SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6), + SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN), +- SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2), ++ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7), + SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C), + SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), + SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2), diff --git a/queue-6.8/alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch b/queue-6.8/alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch new file mode 100644 index 00000000000..10e5cf70d6d --- /dev/null +++ b/queue-6.8/alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch @@ -0,0 +1,31 @@ +From 2d5af3ab9e6f1cf1468b2a5221b5c1f7f46c3333 Mon Sep 17 00:00:00 2001 +From: Aman Dhoot +Date: Mon, 22 Apr 2024 18:08:23 +0530 +Subject: ALSA: hda/realtek: Fix mute led of HP Laptop 15-da3001TU + +From: Aman Dhoot + +commit 2d5af3ab9e6f1cf1468b2a5221b5c1f7f46c3333 upstream. + +This patch simply add SND_PCI_QUIRK for HP Laptop 15-da3001TU to fixed +mute led of laptop. + +Signed-off-by: Aman Dhoot +Cc: +Link: https://lore.kernel.org/r/CAMTp=B+3NG65Z684xMwHqdXDJhY+DJK-kuSw4adn6xwnG+b5JA@mail.gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9934,6 +9934,7 @@ static const struct snd_pci_quirk alc269 + SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), + SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), ++ SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), + SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), + SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), + SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1), diff --git a/queue-6.8/firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch b/queue-6.8/firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch new file mode 100644 index 00000000000..1a413d32bdd --- /dev/null +++ b/queue-6.8/firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch @@ -0,0 +1,62 @@ +From 09773bf55aeabe3fd61745d900798dc1272c778a Mon Sep 17 00:00:00 2001 +From: Takashi Sakamoto +Date: Mon, 29 Apr 2024 17:47:08 +0900 +Subject: firewire: ohci: fulfill timestamp for some local asynchronous transaction + +From: Takashi Sakamoto + +commit 09773bf55aeabe3fd61745d900798dc1272c778a upstream. + +1394 OHCI driver generates packet data for the response subaction to the +request subaction to some local registers. In the case, the driver should +assign timestamp to them by itself. + +This commit fulfills the timestamp for the subaction. + +Cc: stable@vger.kernel.org +Fixes: dcadfd7f7c74 ("firewire: core: use union for callback of transaction completion") +Link: https://lore.kernel.org/r/20240429084709.707473-1-o-takashi@sakamocchi.jp +Signed-off-by: Takashi Sakamoto +Signed-off-by: Greg Kroah-Hartman +--- + drivers/firewire/ohci.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/firewire/ohci.c ++++ b/drivers/firewire/ohci.c +@@ -1556,6 +1556,8 @@ static int handle_at_packet(struct conte + #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) + #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) + ++static u32 get_cycle_time(struct fw_ohci *ohci); ++ + static void handle_local_rom(struct fw_ohci *ohci, + struct fw_packet *packet, u32 csr) + { +@@ -1580,6 +1582,8 @@ static void handle_local_rom(struct fw_o + (void *) ohci->config_rom + i, length); + } + ++ // Timestamping on behalf of the hardware. ++ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); + fw_core_handle_response(&ohci->card, &response); + } + +@@ -1628,6 +1632,8 @@ static void handle_local_lock(struct fw_ + fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0); + + out: ++ // Timestamping on behalf of the hardware. ++ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci)); + fw_core_handle_response(&ohci->card, &response); + } + +@@ -1670,8 +1676,6 @@ static void handle_local_request(struct + } + } + +-static u32 get_cycle_time(struct fw_ohci *ohci); +- + static void at_context_transmit(struct context *ctx, struct fw_packet *packet) + { + unsigned long flags; diff --git a/queue-6.8/series b/queue-6.8/series index 3841b6cd2d2..8767fec5f3e 100644 --- a/queue-6.8/series +++ b/queue-6.8/series @@ -244,3 +244,18 @@ firewire-nosy-ensure-user_length-is-taken-into-account-when-fetching-packet-cont reapply-drm-qxl-simplify-qxl_fence_wait.patch usb-typec-ucsi-check-for-notifications-after-init.patch usb-typec-ucsi-fix-connector-check-on-init.patch +usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch +usb-ohci-prevent-missed-ohci-interrupts.patch +usb-core-fix-access-violation-during-port-device-removal.patch +usb-gadget-composite-fix-os-descriptors-w_value-logic.patch +usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch +usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch +usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch +usb-xhci-plat-don-t-include-xhci.h.patch +usb-dwc3-core-prevent-phy-suspend-during-init.patch +usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch +usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch +usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch +alsa-hda-realtek-fix-mute-led-of-hp-laptop-15-da3001tu.patch +alsa-hda-realtek-fix-conflicting-pci-ssid-17aa-386f-for-lenovo-legion-models.patch +firewire-ohci-fulfill-timestamp-for-some-local-asynchronous-transaction.patch diff --git a/queue-6.8/usb-core-fix-access-violation-during-port-device-removal.patch b/queue-6.8/usb-core-fix-access-violation-during-port-device-removal.patch new file mode 100644 index 00000000000..4cce39f52de --- /dev/null +++ b/queue-6.8/usb-core-fix-access-violation-during-port-device-removal.patch @@ -0,0 +1,69 @@ +From a4b46d450c49f32e9d4247b421e58083fde304ce Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Thu, 18 Apr 2024 11:13:13 -0400 +Subject: USB: core: Fix access violation during port device removal + +From: Alan Stern + +commit a4b46d450c49f32e9d4247b421e58083fde304ce upstream. + +Testing with KASAN and syzkaller revealed a bug in port.c:disable_store(): +usb_hub_to_struct_hub() can return NULL if the hub that the port belongs to +is concurrently removed, but the function does not check for this +possibility before dereferencing the returned value. + +It turns out that the first dereference is unnecessary, since hub->intfdev +is the parent of the port device, so it can be changed easily. Adding a +check for hub == NULL prevents further problems. + +The same bug exists in the disable_show() routine, and it can be fixed the +same way. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Yue Sun +Reported-by: xingwei lee +Link: https://lore.kernel.org/linux-usb/CAEkJfYON+ry7xPx=AiLR9jzUNT+i_Va68ACajOC3HoacOfL1ig@mail.gmail.com/ +Fixes: f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power") +CC: Michael Grzeschik +CC: stable@vger.kernel.org +Link: https://lore.kernel.org/r/393aa580-15a5-44ca-ad3b-6462461cd313@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/port.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -50,13 +50,15 @@ static ssize_t disable_show(struct devic + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev->parent->parent); + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +- struct usb_interface *intf = to_usb_interface(hub->intfdev); ++ struct usb_interface *intf = to_usb_interface(dev->parent); + int port1 = port_dev->portnum; + u16 portstatus, unused; + bool disabled; + int rc; + struct kernfs_node *kn; + ++ if (!hub) ++ return -ENODEV; + hub_get(hub); + rc = usb_autopm_get_interface(intf); + if (rc < 0) +@@ -100,12 +102,14 @@ static ssize_t disable_store(struct devi + struct usb_port *port_dev = to_usb_port(dev); + struct usb_device *hdev = to_usb_device(dev->parent->parent); + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); +- struct usb_interface *intf = to_usb_interface(hub->intfdev); ++ struct usb_interface *intf = to_usb_interface(dev->parent); + int port1 = port_dev->portnum; + bool disabled; + int rc; + struct kernfs_node *kn; + ++ if (!hub) ++ return -ENODEV; + rc = kstrtobool(buf, &disabled); + if (rc) + return rc; diff --git a/queue-6.8/usb-dwc3-core-prevent-phy-suspend-during-init.patch b/queue-6.8/usb-dwc3-core-prevent-phy-suspend-during-init.patch new file mode 100644 index 00000000000..6db3ac29115 --- /dev/null +++ b/queue-6.8/usb-dwc3-core-prevent-phy-suspend-during-init.patch @@ -0,0 +1,262 @@ +From 6d735722063a945de56472bdc6bfcb170fd43b86 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 17 Apr 2024 23:14:36 +0000 +Subject: usb: dwc3: core: Prevent phy suspend during init + +From: Thinh Nguyen + +commit 6d735722063a945de56472bdc6bfcb170fd43b86 upstream. + +GUSB3PIPECTL.SUSPENDENABLE and GUSB2PHYCFG.SUSPHY should be cleared +during initialization. Suspend during initialization can result in +undefined behavior due to clock synchronization failure, which often +seen as core soft reset timeout. + +The programming guide recommended these bits to be cleared during +initialization for DWC_usb3.0 version 1.94 and above (along with +DWC_usb31 and DWC_usb32). The current check in the driver does not +account if it's set by default setting from coreConsultant. + +This is especially the case for DRD when switching mode to ensure the +phy clocks are available to change mode. Depending on the +platforms/design, some may be affected more than others. This is noted +in the DWC_usb3x programming guide under the above registers. + +Let's just disable them during driver load and mode switching. Restore +them when the controller initialization completes. + +Note that some platforms workaround this issue by disabling phy suspend +through "snps,dis_u3_susphy_quirk" and "snps,dis_u2_susphy_quirk" when +they should not need to. + +Cc: stable@vger.kernel.org +Fixes: 9ba3aca8fe82 ("usb: dwc3: Disable phy suspend after power-on reset") +Signed-off-by: Thinh Nguyen +Link: https://lore.kernel.org/r/20da4e5a0c4678c9587d3da23f83bdd6d77353e9.1713394973.git.Thinh.Nguyen@synopsys.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/core.c | 90 +++++++++++++++++++--------------------------- + drivers/usb/dwc3/core.h | 1 + drivers/usb/dwc3/gadget.c | 2 + + drivers/usb/dwc3/host.c | 27 +++++++++++++ + 4 files changed, 68 insertions(+), 52 deletions(-) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 + return 0; + } + ++void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) ++{ ++ u32 reg; ++ ++ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); ++ if (enable && !dwc->dis_u3_susphy_quirk) ++ reg |= DWC3_GUSB3PIPECTL_SUSPHY; ++ else ++ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; ++ ++ dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); ++ ++ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); ++ if (enable && !dwc->dis_u2_susphy_quirk) ++ reg |= DWC3_GUSB2PHYCFG_SUSPHY; ++ else ++ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; ++ ++ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); ++} ++ + void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) + { + u32 reg; +@@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dw + */ + static int dwc3_phy_setup(struct dwc3 *dwc) + { +- unsigned int hw_mode; + u32 reg; + +- hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); +- + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); + + /* +@@ -599,21 +617,16 @@ static int dwc3_phy_setup(struct dwc3 *d + reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; + + /* +- * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY +- * to '0' during coreConsultant configuration. So default value +- * will be '0' when the core is reset. Application needs to set it +- * to '1' after the core initialization is completed. +- */ +- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) +- reg |= DWC3_GUSB3PIPECTL_SUSPHY; +- +- /* +- * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after +- * power-on reset, and it can be set after core initialization, which is +- * after device soft-reset during initialization. ++ * Above DWC_usb3.0 1.94a, it is recommended to set ++ * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration. ++ * So default value will be '0' when the core is reset. Application ++ * needs to set it to '1' after the core initialization is completed. ++ * ++ * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be ++ * cleared after power-on reset, and it can be set after core ++ * initialization. + */ +- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) +- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; ++ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; + + if (dwc->u2ss_inp3_quirk) + reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; +@@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *d + if (dwc->tx_de_emphasis_quirk) + reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); + +- if (dwc->dis_u3_susphy_quirk) +- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; +- + if (dwc->dis_del_phy_power_chg_quirk) + reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; + +@@ -689,24 +699,15 @@ static int dwc3_phy_setup(struct dwc3 *d + } + + /* +- * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to +- * '0' during coreConsultant configuration. So default value will +- * be '0' when the core is reset. Application needs to set it to +- * '1' after the core initialization is completed. +- */ +- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) +- reg |= DWC3_GUSB2PHYCFG_SUSPHY; +- +- /* +- * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after +- * power-on reset, and it can be set after core initialization, which is +- * after device soft-reset during initialization. ++ * Above DWC_usb3.0 1.94a, it is recommended to set ++ * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration. ++ * So default value will be '0' when the core is reset. Application ++ * needs to set it to '1' after the core initialization is completed. ++ * ++ * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared ++ * after power-on reset, and it can be set after core initialization. + */ +- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) +- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; +- +- if (dwc->dis_u2_susphy_quirk) +- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; ++ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; + + if (dwc->dis_enblslpm_quirk) + reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; +@@ -1227,21 +1228,6 @@ static int dwc3_core_init(struct dwc3 *d + if (ret) + goto err_exit_phy; + +- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && +- !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) { +- if (!dwc->dis_u3_susphy_quirk) { +- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); +- reg |= DWC3_GUSB3PIPECTL_SUSPHY; +- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); +- } +- +- if (!dwc->dis_u2_susphy_quirk) { +- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); +- reg |= DWC3_GUSB2PHYCFG_SUSPHY; +- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +- } +- } +- + dwc3_core_setup_global_control(dwc); + dwc3_core_num_eps(dwc); + +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -1578,6 +1578,7 @@ int dwc3_event_buffers_setup(struct dwc3 + void dwc3_event_buffers_cleanup(struct dwc3 *dwc); + + int dwc3_core_soft_reset(struct dwc3 *dwc); ++void dwc3_enable_susphy(struct dwc3 *dwc, bool enable); + + #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) + int dwc3_host_init(struct dwc3 *dwc); +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -2937,6 +2937,7 @@ static int __dwc3_gadget_start(struct dw + dwc3_ep0_out_start(dwc); + + dwc3_gadget_enable_irq(dwc); ++ dwc3_enable_susphy(dwc, true); + + return 0; + +@@ -4703,6 +4704,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc) + if (!dwc->gadget) + return; + ++ dwc3_enable_susphy(dwc, false); + usb_del_gadget(dwc->gadget); + dwc3_gadget_free_endpoints(dwc); + usb_put_gadget(dwc->gadget); +--- a/drivers/usb/dwc3/host.c ++++ b/drivers/usb/dwc3/host.c +@@ -10,9 +10,30 @@ + #include + #include + #include ++#include ++#include + ++#include "../host/xhci-plat.h" + #include "core.h" + ++static void dwc3_xhci_plat_start(struct usb_hcd *hcd) ++{ ++ struct platform_device *pdev; ++ struct dwc3 *dwc; ++ ++ if (!usb_hcd_is_primary_hcd(hcd)) ++ return; ++ ++ pdev = to_platform_device(hcd->self.controller); ++ dwc = dev_get_drvdata(pdev->dev.parent); ++ ++ dwc3_enable_susphy(dwc, true); ++} ++ ++static const struct xhci_plat_priv dwc3_xhci_plat_quirk = { ++ .plat_start = dwc3_xhci_plat_start, ++}; ++ + static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc, + int irq, char *name) + { +@@ -117,6 +138,11 @@ int dwc3_host_init(struct dwc3 *dwc) + } + } + ++ ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk, ++ sizeof(struct xhci_plat_priv)); ++ if (ret) ++ goto err; ++ + ret = platform_device_add(xhci); + if (ret) { + dev_err(dwc->dev, "failed to register xHCI device\n"); +@@ -142,6 +168,7 @@ void dwc3_host_exit(struct dwc3 *dwc) + if (dwc->sys_wakeup) + device_init_wakeup(&dwc->xhci->dev, false); + ++ dwc3_enable_susphy(dwc, false); + platform_device_unregister(dwc->xhci); + dwc->xhci = NULL; + } diff --git a/queue-6.8/usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch b/queue-6.8/usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch new file mode 100644 index 00000000000..b58dedf0cc8 --- /dev/null +++ b/queue-6.8/usb-fix-regression-caused-by-invalid-ep0-maxpacket-in-virtual-superspeed-device.patch @@ -0,0 +1,46 @@ +From c78c3644b772e356ca452ae733a3c4de0fb11dc8 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 30 Apr 2024 10:33:48 -0400 +Subject: usb: Fix regression caused by invalid ep0 maxpacket in virtual SuperSpeed device + +From: Alan Stern + +commit c78c3644b772e356ca452ae733a3c4de0fb11dc8 upstream. + +A virtual SuperSpeed device in the FreeBSD BVCP package +(https://bhyve.npulse.net/) presents an invalid ep0 maxpacket size of 256. +It stopped working with Linux following a recent commit because now we +check these sizes more carefully than before. + +Fix this regression by using the bMaxpacketSize0 value in the device +descriptor for SuperSpeed or faster devices, even if it is invalid. This +is a very simple-minded change; we might want to check more carefully for +values that actually make some sense (for instance, no smaller than 64). + +Signed-off-by: Alan Stern +Reported-and-tested-by: Roger Whittaker +Closes: https://bugzilla.suse.com/show_bug.cgi?id=1220569 +Link: https://lore.kernel.org/linux-usb/9efbd569-7059-4575-983f-0ea30df41871@suse.com/ +Fixes: 59cf44575456 ("USB: core: Fix oversight in SuperSpeed initialization") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/4058ac05-237c-4db4-9ecc-5af42bdb4501@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hub.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -5081,9 +5081,10 @@ hub_port_init(struct usb_hub *hub, struc + } + if (usb_endpoint_maxp(&udev->ep0.desc) == i) { + ; /* Initial ep0 maxpacket guess is right */ +- } else if ((udev->speed == USB_SPEED_FULL || ++ } else if (((udev->speed == USB_SPEED_FULL || + udev->speed == USB_SPEED_HIGH) && +- (i == 8 || i == 16 || i == 32 || i == 64)) { ++ (i == 8 || i == 16 || i == 32 || i == 64)) || ++ (udev->speed >= USB_SPEED_SUPER && i > 0)) { + /* Initial guess is wrong; use the descriptor's value */ + if (udev->speed == USB_SPEED_FULL) + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); diff --git a/queue-6.8/usb-gadget-composite-fix-os-descriptors-w_value-logic.patch b/queue-6.8/usb-gadget-composite-fix-os-descriptors-w_value-logic.patch new file mode 100644 index 00000000000..8d2334d6e54 --- /dev/null +++ b/queue-6.8/usb-gadget-composite-fix-os-descriptors-w_value-logic.patch @@ -0,0 +1,78 @@ +From ec6ce7075ef879b91a8710829016005dc8170f17 Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Thu, 4 Apr 2024 12:06:35 +0200 +Subject: usb: gadget: composite: fix OS descriptors w_value logic + +From: Peter Korsgaard + +commit ec6ce7075ef879b91a8710829016005dc8170f17 upstream. + +The OS descriptors logic had the high/low byte of w_value inverted, causing +the extended properties to not be accessible for interface != 0. + +>From the Microsoft documentation: +https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-os-1-0-descriptors-specification + +OS_Desc_CompatID.doc (w_index = 0x4): + +- wValue: + + High Byte = InterfaceNumber. InterfaceNumber is set to the number of the + interface or function that is associated with the descriptor, typically + 0x00. Because a device can have only one extended compat ID descriptor, + it should ignore InterfaceNumber, regardless of the value, and simply + return the descriptor. + + Low Byte = 0. PageNumber is used to retrieve descriptors that are larger + than 64 KB. The header section is 16 bytes, so PageNumber is set to 0 for + this request. + +We currently do not support >64KB compat ID descriptors, so verify that the +low byte is 0. + +OS_Desc_Ext_Prop.doc (w_index = 0x5): + +- wValue: + + High byte = InterfaceNumber. The high byte of wValue is set to the number + of the interface or function that is associated with the descriptor. + + Low byte = PageNumber. The low byte of wValue is used to retrieve + descriptors that are larger than 64 KB. The header section is 10 bytes, so + PageNumber is set to 0 for this request. + +We also don't support >64KB extended properties, so verify that the low byte +is 0 and use the high byte for the interface number. + +Fixes: 37a3a533429e ("usb: gadget: OS Feature Descriptors support") +Cc: stable +Signed-off-by: Peter Korsgaard +Link: https://lore.kernel.org/r/20240404100635.3215340-1-peter@korsgaard.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/composite.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -2112,7 +2112,7 @@ unknown: + buf[5] = 0x01; + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: +- if (w_index != 0x4 || (w_value >> 8)) ++ if (w_index != 0x4 || (w_value & 0xff)) + break; + buf[6] = w_index; + /* Number of ext compat interfaces */ +@@ -2128,9 +2128,9 @@ unknown: + } + break; + case USB_RECIP_INTERFACE: +- if (w_index != 0x5 || (w_value >> 8)) ++ if (w_index != 0x5 || (w_value & 0xff)) + break; +- interface = w_value & 0xFF; ++ interface = w_value >> 8; + if (interface >= MAX_CONFIG_INTERFACES || + !os_desc_cfg->interface[interface]) + break; diff --git a/queue-6.8/usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch b/queue-6.8/usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch new file mode 100644 index 00000000000..50c954eb887 --- /dev/null +++ b/queue-6.8/usb-gadget-f_fs-fix-a-race-condition-when-processing-setup-packets.patch @@ -0,0 +1,34 @@ +From 0aea736ddb877b93f6d2dd8cf439840d6b4970a9 Mon Sep 17 00:00:00 2001 +From: Chris Wulff +Date: Tue, 23 Apr 2024 18:02:15 +0000 +Subject: usb: gadget: f_fs: Fix a race condition when processing setup packets. + +From: Chris Wulff + +commit 0aea736ddb877b93f6d2dd8cf439840d6b4970a9 upstream. + +If the USB driver passes a pointer into the TRB buffer for creq, this +buffer can be overwritten with the status response as soon as the event +is queued. This can make the final check return USB_GADGET_DELAYED_STATUS +when it shouldn't. Instead use the stored wLength. + +Fixes: 4d644abf2569 ("usb: gadget: f_fs: Only return delayed status when len is 0") +Cc: stable +Signed-off-by: Chris Wulff +Link: https://lore.kernel.org/r/CO1PR17MB5419BD664264A558B2395E28E1112@CO1PR17MB5419.namprd17.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_fs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -3335,7 +3335,7 @@ static int ffs_func_setup(struct usb_fun + __ffs_event_add(ffs, FUNCTIONFS_SETUP); + spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); + +- return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; ++ return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; + } + + static bool ffs_func_req_match(struct usb_function *f, diff --git a/queue-6.8/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch b/queue-6.8/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch new file mode 100644 index 00000000000..ba1dbaaa2c1 --- /dev/null +++ b/queue-6.8/usb-gadget-f_fs-fix-race-between-aio_cancel-and-aio-request-complete.patch @@ -0,0 +1,88 @@ +From 24729b307eefcd7c476065cd7351c1a018082c19 Mon Sep 17 00:00:00 2001 +From: Wesley Cheng +Date: Mon, 8 Apr 2024 18:40:59 -0700 +Subject: usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete + +From: Wesley Cheng + +commit 24729b307eefcd7c476065cd7351c1a018082c19 upstream. + +FFS based applications can utilize the aio_cancel() callback to dequeue +pending USB requests submitted to the UDC. There is a scenario where the +FFS application issues an AIO cancel call, while the UDC is handling a +soft disconnect. For a DWC3 based implementation, the callstack looks +like the following: + + DWC3 Gadget FFS Application +dwc3_gadget_soft_disconnect() ... + --> dwc3_stop_active_transfers() + --> dwc3_gadget_giveback(-ESHUTDOWN) + --> ffs_epfile_async_io_complete() ffs_aio_cancel() + --> usb_ep_free_request() --> usb_ep_dequeue() + +There is currently no locking implemented between the AIO completion +handler and AIO cancel, so the issue occurs if the completion routine is +running in parallel to an AIO cancel call coming from the FFS application. +As the completion call frees the USB request (io_data->req) the FFS +application is also referencing it for the usb_ep_dequeue() call. This can +lead to accessing a stale/hanging pointer. + +commit b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently") +relocated the usb_ep_free_request() into ffs_epfile_async_io_complete(). +However, in order to properly implement locking to mitigate this issue, the +spinlock can't be added to ffs_epfile_async_io_complete(), as +usb_ep_dequeue() (if successfully dequeuing a USB request) will call the +function driver's completion handler in the same context. Hence, leading +into a deadlock. + +Fix this issue by moving the usb_ep_free_request() back to +ffs_user_copy_worker(), and ensuring that it explicitly sets io_data->req +to NULL after freeing it within the ffs->eps_lock. This resolves the race +condition above, as the ffs_aio_cancel() routine will not continue +attempting to dequeue a request that has already been freed, or the +ffs_user_copy_work() not freeing the USB request until the AIO cancel is +done referencing it. + +This fix depends on + commit b566d38857fc ("usb: gadget: f_fs: use io_data->status + consistently") + +Fixes: 2e4c7553cd6f ("usb: gadget: f_fs: add aio support") +Cc: stable # b566d38857fc ("usb: gadget: f_fs: use io_data->status consistently") +Signed-off-by: Wesley Cheng +Link: https://lore.kernel.org/r/20240409014059.6740-1-quic_wcheng@quicinc.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_fs.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -821,6 +821,7 @@ static void ffs_user_copy_worker(struct + work); + int ret = io_data->status; + bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; ++ unsigned long flags; + + if (io_data->read && ret > 0) { + kthread_use_mm(io_data->mm); +@@ -833,6 +834,11 @@ static void ffs_user_copy_worker(struct + if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd) + eventfd_signal(io_data->ffs->ffs_eventfd); + ++ spin_lock_irqsave(&io_data->ffs->eps_lock, flags); ++ usb_ep_free_request(io_data->ep, io_data->req); ++ io_data->req = NULL; ++ spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags); ++ + if (io_data->read) + kfree(io_data->to_free); + ffs_free_buffer(io_data); +@@ -846,7 +852,6 @@ static void ffs_epfile_async_io_complete + struct ffs_data *ffs = io_data->ffs; + + io_data->status = req->status ? req->status : req->actual; +- usb_ep_free_request(_ep, req); + + INIT_WORK(&io_data->work, ffs_user_copy_worker); + queue_work(ffs->io_completion_wq, &io_data->work); diff --git a/queue-6.8/usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch b/queue-6.8/usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch new file mode 100644 index 00000000000..017343485e8 --- /dev/null +++ b/queue-6.8/usb-gadget-uvc-use-correct-buffer-size-when-parsing-configfs-lists.patch @@ -0,0 +1,51 @@ +From 650ae71c80749fc7cb8858c8049f532eaec64410 Mon Sep 17 00:00:00 2001 +From: Ivan Avdeev +Date: Sat, 13 Apr 2024 11:01:24 -0400 +Subject: usb: gadget: uvc: use correct buffer size when parsing configfs lists + +From: Ivan Avdeev + +commit 650ae71c80749fc7cb8858c8049f532eaec64410 upstream. + +This commit fixes uvc gadget support on 32-bit platforms. + +Commit 0df28607c5cb ("usb: gadget: uvc: Generalise helper functions for +reuse") introduced a helper function __uvcg_iter_item_entries() to aid +with parsing lists of items on configfs attributes stores. This function +is a generalization of another very similar function, which used a +stack-allocated temporary buffer of fixed size for each item in the list +and used the sizeof() operator to check for potential buffer overruns. +The new function was changed to allocate the now variably sized temp +buffer on heap, but wasn't properly updated to also check for max buffer +size using the computed size instead of sizeof() operator. + +As a result, the maximum item size was 7 (plus null terminator) on +64-bit platforms, and 3 on 32-bit ones. While 7 is accidentally just +barely enough, 3 is definitely too small for some of UVC configfs +attributes. For example, dwFrameInteval, specified in 100ns units, +usually has 6-digit item values, e.g. 166666 for 60fps. + +Cc: stable@vger.kernel.org +Fixes: 0df28607c5cb ("usb: gadget: uvc: Generalise helper functions for reuse") +Signed-off-by: Ivan Avdeev +Link: https://lore.kernel.org/r/20240413150124.1062026-1-me@provod.works +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/uvc_configfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/function/uvc_configfs.c ++++ b/drivers/usb/gadget/function/uvc_configfs.c +@@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(cons + + while (pg - page < len) { + i = 0; +- while (i < sizeof(buf) && (pg - page < len) && ++ while (i < bufsize && (pg - page < len) && + *pg != '\0' && *pg != '\n') + buf[i++] = *pg++; +- if (i == sizeof(buf)) { ++ if (i == bufsize) { + ret = -EINVAL; + goto out_free_buf; + } diff --git a/queue-6.8/usb-ohci-prevent-missed-ohci-interrupts.patch b/queue-6.8/usb-ohci-prevent-missed-ohci-interrupts.patch new file mode 100644 index 00000000000..bbeb58dbafd --- /dev/null +++ b/queue-6.8/usb-ohci-prevent-missed-ohci-interrupts.patch @@ -0,0 +1,60 @@ +From fe81f354841641c7f71163b84912b25c169ed8ec Mon Sep 17 00:00:00 2001 +From: Guenter Roeck +Date: Mon, 29 Apr 2024 08:40:10 -0700 +Subject: usb: ohci: Prevent missed ohci interrupts + +From: Guenter Roeck + +commit fe81f354841641c7f71163b84912b25c169ed8ec upstream. + +Testing ohci functionality with qemu's pci-ohci emulation often results +in ohci interface stalls, resulting in hung task timeouts. + +The problem is caused by lost interrupts between the emulation and the +Linux kernel code. Additional interrupts raised while the ohci interrupt +handler in Linux is running and before the handler clears the interrupt +status are not handled. The fix for a similar problem in ehci suggests +that the problem is likely caused by edge-triggered MSI interrupts. See +commit 0b60557230ad ("usb: ehci: Prevent missed ehci interrupts with +edge-triggered MSI") for details. + +Ensure that the ohci interrupt code handles all pending interrupts before +returning to solve the problem. + +Cc: Gerd Hoffmann +Cc: David Laight +Cc: stable@vger.kernel.org +Fixes: 306c54d0edb6 ("usb: hcd: Try MSI interrupts on PCI devices") +Signed-off-by: Guenter Roeck +Reviewed-by: Alan Stern +Reviewed-by: Gerd Hoffmann +Link: https://lore.kernel.org/r/20240429154010.1507366-1-linux@roeck-us.net +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/ohci-hcd.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_ + /* Check for an all 1's result which is a typical consequence + * of dead, unclocked, or unplugged (CardBus...) devices + */ ++again: + if (ints == ~(u32)0) { + ohci->rh_state = OHCI_RH_HALTED; + ohci_dbg (ohci, "device removed!\n"); +@@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_ + } + spin_unlock(&ohci->lock); + ++ /* repeat until all enabled interrupts are handled */ ++ if (ohci->rh_state != OHCI_RH_HALTED) { ++ ints = ohci_readl(ohci, ®s->intrstatus); ++ if (ints && (ints & ohci_readl(ohci, ®s->intrenable))) ++ goto again; ++ } ++ + return IRQ_HANDLED; + } + diff --git a/queue-6.8/usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch b/queue-6.8/usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch new file mode 100644 index 00000000000..0241d0a2165 --- /dev/null +++ b/queue-6.8/usb-typec-tcpm-check-for-port-partner-validity-before-consuming-it.patch @@ -0,0 +1,114 @@ +From ae11f04b452b5205536e1c02d31f8045eba249dd Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Sat, 27 Apr 2024 20:28:12 +0000 +Subject: usb: typec: tcpm: Check for port partner validity before consuming it + +From: Badhri Jagan Sridharan + +commit ae11f04b452b5205536e1c02d31f8045eba249dd upstream. + +typec_register_partner() does not guarantee partner registration +to always succeed. In the event of failure, port->partner is set +to the error value or NULL. Given that port->partner validity is +not checked, this results in the following crash: + +Unable to handle kernel NULL pointer dereference at virtual address xx + pc : run_state_machine+0x1bc8/0x1c08 + lr : run_state_machine+0x1b90/0x1c08 +.. + Call trace: + run_state_machine+0x1bc8/0x1c08 + tcpm_state_machine_work+0x94/0xe4 + kthread_worker_fn+0x118/0x328 + kthread+0x1d0/0x23c + ret_from_fork+0x10/0x20 + +To prevent the crash, check for port->partner validity before +derefencing it in all the call sites. + +Cc: stable@vger.kernel.org +Fixes: c97cd0b4b54e ("usb: typec: tcpm: set initial svdm version based on pd revision") +Signed-off-by: Badhri Jagan Sridharan +Reviewed-by: Heikki Krogerus +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20240427202812.3435268-1-badhri@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -1501,7 +1501,8 @@ static void svdm_consume_identity(struct + port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT]; + port->partner_ident.product = product; + +- typec_partner_set_identity(port->partner); ++ if (port->partner) ++ typec_partner_set_identity(port->partner); + + tcpm_log(port, "Identity: %04x:%04x.%04x", + PD_IDH_VID(vdo), +@@ -1589,6 +1590,9 @@ static void tcpm_register_partner_altmod + struct typec_altmode *altmode; + int i; + ++ if (!port->partner) ++ return; ++ + for (i = 0; i < modep->altmodes; i++) { + altmode = typec_partner_register_altmode(port->partner, + &modep->altmode_desc[i]); +@@ -3587,7 +3591,10 @@ static int tcpm_init_vconn(struct tcpm_p + + static void tcpm_typec_connect(struct tcpm_port *port) + { ++ struct typec_partner *partner; ++ + if (!port->connected) { ++ port->connected = true; + /* Make sure we don't report stale identity information */ + memset(&port->partner_ident, 0, sizeof(port->partner_ident)); + port->partner_desc.usb_pd = port->pd_capable; +@@ -3597,9 +3604,13 @@ static void tcpm_typec_connect(struct tc + port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; + else + port->partner_desc.accessory = TYPEC_ACCESSORY_NONE; +- port->partner = typec_register_partner(port->typec_port, +- &port->partner_desc); +- port->connected = true; ++ partner = typec_register_partner(port->typec_port, &port->partner_desc); ++ if (IS_ERR(partner)) { ++ dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner)); ++ return; ++ } ++ ++ port->partner = partner; + typec_partner_set_usb_power_delivery(port->partner, port->partner_pd); + } + } +@@ -3669,9 +3680,11 @@ out_disable_mux: + static void tcpm_typec_disconnect(struct tcpm_port *port) + { + if (port->connected) { +- typec_partner_set_usb_power_delivery(port->partner, NULL); +- typec_unregister_partner(port->partner); +- port->partner = NULL; ++ if (port->partner) { ++ typec_partner_set_usb_power_delivery(port->partner, NULL); ++ typec_unregister_partner(port->partner); ++ port->partner = NULL; ++ } + port->connected = false; + } + } +@@ -3887,6 +3900,9 @@ static enum typec_cc_status tcpm_pwr_opm + + static void tcpm_set_initial_svdm_version(struct tcpm_port *port) + { ++ if (!port->partner) ++ return; ++ + switch (port->negotiated_rev) { + case PD_REV30: + break; diff --git a/queue-6.8/usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch b/queue-6.8/usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch new file mode 100644 index 00000000000..54d9e4b1356 --- /dev/null +++ b/queue-6.8/usb-typec-tcpm-clear-pd_event-queue-in-port_reset.patch @@ -0,0 +1,43 @@ +From bf20c69cf3cf9c6445c4925dd9a8a6ca1b78bfdf Mon Sep 17 00:00:00 2001 +From: RD Babiera +Date: Tue, 23 Apr 2024 20:27:16 +0000 +Subject: usb: typec: tcpm: clear pd_event queue in PORT_RESET + +From: RD Babiera + +commit bf20c69cf3cf9c6445c4925dd9a8a6ca1b78bfdf upstream. + +When a Fast Role Swap control message attempt results in a transition +to ERROR_RECOVERY, the TCPC can still queue a TCPM_SOURCING_VBUS event. + +If the event is queued but processed after the tcpm_reset_port() call +in the PORT_RESET state, then the following occurs: +1. tcpm_reset_port() calls tcpm_init_vbus() to reset the vbus sourcing and +sinking state +2. tcpm_pd_event_handler() turns VBUS on before the port is in the default +state. +3. The port resolves as a sink. In the SNK_DISCOVERY state, +tcpm_set_charge() cannot set vbus to charge. + +Clear pd events within PORT_RESET to get rid of non-applicable events. + +Fixes: b17dd57118fe ("staging: typec: tcpm: Improve role swap with non PD capable partners") +Cc: stable@vger.kernel.org +Signed-off-by: RD Babiera +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20240423202715.3375827-2-rdbabiera@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -4873,6 +4873,7 @@ static void run_state_machine(struct tcp + break; + case PORT_RESET: + tcpm_reset_port(port); ++ port->pd_events = 0; + if (port->self_powered) + tcpm_set_cc(port, TYPEC_CC_OPEN); + else diff --git a/queue-6.8/usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch b/queue-6.8/usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch new file mode 100644 index 00000000000..5c2e5cde947 --- /dev/null +++ b/queue-6.8/usb-typec-tcpm-unregister-existing-source-caps-before-re-registration.patch @@ -0,0 +1,66 @@ +From 230ecdf71a644c9c73e0e6735b33173074ae3f94 Mon Sep 17 00:00:00 2001 +From: Amit Sunil Dhamne +Date: Wed, 24 Apr 2024 15:32:16 -0700 +Subject: usb: typec: tcpm: unregister existing source caps before re-registration + +From: Amit Sunil Dhamne + +commit 230ecdf71a644c9c73e0e6735b33173074ae3f94 upstream. + +Check and unregister existing source caps in tcpm_register_source_caps +function before registering new ones. This change fixes following +warning when port partner resends source caps after negotiating PD contract +for the purpose of re-negotiation. + +[ 343.135030][ T151] sysfs: cannot create duplicate filename '/devices/virtual/usb_power_delivery/pd1/source-capabilities' +[ 343.135071][ T151] Call trace: +[ 343.135076][ T151] dump_backtrace+0xe8/0x108 +[ 343.135099][ T151] show_stack+0x18/0x24 +[ 343.135106][ T151] dump_stack_lvl+0x50/0x6c +[ 343.135119][ T151] dump_stack+0x18/0x24 +[ 343.135126][ T151] sysfs_create_dir_ns+0xe0/0x140 +[ 343.135137][ T151] kobject_add_internal+0x228/0x424 +[ 343.135146][ T151] kobject_add+0x94/0x10c +[ 343.135152][ T151] device_add+0x1b0/0x4c0 +[ 343.135187][ T151] device_register+0x20/0x34 +[ 343.135195][ T151] usb_power_delivery_register_capabilities+0x90/0x20c +[ 343.135209][ T151] tcpm_pd_rx_handler+0x9f0/0x15b8 +[ 343.135216][ T151] kthread_worker_fn+0x11c/0x260 +[ 343.135227][ T151] kthread+0x114/0x1bc +[ 343.135235][ T151] ret_from_fork+0x10/0x20 +[ 343.135265][ T151] kobject: kobject_add_internal failed for source-capabilities with -EEXIST, don't try to register things with the same name in the same directory. + +Fixes: 8203d26905ee ("usb: typec: tcpm: Register USB Power Delivery Capabilities") +Cc: linux-usb@vger.kernel.org +Cc: stable@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Cc: Mark Brown +Signed-off-by: Amit Sunil Dhamne +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20240424223227.1807844-1-amitsd@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -2435,7 +2435,7 @@ static int tcpm_register_sink_caps(struc + { + struct usb_power_delivery_desc desc = { port->negotiated_rev }; + struct usb_power_delivery_capabilities_desc caps = { }; +- struct usb_power_delivery_capabilities *cap; ++ struct usb_power_delivery_capabilities *cap = port->partner_source_caps; + + if (!port->partner_pd) + port->partner_pd = usb_power_delivery_register(NULL, &desc); +@@ -2445,6 +2445,9 @@ static int tcpm_register_sink_caps(struc + memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps); + caps.role = TYPEC_SINK; + ++ if (cap) ++ usb_power_delivery_unregister_capabilities(cap); ++ + cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps); + if (IS_ERR(cap)) + return PTR_ERR(cap); diff --git a/queue-6.8/usb-xhci-plat-don-t-include-xhci.h.patch b/queue-6.8/usb-xhci-plat-don-t-include-xhci.h.patch new file mode 100644 index 00000000000..4de8ea4463b --- /dev/null +++ b/queue-6.8/usb-xhci-plat-don-t-include-xhci.h.patch @@ -0,0 +1,46 @@ +From 4a237d55446ff67655dc3eed2d4a41997536fc4c Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 17 Apr 2024 23:14:30 +0000 +Subject: usb: xhci-plat: Don't include xhci.h + +From: Thinh Nguyen + +commit 4a237d55446ff67655dc3eed2d4a41997536fc4c upstream. + +The xhci_plat.h should not need to include the entire xhci.h header. +This can cause redefinition in dwc3 if it selectively includes some xHCI +definitions. This is a prerequisite change for a fix to disable suspend +during initialization for dwc3. + +Cc: stable@vger.kernel.org +Signed-off-by: Thinh Nguyen +Link: https://lore.kernel.org/r/310acfa01c957a10d9feaca3f7206269866ba2eb.1713394973.git.Thinh.Nguyen@synopsys.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci-plat.h | 4 +++- + drivers/usb/host/xhci-rzv2m.c | 1 + + 2 files changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-plat.h ++++ b/drivers/usb/host/xhci-plat.h +@@ -8,7 +8,9 @@ + #ifndef _XHCI_PLAT_H + #define _XHCI_PLAT_H + +-#include "xhci.h" /* for hcd_to_xhci() */ ++struct device; ++struct platform_device; ++struct usb_hcd; + + struct xhci_plat_priv { + const char *firmware_name; +--- a/drivers/usb/host/xhci-rzv2m.c ++++ b/drivers/usb/host/xhci-rzv2m.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include "xhci.h" + #include "xhci-plat.h" + #include "xhci-rzv2m.h" + -- 2.47.3