in gadget/udc/net2280.c [3098:3353]
static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
{
struct net2280_ep *ep;
u32 num, scratch;
/* most of these don't need individual acks */
stat &= ~BIT(INTA_ASSERTED);
if (!stat)
return;
/* ep_dbg(dev, "irqstat0 %04x\n", stat); */
/* starting a control request? */
if (unlikely(stat & BIT(SETUP_PACKET_INTERRUPT))) {
union {
u32 raw[2];
struct usb_ctrlrequest r;
} u;
int tmp;
struct net2280_request *req;
if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
u32 val = readl(&dev->usb->usbstat);
if (val & BIT(SUPER_SPEED)) {
dev->gadget.speed = USB_SPEED_SUPER;
usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
EP0_SS_MAX_PACKET_SIZE);
} else if (val & BIT(HIGH_SPEED)) {
dev->gadget.speed = USB_SPEED_HIGH;
usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
EP0_HS_MAX_PACKET_SIZE);
} else {
dev->gadget.speed = USB_SPEED_FULL;
usb_ep_set_maxpacket_limit(&dev->ep[0].ep,
EP0_HS_MAX_PACKET_SIZE);
}
net2280_led_speed(dev, dev->gadget.speed);
ep_dbg(dev, "%s\n",
usb_speed_string(dev->gadget.speed));
}
ep = &dev->ep[0];
ep->irqs++;
/* make sure any leftover request state is cleared */
stat &= ~BIT(ENDPOINT_0_INTERRUPT);
while (!list_empty(&ep->queue)) {
req = list_entry(ep->queue.next,
struct net2280_request, queue);
done(ep, req, (req->req.actual == req->req.length)
? 0 : -EPROTO);
}
ep->stopped = 0;
dev->protocol_stall = 0;
if (!(dev->quirks & PLX_PCIE)) {
if (ep->dev->quirks & PLX_2280)
tmp = BIT(FIFO_OVERFLOW) |
BIT(FIFO_UNDERFLOW);
else
tmp = 0;
writel(tmp | BIT(TIMEOUT) |
BIT(USB_STALL_SENT) |
BIT(USB_IN_NAK_SENT) |
BIT(USB_IN_ACK_RCVD) |
BIT(USB_OUT_PING_NAK_SENT) |
BIT(USB_OUT_ACK_SENT) |
BIT(SHORT_PACKET_OUT_DONE_INTERRUPT) |
BIT(SHORT_PACKET_TRANSFERRED_INTERRUPT) |
BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
BIT(DATA_IN_TOKEN_INTERRUPT),
&ep->regs->ep_stat);
}
u.raw[0] = readl(&dev->usb->setup0123);
u.raw[1] = readl(&dev->usb->setup4567);
cpu_to_le32s(&u.raw[0]);
cpu_to_le32s(&u.raw[1]);
if ((dev->quirks & PLX_PCIE) && !dev->bug7734_patched)
defect7374_workaround(dev, u.r);
tmp = 0;
#define w_value le16_to_cpu(u.r.wValue)
#define w_index le16_to_cpu(u.r.wIndex)
#define w_length le16_to_cpu(u.r.wLength)
/* ack the irq */
writel(BIT(SETUP_PACKET_INTERRUPT), &dev->regs->irqstat0);
stat ^= BIT(SETUP_PACKET_INTERRUPT);
/* watch control traffic at the token level, and force
* synchronization before letting the status stage happen.
* FIXME ignore tokens we'll NAK, until driver responds.
* that'll mean a lot less irqs for some drivers.
*/
ep->is_in = (u.r.bRequestType & USB_DIR_IN) != 0;
if (ep->is_in) {
scratch = BIT(DATA_PACKET_TRANSMITTED_INTERRUPT) |
BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
BIT(DATA_IN_TOKEN_INTERRUPT);
stop_out_naking(ep);
} else
scratch = BIT(DATA_PACKET_RECEIVED_INTERRUPT) |
BIT(DATA_OUT_PING_TOKEN_INTERRUPT) |
BIT(DATA_IN_TOKEN_INTERRUPT);
writel(scratch, &dev->epregs[0].ep_irqenb);
/* we made the hardware handle most lowlevel requests;
* everything else goes uplevel to the gadget code.
*/
ep->responded = 1;
if (dev->gadget.speed == USB_SPEED_SUPER) {
handle_stat0_irqs_superspeed(dev, ep, u.r);
goto next_endpoints;
}
switch (u.r.bRequest) {
case USB_REQ_GET_STATUS: {
struct net2280_ep *e;
__le32 status;
/* hw handles device and interface status */
if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
goto delegate;
e = get_ep_by_addr(dev, w_index);
if (!e || w_length > 2)
goto do_stall;
if (readl(&e->regs->ep_rsp) & BIT(SET_ENDPOINT_HALT))
status = cpu_to_le32(1);
else
status = cpu_to_le32(0);
/* don't bother with a request object! */
writel(0, &dev->epregs[0].ep_irqenb);
set_fifo_bytecount(ep, w_length);
writel((__force u32)status, &dev->epregs[0].ep_data);
allow_status(ep);
ep_vdbg(dev, "%s stat %02x\n", ep->ep.name, status);
goto next_endpoints;
}
break;
case USB_REQ_CLEAR_FEATURE: {
struct net2280_ep *e;
/* hw handles device features */
if (u.r.bRequestType != USB_RECIP_ENDPOINT)
goto delegate;
if (w_value != USB_ENDPOINT_HALT || w_length != 0)
goto do_stall;
e = get_ep_by_addr(dev, w_index);
if (!e)
goto do_stall;
if (e->wedged) {
ep_vdbg(dev, "%s wedged, halt not cleared\n",
ep->ep.name);
} else {
ep_vdbg(dev, "%s clear halt\n", e->ep.name);
clear_halt(e);
if ((ep->dev->quirks & PLX_PCIE) &&
!list_empty(&e->queue) && e->td_dma)
restart_dma(e);
}
allow_status(ep);
goto next_endpoints;
}
break;
case USB_REQ_SET_FEATURE: {
struct net2280_ep *e;
/* hw handles device features */
if (u.r.bRequestType != USB_RECIP_ENDPOINT)
goto delegate;
if (w_value != USB_ENDPOINT_HALT || w_length != 0)
goto do_stall;
e = get_ep_by_addr(dev, w_index);
if (!e)
goto do_stall;
if (e->ep.name == ep0name)
goto do_stall;
set_halt(e);
if ((dev->quirks & PLX_PCIE) && e->dma)
abort_dma(e);
allow_status(ep);
ep_vdbg(dev, "%s set halt\n", ep->ep.name);
goto next_endpoints;
}
break;
default:
delegate:
ep_vdbg(dev, "setup %02x.%02x v%04x i%04x l%04x "
"ep_cfg %08x\n",
u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length,
readl(&ep->cfg->ep_cfg));
ep->responded = 0;
if (dev->async_callbacks) {
spin_unlock(&dev->lock);
tmp = dev->driver->setup(&dev->gadget, &u.r);
spin_lock(&dev->lock);
}
}
/* stall ep0 on error */
if (tmp < 0) {
do_stall:
ep_vdbg(dev, "req %02x.%02x protocol STALL; stat %d\n",
u.r.bRequestType, u.r.bRequest, tmp);
dev->protocol_stall = 1;
}
/* some in/out token irq should follow; maybe stall then.
* driver must queue a request (even zlp) or halt ep0
* before the host times out.
*/
}
#undef w_value
#undef w_index
#undef w_length
next_endpoints:
if ((dev->quirks & PLX_PCIE) && dev->enhanced_mode) {
u32 mask = (BIT(ENDPOINT_0_INTERRUPT) |
USB3380_IRQSTAT0_EP_INTR_MASK_IN |
USB3380_IRQSTAT0_EP_INTR_MASK_OUT);
if (stat & mask) {
usb338x_handle_ep_intr(dev, stat & mask);
stat &= ~mask;
}
} else {
/* endpoint data irq ? */
scratch = stat & 0x7f;
stat &= ~0x7f;
for (num = 0; scratch; num++) {
u32 t;
/* do this endpoint's FIFO and queue need tending? */
t = BIT(num);
if ((scratch & t) == 0)
continue;
scratch ^= t;
ep = &dev->ep[num];
handle_ep_small(ep);
}
}
if (stat)
ep_dbg(dev, "unhandled irqstat0 %08x\n", stat);
}