2023-05-08 13:28:07

by Weitao Wang

[permalink] [raw]
Subject: [PATCH v4 0/4] Fix some issues for ZHAOXIN xHCI host

Fix some issues for ZHAOXIN xHCI host.

Weitao Wang (4):
xhci: Fix resume issue of some ZHAOXIN hosts
xhci: Fix TRB prefetch issue of ZHAOXIN hosts
xhci: Show ZHAOXIN xHCI root hub speed correctly
xhci: Add ZHAOXIN xHCI host U1/U2 feature support

drivers/usb/host/xhci-mem.c | 38 ++++++++++++++++++++++++--------
drivers/usb/host/xhci-pci.c | 13 +++++++++++
drivers/usb/host/xhci.c | 43 ++++++++++++++++---------------------
drivers/usb/host/xhci.h | 2 ++
4 files changed, 62 insertions(+), 34 deletions(-)

--
2.32.0


2023-05-08 13:37:53

by Weitao Wang

[permalink] [raw]
Subject: [PATCH v4 4/4] xhci: Add ZHAOXIN xHCI host U1/U2 feature support

Add U1/U2 feature support of xHCI for ZHAOXIN.
Since both INTEL and ZHAOXIN need to check the tier where the device is
located to determine whether to enabled U1/U2, remove the previous INTEL
U1/U2 tier policy and add common policy in xhci_check_tier_policy.
If vendor has specific U1/U2 enable policy,quirks can be add to declare.

Suggested-by: Mathias Nyman <[email protected]>
Signed-off-by: Weitao Wang <[email protected]>
---
drivers/usb/host/xhci-pci.c | 1 +
drivers/usb/host/xhci.c | 43 ++++++++++++++++---------------------
2 files changed, 19 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 4a025ed50686..31f354352e57 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -529,6 +529,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)

if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
xhci->quirks |= XHCI_ZHAOXIN_HOST;
+ xhci->quirks |= XHCI_LPM_SUPPORT;

if (pdev->device == 0x9202) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 78790dc13c5f..cae57f0207a4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4604,7 +4604,7 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
}
}

- if (xhci->quirks & XHCI_INTEL_HOST)
+ if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
else
timeout_ns = udev->u1_params.sel;
@@ -4668,7 +4668,7 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
}
}

- if (xhci->quirks & XHCI_INTEL_HOST)
+ if (xhci->quirks & (XHCI_INTEL_HOST | XHCI_ZHAOXIN_HOST))
timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
else
timeout_ns = udev->u2_params.sel;
@@ -4740,37 +4740,30 @@ static int xhci_update_timeout_for_interface(struct xhci_hcd *xhci,
return 0;
}

-static int xhci_check_intel_tier_policy(struct usb_device *udev,
+static int xhci_check_tier_policy(struct xhci_hcd *xhci,
+ struct usb_device *udev,
enum usb3_link_state state)
{
- struct usb_device *parent;
- unsigned int num_hubs;
+ struct usb_device *parent = udev->parent;
+ int tier = 1; /* roothub is tier1 */

- /* Don't enable U1 if the device is on a 2nd tier hub or lower. */
- for (parent = udev->parent, num_hubs = 0; parent->parent;
- parent = parent->parent)
- num_hubs++;
+ while (parent) {
+ parent = parent->parent;
+ tier++;
+ }

- if (num_hubs < 2)
- return 0;
+ if (xhci->quirks & XHCI_INTEL_HOST && tier > 3)
+ goto fail;
+ if (xhci->quirks & XHCI_ZHAOXIN_HOST && tier > 2)
+ goto fail;

- dev_dbg(&udev->dev, "Disabling U1/U2 link state for device"
- " below second-tier hub.\n");
- dev_dbg(&udev->dev, "Plug device into first-tier hub "
- "to decrease power consumption.\n");
+ return 0;
+fail:
+ dev_dbg(&udev->dev, "Tier policy prevents U1/U2 LPM states for devices at tier %d\n",
+ tier);
return -E2BIG;
}

-static int xhci_check_tier_policy(struct xhci_hcd *xhci,
- struct usb_device *udev,
- enum usb3_link_state state)
-{
- if (xhci->quirks & XHCI_INTEL_HOST)
- return xhci_check_intel_tier_policy(udev, state);
- else
- return 0;
-}
-
/* Returns the U1 or U2 timeout that should be enabled.
* If the tier check or timeout setting functions return with a non-zero exit
* code, that means the timeout value has been finalized and we shouldn't look
--
2.32.0

2023-05-08 13:38:38

by Weitao Wang

[permalink] [raw]
Subject: [PATCH v4 2/4] xhci: Fix TRB prefetch issue of ZHAOXIN hosts

On some ZHAOXIN hosts, xHCI will prefetch TRB for performance
improvement. However this TRB prefetch mechanism may cross page boundary,
which may access memory not allocated by xHCI driver. In order to fix
this issue, two pages was allocated for a segment and only the first
page will be used. And add a quirk XHCI_ZHAOXIN_TRB_FETCH for this issue.

Cc: [email protected]
Signed-off-by: Weitao Wang <[email protected]>
---
drivers/usb/host/xhci-mem.c | 8 ++++++--
drivers/usb/host/xhci-pci.c | 7 ++++++-
drivers/usb/host/xhci.h | 1 +
3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 7e106bd804ca..1532414c8c40 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2352,8 +2352,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
* and our use of dma addresses in the trb_address_map radix tree needs
* TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
*/
- xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
- TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
+ if (xhci->quirks & XHCI_ZHAOXIN_TRB_FETCH)
+ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
+ TRB_SEGMENT_SIZE * 2, TRB_SEGMENT_SIZE * 2, xhci->page_size * 2);
+ else
+ xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
+ TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);

/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 46d4d642c9bd..3dfb3e0c910b 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -528,8 +528,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_NO_SOFT_RETRY;

if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
- if (pdev->device == 0x9202)
+ if (pdev->device == 0x9202) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
+ xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
+ }
+
+ if (pdev->device == 0x9203)
+ xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
}

/* xHC spec requires PCI devices to support D3hot and D3cold */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 08d721921b7b..41c38bfd7348 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1905,6 +1905,7 @@ struct xhci_hcd {
#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42)
#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)
#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
+#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)

unsigned int num_active_eps;
unsigned int limit_active_eps;
--
2.32.0

2023-05-08 13:39:22

by Weitao Wang

[permalink] [raw]
Subject: [PATCH v4 3/4] xhci: Show ZHAOXIN xHCI root hub speed correctly

Some ZHAOXIN xHCI controllers follow usb3.1 spec,
but only support gen1 speed 5Gbps. While in Linux kernel,
if xHCI suspport usb3.1, root hub speed will show on 10Gbps.
To fix this issue of ZHAOXIN xHCI platforms, read usb speed ID
supported by xHCI to determine root hub speed. And add a quirk
XHCI_ZHAOXIN_HOST for this issue.

Suggested-by: Mathias Nyman <[email protected]>
Cc: [email protected]
Signed-off-by: Weitao Wang <[email protected]>
---
drivers/usb/host/xhci-mem.c | 30 +++++++++++++++++++++++-------
drivers/usb/host/xhci-pci.c | 2 ++
drivers/usb/host/xhci.h | 1 +
3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1532414c8c40..0634fba01ac8 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1968,7 +1968,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
{
u32 temp, port_offset, port_count;
int i;
- u8 major_revision, minor_revision;
+ u8 major_revision, minor_revision, tmp_minor_revision;
struct xhci_hub *rhub;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
struct xhci_port_cap *port_cap;
@@ -1988,6 +1988,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
*/
if (minor_revision > 0x00 && minor_revision < 0x10)
minor_revision <<= 4;
+ /*
+ * Some zhaoxin's xHCI controller that follow usb3.1 spec
+ * but only support Gen1.
+ */
+ if (xhci->quirks & XHCI_ZHAOXIN_HOST) {
+ tmp_minor_revision = minor_revision;
+ minor_revision = 0;
+ }
+
} else if (major_revision <= 0x02) {
rhub = &xhci->usb2_rhub;
} else {
@@ -1996,10 +2005,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
/* Ignoring port protocol we can't understand. FIXME */
return;
}
- rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
-
- if (rhub->min_rev < minor_revision)
- rhub->min_rev = minor_revision;

/* Port offset and count in the third dword, see section 7.2 */
temp = readl(addr + 2);
@@ -2017,8 +2022,6 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
if (xhci->num_port_caps > max_caps)
return;

- port_cap->maj_rev = major_revision;
- port_cap->min_rev = minor_revision;
port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);

if (port_cap->psi_count) {
@@ -2039,6 +2042,10 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
port_cap->psi_uid_count++;

+ if (xhci->quirks & XHCI_ZHAOXIN_HOST &&
+ XHCI_EXT_PORT_PSIV(port_cap->psi[i]) >= 5)
+ minor_revision = tmp_minor_revision;
+
xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
@@ -2048,6 +2055,15 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
}
}
+
+ rhub->maj_rev = major_revision;
+
+ if (rhub->min_rev < minor_revision)
+ rhub->min_rev = minor_revision;
+
+ port_cap->maj_rev = major_revision;
+ port_cap->min_rev = minor_revision;
+
/* cache usb2 port capabilities */
if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
xhci->ext_caps[xhci->num_ext_caps++] = temp;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 3dfb3e0c910b..4a025ed50686 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -528,6 +528,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_NO_SOFT_RETRY;

if (pdev->vendor == PCI_VENDOR_ID_ZHAOXIN) {
+ xhci->quirks |= XHCI_ZHAOXIN_HOST;
+
if (pdev->device == 0x9202) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 41c38bfd7348..3737510b5981 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1906,6 +1906,7 @@ struct xhci_hcd {
#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43)
#define XHCI_RESET_TO_DEFAULT BIT_ULL(44)
#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45)
+#define XHCI_ZHAOXIN_HOST BIT_ULL(46)

unsigned int num_active_eps;
unsigned int limit_active_eps;
--
2.32.0

2023-05-09 08:14:03

by Mathias Nyman

[permalink] [raw]
Subject: Re: [PATCH v4 0/4] Fix some issues for ZHAOXIN xHCI host

On 9.5.2023 0.20, Weitao Wang wrote:
> Fix some issues for ZHAOXIN xHCI host.
>
> Weitao Wang (4):
> xhci: Fix resume issue of some ZHAOXIN hosts
> xhci: Fix TRB prefetch issue of ZHAOXIN hosts
> xhci: Show ZHAOXIN xHCI root hub speed correctly
> xhci: Add ZHAOXIN xHCI host U1/U2 feature support
>
> drivers/usb/host/xhci-mem.c | 38 ++++++++++++++++++++++++--------
> drivers/usb/host/xhci-pci.c | 13 +++++++++++
> drivers/usb/host/xhci.c | 43 ++++++++++++++++---------------------
> drivers/usb/host/xhci.h | 2 ++
> 4 files changed, 62 insertions(+), 34 deletions(-)
>

Thanks, added to queue

-Mathias

2023-05-09 09:22:24

by Weitao Wang

[permalink] [raw]
Subject: Re: [PATCH v4 0/4] Fix some issues for ZHAOXIN xHCI host

On 2023/5/9 16:08, Mathias Nyman wrote:
> On 9.5.2023 0.20, Weitao Wang wrote:
>> Fix some issues for ZHAOXIN xHCI host.
>>
>> Weitao Wang (4):
>>    xhci: Fix resume issue of some ZHAOXIN hosts
>>    xhci: Fix TRB prefetch issue of ZHAOXIN hosts
>>    xhci: Show ZHAOXIN xHCI root hub speed correctly
>>    xhci: Add ZHAOXIN xHCI host U1/U2 feature support
>>
>>   drivers/usb/host/xhci-mem.c | 38 ++++++++++++++++++++++++--------
>>   drivers/usb/host/xhci-pci.c | 13 +++++++++++
>>   drivers/usb/host/xhci.c     | 43 ++++++++++++++++---------------------
>>   drivers/usb/host/xhci.h     |  2 ++
>>   4 files changed, 62 insertions(+), 34 deletions(-)
>>
>
> Thanks, added to queue
>
> -Mathias

That's great! Thanks again for your help and suggestion.
Weitao