Anand Gadiyar wrote: > MUSB: Do not enable TX and RX DMA at the same time > > This is a workaround for OMAP3 errata 1.130. > > This bug causes an occassional DMA controller hang when > two DMA channels are simultaneously enabled in RX and TX > directions. > > With this workaround, in the best case, we effectively use > DMA in both directions, and in the worst case, we use PIO > mode in one direction. The average throughput is better > than using PIO mode in one direction all the time. > > Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx> > Signed-off-by: Nilkesh Patra <Nilkesh.patra@xxxxxx> > Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx> Please ignore this patch. I sent out an older version I'll send an updated one shortly - Anand > --- > - To reproduce the hang condition, use g_ether and start > pings in both directions - higher ping sizes reproduce the > failure faster. > > - Needs another patch [1] from me to work reliably. > > [1] <http://marc.info/?l=linux-usb&m=125897074717960&w=2> > > > - An alternative workaround for this bug involves using > the SystemDMA to do a non-synchronized DMA transfer to unload > the RX FIFO, and use the MUSB DMA for all TX channels. > If someone wants to use that patch, I can post it as well. > > drivers/usb/musb/musbhsdma.c | 41 > +++++++++++++++++++++++++++++++++++++++++ > drivers/usb/musb/musbhsdma.h | 2 ++ > 2 files changed, 43 insertions(+) > > Index: linux-omap-2.6/drivers/usb/musb/musbhsdma.c > =================================================================== > --- linux-omap-2.6.orig/drivers/usb/musb/musbhsdma.c > +++ linux-omap-2.6/drivers/usb/musb/musbhsdma.c > @@ -151,6 +151,11 @@ static void configure_channel(struct dma > ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) > : 0); > > + if (musb_channel->transmit) > + controller->tx_active |= (1 << bchannel); > + else > + controller->rx_active |= (1 << bchannel); > + > /* address/count */ > musb_write_hsdma_addr(mbase, bchannel, dma_addr); > musb_write_hsdma_count(mbase, bchannel, len); > @@ -161,11 +166,32 @@ static void configure_channel(struct dma > csr); > } > > +/* In version 1.4, if two DMA channels are simultaneously > + * enabled in opposite directions, there is a chance that > + * the DMA controller will hang. However, it is safe to > + * use channels in the same direction. > + * FIXME: provide a better description here > + */ > +static int musb_okay_to_use_dma(struct musb_dma_controller > *controller, > + int is_tx) > +{ > + struct musb *musb = controller->private_data; > + > + if (musb->hwvers == MUSB_HWVERS_1400) { > + if (is_tx && controller->rx_active) > + return 0; > + else if (!is_tx && controller->tx_active) > + return 0; > + } > + return 1; > +} > + > static int dma_channel_program(struct dma_channel *channel, > u16 packet_sz, u8 mode, > dma_addr_t dma_addr, u32 len) > { > struct musb_dma_channel *musb_channel = channel->private_data; > + struct musb_dma_controller *controller = > musb_channel->controller; > > DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", > musb_channel->epnum, > @@ -175,6 +201,9 @@ static int dma_channel_program(struct dm > BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || > channel->status == MUSB_DMA_STATUS_BUSY); > > + if (!musb_okay_to_use_dma(controller, musb_channel->transmit)) > + return false; > + > channel->actual_len = 0; > musb_channel->start_addr = dma_addr; > musb_channel->len = len; > @@ -229,6 +258,11 @@ static int dma_channel_abort(struct dma_ > musb_write_hsdma_addr(mbase, bchannel, 0); > musb_write_hsdma_count(mbase, bchannel, 0); > channel->status = MUSB_DMA_STATUS_FREE; > + > + if (musb_channel->transmit) > + musb_channel->controller->tx_active &= > ~(1 << bchannel); > + else > + musb_channel->controller->rx_active &= > ~(1 << bchannel); > } > > return 0; > @@ -292,6 +326,13 @@ static irqreturn_t dma_controller_irq(in > > channel->status = MUSB_DMA_STATUS_FREE; > > + if (musb_channel->transmit) > + controller->tx_active &= > + ~(1 << > bchannel); > + else > + controller->rx_active &= > + ~(1 << > bchannel); > + > /* completed */ > if ((devctl & MUSB_DEVCTL_HM) > && (musb_channel->transmit) > Index: linux-omap-2.6/drivers/usb/musb/musbhsdma.h > =================================================================== > --- linux-omap-2.6.orig/drivers/usb/musb/musbhsdma.h > +++ linux-omap-2.6/drivers/usb/musb/musbhsdma.h > @@ -146,4 +146,6 @@ struct musb_dma_controller { > u8 channel_count; > u8 used_channels; > u8 irq; > + u8 tx_active; > + u8 rx_active; > }; > -- 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