From: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx> rewriting of dma code for musb_g_rx function. Signed-off-by: Arnaud Mandy <ext-arnaud.2.mandy@xxxxxxxxx> Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxx> --- drivers/usb/musb/musb_core.c | 7 ++- drivers/usb/musb/musb_core.h | 2 +- drivers/usb/musb/musb_gadget.c | 91 ++++++++++++++++++++++++++++++++++------ drivers/usb/musb/musb_gadget.h | 2 +- 4 files changed, 84 insertions(+), 18 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7ec5f9e..632e8ac 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1537,7 +1537,7 @@ irqreturn_t musb_interrupt(struct musb *musb) musb_host_rx(musb, ep_num); } else { if (is_peripheral_capable()) - musb_g_rx(musb, ep_num); + musb_g_rx(musb, ep_num, false); } } @@ -1608,7 +1608,7 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) musb_host_rx(musb, epnum); } else { if (is_peripheral_capable()) - musb_g_rx(musb, epnum); + musb_g_rx(musb, epnum, true); } } } @@ -1908,6 +1908,7 @@ bad_config: musb->board_mode = plat->mode; musb->board_set_power = plat->set_power; musb->min_power = plat->min_power; + musb->use_dma = use_dma; /* Clock usage is chip-specific ... functional clock (DaVinci, * OMAP2430), or PHY ref (some TUSB6010 boards). All this core @@ -1957,7 +1958,7 @@ bad_config: } #endif /* ideally this would be abstracted in platform setup */ - if (!is_dma_capable() || !musb->dma_controller) + if (!musb->use_dma || !musb->dma_controller) dev->dma_mask = NULL; /* be sure interrupts are disabled before connecting ISR */ diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index cdef6e7..644fcd8 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -116,7 +116,7 @@ struct musb_ep; extern irqreturn_t musb_g_ep0_irq(struct musb *); extern void musb_g_tx(struct musb *, u8); -extern void musb_g_rx(struct musb *, u8); +extern void musb_g_rx(struct musb *, u8, bool); extern void musb_g_reset(struct musb *); extern void musb_g_suspend(struct musb *); extern void musb_g_resume(struct musb *); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 240e16e..cbfb25e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -586,27 +586,52 @@ static void do_pio_rx(struct musb *musb, struct musb_request *req) /* * Data ready for a request; called from IRQ */ -void musb_g_rx(struct musb *musb, u8 epnum) +void musb_g_rx(struct musb *musb, u8 epnum, bool is_dma) { u16 csr; + struct musb_request *req; struct usb_request *request; void __iomem *mbase = musb->mregs; struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; void __iomem *epio = musb->endpoints[epnum].regs; + struct dma_channel *dma; musb_ep_select(mbase, epnum); + csr = musb_readw(epio, MUSB_RXCSR); + +restart: + + if (csr == 0) { + DBG(3, "spurious IRQ\n"); + return; + } + request = next_request(musb_ep); - csr = musb_readw(epio, MUSB_RXCSR); + if (!request) { + DBG(1, "waiting for request for %s (csr %04x)\n", + musb_ep->name, csr); + musb_ep->rx_pending = true; + return; + } - DBG(4, "<== %s, rxcsr %04x %p\n", musb_ep->end_point.name, - csr, request); + dma = musb_ep->dma; + DBG(4, "<== %s, rxcsr %04x %p (dma %s, %s)\n", musb_ep->name, + csr, request, dma ? "enabled" : "disabled", + is_dma ? "true" : "false"); if (csr & MUSB_RXCSR_P_SENTSTALL) { + DBG(5, "ep%d is halted, cannot transfer\n", epnum); csr |= MUSB_RXCSR_P_WZC_BITS; csr &= ~MUSB_RXCSR_P_SENTSTALL; musb_writew(epio, MUSB_RXCSR, csr); + if (dma != NULL && + dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + } + return; } @@ -623,15 +648,55 @@ void musb_g_rx(struct musb *musb, u8 epnum) /* REVISIT not necessarily an error */ DBG(4, "%s, incomprx\n", musb_ep->end_point.name); } + req = to_musb_request(request); - /* analyze request if the ep is hot */ - if (request) { - do_pio_rx(musb, to_musb_request(request)); - } else { - DBG(3, "packet waiting for %s%s request\n", - musb_ep->desc ? "" : "inactive ", - musb_ep->end_point.name); - musb_ep->rx_pending = true; + BUG_ON(dma == NULL && (csr & MUSB_RXCSR_DMAENAB)); + + if (dma != NULL) { + u32 len; + + /* We do handle stalls yet. */ + BUG_ON(csr & MUSB_RXCSR_P_SENDSTALL); + + /* We abort() so dma->actual_len gets updated */ + musb->dma_controller->channel_abort(dma); + + /* We only expect full packets. */ + BUG_ON(dma->actual_len & (musb_ep->packet_sz - 1)); + + request->actual += dma->actual_len; + len = dma->actual_len; + + stop_dma(musb, musb_ep, req); + dma = NULL; + + DBG(4, "RXCSR%d %04x, dma off, %04x, len %zu, req %p\n", + epnum, csr, musb_readw(epio, MUSB_RXCSR), + len, request); + + if (!is_dma) { + /* Unload with pio */ + do_pio_rx(musb, req); + } else { + BUG_ON(request->actual != request->length); + musb_g_giveback(musb_ep, request, 0); + } + return; + } + + if (dma == NULL && musb->use_dma) { + if (start_dma(musb, req) == 0) + dma = musb_ep->dma; + } + + if (dma == NULL) { + do_pio_rx(musb, req); + csr = musb_readw(epio, MUSB_RXCSR); + if (csr & MUSB_RXCSR_RXPKTRDY) { + DBG(2, "new packet in FIFO, restarting RX " + "(CSR %04x)\n", csr); + goto restart; + } } } @@ -934,7 +999,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, if (!request->tx && musb_ep->rx_pending) { DBG(1, "processing pending RX\n"); musb_ep->rx_pending = false; - musb_g_rx(musb, musb_ep->current_epnum); + musb_g_rx(musb, musb_ep->current_epnum, false); } cleanup: diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 3a0899b..f602df8 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -100,7 +100,7 @@ static inline struct usb_request *next_request(struct musb_ep *ep) } extern void musb_g_tx(struct musb *musb, u8 epnum); -extern void musb_g_rx(struct musb *musb, u8 epnum); +extern void musb_g_rx(struct musb *musb, u8 epnum, bool is_dma); extern const struct usb_ep_ops musb_g_ep0_ops; -- 1.6.6.rc0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html