Commit 8066134f authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

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: default avatarAlan Stern <stern@rowland.harvard.edu>
CC: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 851a526d
...@@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -178,6 +178,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* ep_reset() has already been called */ /* ep_reset() has already been called */
ep->stopped = 0; ep->stopped = 0;
ep->wedged = 0;
ep->out_overflow = 0; ep->out_overflow = 0;
/* set speed-dependent max packet; may kick in high bandwidth */ /* 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) ...@@ -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_fifo_status (struct usb_ep *_ep);
static int 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; struct net2280_ep *ep;
unsigned long flags; unsigned long flags;
...@@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value) ...@@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value)
else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
retval = -EAGAIN; retval = -EAGAIN;
else { else {
VDEBUG (ep->dev, "%s %s halt\n", _ep->name, VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
value ? "set" : "clear"); value ? "set" : "clear",
wedged ? "wedge" : "halt");
/* set/clear, then synch memory views with the device */ /* set/clear, then synch memory views with the device */
if (value) { if (value) {
if (ep->num == 0) if (ep->num == 0)
ep->dev->protocol_stall = 1; ep->dev->protocol_stall = 1;
else else
set_halt (ep); set_halt (ep);
} else if (wedged)
ep->wedged = 1;
} else {
clear_halt (ep); clear_halt (ep);
ep->wedged = 0;
}
(void) readl (&ep->regs->ep_rsp); (void) readl (&ep->regs->ep_rsp);
} }
spin_unlock_irqrestore (&ep->dev->lock, flags); spin_unlock_irqrestore (&ep->dev->lock, flags);
...@@ -1256,6 +1262,20 @@ net2280_set_halt (struct usb_ep *_ep, int value) ...@@ -1256,6 +1262,20 @@ net2280_set_halt (struct usb_ep *_ep, int value)
return retval; 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 static int
net2280_fifo_status (struct usb_ep *_ep) net2280_fifo_status (struct usb_ep *_ep)
{ {
...@@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = { ...@@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = {
.dequeue = net2280_dequeue, .dequeue = net2280_dequeue,
.set_halt = net2280_set_halt, .set_halt = net2280_set_halt,
.set_wedge = net2280_set_wedge,
.fifo_status = net2280_fifo_status, .fifo_status = net2280_fifo_status,
.fifo_flush = net2280_fifo_flush, .fifo_flush = net2280_fifo_flush,
}; };
...@@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
goto do_stall; goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0) if ((e = get_ep_by_addr (dev, w_index)) == 0)
goto do_stall; 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); allow_status (ep);
VDEBUG (dev, "%s clear halt\n", ep->ep.name);
goto next_endpoints; goto next_endpoints;
} }
break; break;
...@@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) ...@@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
goto do_stall; goto do_stall;
if ((e = get_ep_by_addr (dev, w_index)) == 0) if ((e = get_ep_by_addr (dev, w_index)) == 0)
goto do_stall; goto do_stall;
if (e->ep.name == ep0name)
goto do_stall;
set_halt (e); set_halt (e);
allow_status (ep); allow_status (ep);
VDEBUG (dev, "%s set halt\n", ep->ep.name); VDEBUG (dev, "%s set halt\n", ep->ep.name);
......
...@@ -109,6 +109,7 @@ struct net2280_ep { ...@@ -109,6 +109,7 @@ struct net2280_ep {
in_fifo_validate : 1, in_fifo_validate : 1,
out_overflow : 1, out_overflow : 1,
stopped : 1, stopped : 1,
wedged : 1,
is_in : 1, is_in : 1,
is_iso : 1, is_iso : 1,
responded : 1; responded : 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment