]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
misc: rtsx: usb: Ensure mmc child device is active when card is present
authorRicky Wu <ricky_wu@realtek.com>
Fri, 11 Jul 2025 14:01:43 +0000 (22:01 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 16 Jul 2025 12:26:39 +0000 (14:26 +0200)
When a card is present in the reader, the driver currently defers
autosuspend by returning -EAGAIN during the suspend callback to
trigger USB remote wakeup signaling. However, this does not guarantee
that the mmc child device has been resumed, which may cause issues if
it remains suspended while the card is accessible.
This patch ensures that all child devices, including the mmc host
controller, are explicitly resumed before returning -EAGAIN. This
fixes a corner case introduced by earlier remote wakeup handling,
improving reliability of runtime PM when a card is inserted.

Fixes: 883a87ddf2f1 ("misc: rtsx_usb: Use USB remote wakeup signaling for card insertion detection")
Cc: stable@vger.kernel.org
Signed-off-by: Ricky Wu <ricky_wu@realtek.com>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20250711140143.2105224-1-ricky_wu@realtek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/cardreader/rtsx_usb.c

index 148107a4547c39badcb9a1de3f4271b126efaf1c..d007a4455ce5ba319f70f66645224d5a24448041 100644 (file)
@@ -698,6 +698,12 @@ static void rtsx_usb_disconnect(struct usb_interface *intf)
 }
 
 #ifdef CONFIG_PM
+static int rtsx_usb_resume_child(struct device *dev, void *data)
+{
+       pm_request_resume(dev);
+       return 0;
+}
+
 static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct rtsx_ucr *ucr =
@@ -713,8 +719,10 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
                        mutex_unlock(&ucr->dev_mutex);
 
                        /* Defer the autosuspend if card exists */
-                       if (val & (SD_CD | MS_CD))
+                       if (val & (SD_CD | MS_CD)) {
+                               device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
                                return -EAGAIN;
+                       }
                } else {
                        /* There is an ongoing operation*/
                        return -EAGAIN;
@@ -724,12 +732,6 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
        return 0;
 }
 
-static int rtsx_usb_resume_child(struct device *dev, void *data)
-{
-       pm_request_resume(dev);
-       return 0;
-}
-
 static int rtsx_usb_resume(struct usb_interface *intf)
 {
        device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);