Hi, >-----Original Message----- >From: Gupta, Ajay Kumar >Sent: Thursday, May 13, 2010 3:41 PM >To: Kalliguddi, Hema; Gadiyar, Anand; me@xxxxxxxxxxxxxxx >Cc: linux-usb@xxxxxxxxxxxxxxx; linux-omap@xxxxxxxxxxxxxxx >Subject: RE: [PATCH 2/5] musb: use system DMA to fix Inventra >DMA issue on RTL-1.4 > >Hi, >> >> > > Another approach to use PIO mode in opposite direction would >> >> > > increase >> >> the >> >> > > cpu loading and thus using system DMA is preferred workaround. >> >> > > >> >> > > Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx> >> >> > > Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx> >> >> > >> >> > I think falling back to pio is better than this patch. >> >At the cost of cpu, which certainly is not preferred. >> > >> >>> It will most likely be only one transfer. >> > >> >How about host mode with multiple devices connected and doing >> >transfers? >> >Falling back to PIO would kill the cpu. >> > >> >>> Another approach is to allocate dma channels on a transfer basis. >> > >> >Can you elaborate this? >> >> It might be good idea to allocate the dma channels on >tarnsfer basis as >> Felipe >> Suggested. The musb driver allocates dma channels for the >first 8 enabled >> endpoints and higher endpoints works in PIO mode. >> For system dma if there are more nummber of Rx endpoints >enabled but not >> used for data >> Transfer you might end up having many sdma channles >allocated biut not >> used which will >> Impact in the system of not utilizing the sdma channels effectively. > >Felipe, Is this what you meant? If so then I have a patch >(copied below) >to fix this and I can post this one along with others. > >-------------- cut here ----------------- >Currently DMA channels are allocated and they remain allocated >even if there is no active data transfer. Added channel_release() >whenever there is no pending request. > >Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx> >--- > drivers/usb/musb/musb_gadget.c | 27 +++++++++++++++++++++------ > drivers/usb/musb/musb_host.c | 14 ++++++++++++-- > 2 files changed, 33 insertions(+), 8 deletions(-) > >diff --git a/drivers/usb/musb/musb_gadget.c >b/drivers/usb/musb/musb_gadget.c >index fd842af..477a009 100644 >--- a/drivers/usb/musb/musb_gadget.c >+++ b/drivers/usb/musb/musb_gadget.c >@@ -297,9 +297,13 @@ static void txstate(struct musb *musb, >struct musb_request *req) > csr); > > #ifndef CONFIG_MUSB_PIO_ONLY >- if (is_dma_capable() && musb_ep->dma) { >+ >+ if (is_dma_capable() && musb->dma_controller) { > struct dma_controller *c = musb->dma_controller; > >+ if (!musb_ep->dma) >+ musb_ep->dma = c->channel_alloc(c, >musb_ep->hw_ep, 1); If the channel_alloc returns failure then there should be a way to fallback to PIO mode. I am posting a patch for dynamic dma channel allocation for mentor dma for gadget driver. ~Hema >+ > use_dma = (request->dma != DMA_ADDR_INVALID); > > /* MUSB_TXCSR_P_ISO is still set correctly */ >@@ -433,6 +437,7 @@ void musb_g_tx(struct musb *musb, u8 epnum) > u8 __iomem *mbase = musb->mregs; > struct musb_ep *musb_ep = >&musb->endpoints[epnum].ep_in; > void __iomem *epio = musb->endpoints[epnum].regs; >+ struct dma_controller *c = musb->dma_controller; > struct dma_channel *dma; > > musb_ep_select(mbase, epnum); >@@ -535,6 +540,10 @@ void musb_g_tx(struct musb *musb, u8 epnum) > if (!request) { > DBG(4, "%s idle now\n", > musb_ep->end_point.name); >+ if (musb_ep->dma) { >+ >c->channel_release(musb_ep->dma); >+ musb_ep->dma = NULL; >+ } > return; > } > } >@@ -585,6 +594,7 @@ static void rxstate(struct musb *musb, >struct musb_request *req) > struct usb_request *request = &req->request; > struct musb_ep *musb_ep = >&musb->endpoints[epnum].ep_out; > void __iomem *epio = musb->endpoints[epnum].regs; >+ struct dma_controller *c = musb->dma_controller; > unsigned fifo_count = 0; > u16 len = musb_ep->packet_sz; > u16 csr = musb_readw(epio, MUSB_RXCSR); >@@ -601,8 +611,10 @@ static void rxstate(struct musb *musb, >struct musb_request *req) > return; > } > >+ if (is_dma_capable() && musb->dma_controller && !musb_ep->dma) >+ musb_ep->dma = c->channel_alloc(c, musb_ep->hw_ep, 0); >+ > if ((is_cppi_enabled() || is_cppi41_enabled()) && >musb_ep->dma) { >- struct dma_controller *c = musb->dma_controller; > struct dma_channel *channel = musb_ep->dma; > > /* NOTE: CPPI won't actually stop advancing the DMA >@@ -633,11 +645,9 @@ static void rxstate(struct musb *musb, >struct musb_request *req) > if (request->actual < request->length) { > #ifdef CONFIG_USB_INVENTRA_DMA > if (is_dma_capable() && musb_ep->dma) { >- struct dma_controller *c; > struct dma_channel *channel; > int use_dma = 0; > >- c = musb->dma_controller; > channel = musb_ep->dma; > > /* We use DMA Req mode 0 in rx_csr, and DMA controller >operates in >@@ -719,7 +729,6 @@ static void rxstate(struct musb *musb, >struct musb_request *req) > > #ifdef CONFIG_USB_TUSB_OMAP_DMA > if (tusb_dma_omap() && musb_ep->dma) { >- struct dma_controller *c = >musb->dma_controller; > struct dma_channel *channel = >musb_ep->dma; > u32 dma_addr = request->dma + >request->actual; > int ret; >@@ -764,6 +773,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) > void __iomem *mbase = musb->mregs; > struct musb_ep *musb_ep = >&musb->endpoints[epnum].ep_out; > void __iomem *epio = musb->endpoints[epnum].regs; >+ struct dma_controller *c = musb->dma_controller; > struct dma_channel *dma; > > musb_ep_select(mbase, epnum); >@@ -838,8 +848,13 @@ void musb_g_rx(struct musb *musb, u8 epnum) > musb_g_giveback(musb_ep, request, 0); > > request = next_request(musb_ep); >- if (!request) >+ if (!request) { >+ if (musb_ep->dma) { >+ c->channel_release(musb_ep->dma); >+ musb_ep->dma = NULL; >+ } > return; >+ } > } > > /* analyze request if the ep is hot */ >diff --git a/drivers/usb/musb/musb_host.c >b/drivers/usb/musb/musb_host.c >index 89c8c35..001a1d6 100644 >--- a/drivers/usb/musb/musb_host.c >+++ b/drivers/usb/musb/musb_host.c >@@ -460,11 +460,21 @@ static void musb_advance_schedule(struct >musb *musb, struct urb *urb, > */ > if (list_empty(&qh->hep->urb_list)) { > struct list_head *head; >+ struct dma_controller *dma = musb->dma_controller; > >- if (is_in) >+ if (is_in) { > ep->rx_reinit = 1; >- else >+ if (ep->rx_channel) { >+ dma->channel_release(ep->rx_channel); >+ ep->rx_channel = NULL; >+ } >+ } else { > ep->tx_reinit = 1; >+ if (ep->tx_channel) { >+ dma->channel_release(ep->tx_channel); >+ ep->tx_channel = NULL; >+ } >+ } > > /* Clobber old pointers to this qh */ > musb_ep_set_qh(ep, is_in, NULL); >-- >1.6.2.4 > > >----------------------------------------- >-Ajay >> >-- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html