diff options
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 86 |
1 files changed, 60 insertions, 26 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 73b0b7fc77f1..742eb8268e9a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1496,6 +1496,7 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc) | |||
1496 | } | 1496 | } |
1497 | 1497 | ||
1498 | static irqreturn_t dwc3_interrupt(int irq, void *_dwc); | 1498 | static irqreturn_t dwc3_interrupt(int irq, void *_dwc); |
1499 | static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc); | ||
1499 | 1500 | ||
1500 | static int dwc3_gadget_start(struct usb_gadget *g, | 1501 | static int dwc3_gadget_start(struct usb_gadget *g, |
1501 | struct usb_gadget_driver *driver) | 1502 | struct usb_gadget_driver *driver) |
@@ -1566,8 +1567,8 @@ static int dwc3_gadget_start(struct usb_gadget *g, | |||
1566 | dwc3_ep0_out_start(dwc); | 1567 | dwc3_ep0_out_start(dwc); |
1567 | 1568 | ||
1568 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); | 1569 | irq = platform_get_irq(to_platform_device(dwc->dev), 0); |
1569 | ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED, | 1570 | ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt, |
1570 | "dwc3", dwc); | 1571 | IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc); |
1571 | if (ret) { | 1572 | if (ret) { |
1572 | dev_err(dwc->dev, "failed to request irq #%d --> %d\n", | 1573 | dev_err(dwc->dev, "failed to request irq #%d --> %d\n", |
1573 | irq, ret); | 1574 | irq, ret); |
@@ -2432,40 +2433,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc, | |||
2432 | } | 2433 | } |
2433 | } | 2434 | } |
2434 | 2435 | ||
2436 | static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc) | ||
2437 | { | ||
2438 | struct dwc3 *dwc = _dwc; | ||
2439 | unsigned long flags; | ||
2440 | irqreturn_t ret = IRQ_NONE; | ||
2441 | int i; | ||
2442 | |||
2443 | spin_lock_irqsave(&dwc->lock, flags); | ||
2444 | |||
2445 | for (i = 0; i < dwc->num_event_buffers; i++) { | ||
2446 | struct dwc3_event_buffer *evt; | ||
2447 | int left; | ||
2448 | |||
2449 | evt = dwc->ev_buffs[i]; | ||
2450 | left = evt->count; | ||
2451 | |||
2452 | if (!(evt->flags & DWC3_EVENT_PENDING)) | ||
2453 | continue; | ||
2454 | |||
2455 | while (left > 0) { | ||
2456 | union dwc3_event event; | ||
2457 | |||
2458 | event.raw = *(u32 *) (evt->buf + evt->lpos); | ||
2459 | |||
2460 | dwc3_process_event_entry(dwc, &event); | ||
2461 | |||
2462 | /* | ||
2463 | * FIXME we wrap around correctly to the next entry as | ||
2464 | * almost all entries are 4 bytes in size. There is one | ||
2465 | * entry which has 12 bytes which is a regular entry | ||
2466 | * followed by 8 bytes data. ATM I don't know how | ||
2467 | * things are organized if we get next to the a | ||
2468 | * boundary so I worry about that once we try to handle | ||
2469 | * that. | ||
2470 | */ | ||
2471 | evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; | ||
2472 | left -= 4; | ||
2473 | |||
2474 | dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4); | ||
2475 | } | ||
2476 | |||
2477 | evt->count = 0; | ||
2478 | evt->flags &= ~DWC3_EVENT_PENDING; | ||
2479 | ret = IRQ_HANDLED; | ||
2480 | } | ||
2481 | |||
2482 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
2483 | |||
2484 | return ret; | ||
2485 | } | ||
2486 | |||
2435 | static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) | 2487 | static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) |
2436 | { | 2488 | { |
2437 | struct dwc3_event_buffer *evt; | 2489 | struct dwc3_event_buffer *evt; |
2438 | int left; | ||
2439 | u32 count; | 2490 | u32 count; |
2440 | 2491 | ||
2492 | evt = dwc->ev_buffs[buf]; | ||
2493 | |||
2441 | count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); | 2494 | count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf)); |
2442 | count &= DWC3_GEVNTCOUNT_MASK; | 2495 | count &= DWC3_GEVNTCOUNT_MASK; |
2443 | if (!count) | 2496 | if (!count) |
2444 | return IRQ_NONE; | 2497 | return IRQ_NONE; |
2445 | 2498 | ||
2446 | evt = dwc->ev_buffs[buf]; | 2499 | evt->count = count; |
2447 | left = count; | 2500 | evt->flags |= DWC3_EVENT_PENDING; |
2448 | |||
2449 | while (left > 0) { | ||
2450 | union dwc3_event event; | ||
2451 | |||
2452 | event.raw = *(u32 *) (evt->buf + evt->lpos); | ||
2453 | |||
2454 | dwc3_process_event_entry(dwc, &event); | ||
2455 | /* | ||
2456 | * XXX we wrap around correctly to the next entry as almost all | ||
2457 | * entries are 4 bytes in size. There is one entry which has 12 | ||
2458 | * bytes which is a regular entry followed by 8 bytes data. ATM | ||
2459 | * I don't know how things are organized if were get next to the | ||
2460 | * a boundary so I worry about that once we try to handle that. | ||
2461 | */ | ||
2462 | evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE; | ||
2463 | left -= 4; | ||
2464 | |||
2465 | dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4); | ||
2466 | } | ||
2467 | 2501 | ||
2468 | return IRQ_HANDLED; | 2502 | return IRQ_WAKE_THREAD; |
2469 | } | 2503 | } |
2470 | 2504 | ||
2471 | static irqreturn_t dwc3_interrupt(int irq, void *_dwc) | 2505 | static irqreturn_t dwc3_interrupt(int irq, void *_dwc) |
@@ -2480,7 +2514,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc) | |||
2480 | irqreturn_t status; | 2514 | irqreturn_t status; |
2481 | 2515 | ||
2482 | status = dwc3_process_event_buf(dwc, i); | 2516 | status = dwc3_process_event_buf(dwc, i); |
2483 | if (status == IRQ_HANDLED) | 2517 | if (status == IRQ_WAKE_THREAD) |
2484 | ret = status; | 2518 | ret = status; |
2485 | } | 2519 | } |
2486 | 2520 | ||