summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/udc/aspeed-vhub
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@linux.vnet.ibm.com>2018-06-28 09:01:54 +1000
committerFelipe Balbi <felipe.balbi@linux.intel.com>2018-07-17 10:12:51 +0300
commit9196b55e1270da125d5f126c1b91f1843e552f17 (patch)
treed7a52c9fefa03d7f8d5f17fdf53e8c820a8f4325 /drivers/usb/gadget/udc/aspeed-vhub
parent24dd9ba1c55f7e00352f4b8d7449fc0cbecb1f54 (diff)
usb: gadget: aspeed-vhub: Fix SETUP packets with OUT data phase
A couple of bugs in the driver are preventing SETUP packets with an OUT data phase from working properly. Interestingly those are incredibly rare (RNDIS typically uses them and thus is broken without this fix). The main problem was an incorrect register offset being applied for arming RX on EP0. The other problem relates to stalling such a packet before the data phase, in which case we don't get an ACK cycle, and get the next SETUP packet directly, so we shouldn't reject it. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/gadget/udc/aspeed-vhub')
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/ep0.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
index 20ffb03ff6ac..44f2b3b53b2f 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/ep0.c
@@ -108,6 +108,13 @@ void ast_vhub_ep0_handle_setup(struct ast_vhub_ep *ep)
/* Check our state, cancel pending requests if needed */
if (ep->ep0.state != ep0_state_token) {
EPDBG(ep, "wrong state\n");
+ ast_vhub_nuke(ep, -EIO);
+
+ /*
+ * Accept the packet regardless, this seems to happen
+ * when stalling a SETUP packet that has an OUT data
+ * phase.
+ */
ast_vhub_nuke(ep, 0);
goto stall;
}
@@ -224,7 +231,7 @@ static void ast_vhub_ep0_rx_prime(struct ast_vhub_ep *ep)
EPVDBG(ep, "rx prime\n");
/* Prime endpoint for receiving data */
- writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat + AST_VHUB_EP0_CTRL);
+ writel(VHUB_EP0_RX_BUFF_RDY, ep->ep0.ctlstat);
}
static void ast_vhub_ep0_do_receive(struct ast_vhub_ep *ep, struct ast_vhub_req *req,