summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-27 14:21:20 +0100
committerMark Brown <broonie@kernel.org>2026-07-27 14:21:20 +0100
commit2d2ceb83bfad00b16ffb96eb63d098524fa017db (patch)
tree0a271a28a8e29287297c4d9321fb5444206f8634 /drivers/misc
parent08d9529b632328de842e451bf8c5feec1705553e (diff)
parent5608386899d9de8030980bce3d05bded28f9bfb8 (diff)
downloadlinux-next-2d2ceb83bfad00b16ffb96eb63d098524fa017db.tar.gz
linux-next-2d2ceb83bfad00b16ffb96eb63d098524fa017db.zip
Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/cardreader/rtsx_usb.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index 1830e9ed2521..a127744918f4 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -312,6 +312,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);
@@ -623,6 +626,7 @@ static int rtsx_usb_probe(struct usb_interface *intf,
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
struct rtsx_ucr *ucr;
+ u16 status;
int ret;
dev_dbg(&intf->dev,
@@ -659,6 +663,9 @@ static int rtsx_usb_probe(struct usb_interface *intf,
if (ret)
goto out_init_fail;
+ /* Prime cached status for runtime autosuspend decisions. */
+ rtsx_usb_get_card_status(ucr, &status);
+
/* initialize USB SG transfer timer */
timer_setup(&ucr->sg_timer, rtsx_usb_sg_timed_out, 0);
@@ -713,22 +720,29 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
struct rtsx_ucr *ucr =
(struct rtsx_ucr *)usb_get_intfdata(intf);
u16 val = 0;
+ bool valid = false;
dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n",
__func__, message.event);
if (PMSG_IS_AUTO(message)) {
if (mutex_trylock(&ucr->dev_mutex)) {
- rtsx_usb_get_card_status(ucr, &val);
+ valid = ucr->card_status_valid;
+ if (valid)
+ val = ucr->card_status_cache;
mutex_unlock(&ucr->dev_mutex);
- /* Defer the autosuspend if card exists */
- if (val & (SD_CD | MS_CD)) {
+ /*
+ * Do not issue USB commands from runtime autosuspend.
+ * Raw SD_CD is not authoritative on tray-based readers,
+ * while a real SD card is protected by the SD/MMC child
+ * runtime-PM reference once the card is powered. Keep
+ * the historical Memory Stick autosuspend deferral when
+ * the cached status says MS media is present.
+ */
+ if (valid && (val & 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*/