|
@@ -300,6 +300,11 @@ static void txstate(struct musb *musb, struct musb_request *req)
|
|
|
#ifndef CONFIG_MUSB_PIO_ONLY
|
|
|
if (is_dma_capable() && musb_ep->dma) {
|
|
|
struct dma_controller *c = musb->dma_controller;
|
|
|
+ size_t request_size;
|
|
|
+
|
|
|
+ /* setup DMA, then program endpoint CSR */
|
|
|
+ request_size = min_t(size_t, request->length - request->actual,
|
|
|
+ musb_ep->dma->max_len);
|
|
|
|
|
|
use_dma = (request->dma != DMA_ADDR_INVALID);
|
|
|
|
|
@@ -307,11 +312,6 @@ static void txstate(struct musb *musb, struct musb_request *req)
|
|
|
|
|
|
#ifdef CONFIG_USB_INVENTRA_DMA
|
|
|
{
|
|
|
- size_t request_size;
|
|
|
-
|
|
|
- /* setup DMA, then program endpoint CSR */
|
|
|
- request_size = min_t(size_t, request->length,
|
|
|
- musb_ep->dma->max_len);
|
|
|
if (request_size < musb_ep->packet_sz)
|
|
|
musb_ep->dma->desired_mode = 0;
|
|
|
else
|
|
@@ -373,8 +373,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
|
|
|
use_dma = use_dma && c->channel_program(
|
|
|
musb_ep->dma, musb_ep->packet_sz,
|
|
|
0,
|
|
|
- request->dma,
|
|
|
- request->length);
|
|
|
+ request->dma + request->actual,
|
|
|
+ request_size);
|
|
|
if (!use_dma) {
|
|
|
c->channel_release(musb_ep->dma);
|
|
|
musb_ep->dma = NULL;
|
|
@@ -386,8 +386,8 @@ static void txstate(struct musb *musb, struct musb_request *req)
|
|
|
use_dma = use_dma && c->channel_program(
|
|
|
musb_ep->dma, musb_ep->packet_sz,
|
|
|
request->zero,
|
|
|
- request->dma,
|
|
|
- request->length);
|
|
|
+ request->dma + request->actual,
|
|
|
+ request_size);
|
|
|
#endif
|
|
|
}
|
|
|
#endif
|
|
@@ -501,26 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epnum)
|
|
|
request->zero = 0;
|
|
|
}
|
|
|
|
|
|
- /* ... or if not, then complete it. */
|
|
|
- musb_g_giveback(musb_ep, request, 0);
|
|
|
-
|
|
|
- /*
|
|
|
- * Kickstart next transfer if appropriate;
|
|
|
- * the packet that just completed might not
|
|
|
- * be transmitted for hours or days.
|
|
|
- * REVISIT for double buffering...
|
|
|
- * FIXME revisit for stalls too...
|
|
|
- */
|
|
|
- musb_ep_select(mbase, epnum);
|
|
|
- csr = musb_readw(epio, MUSB_TXCSR);
|
|
|
- if (csr & MUSB_TXCSR_FIFONOTEMPTY)
|
|
|
- return;
|
|
|
-
|
|
|
- request = musb_ep->desc ? next_request(musb_ep) : NULL;
|
|
|
- if (!request) {
|
|
|
- DBG(4, "%s idle now\n",
|
|
|
- musb_ep->end_point.name);
|
|
|
- return;
|
|
|
+ if (request->actual == request->length) {
|
|
|
+ musb_g_giveback(musb_ep, request, 0);
|
|
|
+ request = musb_ep->desc ? next_request(musb_ep) : NULL;
|
|
|
+ if (!request) {
|
|
|
+ DBG(4, "%s idle now\n",
|
|
|
+ musb_ep->end_point.name);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -568,11 +556,19 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
|
|
{
|
|
|
const u8 epnum = req->epnum;
|
|
|
struct usb_request *request = &req->request;
|
|
|
- struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
|
|
|
+ struct musb_ep *musb_ep;
|
|
|
void __iomem *epio = musb->endpoints[epnum].regs;
|
|
|
unsigned fifo_count = 0;
|
|
|
- u16 len = musb_ep->packet_sz;
|
|
|
+ u16 len;
|
|
|
u16 csr = musb_readw(epio, MUSB_RXCSR);
|
|
|
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
|
|
|
+
|
|
|
+ if (hw_ep->is_shared_fifo)
|
|
|
+ musb_ep = &hw_ep->ep_in;
|
|
|
+ else
|
|
|
+ musb_ep = &hw_ep->ep_out;
|
|
|
+
|
|
|
+ len = musb_ep->packet_sz;
|
|
|
|
|
|
/* We shouldn't get here while DMA is active, but we do... */
|
|
|
if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) {
|
|
@@ -647,8 +643,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
|
|
*/
|
|
|
|
|
|
csr |= MUSB_RXCSR_DMAENAB;
|
|
|
-#ifdef USE_MODE1
|
|
|
csr |= MUSB_RXCSR_AUTOCLEAR;
|
|
|
+#ifdef USE_MODE1
|
|
|
/* csr |= MUSB_RXCSR_DMAMODE; */
|
|
|
|
|
|
/* this special sequence (enabling and then
|
|
@@ -663,10 +659,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
|
|
if (request->actual < request->length) {
|
|
|
int transfer_size = 0;
|
|
|
#ifdef USE_MODE1
|
|
|
- transfer_size = min(request->length,
|
|
|
+ transfer_size = min(request->length - request->actual,
|
|
|
channel->max_len);
|
|
|
#else
|
|
|
- transfer_size = len;
|
|
|
+ transfer_size = min(request->length - request->actual,
|
|
|
+ (unsigned)len);
|
|
|
#endif
|
|
|
if (transfer_size <= musb_ep->packet_sz)
|
|
|
musb_ep->dma->desired_mode = 0;
|
|
@@ -740,9 +737,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
|
|
|
u16 csr;
|
|
|
struct usb_request *request;
|
|
|
void __iomem *mbase = musb->mregs;
|
|
|
- struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
|
|
|
+ struct musb_ep *musb_ep;
|
|
|
void __iomem *epio = musb->endpoints[epnum].regs;
|
|
|
struct dma_channel *dma;
|
|
|
+ struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
|
|
|
+
|
|
|
+ if (hw_ep->is_shared_fifo)
|
|
|
+ musb_ep = &hw_ep->ep_in;
|
|
|
+ else
|
|
|
+ musb_ep = &hw_ep->ep_out;
|
|
|
|
|
|
musb_ep_select(mbase, epnum);
|
|
|
|
|
@@ -1081,7 +1084,7 @@ struct free_record {
|
|
|
/*
|
|
|
* Context: controller locked, IRQs blocked.
|
|
|
*/
|
|
|
-static void musb_ep_restart(struct musb *musb, struct musb_request *req)
|
|
|
+void musb_ep_restart(struct musb *musb, struct musb_request *req)
|
|
|
{
|
|
|
DBG(3, "<== %s request %p len %u on hw_ep%d\n",
|
|
|
req->tx ? "TX/IN" : "RX/OUT",
|