Frank Hofmann | 13 Apr 19:17 2011

more on TOI / ARM hibernation (workaround for usb gadget crash on resume)


John reported the problem already that on resume, the usb gadget driver 
crashes in musb_g_giveback().

This actually looks to be (yet another) Android "interaction". Android 
isn't exactly "cooperative" with normal Linux power management, alas, and 
the adb driver is no exception...

What happens is that the adb driver enqueues the same USB request twice:

Once early on, before suspend, it's in the endpoint's queue by the time 
suspend writes the image out. After restore, it's still there.
But the adb gadget driver, when waking up, decides to queue exactly that 
request again. It obviously assumes that after a resume, the gadget queues 
are empty ...

That corrupts the list, and any later attempt to drain the endpoint 
(either by pluggin the cable or by another hibernate attempt) then crashes.

A quick&dirty "fix" is to make the USB gadget driver kill the offender 
(adb) right when it's reaching for the forbidden fruit:

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 3f6f8ac..b4fc592 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
 <at>  <at>  -1159,6 +1159,7  <at>  <at>  static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
  	struct musb		*musb;
  	int			status = 0;
  	unsigned long		lockflags;
+	struct usb_request	*r, *tmp;

  	if (!ep || !req)
  		return -EINVAL;
 <at>  <at>  -1216,6 +1217,16  <at>  <at>  static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
  		goto cleanup;

+	/* If we have the request already, kill the offender (no mercy !) */
+	list_for_each_entry_safe(r, tmp, &musb_ep->req_list, list) {
+		if (to_musb_request(r) != request)
+			continue;
+		WARN_ON(1);
+		send_sig(SIGKILL, current, 0);
+		status = -ESHUTDOWN;
+		goto cleanup;
+	}
  	/* add request to the list */
  	list_add_tail(&(request->request.list), &(musb_ep->req_list));


but a better way (apart from finding and fixing the problem with the adb 
gadget driver) might be to stop/restart the android debugger server via 
pre/post hibernation script.

Now looking into the graphics driver and the OMAP4 restore issue; more on 
that later in the week see what I find.