| From 966c5cd72be8989c8a559ddef8e8ff07a37c5eb0 Mon Sep 17 00:00:00 2001 |
| From: Ricky Wu <ricky_wu@realtek.com> |
| Date: Fri, 11 Jul 2025 22:01:43 +0800 |
| Subject: misc: rtsx: usb: Ensure mmc child device is active when card is present |
| |
| From: Ricky Wu <ricky_wu@realtek.com> |
| |
| commit 966c5cd72be8989c8a559ddef8e8ff07a37c5eb0 upstream. |
| |
| 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 | 16 +++++++++------- |
| 1 file changed, 9 insertions(+), 7 deletions(-) |
| |
| --- a/drivers/misc/cardreader/rtsx_usb.c |
| +++ b/drivers/misc/cardreader/rtsx_usb.c |
| @@ -698,6 +698,12 @@ static void rtsx_usb_disconnect(struct u |
| } |
| |
| #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_i |
| 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_i |
| 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); |