USB: musb_gadget: implement set_wedge() method
authorSergei Shtylyov <sshtylyov@ru.mvista.com>
Wed, 18 Nov 2009 19:51:51 +0000 (22:51 +0300)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 11 Dec 2009 19:55:25 +0000 (11:55 -0800)
Implement the driver's set_wedge() method by adding the 'wedged' flag
to the 'struct musb_ep'.

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget.h
drivers/usb/musb/musb_gadget_ep0.c

index 74073f9a43f09cafc6afed82e5a9cadd17304d62..173c963e7f020f0d1c2e80d72efbd4c4ee385328 100644 (file)
@@ -966,6 +966,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 
        musb_ep->desc = desc;
        musb_ep->busy = 0;
+       musb_ep->wedged = 0;
        status = 0;
 
        pr_debug("%s periph: enabled %s for %s %s, %smaxpacket %d\n",
@@ -1262,7 +1263,8 @@ int musb_gadget_set_halt(struct usb_ep *ep, int value)
                                goto done;
                        }
                }
-       }
+       } else
+               musb_ep->wedged = 0;
 
        /* set/clear the stall and toggle bits */
        DBG(2, "%s: %s stall\n", ep->name, value ? "set" : "clear");
@@ -1301,6 +1303,21 @@ done:
        return status;
 }
 
+/*
+ * Sets the halt feature with the clear requests ignored
+ */
+int musb_gadget_set_wedge(struct usb_ep *ep)
+{
+       struct musb_ep          *musb_ep = to_musb_ep(ep);
+
+       if (!ep)
+               return -EINVAL;
+
+       musb_ep->wedged = 1;
+
+       return usb_ep_set_halt(ep);
+}
+
 static int musb_gadget_fifo_status(struct usb_ep *ep)
 {
        struct musb_ep          *musb_ep = to_musb_ep(ep);
@@ -1371,6 +1388,7 @@ static const struct usb_ep_ops musb_ep_ops = {
        .queue          = musb_gadget_queue,
        .dequeue        = musb_gadget_dequeue,
        .set_halt       = musb_gadget_set_halt,
+       .set_wedge      = musb_gadget_set_wedge,
        .fifo_status    = musb_gadget_fifo_status,
        .fifo_flush     = musb_gadget_fifo_flush
 };
index 59502da9f739ce179bca5faa549147d6c34ad078..90966695ae53b2345fe109759f3fafc50f436732 100644 (file)
@@ -75,6 +75,8 @@ struct musb_ep {
        /* later things are modified based on usage */
        struct list_head                req_list;
 
+       u8                              wedged;
+
        /* true if lock must be dropped but req_list may not be advanced */
        u8                              busy;
 };
index 1c44b975049ca3efdd882ebd03169ca2a74dcdc6..c63aff110c455cc01873577753792faee3583433 100644 (file)
@@ -273,6 +273,11 @@ __acquires(musb->lock)
                                if (!musb_ep->desc)
                                        break;
 
+                               handled = 1;
+                               /* Ignore request if endpoint is wedged */
+                               if (musb_ep->wedged)
+                                       break;
+
                                /* REVISIT do it directly, no locking games */
                                spin_unlock(&musb->lock);
                                musb_gadget_set_halt(&musb_ep->end_point, 0);
@@ -280,7 +285,6 @@ __acquires(musb->lock)
 
                                /* select ep0 again */
                                musb_ep_select(mbase, 0);
-                               handled = 1;
                                } break;
                        default:
                                /* class, vendor, etc ... delegate */