Blob Blame History Raw
From fbe2026f3ad2bc8172353f902b5a8a8998eaf198 Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oneukum@suse.com>
Date: Wed, 7 Jun 2023 14:32:59 +0200
Subject: [PATCH] usb: xhci: rework grace period logic
Patch-mainline: never (kABI fixup)
References: git-fixes

Use a global variable and a global lock.
As the time on the lock extends monotonically
and waiting longer than necessary only cost a little energy
we can save the kABI by going global.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/usb/host/xhci-hub.c | 11 ++++++++---
 drivers/usb/host/xhci.c     |  7 ++++++-
 drivers/usb/host/xhci.h     |  1 -
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9f6636170..3f21859de 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -31,6 +31,9 @@
 #define	PORT_RWC_BITS	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
 			 PORT_RC | PORT_PLC | PORT_PE)
 
+extern unsigned long suse_xhci_grace_period;
+extern struct spinlock suse_grace_lock;
+
 /* USB 3 BOS descriptor and a capability descriptors, combined.
  * Fields will be adjusted and added later in xhci_create_usb3_bos_desc()
  */
@@ -1457,12 +1460,14 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 	 * SS devices are only visible to roothub after link training completes.
 	 * Keep polling roothubs for a grace period after xHC start
 	 */
-	if (xhci->run_graceperiod) {
-		if (time_before(jiffies, xhci->run_graceperiod))
+	spin_lock(&suse_grace_lock);
+	if (suse_xhci_grace_period) {
+		if (time_before(jiffies, suse_xhci_grace_period))
 			status = 1;
 		else
-			xhci->run_graceperiod = 0;
+			suse_xhci_grace_period = 0;
 	}
+	spin_unlock(&suse_grace_lock);
 
 	mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC;
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index fd8c10c47..0bf07a4df 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -53,6 +53,9 @@ static unsigned long long quirks;
 module_param(quirks, ullong, S_IRUGO);
 MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");
 
+unsigned long suse_xhci_grace_period = 0;
+DEFINE_SPINLOCK(suse_grace_lock);
+
 static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
 {
 	struct xhci_segment *seg = ring->first_seg;
@@ -165,9 +168,11 @@ int xhci_start(struct xhci_hcd *xhci)
 				"waited %u microseconds.\n",
 				XHCI_MAX_HALT_USEC);
 	if (!ret) {
+		spin_lock_irq(&suse_grace_lock);
 		/* clear state flags. Including dying, halted or removing */
 		xhci->xhc_state = 0;
-		xhci->run_graceperiod = jiffies + msecs_to_jiffies(500);
+		suse_xhci_grace_period = jiffies + msecs_to_jiffies(500);
+		spin_unlock_irq(&suse_grace_lock);
 	}
 
 	return ret;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 30a17a4fd..87e2fb20d 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1810,7 +1810,6 @@ struct xhci_hcd {
 
 	/* Host controller watchdog timer structures */
 	unsigned int		xhc_state;
-	unsigned long		run_graceperiod;
 	u32			command;
 	struct s3_save		s3;
 /* Host controller is dying - not responding to commands. "I'm not dead yet!"
-- 
2.40.1