mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 13:15:57 +00:00
usb: musb: cppi41: fix not transmitting zero length packet issue
CPPI TX does not transmit ZLP for TX transfers which - transfer size is multiple of EP packet size, - and URB_ZERO_PACKET is set in urb->transfer_flags. The fix is transmitting the ZLP using PIO mode after the CPPI TX is done. Validated using the following usbtest write case in MUSB host mode. # testusb -t1 -c1 Signed-off-by: Bin Liu <b-liu@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
69e273c0b0
commit
9267edaf8c
@ -39,6 +39,7 @@ struct cppi41_dma_channel {
|
|||||||
u32 transferred;
|
u32 transferred;
|
||||||
u32 packet_sz;
|
u32 packet_sz;
|
||||||
struct list_head tx_check;
|
struct list_head tx_check;
|
||||||
|
int tx_zlp;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MUSB_DMA_NUM_CHANNELS 15
|
#define MUSB_DMA_NUM_CHANNELS 15
|
||||||
@ -122,6 +123,8 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
|
|||||||
{
|
{
|
||||||
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
|
struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
|
||||||
struct musb *musb = hw_ep->musb;
|
struct musb *musb = hw_ep->musb;
|
||||||
|
void __iomem *epio = hw_ep->regs;
|
||||||
|
u16 csr;
|
||||||
|
|
||||||
if (!cppi41_channel->prog_len ||
|
if (!cppi41_channel->prog_len ||
|
||||||
(cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {
|
(cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {
|
||||||
@ -131,15 +134,24 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
|
|||||||
cppi41_channel->transferred;
|
cppi41_channel->transferred;
|
||||||
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
|
cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
|
||||||
cppi41_channel->channel.rx_packet_done = true;
|
cppi41_channel->channel.rx_packet_done = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* transmit ZLP using PIO mode for transfers which size is
|
||||||
|
* multiple of EP packet size.
|
||||||
|
*/
|
||||||
|
if (cppi41_channel->tx_zlp && (cppi41_channel->transferred %
|
||||||
|
cppi41_channel->packet_sz) == 0) {
|
||||||
|
musb_ep_select(musb->mregs, hw_ep->epnum);
|
||||||
|
csr = MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY;
|
||||||
|
musb_writew(epio, MUSB_TXCSR, csr);
|
||||||
|
}
|
||||||
musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
|
musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
|
||||||
} else {
|
} else {
|
||||||
/* next iteration, reload */
|
/* next iteration, reload */
|
||||||
struct dma_chan *dc = cppi41_channel->dc;
|
struct dma_chan *dc = cppi41_channel->dc;
|
||||||
struct dma_async_tx_descriptor *dma_desc;
|
struct dma_async_tx_descriptor *dma_desc;
|
||||||
enum dma_transfer_direction direction;
|
enum dma_transfer_direction direction;
|
||||||
u16 csr;
|
|
||||||
u32 remain_bytes;
|
u32 remain_bytes;
|
||||||
void __iomem *epio = cppi41_channel->hw_ep->regs;
|
|
||||||
|
|
||||||
cppi41_channel->buf_addr += cppi41_channel->packet_sz;
|
cppi41_channel->buf_addr += cppi41_channel->packet_sz;
|
||||||
|
|
||||||
@ -363,6 +375,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
|
|||||||
cppi41_channel->total_len = len;
|
cppi41_channel->total_len = len;
|
||||||
cppi41_channel->transferred = 0;
|
cppi41_channel->transferred = 0;
|
||||||
cppi41_channel->packet_sz = packet_sz;
|
cppi41_channel->packet_sz = packet_sz;
|
||||||
|
cppi41_channel->tx_zlp = (cppi41_channel->is_tx && mode) ? 1 : 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
|
* Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
|
||||||
|
Loading…
x
Reference in New Issue
Block a user