Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp429979imu; Tue, 8 Jan 2019 23:39:19 -0800 (PST) X-Google-Smtp-Source: ALg8bN67QWbX7hv+VeOEVqaAaeuBMQHqm7ERWYS8NjIJM/pPHEYN9jMfr6Nr+gZXZci5uqFJYTrX X-Received: by 2002:a63:4611:: with SMTP id t17mr4400715pga.119.1547019558993; Tue, 08 Jan 2019 23:39:18 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547019558; cv=none; d=google.com; s=arc-20160816; b=EH9P+hY8K2ChiqM/TErrz/co6tJXr8VJZvSTvBumPcCyc/8fi3tuyZH6F5yDbHdnlQ qdDbVMdUlGJo+lEdhXDHM8Kj8HJlz1rXVq9XRnYWPb+v7DpRTxYipz/jodeQdEkSobhE 1g7srdxgdxion55HqiJhGkM8RDKPaFUFaucRyqLGHo2NFYbVhDeolScS45rGzn3tgi3O L3GtCcTTAFtNOIFkPD/GyocY93u0CucIueRxwm67fzP6aJ0prdMqGE47WdX5/7LUj3Ze NkEavDo+4KtNmUJWeV4ld9AgiWlr1ApjFzdKGECyJiZMq+kjtnxr+QLJ/Qc0RF+tmeER 9gtA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=UOH0+Gym9AUXSaTTNZOGl8AG4pBrIfxMAmp1Slf1HM0=; b=X8bi3Zu3GGTc3iXj0ns6H4QQUaLiu+Tt+NSbkC/+az6AH8atgrMqiIkykTlXHqjyZ7 VEGYodOI7SIHVXvqbZ8lBznEDHbhDPs7+zIB3gRqKZIm817mbsdgVAxlpw3Qf5lLVeYE 3V8A71boAhlzHoifNI4SvQgYirYII0nZk9zfvftaxp7uucou6UJqwd1y1AXCirO1S6PH H5J6ZhHCjZFgeH8yXzLkER1iz3e/YDwXUWxsN/8c1VlvArZX3nfqDqUs+qTacEtPeUOV e2f6LafzgEDAXPnBMtP+exhFwy6Wk81q5LVCBlATHfi6jMk/y+ZQD2rPovABZTfjEdzF q1SQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=uwHupPkp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 66si2538539plc.125.2019.01.08.23.39.04; Tue, 08 Jan 2019 23:39:18 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=uwHupPkp; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729952AbfAIHKf (ORCPT + 99 others); Wed, 9 Jan 2019 02:10:35 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:50432 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729158AbfAIHKd (ORCPT ); Wed, 9 Jan 2019 02:10:33 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 2B2DC56D; Wed, 9 Jan 2019 08:10:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1547017831; bh=CDwyaoUsdx/TBITpDivgHrnF++KmX3Jy7YDopjvE9ps=; h=From:To:Cc:Subject:Date:From; b=uwHupPkpTMQXq/akMOnJmKXAk53VzQh+Bpq1ncLt9oAOdvShR/m75G5e9Mg8M8z+W e1vHnxWDTQtlNHy5Z42TCnnqRykZmf29YOHJLSaLqwA+BPg5mvwhfBQwGvM5DMk8qp p/IHogtHyQ9ugnRNBmjoI86Pg8D4SSMjsBVq1zXY= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , drinkcat@chromium.org, b-liu@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] usb: gadget: musb: fix short isoc packets with inventra dma Date: Wed, 9 Jan 2019 02:10:09 -0500 Message-Id: <20190109071009.27625-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Handling short packets (length < max packet size) in the Inventra DMA engine in the MUSB driver causes the MUSB DMA controller to hang. An example of a problem that is caused by this problem is when streaming video out of a UVC gadget, only the first video frame is transferred. For short packets (mode-0 or mode-1 DMA), MUSB_TXCSR_TXPKTRDY must be set manually by the driver. This was previously done in musb_g_tx (musb_gadget.c), but incorrectly (all csr flags were cleared, and only MUSB_TXCSR_MODE and MUSB_TXCSR_TXPKTRDY were set). Fixing that problem allows some requests to be transferred correctly, but multiple requests were often put together in one USB packet, and caused problems if the packet size was not a multiple of 4. Instead, set MUSB_TXCSR_TXPKTRDY in dma_controller_irq (musbhsdma.c), just like host mode transfers. This topic was originally tackled by Nicolas Boichat [0] [1] and is discussed further at [2] as part of his GSoC project [3]. [0] https://groups.google.com/forum/?hl=en#!topic/beagleboard-gsoc/k8Azwfp75CU [1] https://gitorious.org/beagleboard-usbsniffer/beagleboard-usbsniffer-kernel/commit/b0be3b6cc195ba732189b04f1d43ec843c3e54c9?p=beagleboard-usbsniffer:beagleboard-usbsniffer-kernel.git;a=patch;h=b0be3b6cc195ba732189b04f1d43ec843c3e54c9 [2] http://beagleboard-usbsniffer.blogspot.com/2010/07/musb-isochronous-transfers-fixed.html [3] http://elinux.org/BeagleBoard/GSoC/USBSniffer Signed-off-by: Paul Elder --- Changes in v2: - no more flushing FIFO - greatly simplified short packet if guard in musb_g_tx, and removed unnecessary variables - minor indentation and wording changes drivers/usb/musb/musb_gadget.c | 19 +++++-------------- drivers/usb/musb/musbhsdma.c | 21 +++++++++++---------- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index eae8b1b1b45b..496643f54faa 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum) } if (request) { - u8 is_dma = 0; - bool short_packet = false; trace_musb_req_tx(req); if (dma && (csr & MUSB_TXCSR_DMAENAB)) { - is_dma = 1; csr |= MUSB_TXCSR_P_WZC_BITS; csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET); @@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum) */ if ((request->zero && request->length) && (request->length % musb_ep->packet_sz == 0) - && (request->actual == request->length)) - short_packet = true; + && (request->actual == request->length)) { - if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) && - (is_dma && (!dma->desired_mode || - (request->actual & - (musb_ep->packet_sz - 1))))) - short_packet = true; - - if (short_packet) { /* * On DMA completion, FIFO may not be * available yet... @@ -493,8 +482,10 @@ void musb_g_tx(struct musb *musb, u8 epnum) if (csr & MUSB_TXCSR_TXPKTRDY) return; - musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_MODE - | MUSB_TXCSR_TXPKTRDY); + musb_dbg(musb, "sending short pkt (zero=%d, length=%d, actual=%d, dma->desired_mode=%d)\n", + request->zero, request->length, request->actual, + dma->desired_mode); + musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_TXPKTRDY); request->zero = 0; } diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index a688f7f87829..5fc6825745f2 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) channel->status = MUSB_DMA_STATUS_FREE; /* completed */ - if ((devctl & MUSB_DEVCTL_HM) - && (musb_channel->transmit) - && ((channel->desired_mode == 0) - || (channel->actual_len & - (musb_channel->max_packet_sz - 1))) - ) { + if (musb_channel->transmit && + (!channel->desired_mode || + (channel->actual_len % + musb_channel->max_packet_sz))) { u8 epnum = musb_channel->epnum; int offset = musb->io.ep_offset(epnum, MUSB_TXCSR); @@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) */ musb_ep_select(mbase, epnum); txcsr = musb_readw(mbase, offset); - txcsr &= ~(MUSB_TXCSR_DMAENAB + if (channel->desired_mode == 1) { + txcsr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_AUTOSET); - musb_writew(mbase, offset, txcsr); - /* Send out the packet */ - txcsr &= ~MUSB_TXCSR_DMAMODE; + musb_writew(mbase, offset, txcsr); + /* Send out the packet */ + txcsr &= ~MUSB_TXCSR_DMAMODE; + txcsr |= MUSB_TXCSR_DMAENAB; + } txcsr |= MUSB_TXCSR_TXPKTRDY; musb_writew(mbase, offset, txcsr); } -- 2.20.1