Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: net2280: don't send unwanted zero-length packets

The net2280 driver is too eager to send zero-length packets when
IN tokens are received on ep0. No such packet should be sent (the
driver should NAK) before the gadget driver has queued the proper
response. Otherwise deferred responses are impossible.

This patch (as823) makes net2280 avoid sending ZLPs for IN transfers
on ep0 until a response has been submitted, and avoids stalling when an
OUT packet is received before a request has been submitted for an OUT
transfer on ep0.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
1f26e28d a3b1f50c

+8 -3
+6 -2
drivers/usb/gadget/net2280.c
··· 1040 1040 1041 1041 } /* else the irq handler advances the queue. */ 1042 1042 1043 + ep->responded = 1; 1043 1044 if (req) 1044 1045 list_add_tail (&req->queue, &ep->queue); 1045 1046 done: ··· 2189 2188 ep->stopped = 1; 2190 2189 set_halt (ep); 2191 2190 mode = 2; 2192 - } else if (!req && !ep->stopped) 2191 + } else if (ep->responded && 2192 + !req && !ep->stopped) 2193 2193 write_fifo (ep, NULL); 2194 2194 } 2195 2195 } else { ··· 2205 2203 } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) 2206 2204 && req 2207 2205 && req->req.actual == req->req.length) 2208 - || !req) { 2206 + || (ep->responded && !req)) { 2209 2207 ep->dev->protocol_stall = 1; 2210 2208 set_halt (ep); 2211 2209 ep->stopped = 1; ··· 2471 2469 /* we made the hardware handle most lowlevel requests; 2472 2470 * everything else goes uplevel to the gadget code. 2473 2471 */ 2472 + ep->responded = 1; 2474 2473 switch (u.r.bRequest) { 2475 2474 case USB_REQ_GET_STATUS: { 2476 2475 struct net2280_ep *e; ··· 2540 2537 u.r.bRequestType, u.r.bRequest, 2541 2538 w_value, w_index, w_length, 2542 2539 readl (&ep->regs->ep_cfg)); 2540 + ep->responded = 0; 2543 2541 spin_unlock (&dev->lock); 2544 2542 tmp = dev->driver->setup (&dev->gadget, &u.r); 2545 2543 spin_lock (&dev->lock);
+2 -1
drivers/usb/gadget/net2280.h
··· 110 110 out_overflow : 1, 111 111 stopped : 1, 112 112 is_in : 1, 113 - is_iso : 1; 113 + is_iso : 1, 114 + responded : 1; 114 115 }; 115 116 116 117 static inline void allow_status (struct net2280_ep *ep)