aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2011-06-30 09:57:15 -0400
committerFelipe Balbi <balbi@ti.com>2013-03-18 05:17:11 -0400
commitb15a762f02acb4f1e695a17435f719350f9d5bc1 (patch)
tree3153d80d78c504213d3580b8262b182bd0df3ecd /drivers/usb/dwc3
parent60d04bbee0b729dc1e95d4dc669f68dea2a32570 (diff)
usb: dwc3: gadget: move to threaded IRQ
by moving to threaded IRQs, we allow our IRQ priorities to be configurable when running with realtime patch. Also, since we're running in thread context, we can call functions which might sleep, such as sysfs_notify() without problems. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/gadget.c86
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
1498static irqreturn_t dwc3_interrupt(int irq, void *_dwc); 1498static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
1499static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
1499 1500
1500static int dwc3_gadget_start(struct usb_gadget *g, 1501static 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
2436static 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
2435static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf) 2487static 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
2471static irqreturn_t dwc3_interrupt(int irq, void *_dwc) 2505static 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