diff options
Diffstat (limited to 'drivers/usb/musb/musb_gadget.c')
| -rw-r--r-- | drivers/usb/musb/musb_gadget.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 6fca870e957e..d065e23f123e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
| @@ -300,6 +300,11 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
| 300 | #ifndef CONFIG_MUSB_PIO_ONLY | 300 | #ifndef CONFIG_MUSB_PIO_ONLY |
| 301 | if (is_dma_capable() && musb_ep->dma) { | 301 | if (is_dma_capable() && musb_ep->dma) { |
| 302 | struct dma_controller *c = musb->dma_controller; | 302 | struct dma_controller *c = musb->dma_controller; |
| 303 | size_t request_size; | ||
| 304 | |||
| 305 | /* setup DMA, then program endpoint CSR */ | ||
| 306 | request_size = min_t(size_t, request->length - request->actual, | ||
| 307 | musb_ep->dma->max_len); | ||
| 303 | 308 | ||
| 304 | use_dma = (request->dma != DMA_ADDR_INVALID); | 309 | use_dma = (request->dma != DMA_ADDR_INVALID); |
| 305 | 310 | ||
| @@ -307,11 +312,6 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
| 307 | 312 | ||
| 308 | #ifdef CONFIG_USB_INVENTRA_DMA | 313 | #ifdef CONFIG_USB_INVENTRA_DMA |
| 309 | { | 314 | { |
| 310 | size_t request_size; | ||
| 311 | |||
| 312 | /* setup DMA, then program endpoint CSR */ | ||
| 313 | request_size = min_t(size_t, request->length, | ||
| 314 | musb_ep->dma->max_len); | ||
| 315 | if (request_size < musb_ep->packet_sz) | 315 | if (request_size < musb_ep->packet_sz) |
| 316 | musb_ep->dma->desired_mode = 0; | 316 | musb_ep->dma->desired_mode = 0; |
| 317 | else | 317 | else |
| @@ -373,8 +373,8 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
| 373 | use_dma = use_dma && c->channel_program( | 373 | use_dma = use_dma && c->channel_program( |
| 374 | musb_ep->dma, musb_ep->packet_sz, | 374 | musb_ep->dma, musb_ep->packet_sz, |
| 375 | 0, | 375 | 0, |
| 376 | request->dma, | 376 | request->dma + request->actual, |
| 377 | request->length); | 377 | request_size); |
| 378 | if (!use_dma) { | 378 | if (!use_dma) { |
| 379 | c->channel_release(musb_ep->dma); | 379 | c->channel_release(musb_ep->dma); |
| 380 | musb_ep->dma = NULL; | 380 | musb_ep->dma = NULL; |
| @@ -386,8 +386,8 @@ static void txstate(struct musb *musb, struct musb_request *req) | |||
| 386 | use_dma = use_dma && c->channel_program( | 386 | use_dma = use_dma && c->channel_program( |
| 387 | musb_ep->dma, musb_ep->packet_sz, | 387 | musb_ep->dma, musb_ep->packet_sz, |
| 388 | request->zero, | 388 | request->zero, |
| 389 | request->dma, | 389 | request->dma + request->actual, |
| 390 | request->length); | 390 | request_size); |
| 391 | #endif | 391 | #endif |
| 392 | } | 392 | } |
| 393 | #endif | 393 | #endif |
| @@ -501,26 +501,14 @@ void musb_g_tx(struct musb *musb, u8 epnum) | |||
| 501 | request->zero = 0; | 501 | request->zero = 0; |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | /* ... or if not, then complete it. */ | 504 | if (request->actual == request->length) { |
| 505 | musb_g_giveback(musb_ep, request, 0); | 505 | musb_g_giveback(musb_ep, request, 0); |
| 506 | 506 | request = musb_ep->desc ? next_request(musb_ep) : NULL; | |
| 507 | /* | 507 | if (!request) { |
| 508 | * Kickstart next transfer if appropriate; | 508 | DBG(4, "%s idle now\n", |
| 509 | * the packet that just completed might not | 509 | musb_ep->end_point.name); |
| 510 | * be transmitted for hours or days. | 510 | return; |
| 511 | * REVISIT for double buffering... | 511 | } |
| 512 | * FIXME revisit for stalls too... | ||
| 513 | */ | ||
| 514 | musb_ep_select(mbase, epnum); | ||
| 515 | csr = musb_readw(epio, MUSB_TXCSR); | ||
| 516 | if (csr & MUSB_TXCSR_FIFONOTEMPTY) | ||
| 517 | return; | ||
| 518 | |||
| 519 | request = musb_ep->desc ? next_request(musb_ep) : NULL; | ||
| 520 | if (!request) { | ||
| 521 | DBG(4, "%s idle now\n", | ||
| 522 | musb_ep->end_point.name); | ||
| 523 | return; | ||
| 524 | } | 512 | } |
| 525 | } | 513 | } |
| 526 | 514 | ||
| @@ -568,11 +556,19 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
| 568 | { | 556 | { |
| 569 | const u8 epnum = req->epnum; | 557 | const u8 epnum = req->epnum; |
| 570 | struct usb_request *request = &req->request; | 558 | struct usb_request *request = &req->request; |
| 571 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; | 559 | struct musb_ep *musb_ep; |
| 572 | void __iomem *epio = musb->endpoints[epnum].regs; | 560 | void __iomem *epio = musb->endpoints[epnum].regs; |
| 573 | unsigned fifo_count = 0; | 561 | unsigned fifo_count = 0; |
| 574 | u16 len = musb_ep->packet_sz; | 562 | u16 len; |
| 575 | u16 csr = musb_readw(epio, MUSB_RXCSR); | 563 | u16 csr = musb_readw(epio, MUSB_RXCSR); |
| 564 | struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; | ||
| 565 | |||
| 566 | if (hw_ep->is_shared_fifo) | ||
| 567 | musb_ep = &hw_ep->ep_in; | ||
| 568 | else | ||
| 569 | musb_ep = &hw_ep->ep_out; | ||
| 570 | |||
| 571 | len = musb_ep->packet_sz; | ||
| 576 | 572 | ||
| 577 | /* We shouldn't get here while DMA is active, but we do... */ | 573 | /* We shouldn't get here while DMA is active, but we do... */ |
| 578 | if (dma_channel_status(musb_ep->dma) == MUSB_DMA_STATUS_BUSY) { | 574 | 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) | |||
| 647 | */ | 643 | */ |
| 648 | 644 | ||
| 649 | csr |= MUSB_RXCSR_DMAENAB; | 645 | csr |= MUSB_RXCSR_DMAENAB; |
| 650 | #ifdef USE_MODE1 | ||
| 651 | csr |= MUSB_RXCSR_AUTOCLEAR; | 646 | csr |= MUSB_RXCSR_AUTOCLEAR; |
| 647 | #ifdef USE_MODE1 | ||
| 652 | /* csr |= MUSB_RXCSR_DMAMODE; */ | 648 | /* csr |= MUSB_RXCSR_DMAMODE; */ |
| 653 | 649 | ||
| 654 | /* this special sequence (enabling and then | 650 | /* this special sequence (enabling and then |
| @@ -663,10 +659,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) | |||
| 663 | if (request->actual < request->length) { | 659 | if (request->actual < request->length) { |
| 664 | int transfer_size = 0; | 660 | int transfer_size = 0; |
| 665 | #ifdef USE_MODE1 | 661 | #ifdef USE_MODE1 |
| 666 | transfer_size = min(request->length, | 662 | transfer_size = min(request->length - request->actual, |
| 667 | channel->max_len); | 663 | channel->max_len); |
| 668 | #else | 664 | #else |
| 669 | transfer_size = len; | 665 | transfer_size = min(request->length - request->actual, |
| 666 | (unsigned)len); | ||
| 670 | #endif | 667 | #endif |
| 671 | if (transfer_size <= musb_ep->packet_sz) | 668 | if (transfer_size <= musb_ep->packet_sz) |
| 672 | musb_ep->dma->desired_mode = 0; | 669 | musb_ep->dma->desired_mode = 0; |
| @@ -740,9 +737,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) | |||
| 740 | u16 csr; | 737 | u16 csr; |
| 741 | struct usb_request *request; | 738 | struct usb_request *request; |
| 742 | void __iomem *mbase = musb->mregs; | 739 | void __iomem *mbase = musb->mregs; |
| 743 | struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out; | 740 | struct musb_ep *musb_ep; |
| 744 | void __iomem *epio = musb->endpoints[epnum].regs; | 741 | void __iomem *epio = musb->endpoints[epnum].regs; |
| 745 | struct dma_channel *dma; | 742 | struct dma_channel *dma; |
| 743 | struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; | ||
| 744 | |||
| 745 | if (hw_ep->is_shared_fifo) | ||
| 746 | musb_ep = &hw_ep->ep_in; | ||
| 747 | else | ||
| 748 | musb_ep = &hw_ep->ep_out; | ||
| 746 | 749 | ||
| 747 | musb_ep_select(mbase, epnum); | 750 | musb_ep_select(mbase, epnum); |
| 748 | 751 | ||
| @@ -1081,7 +1084,7 @@ struct free_record { | |||
| 1081 | /* | 1084 | /* |
| 1082 | * Context: controller locked, IRQs blocked. | 1085 | * Context: controller locked, IRQs blocked. |
| 1083 | */ | 1086 | */ |
| 1084 | static void musb_ep_restart(struct musb *musb, struct musb_request *req) | 1087 | void musb_ep_restart(struct musb *musb, struct musb_request *req) |
| 1085 | { | 1088 | { |
| 1086 | DBG(3, "<== %s request %p len %u on hw_ep%d\n", | 1089 | DBG(3, "<== %s request %p len %u on hw_ep%d\n", |
| 1087 | req->tx ? "TX/IN" : "RX/OUT", | 1090 | req->tx ? "TX/IN" : "RX/OUT", |
