aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/net2280.c40
-rw-r--r--drivers/usb/gadget/net2280.h1
2 files changed, 35 insertions, 6 deletions
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 5cfb5ebf3881..8ae70de2c37d 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)
178 178
179 /* ep_reset() has already been called */ 179 /* ep_reset() has already been called */
180 ep->stopped = 0; 180 ep->stopped = 0;
181 ep->wedged = 0;
181 ep->out_overflow = 0; 182 ep->out_overflow = 0;
182 183
183 /* set speed-dependent max packet; may kick in high bandwidth */ 184 /* 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)
1218static int net2280_fifo_status (struct usb_ep *_ep); 1219static int net2280_fifo_status (struct usb_ep *_ep);
1219 1220
1220static int 1221static int
1221net2280_set_halt (struct usb_ep *_ep, int value) 1222net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
1222{ 1223{
1223 struct net2280_ep *ep; 1224 struct net2280_ep *ep;
1224 unsigned long flags; 1225 unsigned long flags;
@@ -1239,16 +1240,21 @@ net2280_set_halt (struct usb_ep *_ep, int value)
1239 else if (ep->is_in && value && net2280_fifo_status (_ep) != 0) 1240 else if (ep->is_in && value && net2280_fifo_status (_ep) != 0)
1240 retval = -EAGAIN; 1241 retval = -EAGAIN;
1241 else { 1242 else {
1242 VDEBUG (ep->dev, "%s %s halt\n", _ep->name, 1243 VDEBUG (ep->dev, "%s %s %s\n", _ep->name,
1243 value ? "set" : "clear"); 1244 value ? "set" : "clear",
1245 wedged ? "wedge" : "halt");
1244 /* set/clear, then synch memory views with the device */ 1246 /* set/clear, then synch memory views with the device */
1245 if (value) { 1247 if (value) {
1246 if (ep->num == 0) 1248 if (ep->num == 0)
1247 ep->dev->protocol_stall = 1; 1249 ep->dev->protocol_stall = 1;
1248 else 1250 else
1249 set_halt (ep); 1251 set_halt (ep);
1250 } else 1252 if (wedged)
1253 ep->wedged = 1;
1254 } else {
1251 clear_halt (ep); 1255 clear_halt (ep);
1256 ep->wedged = 0;
1257 }
1252 (void) readl (&ep->regs->ep_rsp); 1258 (void) readl (&ep->regs->ep_rsp);
1253 } 1259 }
1254 spin_unlock_irqrestore (&ep->dev->lock, flags); 1260 spin_unlock_irqrestore (&ep->dev->lock, flags);
@@ -1257,6 +1263,20 @@ net2280_set_halt (struct usb_ep *_ep, int value)
1257} 1263}
1258 1264
1259static int 1265static int
1266net2280_set_halt(struct usb_ep *_ep, int value)
1267{
1268 return net2280_set_halt_and_wedge(_ep, value, 0);
1269}
1270
1271static int
1272net2280_set_wedge(struct usb_ep *_ep)
1273{
1274 if (!_ep || _ep->name == ep0name)
1275 return -EINVAL;
1276 return net2280_set_halt_and_wedge(_ep, 1, 1);
1277}
1278
1279static int
1260net2280_fifo_status (struct usb_ep *_ep) 1280net2280_fifo_status (struct usb_ep *_ep)
1261{ 1281{
1262 struct net2280_ep *ep; 1282 struct net2280_ep *ep;
@@ -1302,6 +1322,7 @@ static const struct usb_ep_ops net2280_ep_ops = {
1302 .dequeue = net2280_dequeue, 1322 .dequeue = net2280_dequeue,
1303 1323
1304 .set_halt = net2280_set_halt, 1324 .set_halt = net2280_set_halt,
1325 .set_wedge = net2280_set_wedge,
1305 .fifo_status = net2280_fifo_status, 1326 .fifo_status = net2280_fifo_status,
1306 .fifo_flush = net2280_fifo_flush, 1327 .fifo_flush = net2280_fifo_flush,
1307}; 1328};
@@ -2410,9 +2431,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2410 goto do_stall; 2431 goto do_stall;
2411 if ((e = get_ep_by_addr (dev, w_index)) == 0) 2432 if ((e = get_ep_by_addr (dev, w_index)) == 0)
2412 goto do_stall; 2433 goto do_stall;
2413 clear_halt (e); 2434 if (e->wedged) {
2435 VDEBUG(dev, "%s wedged, halt not cleared\n",
2436 ep->ep.name);
2437 } else {
2438 VDEBUG(dev, "%s clear halt\n", ep->ep.name);
2439 clear_halt(e);
2440 }
2414 allow_status (ep); 2441 allow_status (ep);
2415 VDEBUG (dev, "%s clear halt\n", ep->ep.name);
2416 goto next_endpoints; 2442 goto next_endpoints;
2417 } 2443 }
2418 break; 2444 break;
@@ -2427,6 +2453,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2427 goto do_stall; 2453 goto do_stall;
2428 if ((e = get_ep_by_addr (dev, w_index)) == 0) 2454 if ((e = get_ep_by_addr (dev, w_index)) == 0)
2429 goto do_stall; 2455 goto do_stall;
2456 if (e->ep.name == ep0name)
2457 goto do_stall;
2430 set_halt (e); 2458 set_halt (e);
2431 allow_status (ep); 2459 allow_status (ep);
2432 VDEBUG (dev, "%s set halt\n", ep->ep.name); 2460 VDEBUG (dev, "%s set halt\n", ep->ep.name);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 81a71dbdc2c6..c36852263d93 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -109,6 +109,7 @@ struct net2280_ep {
109 in_fifo_validate : 1, 109 in_fifo_validate : 1,
110 out_overflow : 1, 110 out_overflow : 1,
111 stopped : 1, 111 stopped : 1,
112 wedged : 1,
112 is_in : 1, 113 is_in : 1,
113 is_iso : 1, 114 is_iso : 1,
114 responded : 1; 115 responded : 1;