Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Jun 2011 00:38:26 +0100 (BST)
From:      Gavin Atkinson <gavin@FreeBSD.org>
To:        Hans Petter Selasky <hselasky@c2i.net>
Cc:        freebsd-usb@freebsd.org
Subject:   Re: USB suspend/resume
Message-ID:  <alpine.LNX.2.00.1106050014050.26975@ury.york.ac.uk.>
In-Reply-To: <201106042212.12397.hselasky@c2i.net>
References:  <alpine.LNX.2.00.1106041548370.26975@ury.york.ac.uk.> <201106042212.12397.hselasky@c2i.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 4 Jun 2011, Hans Petter Selasky wrote:
> On Saturday 04 June 2011 19:08:22 Gavin Atkinson wrote:
> > Hi all,
> > 
> > I've been trying to get a IBM ThinkPad X60 suspend/resume working
> > correctly, and discovered that with uhci loaded, the machine would hang on
> > resume.  This is on head, but I believe this is aslo the cause of the
> > laptop not resuming on stable/8.
> > 
> > It turns out that this is because we sleep in the resume path.  The resume
> > path appears to run with interrupts disabled, and as a result we never
> > wake up.  A comment above uhci_suspend() saggests similar:
> > 
> > 	/* NOTE: suspend/resume is called from
> > 	 * interrupt context and cannot sleep!
> > 
> > However, we do sleep.  We call usb_pause_mtx() several times during both
> > tthe suspend and resume path, and on resume this is fatal.
> > usb_pause_mtx() will use DELAY() when called before the machine has
> > finished booting (ie cold != 0), but will call pause() once booted.
> > 
[snip]
> > 
> > So, I guess my question to the USB experts is:  What is the correct fix?
> > I see two possibilities:
> > 
> > 1) Have a variable somewhere called "suspres" or similar, which is set at
> >    the start of the suspend, and cleared at the end of the resume.
> >    usb_pause_mtx() then changes it's behaviour on (cold || suspres).
> >    This may have to be a global variable, being incremented on suspend and
> >    decremented on resume, as we don't pass a softc into usb_pause_mtx(),
> >    however then we have issues relating to when one controller suspends
> >    before the others, or resume before the others.
> > 
> > 2) Kick off a separate task to do the resume.  Problems with this is thet
> >    it doesn't fix the suspend path, but also that we may need to rely on
> >    USB being back before the rest of the resume completes. (What happens
> >    if we have / or another filesystem mounted from a USB device?)
> > 
> > I guess #1 is the simplest solution, and should have fewest side effects,
> > however it does mean that every attachment would need to be modified in
> > order to set and clear the variable.  It sort of feels like this should be
> > handled more centrally, but I'm not sure of the best way to achieve this.
> > 
> 
> Where is it documented that the resume/suspend callbacks are not run from a 
> thread context?

As far as I can tell, it does run in a thread context.  I've not found any 
specific documentation saying what can and cannot be done during 
suspend/resume, other than that comment in uhci.c above uhci_suspend().  
Do you have any idea where you got that information from?  The old stack 
had this comment:

  * We need to switch to polling mode here, because this routine is
  * called from an interrupt context.  This is all right since we
  * are almost suspended anyway.

It was purely based on htat comment that I investigated the possibility 
that this was related to pause().  I believe that the reason that this 
works on some machines but not this one right now is purely down to the 
order in which things are brought back.  On this laptop, hpet(4) is 
resumed after the USB busses.  Presumably from that point onwards, it is 
possible to sleep for a length of time?  I'm not sure.  Before that, 
pause() hangs indefinitely, waiting for an interrupt that never happens.  
This is just a theory - I've not proved it conclusively yet.

I'm sort of hoping that somebody who knows more about suspend/resume can 
offer some pointers here.

Gavin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.LNX.2.00.1106050014050.26975>