public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] rtsx_usb: runtime PM fixes before tray-reader detect rework
@ 2026-04-13 11:42 Sean Rhodes
  2026-04-13 11:42 ` [RFC PATCH 1/2] rtsx_usb: hold runtime PM during transfers Sean Rhodes
  2026-04-13 11:42 ` [RFC PATCH 2/2] rtsx_usb: avoid USB I/O in runtime autosuspend Sean Rhodes
  0 siblings, 2 replies; 3+ messages in thread
From: Sean Rhodes @ 2026-04-13 11:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Sean Rhodes, Ulf Hansson,
	Ricky Wu, Ingo Molnar, Thomas Gleixner, linux-usb, linux-mmc

This is an RFC for the USB/cardreader side of the rtsx tray-reader issue.

Assuming the separate resume-reset fix has landed, this is the next step:
clean up runtime PM handling in the USB/cardreader layer before attempting
any further MMC-side detect changes.

Patch 1 holds a runtime PM reference across transfers and marks the device
busy afterwards.

Patch 2 avoids issuing USB register I/O from the runtime autosuspend path,
which can deadlock runtime PM and leave the device stuck in a suspending
state.

The remaining tray-reader false-detect problem likely needs event
qualification on the USB/cardreader side rather than MMC command probing
from ->get_cd(). Guidance on the right place for that logic would be
useful.

Sean Rhodes (2):
  rtsx_usb: hold runtime PM during transfers
  rtsx_usb: avoid USB I/O in runtime autosuspend

 drivers/misc/cardreader/rtsx_usb.c | 49 +++++++++++++++++++++++-------
 include/linux/rtsx_usb.h           |  3 ++
 2 files changed, 41 insertions(+), 11 deletions(-)


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC PATCH 1/2] rtsx_usb: hold runtime PM during transfers
  2026-04-13 11:42 [RFC PATCH 0/2] rtsx_usb: runtime PM fixes before tray-reader detect rework Sean Rhodes
@ 2026-04-13 11:42 ` Sean Rhodes
  2026-04-13 11:42 ` [RFC PATCH 2/2] rtsx_usb: avoid USB I/O in runtime autosuspend Sean Rhodes
  1 sibling, 0 replies; 3+ messages in thread
From: Sean Rhodes @ 2026-04-13 11:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Sean Rhodes, Ulf Hansson,
	Ricky Wu, Ingo Molnar, Thomas Gleixner, linux-usb, linux-mmc

Hold a runtime-PM reference across bulk transfers, and mark the device
busy afterwards.

When runtime PM is already in progress (e.g. from rtsx_usb_suspend()),
avoid forcing a runtime resume from within the PM path by using
usb_autopm_get_interface_no_resume() unless the interface is already
runtime-suspended.

Signed-off-by: Sean Rhodes <sean@starlabs.systems>
---
 drivers/misc/cardreader/rtsx_usb.c | 38 ++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index f65acf4d1164..c8badd0db87b 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -12,6 +12,7 @@
 #include <linux/usb.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
+#include <linux/pm_runtime.h>
 #include <linux/rtsx_usb.h>
 
 static int polling_pipe = 1;
@@ -65,19 +66,42 @@ static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
 }
 
 int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
-			      void *buf, unsigned int len, int num_sg,
-			      unsigned int *act_len, int timeout)
+				      void *buf, unsigned int len, int num_sg,
+				      unsigned int *act_len, int timeout)
 {
+	int ret;
+	struct device *dev = &ucr->pusb_intf->dev;
+
 	if (timeout < 600)
 		timeout = 600;
 
+	/*
+	 * During runtime suspend/resume callbacks, avoid forcing a runtime resume
+	 * from within the PM path. The device is still active when
+	 * rtsx_usb_suspend() runs, but usb_autopm_get_interface() can block when
+	 * runtime PM is already in progress.
+	 */
+	if (pm_runtime_status_suspended(dev)) {
+		ret = usb_autopm_get_interface(ucr->pusb_intf);
+	} else {
+		usb_autopm_get_interface_no_resume(ucr->pusb_intf);
+		ret = 0;
+	}
+	if (ret)
+		return ret;
+
 	if (num_sg)
-		return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
-				(struct scatterlist *)buf, num_sg, len, act_len,
-				timeout);
+		ret = rtsx_usb_bulk_transfer_sglist(ucr, pipe,
+						    (struct scatterlist *)buf,
+						    num_sg, len, act_len,
+						    timeout);
 	else
-		return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
-				timeout);
+		ret = usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
+				   timeout);
+
+	usb_mark_last_busy(ucr->pusb_dev);
+	usb_autopm_put_interface(ucr->pusb_intf);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
 

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC PATCH 2/2] rtsx_usb: avoid USB I/O in runtime autosuspend
  2026-04-13 11:42 [RFC PATCH 0/2] rtsx_usb: runtime PM fixes before tray-reader detect rework Sean Rhodes
  2026-04-13 11:42 ` [RFC PATCH 1/2] rtsx_usb: hold runtime PM during transfers Sean Rhodes
@ 2026-04-13 11:42 ` Sean Rhodes
  1 sibling, 0 replies; 3+ messages in thread
From: Sean Rhodes @ 2026-04-13 11:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: Arnd Bergmann, Greg Kroah-Hartman, Sean Rhodes, Ulf Hansson,
	Ricky Wu, Ingo Molnar, Thomas Gleixner, linux-usb, linux-mmc

The runtime autosuspend callback currently queries card status and clears
OCP via USB register accesses.

On some systems this can deadlock runtime PM and leave the USB device
stuck in the "suspending" state.

Avoid issuing USB commands from the runtime autosuspend callback.
Instead, use the last cached card status (updated on successful status
reads) and conservatively assume a card may be present until status is
known.

Signed-off-by: Sean Rhodes <sean@starlabs.systems>
---
 drivers/misc/cardreader/rtsx_usb.c | 11 +++++++----
 include/linux/rtsx_usb.h           |  3 +++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index c8badd0db87b..727205e84640 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -336,6 +336,9 @@ int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
 	if (ret < 0)
 		return ret;
 
+	ucr->card_status_cache = *status;
+	ucr->card_status_valid = true;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
@@ -753,16 +756,16 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
 
 	if (PMSG_IS_AUTO(message)) {
 		if (mutex_trylock(&ucr->dev_mutex)) {
-			rtsx_usb_get_card_status(ucr, &val);
+			if (ucr->card_status_valid)
+				val = ucr->card_status_cache;
+			else
+				val = SD_CD | MS_CD;
 			mutex_unlock(&ucr->dev_mutex);
 
 			/* Defer the autosuspend if card exists */
 			if (val & (SD_CD | MS_CD)) {
 				device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
 				return -EAGAIN;
-			} else {
-				/* if the card does not exists, clear OCP status */
-				rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR);
 			}
 		} else {
 			/* There is an ongoing operation*/
diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h
index 54c6ea82bf43..fed695760691 100644
--- a/include/linux/rtsx_usb.h
+++ b/include/linux/rtsx_usb.h
@@ -62,6 +62,9 @@ struct rtsx_ucr {
 	struct usb_interface	*pusb_intf;
 	struct usb_sg_request	current_sg;
 
+	u16			card_status_cache;
+	bool			card_status_valid;
+
 	struct timer_list	sg_timer;
 	struct mutex		dev_mutex;
 };

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-13 11:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-13 11:42 [RFC PATCH 0/2] rtsx_usb: runtime PM fixes before tray-reader detect rework Sean Rhodes
2026-04-13 11:42 ` [RFC PATCH 1/2] rtsx_usb: hold runtime PM during transfers Sean Rhodes
2026-04-13 11:42 ` [RFC PATCH 2/2] rtsx_usb: avoid USB I/O in runtime autosuspend Sean Rhodes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox