|
@@ -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);
|