diff options
| author | Mark Brown <broonie@kernel.org> | 2026-07-27 14:21:20 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-07-27 14:21:20 +0100 |
| commit | 2d2ceb83bfad00b16ffb96eb63d098524fa017db (patch) | |
| tree | 0a271a28a8e29287297c4d9321fb5444206f8634 /drivers/misc | |
| parent | 08d9529b632328de842e451bf8c5feec1705553e (diff) | |
| parent | 5608386899d9de8030980bce3d05bded28f9bfb8 (diff) | |
| download | linux-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.c | 26 |
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*/ |
