diff mbox

[v2,2/5] usb: musb: call musb_port_suspend from musb_bus_suspend

Message ID 1380634797-29541-3-git-send-email-zonque@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Mack Oct. 1, 2013, 1:39 p.m. UTC
Make musb_port_suspend() externally available, and call it when to host
goes into suspend. This allows the core to go into suspend while a
device is connected.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 drivers/usb/musb/musb_host.c    | 2 ++
 drivers/usb/musb/musb_host.h    | 2 ++
 drivers/usb/musb/musb_virthub.c | 2 +-
 3 files changed, 5 insertions(+), 1 deletion(-)

Comments

Sebastian Sewior Oct. 2, 2013, 10:49 a.m. UTC | #1
* Daniel Mack | 2013-10-01 15:39:54 [+0200]:

>Make musb_port_suspend() externally available, and call it when to host
>goes into suspend. This allows the core to go into suspend while a
>device is connected.

Sorry for asking this stupid question but what is usally happening when
the host goes to suspend and a device is connected? I think it is
disconnected & re-enumerated and resume and this not what you want,
right?
What happens if the device is unplugged while the host is suspended and
not there on resume?

>Signed-off-by: Daniel Mack <zonque@gmail.com>

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Daniel Mack Oct. 2, 2013, 11:14 a.m. UTC | #2
On 02.10.2013 12:49, Sebastian Andrzej Siewior wrote:
> * Daniel Mack | 2013-10-01 15:39:54 [+0200]:
> 
>> Make musb_port_suspend() externally available, and call it when to host
>> goes into suspend. This allows the core to go into suspend while a
>> device is connected.
> 
> Sorry for asking this stupid question but what is usally happening when
> the host goes to suspend and a device is connected? I think it is
> disconnected & re-enumerated and resume and this not what you want,
> right?

It is usually put into USB suspend and the host preserves its state.
After resume, the usb storage driver, for example, will not register new
partitions but expect things to be as they were before. That is, your
previously mounted devices remain functional.

However, the enumeration process has to be done again, because when the
device looses power, it can't memorize its address.

> What happens if the device is unplugged while the host is suspended and
> not there on resume?

That condition is detected and a full teardown of the connected drivers
is conducted. Try what happens on your notebook when you do that.
Embedded systems should behave just the same.


Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sebastian Sewior Oct. 2, 2013, 12:01 p.m. UTC | #3
On 10/02/2013 01:14 PM, Daniel Mack wrote:
> On 02.10.2013 12:49, Sebastian Andrzej Siewior wrote:
>> * Daniel Mack | 2013-10-01 15:39:54 [+0200]:
>>
>>> Make musb_port_suspend() externally available, and call it when to host
>>> goes into suspend. This allows the core to go into suspend while a
>>> device is connected.
>>
>> Sorry for asking this stupid question but what is usally happening when
>> the host goes to suspend and a device is connected? I think it is
>> disconnected & re-enumerated and resume and this not what you want,
>> right?
> 
> It is usually put into USB suspend and the host preserves its state.
> After resume, the usb storage driver, for example, will not register new
> partitions but expect things to be as they were before. That is, your
> previously mounted devices remain functional.
> 
> However, the enumeration process has to be done again, because when the
> device looses power, it can't memorize its address.
> 
>> What happens if the device is unplugged while the host is suspended and
>> not there on resume?
> 
> That condition is detected and a full teardown of the connected drivers
> is conducted. Try what happens on your notebook when you do that.
> Embedded systems should behave just the same.

I had the feeling that the USB device gets disconnected and
re-enumerated on resume. But if you say that the ehci-hcd saves the
state and keeps the device connected if it wasn't disconnected during
suspend then there is no reason for musb to behave differently.

> Daniel

Sebastian
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Daniel Mack Oct. 2, 2013, 12:12 p.m. UTC | #4
On 02.10.2013 14:01, Sebastian Andrzej Siewior wrote:
> On 10/02/2013 01:14 PM, Daniel Mack wrote:
>> On 02.10.2013 12:49, Sebastian Andrzej Siewior wrote:

>>> What happens if the device is unplugged while the host is suspended and
>>> not there on resume?
>>
>> That condition is detected and a full teardown of the connected drivers
>> is conducted. Try what happens on your notebook when you do that.
>> Embedded systems should behave just the same.
> 
> I had the feeling that the USB device gets disconnected and
> re-enumerated on resume.

Yes. The device looses its +5V power supply, so it has to be reset and
re-enumerated on resume of course. It's just that USB drivers know about
the state the device has to be put back into after resume, and don't
assume the device was disconnected and reconnected. The latter would
(for usb-storage) also cause paritions to be removed and added.

> But if you say that the ehci-hcd saves the
> state and keeps the device connected if it wasn't disconnected during
> suspend then there is no reason for musb to behave differently.

Which it doesn't with my patches applied. I can mount a USB volume, put
the system into suspend and access the contents after resume. Just the
way it should be :)


Daniel

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alan Stern Oct. 2, 2013, 2:52 p.m. UTC | #5
On Wed, 2 Oct 2013, Daniel Mack wrote:

> On 02.10.2013 14:01, Sebastian Andrzej Siewior wrote:
> > On 10/02/2013 01:14 PM, Daniel Mack wrote:
> >> On 02.10.2013 12:49, Sebastian Andrzej Siewior wrote:
> 
> >>> What happens if the device is unplugged while the host is suspended and
> >>> not there on resume?
> >>
> >> That condition is detected and a full teardown of the connected drivers
> >> is conducted. Try what happens on your notebook when you do that.
> >> Embedded systems should behave just the same.
> > 
> > I had the feeling that the USB device gets disconnected and
> > re-enumerated on resume.
> 
> Yes. The device looses its +5V power supply, so it has to be reset and
> re-enumerated on resume of course. It's just that USB drivers know about
> the state the device has to be put back into after resume, and don't
> assume the device was disconnected and reconnected. The latter would
> (for usb-storage) also cause paritions to be removed and added.

This description may be slightly misleading.

According to the USB spec, a device is not supposed to lose its +5V 
power supply during suspend.  Therefore it does not need to be reset 
and re-enumerated upon resume.  (Except that some devices don't handle 
suspend properly because of buggy firmware; they _do_ need to be 
reset.)

Of course, some systems don't follow the spec.  If they can't supply
suspend power to the host controller and the USB bus, then the device
_will_ need to be reset and re-enumerated.

Some USB drivers (those which define a reset_resume method) are able to
handle this -- they put the device back into the right state and then
act as if nothing had happened.  Others aren't; they get unbound and
rebound just as though the device really had been disconnected and
reconnected.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 9a2b8c8..2b60596 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2433,6 +2433,8 @@  static int musb_bus_suspend(struct usb_hcd *hcd)
 	struct musb	*musb = hcd_to_musb(hcd);
 	u8		devctl;
 
+	musb_port_suspend(musb, true);
+
 	if (!is_host_active(musb))
 		return 0;
 
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h
index 843f48e..dcffea7 100644
--- a/drivers/usb/musb/musb_host.h
+++ b/drivers/usb/musb/musb_host.h
@@ -93,6 +93,7 @@  extern void musb_root_disconnect(struct musb *musb);
 extern void musb_host_resume_root_hub(struct musb *musb);
 extern void musb_host_poke_root_hub(struct musb *musb);
 extern void musb_port_reset(struct musb *musb);
+extern void musb_port_suspend(struct musb *musb, bool do_suspend);
 #else
 static inline struct musb *hcd_to_musb(struct usb_hcd *hcd)
 {
@@ -123,6 +124,7 @@  static inline void musb_host_resume_root_hub(struct musb *musb)	{}
 static inline void musb_host_poll_rh_status(struct musb *musb)	{}
 static inline void musb_host_poke_root_hub(struct musb *musb)	{}
 static inline void musb_port_reset(struct musb *musb)		{}
+static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {}
 #endif
 
 struct usb_hcd;
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index 30b43a1..9f3a0f3 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -90,7 +90,7 @@  static void musb_start(struct musb *musb)
 	musb_writeb(regs, MUSB_DEVCTL, devctl);
 }
 
-static void musb_port_suspend(struct musb *musb, bool do_suspend)
+void musb_port_suspend(struct musb *musb, bool do_suspend)
 {
 	struct usb_otg	*otg = musb->xceiv->otg;
 	u8		power;