diff mbox series

[1/5] misc: rtsx_usb: Use USB remote wakeup signaling for card insertion detection

Message ID 20180731061721.15831-2-kai.heng.feng@canonical.com (mailing list archive)
State New, archived
Headers show
Series Keep rtsx_usb suspended when there's no card | expand

Commit Message

Kai-Heng Feng July 31, 2018, 6:17 a.m. UTC
Although rtsx_usb doesn't support card removal detection, card insertion
will resume rtsx_usb by USB remote wakeup signaling.

When rtsx_usb gets resumed, also resumes its child devices,
rtsx_usb_sdmmc and rtsx_usb_ms, to notify them there's a card in its
slot.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
 drivers/misc/cardreader/rtsx_usb.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Kai-Heng Feng Sept. 13, 2018, 10:31 a.m. UTC | #1
Hi Alan, Ulf,

at 14:17, Kai-Heng Feng <kai.heng.feng@canonical.com> wrote:

> Although rtsx_usb doesn't support card removal detection, card insertion
> will resume rtsx_usb by USB remote wakeup signaling.
>
> When rtsx_usb gets resumed, also resumes its child devices,
> rtsx_usb_sdmmc and rtsx_usb_ms, to notify them there's a card in its
> slot.
>
> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
> ---
>  drivers/misc/cardreader/rtsx_usb.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/misc/cardreader/rtsx_usb.c  
> b/drivers/misc/cardreader/rtsx_usb.c
> index b97903ff1a72..f7a66f614085 100644
> --- a/drivers/misc/cardreader/rtsx_usb.c
> +++ b/drivers/misc/cardreader/rtsx_usb.c
> @@ -723,8 +723,15 @@ 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);
>  	return 0;
>  }
>
> @@ -734,6 +741,7 @@ static int rtsx_usb_reset_resume(struct usb_interface  
> *intf)
>  		(struct rtsx_ucr *)usb_get_intfdata(intf);
>
>  	rtsx_usb_reset_chip(ucr);
> +	device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
>  	return 0;
>  }

I am working on the next version of this series, and the last missing  
puzzle is to differentiate system-wide resume from runtime resume in  
usb_driver's resume() and reset_resume() callback.

The parent device, rtsx_usb, has two child devices, rtsx_usb_ms and  
rtsx_usb_sdmmc.
pm_request_resume() is used in rtsx_usb's resume() to facilitate USB remote  
wakeup signaling, so we don't need to poll the card slot status.
But this has a side effect: during system resume the rtsx_usb calls  
pm_request_resume() in its resume(), so child devices calls their  
runtime_resume() instead of resume() callback.

So, is it reasonable to pass pm_message_t to resume() and reset_resume()  
callbacks and use PMSG_IS_AUTO() to differentiate them?

Kai-Heng

>
> -- 
> 2.17.1
Alan Stern Sept. 13, 2018, 1:41 p.m. UTC | #2
On Thu, 13 Sep 2018, Kai-Heng Feng wrote:

> I am working on the next version of this series, and the last missing  
> puzzle is to differentiate system-wide resume from runtime resume in  
> usb_driver's resume() and reset_resume() callback.
> 
> The parent device, rtsx_usb, has two child devices, rtsx_usb_ms and  
> rtsx_usb_sdmmc.
> pm_request_resume() is used in rtsx_usb's resume() to facilitate USB remote  
> wakeup signaling, so we don't need to poll the card slot status.
> But this has a side effect: during system resume the rtsx_usb calls  
> pm_request_resume() in its resume(), so child devices calls their  
> runtime_resume() instead of resume() callback.

Have you actually observed this?  It shouldn't happen.  
pm_request_resume() schedules a runtime resume on the PM work queue, 
but this work queue is frozen during system sleep.  It doesn't unfreeze 
until after all the devices have been restored to full power.  Thus the 
child device's resume() callback should be invoked before 
runtime_resume().

> So, is it reasonable to pass pm_message_t to resume() and reset_resume()  
> callbacks and use PMSG_IS_AUTO() to differentiate them?

It should not be necessary to do this.

Alan Stern
Kai-Heng Feng Sept. 17, 2018, 8:07 a.m. UTC | #3
at 21:41, Alan Stern <stern@rowland.harvard.edu> wrote:

> On Thu, 13 Sep 2018, Kai-Heng Feng wrote:
>
>> I am working on the next version of this series, and the last missing
>> puzzle is to differentiate system-wide resume from runtime resume in
>> usb_driver's resume() and reset_resume() callback.
>>
>> The parent device, rtsx_usb, has two child devices, rtsx_usb_ms and
>> rtsx_usb_sdmmc.
>> pm_request_resume() is used in rtsx_usb's resume() to facilitate USB  
>> remote
>> wakeup signaling, so we don't need to poll the card slot status.
>> But this has a side effect: during system resume the rtsx_usb calls
>> pm_request_resume() in its resume(), so child devices calls their
>> runtime_resume() instead of resume() callback.
>
> Have you actually observed this?  It shouldn't happen.
> pm_request_resume() schedules a runtime resume on the PM work queue,
> but this work queue is frozen during system sleep.  It doesn't unfreeze
> until after all the devices have been restored to full power.  Thus the
> child device's resume() callback should be invoked before
> runtime_resume().

You are right, I read the trace wrong.

It happens right before system-wide suspension, when the PM core resumes it  
to fully functional state.

>
>> So, is it reasonable to pass pm_message_t to resume() and reset_resume()
>> callbacks and use PMSG_IS_AUTO() to differentiate them?
>
> It should not be necessary to do this.

Understood, thanks.

Kai-Heng

>
> Alan Stern
diff mbox series

Patch

diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index b97903ff1a72..f7a66f614085 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -723,8 +723,15 @@  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);
 	return 0;
 }
 
@@ -734,6 +741,7 @@  static int rtsx_usb_reset_resume(struct usb_interface *intf)
 		(struct rtsx_ucr *)usb_get_intfdata(intf);
 
 	rtsx_usb_reset_chip(ucr);
+	device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child);
 	return 0;
 }