From 8066134ff8140ae9d8d15cdad3fc6c60c2a8a4e5 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 14 Aug 2008 15:49:11 -0400 Subject: USB: gadget: net2280: implement set_wedge This patch (as1132) implements the set_wedge() method for net2280. This method is necessary for strict USBCV compliance in g_file_storage. Signed-off-by: Alan Stern CC: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/net2280.c | 40 ++++++++++++++++++++++++++++++++++------ drivers/usb/gadget/net2280.h | 1 + 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 5cfb5ebf388..8ae70de2c37 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) /* ep_reset() has already been called */ ep->stopped = 0; + ep->wedged = 0; ep->out_overflow = 0; /* set speed-dependent max packet; may kick in high bandwidth */ @@ -1218,7 +1219,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req) static int net2280_fifo_status (struct usb_ep *_ep); static int -net2280_set_halt (struct usb_ep *_ep, int value) +net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged) { struct net2280_ep *ep; unsigned long flags; @@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value) else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) retval = -EAGAIN; else { - VDEBUG (ep->dev, "%s %s halt\n", _ep->name, - value ? "set" : "clear"); + VDEBUG (ep->dev, "%s %s %s\n", _ep->name, + value ? "set" : "clear", + wedged ? "wedge" : "halt"); /* set/clear, then synch memory views with the device */ if (value) { if (ep->num == 0) ep->dev->protocol_stall = 1; else set_halt (ep); - } else + if (wedged) + ep->wedged = 1; + } else { clear_halt (ep); + ep->wedged = 0; + } (void) readl (&ep->regs->ep_rsp); } spin_unlock_irqrestore (&ep->dev->lock, flags); @@ -1256,6 +1262,20 @@ net2280_set_halt (struct usb_ep *_ep, int value) return retval; } +static int +net2280_set_halt(struct usb_ep *_ep, int value) +{ + return net2280_set_halt_and_wedge(_ep, value, 0); +} + +static int +net2280_set_wedge(struct usb_ep *_ep) +{ + if (!_ep || _ep->name == ep0name) + return -EINVAL; + return net2280_set_halt_and_wedge(_ep, 1, 1); +} + static int net2280_fifo_status (struct usb_ep *_ep) { @@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = { .dequeue = net2280_dequeue, .set_halt = net2280_set_halt, + .set_wedge = net2280_set_wedge, .fifo_status = net2280_fifo_status, .fifo_flush = net2280_fifo_flush, }; @@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) goto do_stall; if ((e = get_ep_by_addr (dev, w_index)) == 0) goto do_stall; - clear_halt (e); + if (e->wedged) { + VDEBUG(dev, "%s wedged, halt not cleared\n", + ep->ep.name); + } else { + VDEBUG(dev, "%s clear halt\n", ep->ep.name); + clear_halt(e); + } allow_status (ep); - VDEBUG (dev, "%s clear halt\n", ep->ep.name); goto next_endpoints; } break; @@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) goto do_stall; if ((e = get_ep_by_addr (dev, w_index)) == 0) goto do_stall; + if (e->ep.name == ep0name) + goto do_stall; set_halt (e); allow_status (ep); VDEBUG (dev, "%s set halt\n", ep->ep.name); diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index 81a71dbdc2c..c36852263d9 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -109,6 +109,7 @@ struct net2280_ep { in_fifo_validate : 1, out_overflow : 1, stopped : 1, + wedged : 1, is_in : 1, is_iso : 1, responded : 1; -- cgit v1.2.3-70-g09d2