* [PATCH AUTOSEL 6.6 02/18] thunderbolt: Apply USB 3.x bandwidth quirk only in software connection manager
[not found] <20231107232231.3775605-1-sashal@kernel.org>
@ 2023-11-07 23:21 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 07/18] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Sasha Levin
` (6 subsequent siblings)
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:21 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Mika Westerberg, Sasha Levin, andreas.noever, michael.jamet,
YehezkelShB, linux-usb
From: Mika Westerberg <mika.westerberg@linux.intel.com>
[ Upstream commit 0c35ac18256942e66d8dab6ca049185812e60c69 ]
This is not needed when firmware connection manager is run so limit this
to software connection manager.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/thunderbolt/quirks.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c
index 488138a28ae13..e6bfa63b40aee 100644
--- a/drivers/thunderbolt/quirks.c
+++ b/drivers/thunderbolt/quirks.c
@@ -31,6 +31,9 @@ static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
{
struct tb_port *port;
+ if (tb_switch_is_icm(sw))
+ return;
+
tb_switch_for_each_port(sw, port) {
if (!tb_port_is_usb3_down(port))
continue;
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 07/18] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
[not found] <20231107232231.3775605-1-sashal@kernel.org>
2023-11-07 23:21 ` [PATCH AUTOSEL 6.6 02/18] thunderbolt: Apply USB 3.x bandwidth quirk only in software connection manager Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 08/18] usb: pci-quirks: group AMD specific quirk code together Sasha Levin
` (5 subsequent siblings)
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Stanley Chang, Thinh Nguyen, Greg Kroah-Hartman, Sasha Levin,
linux-usb
From: Stanley Chang <stanley_chang@realtek.com>
[ Upstream commit e72fc8d6a12af7ae8dd1b52cf68ed68569d29f80 ]
In Synopsys's dwc3 data book:
To avoid underrun and overrun during the burst, in a high-latency bus
system (like USB), threshold and burst size control is provided through
GTXTHRCFG and GRXTHRCFG registers.
In Realtek DHC SoC, DWC3 USB 3.0 uses AHB system bus. When dwc3 is
connected with USB 2.5G Ethernet, there will be overrun problem.
Therefore, setting TX/RX thresholds can avoid this issue.
Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20230912041904.30721-1-stanley_chang@realtek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/dwc3/core.c | 160 +++++++++++++++++++++++++++++++---------
drivers/usb/dwc3/core.h | 13 ++++
2 files changed, 137 insertions(+), 36 deletions(-)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 343d2570189ff..d25490965b27f 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1094,6 +1094,111 @@ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
}
}
+static void dwc3_config_threshold(struct dwc3 *dwc)
+{
+ u32 reg;
+ u8 rx_thr_num;
+ u8 rx_maxburst;
+ u8 tx_thr_num;
+ u8 tx_maxburst;
+
+ /*
+ * Must config both number of packets and max burst settings to enable
+ * RX and/or TX threshold.
+ */
+ if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
+ rx_thr_num = dwc->rx_thr_num_pkt_prd;
+ rx_maxburst = dwc->rx_max_burst_prd;
+ tx_thr_num = dwc->tx_thr_num_pkt_prd;
+ tx_maxburst = dwc->tx_max_burst_prd;
+
+ if (rx_thr_num && rx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+ reg |= DWC31_RXTHRNUMPKTSEL_PRD;
+
+ reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
+ reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
+
+ reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
+ reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+ reg |= DWC31_TXTHRNUMPKTSEL_PRD;
+
+ reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
+ reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
+
+ reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
+ reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+ }
+ }
+
+ rx_thr_num = dwc->rx_thr_num_pkt;
+ rx_maxburst = dwc->rx_max_burst;
+ tx_thr_num = dwc->tx_thr_num_pkt;
+ tx_maxburst = dwc->tx_max_burst;
+
+ if (DWC3_IP_IS(DWC3)) {
+ if (rx_thr_num && rx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+ reg |= DWC3_GRXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC3_GRXTHRCFG_RXPKTCNT(~0);
+ reg |= DWC3_GRXTHRCFG_RXPKTCNT(rx_thr_num);
+
+ reg &= ~DWC3_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+ reg |= DWC3_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+ reg |= DWC3_GTXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0);
+ reg |= DWC3_GTXTHRCFG_TXPKTCNT(tx_thr_num);
+
+ reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+ reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+ }
+ } else {
+ if (rx_thr_num && rx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+ reg |= DWC31_GRXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC31_GRXTHRCFG_RXPKTCNT(~0);
+ reg |= DWC31_GRXTHRCFG_RXPKTCNT(rx_thr_num);
+
+ reg &= ~DWC31_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+ reg |= DWC31_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+ reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+ reg |= DWC31_GTXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC31_GTXTHRCFG_TXPKTCNT(~0);
+ reg |= DWC31_GTXTHRCFG_TXPKTCNT(tx_thr_num);
+
+ reg &= ~DWC31_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+ reg |= DWC31_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+ dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+ }
+ }
+}
+
/**
* dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure
@@ -1246,42 +1351,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}
- /*
- * Must config both number of packets and max burst settings to enable
- * RX and/or TX threshold.
- */
- if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
- u8 rx_thr_num = dwc->rx_thr_num_pkt_prd;
- u8 rx_maxburst = dwc->rx_max_burst_prd;
- u8 tx_thr_num = dwc->tx_thr_num_pkt_prd;
- u8 tx_maxburst = dwc->tx_max_burst_prd;
-
- if (rx_thr_num && rx_maxburst) {
- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
- reg |= DWC31_RXTHRNUMPKTSEL_PRD;
-
- reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
- reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
-
- reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
- reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
-
- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
- }
-
- if (tx_thr_num && tx_maxburst) {
- reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
- reg |= DWC31_TXTHRNUMPKTSEL_PRD;
-
- reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
- reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
-
- reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
- reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
-
- dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
- }
- }
+ dwc3_config_threshold(dwc);
return 0;
@@ -1417,6 +1487,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 lpm_nyet_threshold;
u8 tx_de_emphasis;
u8 hird_threshold;
+ u8 rx_thr_num_pkt = 0;
+ u8 rx_max_burst = 0;
+ u8 tx_thr_num_pkt = 0;
+ u8 tx_max_burst = 0;
u8 rx_thr_num_pkt_prd = 0;
u8 rx_max_burst_prd = 0;
u8 tx_thr_num_pkt_prd = 0;
@@ -1479,6 +1553,14 @@ static void dwc3_get_properties(struct dwc3 *dwc)
"snps,usb2-lpm-disable");
dwc->usb2_gadget_lpm_disable = device_property_read_bool(dev,
"snps,usb2-gadget-lpm-disable");
+ device_property_read_u8(dev, "snps,rx-thr-num-pkt",
+ &rx_thr_num_pkt);
+ device_property_read_u8(dev, "snps,rx-max-burst",
+ &rx_max_burst);
+ device_property_read_u8(dev, "snps,tx-thr-num-pkt",
+ &tx_thr_num_pkt);
+ device_property_read_u8(dev, "snps,tx-max-burst",
+ &tx_max_burst);
device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
&rx_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,rx-max-burst-prd",
@@ -1560,6 +1642,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->hird_threshold = hird_threshold;
+ dwc->rx_thr_num_pkt = rx_thr_num_pkt;
+ dwc->rx_max_burst = rx_max_burst;
+
+ dwc->tx_thr_num_pkt = tx_thr_num_pkt;
+ dwc->tx_max_burst = tx_max_burst;
+
dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd;
dwc->rx_max_burst_prd = rx_max_burst_prd;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index a69ac67d89fe6..6782ec8bfd64c 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -211,6 +211,11 @@
#define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24)
#define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29)
+/* Global TX Threshold Configuration Register */
+#define DWC3_GTXTHRCFG_MAXTXBURSTSIZE(n) (((n) & 0xff) << 16)
+#define DWC3_GTXTHRCFG_TXPKTCNT(n) (((n) & 0xf) << 24)
+#define DWC3_GTXTHRCFG_PKTCNTSEL BIT(29)
+
/* Global RX Threshold Configuration Register for DWC_usb31 only */
#define DWC31_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 16)
#define DWC31_GRXTHRCFG_RXPKTCNT(n) (((n) & 0x1f) << 21)
@@ -1045,6 +1050,10 @@ struct dwc3_scratchpad_array {
* @test_mode_nr: test feature selector
* @lpm_nyet_threshold: LPM NYET response threshold
* @hird_threshold: HIRD threshold
+ * @rx_thr_num_pkt: USB receive packet count
+ * @rx_max_burst: max USB receive burst size
+ * @tx_thr_num_pkt: USB transmit packet count
+ * @tx_max_burst: max USB transmit burst size
* @rx_thr_num_pkt_prd: periodic ESS receive packet count
* @rx_max_burst_prd: max periodic ESS receive burst size
* @tx_thr_num_pkt_prd: periodic ESS transmit packet count
@@ -1273,6 +1282,10 @@ struct dwc3 {
u8 test_mode_nr;
u8 lpm_nyet_threshold;
u8 hird_threshold;
+ u8 rx_thr_num_pkt;
+ u8 rx_max_burst;
+ u8 tx_thr_num_pkt;
+ u8 tx_max_burst;
u8 rx_thr_num_pkt_prd;
u8 rx_max_burst_prd;
u8 tx_thr_num_pkt_prd;
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 08/18] usb: pci-quirks: group AMD specific quirk code together
[not found] <20231107232231.3775605-1-sashal@kernel.org>
2023-11-07 23:21 ` [PATCH AUTOSEL 6.6 02/18] thunderbolt: Apply USB 3.x bandwidth quirk only in software connection manager Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 07/18] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 09/18] usb: pci-quirks: handle HAS_IOPORT dependency for AMD quirk Sasha Levin
` (4 subsequent siblings)
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Niklas Schnelle, Arnd Bergmann, Greg Kroah-Hartman, Sasha Levin,
mathias.nyman, linux-usb
From: Niklas Schnelle <schnelle@linux.ibm.com>
[ Upstream commit 7ca9f9ba8aa7380dee5dd8346b57bbaf198b075a ]
A follow on patch will introduce CONFIG_USB_PCI_AMD governing the AMD
quirk and adding its compile time dependency on HAS_IOPORT. In order to
minimize the number of #ifdefs in C files and make that patch easier
to read first group the code together. This is pure code movement
no functional change is intended.
Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Link: https://lore.kernel.org/r/20230911125653.1393895-2-schnelle@linux.ibm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/host/pci-quirks.c | 119 +++++++++++++++++-----------------
drivers/usb/host/pci-quirks.h | 14 ++--
2 files changed, 68 insertions(+), 65 deletions(-)
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 2665832f9addf..5e06fad82a228 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -60,6 +60,22 @@
#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
+/* ASMEDIA quirk use */
+#define ASMT_DATA_WRITE0_REG 0xF8
+#define ASMT_DATA_WRITE1_REG 0xFC
+#define ASMT_CONTROL_REG 0xE0
+#define ASMT_CONTROL_WRITE_BIT 0x02
+#define ASMT_WRITEREG_CMD 0x10423
+#define ASMT_FLOWCTL_ADDR 0xFA30
+#define ASMT_FLOWCTL_DATA 0xBA
+#define ASMT_PSEUDO_DATA 0
+
+/* Intel quirk use */
+#define USB_INTEL_XUSB2PR 0xD0
+#define USB_INTEL_USB2PRM 0xD4
+#define USB_INTEL_USB3_PSSEN 0xD8
+#define USB_INTEL_USB3PRM 0xDC
+
/* AMD quirk use */
#define AB_REG_BAR_LOW 0xe0
#define AB_REG_BAR_HIGH 0xe1
@@ -93,21 +109,6 @@
#define NB_PIF0_PWRDOWN_0 0x01100012
#define NB_PIF0_PWRDOWN_1 0x01100013
-#define USB_INTEL_XUSB2PR 0xD0
-#define USB_INTEL_USB2PRM 0xD4
-#define USB_INTEL_USB3_PSSEN 0xD8
-#define USB_INTEL_USB3PRM 0xDC
-
-/* ASMEDIA quirk use */
-#define ASMT_DATA_WRITE0_REG 0xF8
-#define ASMT_DATA_WRITE1_REG 0xFC
-#define ASMT_CONTROL_REG 0xE0
-#define ASMT_CONTROL_WRITE_BIT 0x02
-#define ASMT_WRITEREG_CMD 0x10423
-#define ASMT_FLOWCTL_ADDR 0xFA30
-#define ASMT_FLOWCTL_DATA 0xBA
-#define ASMT_PSEUDO_DATA 0
-
/*
* amd_chipset_gen values represent AMD different chipset generations
*/
@@ -458,50 +459,6 @@ void usb_amd_quirk_pll_disable(void)
}
EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
-static int usb_asmedia_wait_write(struct pci_dev *pdev)
-{
- unsigned long retry_count;
- unsigned char value;
-
- for (retry_count = 1000; retry_count > 0; --retry_count) {
-
- pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
-
- if (value == 0xff) {
- dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
- return -EIO;
- }
-
- if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
- return 0;
-
- udelay(50);
- }
-
- dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
- return -ETIMEDOUT;
-}
-
-void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
-{
- if (usb_asmedia_wait_write(pdev) != 0)
- return;
-
- /* send command and address to device */
- pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
- pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
- pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
-
- if (usb_asmedia_wait_write(pdev) != 0)
- return;
-
- /* send data to device */
- pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
- pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
- pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
-}
-EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
-
void usb_amd_quirk_pll_enable(void)
{
usb_amd_quirk_pll(0);
@@ -631,6 +588,50 @@ bool usb_amd_pt_check_port(struct device *device, int port)
}
EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);
+static int usb_asmedia_wait_write(struct pci_dev *pdev)
+{
+ unsigned long retry_count;
+ unsigned char value;
+
+ for (retry_count = 1000; retry_count > 0; --retry_count) {
+
+ pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
+
+ if (value == 0xff) {
+ dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
+ return -EIO;
+ }
+
+ if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
+ return 0;
+
+ udelay(50);
+ }
+
+ dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
+ return -ETIMEDOUT;
+}
+
+void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
+{
+ if (usb_asmedia_wait_write(pdev) != 0)
+ return;
+
+ /* send command and address to device */
+ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
+ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
+ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+
+ if (usb_asmedia_wait_write(pdev) != 0)
+ return;
+
+ /* send data to device */
+ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
+ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
+ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+}
+EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
+
/*
* Make sure the controller is completely inactive, unable to
* generate interrupts or do DMA.
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index e729de21fad7a..cde2263a9d2e4 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -3,8 +3,6 @@
#define __LINUX_USB_PCI_QUIRKS_H
#ifdef CONFIG_USB_PCI
-void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
bool usb_amd_hang_symptom_quirk(void);
bool usb_amd_prefetch_quirk(void);
@@ -12,23 +10,27 @@ void usb_amd_dev_put(void);
bool usb_amd_quirk_pll_check(void);
void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
+void sb800_prefetch(struct device *dev, int on);
+bool usb_amd_pt_check_port(struct device *device, int port);
+
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
-void sb800_prefetch(struct device *dev, int on);
-bool usb_amd_pt_check_port(struct device *device, int port);
#else
struct pci_dev;
static inline void usb_amd_quirk_pll_disable(void) {}
static inline void usb_amd_quirk_pll_enable(void) {}
-static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
static inline void usb_amd_dev_put(void) {}
-static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
static inline void sb800_prefetch(struct device *dev, int on) {}
static inline bool usb_amd_pt_check_port(struct device *device, int port)
{
return false;
}
+
+static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
+static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
#endif /* CONFIG_USB_PCI */
#endif /* __LINUX_USB_PCI_QUIRKS_H */
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 09/18] usb: pci-quirks: handle HAS_IOPORT dependency for AMD quirk
[not found] <20231107232231.3775605-1-sashal@kernel.org>
` (2 preceding siblings ...)
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 08/18] usb: pci-quirks: group AMD specific quirk code together Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 10/18] usb: pci-quirks: handle HAS_IOPORT dependency for UHCI handoff Sasha Levin
` (3 subsequent siblings)
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Niklas Schnelle, Arnd Bergmann, Greg Kroah-Hartman, Sasha Levin,
mathias.nyman, stern, Basavaraj.Natikar, linux-usb
From: Niklas Schnelle <schnelle@linux.ibm.com>
[ Upstream commit 52e24f8c0a102ac76649c6b71224fadcc82bd5da ]
In a future patch HAS_IOPORT=n will result in inb()/outb() and friends
not being declared. In the pci-quirks case the I/O port acceses are
used in the quirks for several AMD south bridges, Add a config option
for the AMD quirks to depend on HAS_IOPORT and #ifdef the quirk code.
Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Link: https://lore.kernel.org/r/20230911125653.1393895-3-schnelle@linux.ibm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/Kconfig | 10 ++++++++++
drivers/usb/core/hcd-pci.c | 3 +--
drivers/usb/host/pci-quirks.c | 2 ++
drivers/usb/host/pci-quirks.h | 30 ++++++++++++++++++++++--------
include/linux/usb/hcd.h | 17 +++++++++++++++++
5 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 7f33bcc315f27..abf8c6cdea9ea 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -91,6 +91,16 @@ config USB_PCI
If you have such a device you may say N here and PCI related code
will not be built in the USB driver.
+config USB_PCI_AMD
+ bool "AMD PCI USB host support"
+ depends on USB_PCI && HAS_IOPORT
+ default X86 || MACH_LOONGSON64 || PPC_PASEMI
+ help
+ Enable workarounds for USB implementation quirks in SB600/SB700/SB800
+ and later south bridge implementations. These are common on x86 PCs
+ with AMD CPUs but rarely used elsewhere, with the exception of a few
+ powerpc and mips desktop machines.
+
if USB
source "drivers/usb/core/Kconfig"
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 990280688b254..ee3156f495338 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -206,8 +206,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct hc_driver *driver)
goto free_irq_vectors;
}
- hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
- driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0;
+ hcd->amd_resume_bug = usb_hcd_amd_resume_bug(dev, driver);
if (driver->flags & HCD_MEMORY) {
/* EHCI, OHCI */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 5e06fad82a228..10813096d00c6 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -76,6 +76,7 @@
#define USB_INTEL_USB3_PSSEN 0xD8
#define USB_INTEL_USB3PRM 0xDC
+#ifdef CONFIG_USB_PCI_AMD
/* AMD quirk use */
#define AB_REG_BAR_LOW 0xe0
#define AB_REG_BAR_HIGH 0xe1
@@ -587,6 +588,7 @@ bool usb_amd_pt_check_port(struct device *device, int port)
return !(value & BIT(port_shift));
}
EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);
+#endif /* CONFIG_USB_PCI_AMD */
static int usb_asmedia_wait_write(struct pci_dev *pdev)
{
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index cde2263a9d2e4..a5230b0b9e913 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -2,7 +2,7 @@
#ifndef __LINUX_USB_PCI_QUIRKS_H
#define __LINUX_USB_PCI_QUIRKS_H
-#ifdef CONFIG_USB_PCI
+#ifdef CONFIG_USB_PCI_AMD
int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
bool usb_amd_hang_symptom_quirk(void);
bool usb_amd_prefetch_quirk(void);
@@ -12,23 +12,37 @@ void usb_amd_quirk_pll_disable(void);
void usb_amd_quirk_pll_enable(void);
void sb800_prefetch(struct device *dev, int on);
bool usb_amd_pt_check_port(struct device *device, int port);
-
-void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
-int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
-void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
-void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
#else
-struct pci_dev;
+static inline bool usb_amd_hang_symptom_quirk(void)
+{
+ return false;
+};
+static inline bool usb_amd_prefetch_quirk(void)
+{
+ return false;
+}
static inline void usb_amd_quirk_pll_disable(void) {}
static inline void usb_amd_quirk_pll_enable(void) {}
static inline void usb_amd_dev_put(void) {}
+static inline bool usb_amd_quirk_pll_check(void)
+{
+ return false;
+}
static inline void sb800_prefetch(struct device *dev, int on) {}
static inline bool usb_amd_pt_check_port(struct device *device, int port)
{
return false;
}
+#endif /* CONFIG_USB_PCI_AMD */
+#ifdef CONFIG_USB_PCI
+void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
+void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+#else
+struct pci_dev;
static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
#endif /* CONFIG_USB_PCI */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 61d4f0b793dcd..00724b4f6e122 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -484,8 +484,25 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
extern void usb_hcd_pci_remove(struct pci_dev *dev);
extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
+#ifdef CONFIG_USB_PCI_AMD
extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
+static inline bool usb_hcd_amd_resume_bug(struct pci_dev *dev,
+ const struct hc_driver *driver)
+{
+ if (!usb_hcd_amd_remote_wakeup_quirk(dev))
+ return false;
+ if (driver->flags & (HCD_USB11 | HCD_USB3))
+ return true;
+ return false;
+}
+#else /* CONFIG_USB_PCI_AMD */
+static inline bool usb_hcd_amd_resume_bug(struct pci_dev *dev,
+ const struct hc_driver *driver)
+{
+ return false;
+}
+#endif
extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
#endif /* CONFIG_USB_PCI */
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 10/18] usb: pci-quirks: handle HAS_IOPORT dependency for UHCI handoff
[not found] <20231107232231.3775605-1-sashal@kernel.org>
` (3 preceding siblings ...)
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 09/18] usb: pci-quirks: handle HAS_IOPORT dependency for AMD quirk Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 11/18] usb: ucsi: glink: use the connector orientation GPIO to provide switch events Sasha Levin
` (2 subsequent siblings)
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Niklas Schnelle, Arnd Bergmann, Greg Kroah-Hartman, Sasha Levin,
mathias.nyman, linux-usb
From: Niklas Schnelle <schnelle@linux.ibm.com>
[ Upstream commit 358ad297e379ff548247e3e24c6619559942bfdd ]
In a future patch HAS_IOPORT=n will result in inb()/outb() and friends
not being declared. With the AMD quirk handled USB PCI quirks still use
inw() in uhci_check_and_reset_hc() and thus indirectly in
quirk_usb_handoff_uhci(). Handle this by conditionally compiling
uhci_check_and_reset_hc() and stubbing out quirk_usb_handoff_uhci() when
HAS_IOPORT is not available.
Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Link: https://lore.kernel.org/r/20230911125653.1393895-4-schnelle@linux.ibm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/host/pci-quirks.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 10813096d00c6..1f9c1b1435d86 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -634,6 +634,16 @@ void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
+static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
+{
+ u16 cmd;
+
+ return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
+}
+
+#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
+
+#if defined(CONFIG_HAS_IOPORT) && IS_ENABLED(CONFIG_USB_UHCI_HCD)
/*
* Make sure the controller is completely inactive, unable to
* generate interrupts or do DMA.
@@ -715,14 +725,7 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
}
EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
-static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
-{
- u16 cmd;
- return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
-}
-
#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
-#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
{
@@ -742,6 +745,12 @@ static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
uhci_check_and_reset_hc(pdev, base);
}
+#else /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */
+
+static void quirk_usb_handoff_uhci(struct pci_dev *pdev) {}
+
+#endif /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */
+
static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
{
return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 11/18] usb: ucsi: glink: use the connector orientation GPIO to provide switch events
[not found] <20231107232231.3775605-1-sashal@kernel.org>
` (4 preceding siblings ...)
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 10/18] usb: pci-quirks: handle HAS_IOPORT dependency for UHCI handoff Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 15/18] usb: host: xhci: Avoid XHCI resume delay if SSUSB device is not present Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 16/18] usb: gadget: f_ncm: Always set current gadget in ncm_bind() Sasha Levin
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Neil Armstrong, Heikki Krogerus, Dmitry Baryshkov, Konrad Dybcio,
Greg Kroah-Hartman, Sasha Levin, minhuadotchen, robh, linux-usb
From: Neil Armstrong <neil.armstrong@linaro.org>
[ Upstream commit c6165ed2f425c273244191930a47c8be23bc51bd ]
On SM8550, the non-altmode orientation is not given anymore within
altmode events, even with USB SVIDs events.
On the other side, the Type-C connector orientation is correctly
reported by a signal from the PMIC.
Take this gpio signal when we detect some Type-C port activity
to notify any Type-C switches tied to the Type-C port connectors.
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Acked-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20231002-topic-sm8550-upstream-type-c-orientation-v2-2-125410d3ff95@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/typec/ucsi/ucsi_glink.c | 54 ++++++++++++++++++++++++++++-
1 file changed, 53 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index bb1854b3311dc..db6e248f82083 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -8,9 +8,13 @@
#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/soc/qcom/pdr.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/gpio/consumer.h>
#include <linux/soc/qcom/pmic_glink.h>
#include "ucsi.h"
+#define PMIC_GLINK_MAX_PORTS 2
+
#define UCSI_BUF_SIZE 48
#define MSG_TYPE_REQ_RESP 1
@@ -52,6 +56,9 @@ struct ucsi_notify_ind_msg {
struct pmic_glink_ucsi {
struct device *dev;
+ struct gpio_desc *port_orientation[PMIC_GLINK_MAX_PORTS];
+ struct typec_switch *port_switch[PMIC_GLINK_MAX_PORTS];
+
struct pmic_glink_client *client;
struct ucsi *ucsi;
@@ -220,8 +227,20 @@ static void pmic_glink_ucsi_notify(struct work_struct *work)
}
con_num = UCSI_CCI_CONNECTOR(cci);
- if (con_num)
+ if (con_num) {
+ if (con_num < PMIC_GLINK_MAX_PORTS &&
+ ucsi->port_orientation[con_num - 1]) {
+ int orientation = gpiod_get_value(ucsi->port_orientation[con_num - 1]);
+
+ if (orientation >= 0) {
+ typec_switch_set(ucsi->port_switch[con_num - 1],
+ orientation ? TYPEC_ORIENTATION_REVERSE
+ : TYPEC_ORIENTATION_NORMAL);
+ }
+ }
+
ucsi_connector_change(ucsi->ucsi, con_num);
+ }
if (ucsi->sync_pending && cci & UCSI_CCI_BUSY) {
ucsi->sync_val = -EBUSY;
@@ -282,6 +301,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
{
struct pmic_glink_ucsi *ucsi;
struct device *dev = &adev->dev;
+ struct fwnode_handle *fwnode;
int ret;
ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL);
@@ -309,6 +329,38 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ucsi_set_drvdata(ucsi->ucsi, ucsi);
+ device_for_each_child_node(dev, fwnode) {
+ struct gpio_desc *desc;
+ u32 port;
+
+ ret = fwnode_property_read_u32(fwnode, "reg", &port);
+ if (ret < 0) {
+ dev_err(dev, "missing reg property of %pOFn\n", fwnode);
+ return ret;
+ }
+
+ if (port >= PMIC_GLINK_MAX_PORTS) {
+ dev_warn(dev, "invalid connector number, ignoring\n");
+ continue;
+ }
+
+ desc = devm_gpiod_get_index_optional(&adev->dev, "orientation", port, GPIOD_IN);
+
+ /* If GPIO isn't found, continue */
+ if (!desc)
+ continue;
+
+ if (IS_ERR(desc))
+ return dev_err_probe(dev, PTR_ERR(desc),
+ "unable to acquire orientation gpio\n");
+ ucsi->port_orientation[port] = desc;
+
+ ucsi->port_switch[port] = fwnode_typec_switch_get(fwnode);
+ if (IS_ERR(ucsi->port_switch[port]))
+ return dev_err_probe(dev, PTR_ERR(ucsi->port_switch[port]),
+ "failed to acquire orientation-switch\n");
+ }
+
ucsi->client = devm_pmic_glink_register_client(dev,
PMIC_GLINK_OWNER_USBC,
pmic_glink_ucsi_callback,
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 15/18] usb: host: xhci: Avoid XHCI resume delay if SSUSB device is not present
[not found] <20231107232231.3775605-1-sashal@kernel.org>
` (5 preceding siblings ...)
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 11/18] usb: ucsi: glink: use the connector orientation GPIO to provide switch events Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 16/18] usb: gadget: f_ncm: Always set current gadget in ncm_bind() Sasha Levin
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Wesley Cheng, Mathias Nyman, Greg Kroah-Hartman, Sasha Levin,
mathias.nyman, linux-usb
From: Wesley Cheng <quic_wcheng@quicinc.com>
[ Upstream commit 6add6dd345cb754ce18ff992c7264cabf31e59f6 ]
There is a 120ms delay implemented for allowing the XHCI host controller to
detect a U3 wakeup pulse. The intention is to wait for the device to retry
the wakeup event if the USB3 PORTSC doesn't reflect the RESUME link status
by the time it is checked. As per the USB3 specification:
tU3WakeupRetryDelay ("Table 7-12. LTSSM State Transition Timeouts")
This would allow the XHCI resume sequence to determine if the root hub
needs to be also resumed. However, in case there is no device connected,
or if there is only a HSUSB device connected, this delay would still affect
the overall resume timing.
Since this delay is solely for detecting U3 wake events (USB3 specific)
then ignore this delay for the disconnected case and the HSUSB connected
only case.
[skip helper function, rename usb3_connected variable -Mathias ]
Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20231019102924.2797346-20-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/host/xhci.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e1b1b64a07232..132b76fa7ca60 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -968,6 +968,7 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
int retval = 0;
bool comp_timer_running = false;
bool pending_portevent = false;
+ bool suspended_usb3_devs = false;
bool reinit_xhc = false;
if (!hcd->state)
@@ -1115,10 +1116,17 @@ int xhci_resume(struct xhci_hcd *xhci, pm_message_t msg)
/*
* Resume roothubs only if there are pending events.
* USB 3 devices resend U3 LFPS wake after a 100ms delay if
- * the first wake signalling failed, give it that chance.
+ * the first wake signalling failed, give it that chance if
+ * there are suspended USB 3 devices.
*/
+ if (xhci->usb3_rhub.bus_state.suspended_ports ||
+ xhci->usb3_rhub.bus_state.bus_suspended)
+ suspended_usb3_devs = true;
+
pending_portevent = xhci_pending_portevent(xhci);
- if (!pending_portevent && msg.event == PM_EVENT_AUTO_RESUME) {
+
+ if (suspended_usb3_devs && !pending_portevent &&
+ msg.event == PM_EVENT_AUTO_RESUME) {
msleep(120);
pending_portevent = xhci_pending_portevent(xhci);
}
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH AUTOSEL 6.6 16/18] usb: gadget: f_ncm: Always set current gadget in ncm_bind()
[not found] <20231107232231.3775605-1-sashal@kernel.org>
` (6 preceding siblings ...)
2023-11-07 23:22 ` [PATCH AUTOSEL 6.6 15/18] usb: host: xhci: Avoid XHCI resume delay if SSUSB device is not present Sasha Levin
@ 2023-11-07 23:22 ` Sasha Levin
7 siblings, 0 replies; 8+ messages in thread
From: Sasha Levin @ 2023-11-07 23:22 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Hardik Gajjar, Greg Kroah-Hartman, Sasha Levin, quic_linyyuan,
maze, quic_kriskura, linux-usb
From: Hardik Gajjar <hgajjar@de.adit-jv.com>
[ Upstream commit a04224da1f3424b2c607b12a3bd1f0e302fb8231 ]
Previously, gadget assignment to the net device occurred exclusively
during the initial binding attempt.
Nevertheless, the gadget pointer could change during bind/unbind
cycles due to various conditions, including the unloading/loading
of the UDC device driver or the detachment/reconnection of an
OTG-capable USB hub device.
This patch relocates the gether_set_gadget() function out from
ncm_opts->bound condition check, ensuring that the correct gadget
is assigned during each bind request.
The provided logs demonstrate the consistency of ncm_opts throughout
the power cycle, while the gadget may change.
* OTG hub connected during boot up and assignment of gadget and
ncm_opts pointer
[ 2.366301] usb 2-1.5: New USB device found, idVendor=2996, idProduct=0105
[ 2.366304] usb 2-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2.366306] usb 2-1.5: Product: H2H Bridge
[ 2.366308] usb 2-1.5: Manufacturer: Aptiv
[ 2.366309] usb 2-1.5: SerialNumber: 13FEB2021
[ 2.427989] usb 2-1.5: New USB device found, VID=2996, PID=0105
[ 2.428959] dabridge 2-1.5:1.0: dabridge 2-4 total endpoints=5, 0000000093a8d681
[ 2.429710] dabridge 2-1.5:1.0: P(0105) D(22.06.22) F(17.3.16) H(1.1) high-speed
[ 2.429714] dabridge 2-1.5:1.0: Hub 2-2 P(0151) V(06.87)
[ 2.429956] dabridge 2-1.5:1.0: All downstream ports in host mode
[ 2.430093] gadget 000000003c414d59 ------> gadget pointer
* NCM opts and associated gadget pointer during First ncm_bind
[ 34.763929] NCM opts 00000000aa304ac9
[ 34.763930] NCM gadget 000000003c414d59
* OTG capable hub disconnecte or assume driver unload.
[ 97.203114] usb 2-1: USB disconnect, device number 2
[ 97.203118] usb 2-1.1: USB disconnect, device number 3
[ 97.209217] usb 2-1.5: USB disconnect, device number 4
[ 97.230990] dabr_udc deleted
* Reconnect the OTG hub or load driver assaign new gadget pointer.
[ 111.534035] usb 2-1.1: New USB device found, idVendor=2996, idProduct=0120, bcdDevice= 6.87
[ 111.534038] usb 2-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 111.534040] usb 2-1.1: Product: Vendor
[ 111.534041] usb 2-1.1: Manufacturer: Aptiv
[ 111.534042] usb 2-1.1: SerialNumber: Superior
[ 111.535175] usb 2-1.1: New USB device found, VID=2996, PID=0120
[ 111.610995] usb 2-1.5: new high-speed USB device number 8 using xhci-hcd
[ 111.630052] usb 2-1.5: New USB device found, idVendor=2996, idProduct=0105, bcdDevice=21.02
[ 111.630055] usb 2-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 111.630057] usb 2-1.5: Product: H2H Bridge
[ 111.630058] usb 2-1.5: Manufacturer: Aptiv
[ 111.630059] usb 2-1.5: SerialNumber: 13FEB2021
[ 111.687464] usb 2-1.5: New USB device found, VID=2996, PID=0105
[ 111.690375] dabridge 2-1.5:1.0: dabridge 2-8 total endpoints=5, 000000000d87c961
[ 111.691172] dabridge 2-1.5:1.0: P(0105) D(22.06.22) F(17.3.16) H(1.1) high-speed
[ 111.691176] dabridge 2-1.5:1.0: Hub 2-6 P(0151) V(06.87)
[ 111.691646] dabridge 2-1.5:1.0: All downstream ports in host mode
[ 111.692298] gadget 00000000dc72f7a9 --------> new gadget ptr on connect
* NCM opts and associated gadget pointer during second ncm_bind
[ 113.271786] NCM opts 00000000aa304ac9 -----> same opts ptr used during first bind
[ 113.271788] NCM gadget 00000000dc72f7a9 ----> however new gaget ptr, that will not set
in net_device due to ncm_opts->bound = true
Signed-off-by: Hardik Gajjar <hgajjar@de.adit-jv.com>
Link: https://lore.kernel.org/r/20231020153324.82794-1-hgajjar@de.adit-jv.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/gadget/function/f_ncm.c | 27 +++++++++++----------------
1 file changed, 11 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index e6ab8cc225ffd..cc0ed29a4adc0 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1410,7 +1410,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev;
struct f_ncm *ncm = func_to_ncm(f);
struct usb_string *us;
- int status;
+ int status = 0;
struct usb_ep *ep;
struct f_ncm_opts *ncm_opts;
@@ -1428,22 +1428,17 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
f->os_desc_table[0].os_desc = &ncm_opts->ncm_os_desc;
}
- /*
- * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
- * configurations are bound in sequence with list_for_each_entry,
- * in each configuration its functions are bound in sequence
- * with list_for_each_entry, so we assume no race condition
- * with regard to ncm_opts->bound access
- */
- if (!ncm_opts->bound) {
- mutex_lock(&ncm_opts->lock);
- gether_set_gadget(ncm_opts->net, cdev->gadget);
+ mutex_lock(&ncm_opts->lock);
+ gether_set_gadget(ncm_opts->net, cdev->gadget);
+ if (!ncm_opts->bound)
status = gether_register_netdev(ncm_opts->net);
- mutex_unlock(&ncm_opts->lock);
- if (status)
- goto fail;
- ncm_opts->bound = true;
- }
+ mutex_unlock(&ncm_opts->lock);
+
+ if (status)
+ goto fail;
+
+ ncm_opts->bound = true;
+
us = usb_gstrings_attach(cdev, ncm_strings,
ARRAY_SIZE(ncm_string_defs));
if (IS_ERR(us)) {
--
2.42.0
^ permalink raw reply related [flat|nested] 8+ messages in thread