summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-11-16 10:16:00 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-12-01 14:23:36 -0800
commit1f26e28d3e32339ca683f087cd55a70e2befc333 (patch)
tree37470456cc7017af04fc9db20471c19fad17f976 /drivers/usb
parenta3b1f50ce2fdc73c7e60e04c0a2235af74deac2b (diff)
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/net2280.c8
-rw-r--r--drivers/usb/gadget/net2280.h3
2 files changed, 8 insertions, 3 deletions
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 3acc896a5d4..0b590831582 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
} /* else the irq handler advances the queue. */
+ ep->responded = 1;
if (req)
list_add_tail (&req->queue, &ep->queue);
done:
@@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && !ep->stopped)
+ } else if (ep->responded &&
+ !req && !ep->stopped)
write_fifo (ep, NULL);
}
} else {
@@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
&& req
&& req->req.actual == req->req.length)
- || !req) {
+ || (ep->responded && !req)) {
ep->dev->protocol_stall = 1;
set_halt (ep);
ep->stopped = 1;
@@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* we made the hardware handle most lowlevel requests;
* everything else goes uplevel to the gadget code.
*/
+ ep->responded = 1;
switch (u.r.bRequest) {
case USB_REQ_GET_STATUS: {
struct net2280_ep *e;
@@ -2537,6 +2540,7 @@ delegate:
u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length,
readl (&ep->regs->ep_cfg));
+ ep->responded = 0;
spin_unlock (&dev->lock);
tmp = dev->driver->setup (&dev->gadget, &u.r);
spin_lock (&dev->lock);
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index 957d6df3401..44ca139983d 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -110,7 +110,8 @@ struct net2280_ep {
out_overflow : 1,
stopped : 1,
is_in : 1,
- is_iso : 1;
+ is_iso : 1,
+ responded : 1;
};
static inline void allow_status (struct net2280_ep *ep)