From d0ce2cadfb2e6ffac02cfb46c4f647e822402b1f Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 1 Aug 2025 19:49:00 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...c-intel-fix-snd_soc_sof-dependencies.patch | 64 ++++++++++ ...ntel-fix-building-with-large-nr_cpus.patch | 100 +++++++++++++++ queue-5.4/series | 7 ++ .../usb-chipidea-add-usb-phy-event.patch | 95 +++++++++++++++ ...roduce-ci_hdrc_controller_vbus_event.patch | 65 ++++++++++ ...c-add-new-api-ci_hdrc_gadget_connect.patch | 114 ++++++++++++++++++ ...dea-udc-protect-usb-interrupt-enable.patch | 97 +++++++++++++++ ...onnect-line-when-usb-charger-is-atta.patch | 48 ++++++++ 8 files changed, 590 insertions(+) create mode 100644 queue-5.4/asoc-intel-fix-snd_soc_sof-dependencies.patch create mode 100644 queue-5.4/ethernet-intel-fix-building-with-large-nr_cpus.patch create mode 100644 queue-5.4/usb-chipidea-add-usb-phy-event.patch create mode 100644 queue-5.4/usb-chipidea-introduce-ci_hdrc_controller_vbus_event.patch create mode 100644 queue-5.4/usb-chipidea-udc-add-new-api-ci_hdrc_gadget_connect.patch create mode 100644 queue-5.4/usb-chipidea-udc-protect-usb-interrupt-enable.patch create mode 100644 queue-5.4/usb-phy-mxs-disconnect-line-when-usb-charger-is-atta.patch diff --git a/queue-5.4/asoc-intel-fix-snd_soc_sof-dependencies.patch b/queue-5.4/asoc-intel-fix-snd_soc_sof-dependencies.patch new file mode 100644 index 0000000000..2769d3624c --- /dev/null +++ b/queue-5.4/asoc-intel-fix-snd_soc_sof-dependencies.patch @@ -0,0 +1,64 @@ +From 6ce88388c7cdadc6d4bd9df5f02186a37e9e85a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Jul 2025 16:56:07 +0200 +Subject: ASoC: Intel: fix SND_SOC_SOF dependencies + +From: Arnd Bergmann + +[ Upstream commit e837b59f8b411b5baf5e3de7a5aea10b1c545a63 ] + +It is currently possible to configure a kernel with all Intel SoC +configs as loadable modules, but the board config as built-in. This +causes a link failure in the reference to the snd_soc_sof.ko module: + +x86_64-linux-ld: sound/soc/intel/boards/sof_rt5682.o: in function `sof_rt5682_hw_params': +sof_rt5682.c:(.text+0x1f9): undefined reference to `sof_dai_get_mclk' +x86_64-linux-ld: sof_rt5682.c:(.text+0x234): undefined reference to `sof_dai_get_bclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_rt5682.o: in function `sof_rt5682_codec_init': +sof_rt5682.c:(.text+0x3e0): undefined reference to `sof_dai_get_mclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_cs42l42.o: in function `sof_cs42l42_hw_params': +sof_cs42l42.c:(.text+0x2a): undefined reference to `sof_dai_get_bclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_nau8825.o: in function `sof_nau8825_hw_params': +sof_nau8825.c:(.text+0x7f): undefined reference to `sof_dai_get_bclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_da7219.o: in function `da7219_codec_init': +sof_da7219.c:(.text+0xbf): undefined reference to `sof_dai_get_mclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_maxim_common.o: in function `max_98373_hw_params': +sof_maxim_common.c:(.text+0x6f9): undefined reference to `sof_dai_get_tdm_slots' +x86_64-linux-ld: sound/soc/intel/boards/sof_realtek_common.o: in function `rt1015_hw_params': +sof_realtek_common.c:(.text+0x54c): undefined reference to `sof_dai_get_bclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_realtek_common.o: in function `rt1308_hw_params': +sof_realtek_common.c:(.text+0x702): undefined reference to `sof_dai_get_mclk' +x86_64-linux-ld: sound/soc/intel/boards/sof_cirrus_common.o: in function `cs35l41_hw_params': +sof_cirrus_common.c:(.text+0x2f): undefined reference to `sof_dai_get_bclk' + +Add an optional dependency on SND_SOC_SOF_INTEL_COMMON, to ensure that whenever +the SOF support is in a loadable module, none of the board code can be built-in. + +This may be be a little heavy-handed, but I also don't see a reason why one would +want the boards to be built-in but not the SoC, so it shouldn't actually cause +any usability problems. + +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20250709145626.64125-1-arnd@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig +index 5c27f7ab4a5f..78a75c29ed88 100644 +--- a/sound/soc/intel/boards/Kconfig ++++ b/sound/soc/intel/boards/Kconfig +@@ -11,7 +11,7 @@ menuconfig SND_SOC_INTEL_MACH + kernel: saying N will just cause the configurator to skip all + the questions about Intel ASoC machine drivers. + +-if SND_SOC_INTEL_MACH ++if SND_SOC_INTEL_MACH && (SND_SOC_SOF_INTEL_COMMON || !SND_SOC_SOF_INTEL_COMMON) + + if SND_SOC_INTEL_HASWELL + +-- +2.39.5 + diff --git a/queue-5.4/ethernet-intel-fix-building-with-large-nr_cpus.patch b/queue-5.4/ethernet-intel-fix-building-with-large-nr_cpus.patch new file mode 100644 index 0000000000..3a3a258171 --- /dev/null +++ b/queue-5.4/ethernet-intel-fix-building-with-large-nr_cpus.patch @@ -0,0 +1,100 @@ +From f06c4a120c3f6a6761afaf178eee2aa6cf89e660 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jun 2025 19:31:24 +0200 +Subject: ethernet: intel: fix building with large NR_CPUS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arnd Bergmann + +[ Upstream commit 24171a5a4a952c26568ff0d2a0bc8c4708a95e1d ] + +With large values of CONFIG_NR_CPUS, three Intel ethernet drivers fail to +compile like: + +In function ‘i40e_free_q_vector’, + inlined from ‘i40e_vsi_alloc_q_vectors’ at drivers/net/ethernet/intel/i40e/i40e_main.c:12112:3: + 571 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) +include/linux/rcupdate.h:1084:17: note: in expansion of macro ‘BUILD_BUG_ON’ + 1084 | BUILD_BUG_ON(offsetof(typeof(*(ptr)), rhf) >= 4096); \ +drivers/net/ethernet/intel/i40e/i40e_main.c:5113:9: note: in expansion of macro ‘kfree_rcu’ + 5113 | kfree_rcu(q_vector, rcu); + | ^~~~~~~~~ + +The problem is that the 'rcu' member in 'q_vector' is too far from the start +of the structure. Move this member before the CPU mask instead, in all three +drivers. + +Signed-off-by: Arnd Bergmann +Acked-by: David S. Miller +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Alexander Lobakin +Tested-by: Sunitha Mekala (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/fm10k/fm10k.h | 3 ++- + drivers/net/ethernet/intel/i40e/i40e.h | 2 +- + drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3 ++- + 3 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h +index b14441944b4b..db72e5e4acd3 100644 +--- a/drivers/net/ethernet/intel/fm10k/fm10k.h ++++ b/drivers/net/ethernet/intel/fm10k/fm10k.h +@@ -189,13 +189,14 @@ struct fm10k_q_vector { + struct fm10k_ring_container rx, tx; + + struct napi_struct napi; ++ struct rcu_head rcu; /* to avoid race with update stats on free */ ++ + cpumask_t affinity_mask; + char name[IFNAMSIZ + 9]; + + #ifdef CONFIG_DEBUG_FS + struct dentry *dbg_q_vector; + #endif /* CONFIG_DEBUG_FS */ +- struct rcu_head rcu; /* to avoid race with update stats on free */ + + /* for dynamic allocation of rings associated with this q_vector */ + struct fm10k_ring ring[0] ____cacheline_internodealigned_in_smp; +diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h +index 4c8c31692e9e..edb5e408c980 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e.h ++++ b/drivers/net/ethernet/intel/i40e/i40e.h +@@ -864,6 +864,7 @@ struct i40e_q_vector { + u16 reg_idx; /* register index of the interrupt */ + + struct napi_struct napi; ++ struct rcu_head rcu; /* to avoid race with update stats on free */ + + struct i40e_ring_container rx; + struct i40e_ring_container tx; +@@ -874,7 +875,6 @@ struct i40e_q_vector { + cpumask_t affinity_mask; + struct irq_affinity_notify affinity_notify; + +- struct rcu_head rcu; /* to avoid race with update stats on free */ + char name[I40E_INT_NAME_STR_LEN]; + bool arm_wb_state; + } ____cacheline_internodealigned_in_smp; +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h +index 0142ca226bf5..0f9a1fce0dee 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h +@@ -458,9 +458,10 @@ struct ixgbe_q_vector { + struct ixgbe_ring_container rx, tx; + + struct napi_struct napi; ++ struct rcu_head rcu; /* to avoid race with update stats on free */ ++ + cpumask_t affinity_mask; + int numa_node; +- struct rcu_head rcu; /* to avoid race with update stats on free */ + char name[IFNAMSIZ + 9]; + + /* for dynamic allocation of rings associated with this q_vector */ +-- +2.39.5 + diff --git a/queue-5.4/series b/queue-5.4/series index 7eced043b4..978fb011aa 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -61,3 +61,10 @@ i2c-qup-jump-out-of-the-loop-in-case-of-timeout.patch nilfs2-reject-invalid-file-types-when-reading-inodes.patch comedi-comedi_test-fix-possible-deletion-of-uninitialized-timers.patch alsa-hda-add-missing-nvidia-hda-codec-ids.patch +usb-chipidea-udc-add-new-api-ci_hdrc_gadget_connect.patch +usb-chipidea-udc-protect-usb-interrupt-enable.patch +usb-chipidea-introduce-ci_hdrc_controller_vbus_event.patch +usb-chipidea-add-usb-phy-event.patch +usb-phy-mxs-disconnect-line-when-usb-charger-is-atta.patch +ethernet-intel-fix-building-with-large-nr_cpus.patch +asoc-intel-fix-snd_soc_sof-dependencies.patch diff --git a/queue-5.4/usb-chipidea-add-usb-phy-event.patch b/queue-5.4/usb-chipidea-add-usb-phy-event.patch new file mode 100644 index 0000000000..e173876c58 --- /dev/null +++ b/queue-5.4/usb-chipidea-add-usb-phy-event.patch @@ -0,0 +1,95 @@ +From 8dc55a08d1fce4557bb6a8fcb3df10bc413148e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jun 2023 19:03:51 +0800 +Subject: usb: chipidea: add USB PHY event + +From: Xu Yang + +[ Upstream commit b7a62611fab72e585c729a7fcf666aa9c4144214 ] + +Add USB PHY event for below situation: +- usb role changed +- vbus connect +- vbus disconnect +- gadget driver is enumerated + +USB PHY driver can get the last event after above situation occurs +and deal with different situations. + +Signed-off-by: Xu Yang +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/20230627110353.1879477-1-xu.yang_2@nxp.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/chipidea/ci.h | 18 ++++++++++++++++-- + drivers/usb/chipidea/udc.c | 10 ++++++++++ + 2 files changed, 26 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h +index ff61f88fc867..3a22bc727bb9 100644 +--- a/drivers/usb/chipidea/ci.h ++++ b/drivers/usb/chipidea/ci.h +@@ -277,8 +277,19 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) + return -ENXIO; + + ret = ci->roles[role]->start(ci); +- if (!ret) +- ci->role = role; ++ if (ret) ++ return ret; ++ ++ ci->role = role; ++ ++ if (ci->usb_phy) { ++ if (role == CI_ROLE_HOST) ++ usb_phy_set_event(ci->usb_phy, USB_EVENT_ID); ++ else ++ /* in device mode but vbus is invalid*/ ++ usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); ++ } ++ + return ret; + } + +@@ -292,6 +303,9 @@ static inline void ci_role_stop(struct ci_hdrc *ci) + ci->role = CI_ROLE_END; + + ci->roles[role]->stop(ci); ++ ++ if (ci->usb_phy) ++ usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); + } + + static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci) +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index dfae454ca9ba..19a9a4b83346 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1583,6 +1583,13 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + ret = ci->platdata->notify_event(ci, + CI_HDRC_CONTROLLER_VBUS_EVENT); + ++ if (ci->usb_phy) { ++ if (is_active) ++ usb_phy_set_event(ci->usb_phy, USB_EVENT_VBUS); ++ else ++ usb_phy_set_event(ci->usb_phy, USB_EVENT_NONE); ++ } ++ + if (ci->driver) + ci_hdrc_gadget_connect(_gadget, is_active); + +@@ -1898,6 +1905,9 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci) + if (USBi_PCI & intr) { + ci->gadget.speed = hw_port_is_high_speed(ci) ? + USB_SPEED_HIGH : USB_SPEED_FULL; ++ if (ci->usb_phy) ++ usb_phy_set_event(ci->usb_phy, ++ USB_EVENT_ENUMERATED); + if (ci->suspended) { + if (ci->driver->resume) { + spin_unlock(&ci->lock); +-- +2.39.5 + diff --git a/queue-5.4/usb-chipidea-introduce-ci_hdrc_controller_vbus_event.patch b/queue-5.4/usb-chipidea-introduce-ci_hdrc_controller_vbus_event.patch new file mode 100644 index 0000000000..56c383237d --- /dev/null +++ b/queue-5.4/usb-chipidea-introduce-ci_hdrc_controller_vbus_event.patch @@ -0,0 +1,65 @@ +From c0e23a5b77f2af58340928a03516bd99f63fb386 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jan 2020 14:00:26 +0800 +Subject: usb: chipidea: introduce CI_HDRC_CONTROLLER_VBUS_EVENT glue layer use + +From: Peter Chen + +[ Upstream commit d755cdb1b9d7e1b645e176b97eb137194bbe8cf9 ] + +Some vendors glue layer need to handle some events for vbus, eg, +some i.mx platforms (imx7d, imx8mm, imx8mn, etc) needs vbus event +to handle charger detection, its charger detection is finished at +glue layer code, but not at USB PHY driver. + +Signed-off-by: Peter Chen +Stable-dep-of: b7a62611fab7 ("usb: chipidea: add USB PHY event") +Signed-off-by: Sasha Levin +--- + drivers/usb/chipidea/udc.c | 7 ++++++- + include/linux/usb/chipidea.h | 1 + + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index 9212c3842a1b..dfae454ca9ba 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1569,6 +1569,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + { + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); + unsigned long flags; ++ int ret = 0; + + spin_lock_irqsave(&ci->lock, flags); + ci->vbus_active = is_active; +@@ -1578,10 +1579,14 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + usb_phy_set_charger_state(ci->usb_phy, is_active ? + USB_CHARGER_PRESENT : USB_CHARGER_ABSENT); + ++ if (ci->platdata->notify_event) ++ ret = ci->platdata->notify_event(ci, ++ CI_HDRC_CONTROLLER_VBUS_EVENT); ++ + if (ci->driver) + ci_hdrc_gadget_connect(_gadget, is_active); + +- return 0; ++ return ret; + } + + static int ci_udc_wakeup(struct usb_gadget *_gadget) +diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h +index edd89b7c8f18..54167a2d28ea 100644 +--- a/include/linux/usb/chipidea.h ++++ b/include/linux/usb/chipidea.h +@@ -67,6 +67,7 @@ struct ci_hdrc_platform_data { + #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 + #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 + #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 ++#define CI_HDRC_CONTROLLER_VBUS_EVENT 4 + int (*notify_event) (struct ci_hdrc *ci, unsigned event); + struct regulator *reg_vbus; + struct usb_otg_caps ci_otg_caps; +-- +2.39.5 + diff --git a/queue-5.4/usb-chipidea-udc-add-new-api-ci_hdrc_gadget_connect.patch b/queue-5.4/usb-chipidea-udc-add-new-api-ci_hdrc_gadget_connect.patch new file mode 100644 index 0000000000..667a21d498 --- /dev/null +++ b/queue-5.4/usb-chipidea-udc-add-new-api-ci_hdrc_gadget_connect.patch @@ -0,0 +1,114 @@ +From 022cd82b10f3c5d5ed9d7fcc4b81ae3581444153 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Sep 2019 10:54:52 +0800 +Subject: usb: chipidea: udc: add new API ci_hdrc_gadget_connect + +From: Peter Chen + +[ Upstream commit d16ab536aad208421c5ed32cdcb01b5ab6aa1f19 ] + +This API is used enable device function, it is called at below +situations: +- VBUS is connected during boots up +- Hot plug occurs during runtime + +Signed-off-by: Peter Chen +Signed-off-by: Jun Li +Stable-dep-of: b7a62611fab7 ("usb: chipidea: add USB PHY event") +Signed-off-by: Sasha Levin +--- + drivers/usb/chipidea/udc.c | 63 +++++++++++++++++++------------------- + 1 file changed, 32 insertions(+), 31 deletions(-) + +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index a6ce6b89b271..e9ef6271e20d 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1533,6 +1533,33 @@ static const struct usb_ep_ops usb_ep_ops = { + /****************************************************************************** + * GADGET block + *****************************************************************************/ ++/** ++ * ci_hdrc_gadget_connect: caller makes sure gadget driver is binded ++ */ ++static void ci_hdrc_gadget_connect(struct usb_gadget *_gadget, int is_active) ++{ ++ struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); ++ ++ if (is_active) { ++ pm_runtime_get_sync(&_gadget->dev); ++ hw_device_reset(ci); ++ hw_device_state(ci, ci->ep0out->qh.dma); ++ usb_gadget_set_state(_gadget, USB_STATE_POWERED); ++ usb_udc_vbus_handler(_gadget, true); ++ } else { ++ usb_udc_vbus_handler(_gadget, false); ++ if (ci->driver) ++ ci->driver->disconnect(&ci->gadget); ++ hw_device_state(ci, 0); ++ if (ci->platdata->notify_event) ++ ci->platdata->notify_event(ci, ++ CI_HDRC_CONTROLLER_STOPPED_EVENT); ++ _gadget_stop_activity(&ci->gadget); ++ pm_runtime_put_sync(&_gadget->dev); ++ usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED); ++ } ++} ++ + static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + { + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); +@@ -1549,26 +1576,8 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + usb_phy_set_charger_state(ci->usb_phy, is_active ? + USB_CHARGER_PRESENT : USB_CHARGER_ABSENT); + +- if (gadget_ready) { +- if (is_active) { +- pm_runtime_get_sync(&_gadget->dev); +- hw_device_reset(ci); +- hw_device_state(ci, ci->ep0out->qh.dma); +- usb_gadget_set_state(_gadget, USB_STATE_POWERED); +- usb_udc_vbus_handler(_gadget, true); +- } else { +- usb_udc_vbus_handler(_gadget, false); +- if (ci->driver) +- ci->driver->disconnect(&ci->gadget); +- hw_device_state(ci, 0); +- if (ci->platdata->notify_event) +- ci->platdata->notify_event(ci, +- CI_HDRC_CONTROLLER_STOPPED_EVENT); +- _gadget_stop_activity(&ci->gadget); +- pm_runtime_put_sync(&_gadget->dev); +- usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED); +- } +- } ++ if (gadget_ready) ++ ci_hdrc_gadget_connect(_gadget, is_active); + + return 0; + } +@@ -1794,18 +1803,10 @@ static int ci_udc_start(struct usb_gadget *gadget, + return retval; + } + +- pm_runtime_get_sync(&ci->gadget.dev); +- if (ci->vbus_active) { +- hw_device_reset(ci); +- } else { ++ if (ci->vbus_active) ++ ci_hdrc_gadget_connect(gadget, 1); ++ else + usb_udc_vbus_handler(&ci->gadget, false); +- pm_runtime_put_sync(&ci->gadget.dev); +- return retval; +- } +- +- retval = hw_device_state(ci, ci->ep0out->qh.dma); +- if (retval) +- pm_runtime_put_sync(&ci->gadget.dev); + + return retval; + } +-- +2.39.5 + diff --git a/queue-5.4/usb-chipidea-udc-protect-usb-interrupt-enable.patch b/queue-5.4/usb-chipidea-udc-protect-usb-interrupt-enable.patch new file mode 100644 index 0000000000..13e85c5479 --- /dev/null +++ b/queue-5.4/usb-chipidea-udc-protect-usb-interrupt-enable.patch @@ -0,0 +1,97 @@ +From 9c86d1b2d5376f748ca9da958a7b8449abd96f7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Sep 2019 14:54:57 +0800 +Subject: usb: chipidea: udc: protect usb interrupt enable + +From: Jun Li + +[ Upstream commit 72dc8df7920fc24eba0f586c56e900a1643ff2b3 ] + +We hit the problem with below sequence: +- ci_udc_vbus_session() update vbus_active flag and ci->driver +is valid, +- before calling the ci_hdrc_gadget_connect(), +usb_gadget_udc_stop() is called by application remove gadget +driver, +- ci_udc_vbus_session() will contine do ci_hdrc_gadget_connect() as +gadget_ready is 1, so udc interrupt is enabled, but ci->driver is +NULL. +- USB connection irq generated but ci->driver is NULL. + +As udc irq only should be enabled when gadget driver is binded, so +add spinlock to protect the usb irq enable for vbus session handling. + +Signed-off-by: Jun Li +Signed-off-by: Peter Chen +Stable-dep-of: b7a62611fab7 ("usb: chipidea: add USB PHY event") +Signed-off-by: Sasha Levin +--- + drivers/usb/chipidea/udc.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c +index e9ef6271e20d..9212c3842a1b 100644 +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1539,13 +1539,18 @@ static const struct usb_ep_ops usb_ep_ops = { + static void ci_hdrc_gadget_connect(struct usb_gadget *_gadget, int is_active) + { + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); ++ unsigned long flags; + + if (is_active) { + pm_runtime_get_sync(&_gadget->dev); + hw_device_reset(ci); +- hw_device_state(ci, ci->ep0out->qh.dma); +- usb_gadget_set_state(_gadget, USB_STATE_POWERED); +- usb_udc_vbus_handler(_gadget, true); ++ spin_lock_irqsave(&ci->lock, flags); ++ if (ci->driver) { ++ hw_device_state(ci, ci->ep0out->qh.dma); ++ usb_gadget_set_state(_gadget, USB_STATE_POWERED); ++ usb_udc_vbus_handler(_gadget, true); ++ } ++ spin_unlock_irqrestore(&ci->lock, flags); + } else { + usb_udc_vbus_handler(_gadget, false); + if (ci->driver) +@@ -1564,19 +1569,16 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) + { + struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); + unsigned long flags; +- int gadget_ready = 0; + + spin_lock_irqsave(&ci->lock, flags); + ci->vbus_active = is_active; +- if (ci->driver) +- gadget_ready = 1; + spin_unlock_irqrestore(&ci->lock, flags); + + if (ci->usb_phy) + usb_phy_set_charger_state(ci->usb_phy, is_active ? + USB_CHARGER_PRESENT : USB_CHARGER_ABSENT); + +- if (gadget_ready) ++ if (ci->driver) + ci_hdrc_gadget_connect(_gadget, is_active); + + return 0; +@@ -1836,6 +1838,7 @@ static int ci_udc_stop(struct usb_gadget *gadget) + unsigned long flags; + + spin_lock_irqsave(&ci->lock, flags); ++ ci->driver = NULL; + + if (ci->vbus_active) { + hw_device_state(ci, 0); +@@ -1848,7 +1851,6 @@ static int ci_udc_stop(struct usb_gadget *gadget) + pm_runtime_put(&ci->gadget.dev); + } + +- ci->driver = NULL; + spin_unlock_irqrestore(&ci->lock, flags); + + ci_udc_stop_for_otg_fsm(ci); +-- +2.39.5 + diff --git a/queue-5.4/usb-phy-mxs-disconnect-line-when-usb-charger-is-atta.patch b/queue-5.4/usb-phy-mxs-disconnect-line-when-usb-charger-is-atta.patch new file mode 100644 index 0000000000..08083c4047 --- /dev/null +++ b/queue-5.4/usb-phy-mxs-disconnect-line-when-usb-charger-is-atta.patch @@ -0,0 +1,48 @@ +From 65d942627e1dd8fc9b8f28720e1c006bffbb3b7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Jun 2023 19:03:53 +0800 +Subject: usb: phy: mxs: disconnect line when USB charger is attached + +From: Xu Yang + +[ Upstream commit 87ed257acb0934e08644568df6495988631afd4c ] + +For mxs PHY, if there is a vbus but the bus is not enumerated, we need +to force the dp/dm as SE0 from the controller side. If not, there is +possible USB wakeup due to unstable dp/dm, since there is possible no +pull on dp/dm, such as there is a USB charger on the port. + +Signed-off-by: Xu Yang +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/20230627110353.1879477-3-xu.yang_2@nxp.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/phy/phy-mxs-usb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c +index 6dfecbd47d7a..7c81ccaaf2e9 100644 +--- a/drivers/usb/phy/phy-mxs-usb.c ++++ b/drivers/usb/phy/phy-mxs-usb.c +@@ -394,6 +394,7 @@ static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy) + static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on) + { + bool vbus_is_on = false; ++ enum usb_phy_events last_event = mxs_phy->phy.last_event; + + /* If the SoCs don't need to disconnect line without vbus, quit */ + if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS)) +@@ -405,7 +406,8 @@ static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on) + + vbus_is_on = mxs_phy_get_vbus_status(mxs_phy); + +- if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy)) ++ if (on && ((!vbus_is_on && !mxs_phy_is_otg_host(mxs_phy)) ++ || (last_event == USB_EVENT_VBUS))) + __mxs_phy_disconnect_line(mxs_phy, true); + else + __mxs_phy_disconnect_line(mxs_phy, false); +-- +2.39.5 + -- 2.47.2