From patchwork Fri Feb 6 11:52:35 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ajay Kumar Gupta X-Patchwork-Id: 5867 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n16Bqtrg007887 for ; Fri, 6 Feb 2009 11:52:55 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752389AbZBFLwx (ORCPT ); Fri, 6 Feb 2009 06:52:53 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754680AbZBFLwx (ORCPT ); Fri, 6 Feb 2009 06:52:53 -0500 Received: from comal.ext.ti.com ([198.47.26.152]:40070 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752389AbZBFLww (ORCPT ); Fri, 6 Feb 2009 06:52:52 -0500 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id n16BqbLd003731; Fri, 6 Feb 2009 05:52:43 -0600 Received: from gitsvr01.india.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id n16BqZ0W002806; Fri, 6 Feb 2009 17:22:36 +0530 (IST) Received: from gitsvr01.india.ti.com (localhost [127.0.0.1]) by gitsvr01.india.ti.com (8.13.1/8.13.1) with ESMTP id n16BqZuY004107; Fri, 6 Feb 2009 17:22:35 +0530 Received: (from a0393629@localhost) by gitsvr01.india.ti.com (8.13.1/8.13.1/Submit) id n16BqZob004104; Fri, 6 Feb 2009 17:22:35 +0530 From: Ajay Kumar Gupta To: linux-usb@vger.kernel.org Cc: linux-omap@vger.kernel.org, david-b@pacbell.net, felipe.balbi@nokia.com, Ajay Kumar Gupta Subject: [PATCH 3/3] usb: musb: NAK timeout scheme on bulk reserved ep Date: Fri, 6 Feb 2009 17:22:35 +0530 Message-Id: <1233921155-4077-1-git-send-email-ajay.gupta@ti.com> X-Mailer: git-send-email 1.5.6 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org Fixes endpoint starvation issue when more than one bulk qhs are multiplexed on reserved bulk endpoint.NAK timeout interval is set for such qhs and next qh is scheduled when NAK timeout occurs. This scheme doesn't work for devices which are connected to a high to full speed tree as there is no NAK timeout interrupt at musb controller from such devices. Signed-off-by: Ajay Kumar Gupta --- drivers/usb/musb/musb_host.c | 63 ++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 60 insertions(+), 3 deletions(-) diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 1a78f00..255b1d1 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1366,6 +1366,49 @@ finish: #endif +/* Schedule next qh from musb->in_bulk and add the current qh at tail + * to avoid endpoint starvation. + */ +static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) +{ + struct dma_channel *dma; + struct urb *urb; + void __iomem *mbase = musb->mregs; + void __iomem *epio = ep->regs; + struct musb_qh *cur_qh, *next_qh; + u16 rx_csr; + + musb_ep_select(mbase, ep->epnum); + dma = is_dma_capable() ? ep->rx_channel : NULL; + + /* clear nak timeout bit */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + + cur_qh = first_qh(&musb->in_bulk); + if (cur_qh) { + urb = next_urb(cur_qh); + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } + musb_save_toggle(ep, 1, urb); + + /* delete cur_qh and add to tail to musb->in_bulk */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); + + /* get the next qh from musb->in_bulk */ + next_qh = first_qh(&musb->in_bulk); + + /* set rx_reinit and schedule the next qh */ + ep->rx_reinit = 1; + musb_start_urb(musb, 1, next_qh); + } +} + /* * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, * and high-bandwidth IN transfer cases. @@ -1437,10 +1480,14 @@ void musb_host_rx(struct musb *musb, u8 epnum) * we have a candidate... NAKing is *NOT* an error */ DBG(6, "RX end %d NAK timeout\n", epnum); + if (usb_pipebulk(urb->pipe) && qh->mux == 1 && + !list_is_singular(&musb->in_bulk)) { + musb_bulk_nak_timeout(musb, hw_ep); + return; + } musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS - | MUSB_RXCSR_H_REQPKT); + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); goto finish; } else { @@ -1774,6 +1821,16 @@ static int musb_schedule( head = &musb->in_bulk; else head = &musb->out_bulk; + /* Enable bulk NAK time out scheme when bulk requests are + * multiplxed.This scheme doen't work in high speed to full + * speed scenario as NAK interrupts are not coming from a + * full speed device connected to a high speed device. + * NAK timeout interval is 8 (128 uframe or 16ms) for HS and + * 4 (8 frame or 8ms) for FS device. + */ + if (is_in && qh->dev) + qh->intv_reg = + (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; goto success; } else if (best_end < 0) { return -ENOSPC;