From patchwork Fri Jan 22 18:18:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Anderson X-Patchwork-Id: 8091781 Return-Path: X-Original-To: patchwork-linux-rockchip@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 8B91EBEEE5 for ; Fri, 22 Jan 2016 18:20:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6D8442053D for ; Fri, 22 Jan 2016 18:20:06 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6859F204AF for ; Fri, 22 Jan 2016 18:20:05 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aMgJY-0004DE-Qi; Fri, 22 Jan 2016 18:20:04 +0000 Received: from mail-pa0-x22a.google.com ([2607:f8b0:400e:c03::22a]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aMgJR-0003tN-1o for linux-rockchip@lists.infradead.org; Fri, 22 Jan 2016 18:19:58 +0000 Received: by mail-pa0-x22a.google.com with SMTP id uo6so46332093pac.1 for ; Fri, 22 Jan 2016 10:19:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=1Ba2NAPUbbm5W5iFBpXsrWcjgCbMLcF2mkxa5QwGh9A=; b=d91RyedNnTiVqFSoIv63BuL/mESF2HvT6n+IZJceBy6E1IAwYSSST43p6HShuVctSk rhlKQjQs9PmdclY8PLLgML1vXpVtiMRC1zvgXZHjo1RGDahzp0slAyNI+bmRz8oLHjGD 56cYhTQFZAzY/K2TNlQ/TkGaFYFlAdRixCC+M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1Ba2NAPUbbm5W5iFBpXsrWcjgCbMLcF2mkxa5QwGh9A=; b=kbP2b2Asxk1ZP9McUm8T0PitUdxdOx593OG1hkkByuFRZGmCQOL3YG0nmpEbVgfENu JVX6FkWo8Np94zBRTcLbU6/0dxRTpzJ3kAtbDjVPSlYoOSRT5jyQh5BvAjH30a5Brnip QHh3rJnSDx7Bun5TBLno/nFNSyv5txszl//Rcx1a7OuLlbrLG+GwBS9ekrE0el01XFan JAgEQf1FaQ8BCcUMD7bwtROP1o6aEIqo72HVpKZY7DJ1n8i+CshyYmPmlSh2FceOYCu2 kgAsxJ0vA3RdtbxxFD9flOh1bDxisBrCRSwMeHyj8yZ578EL1v5EGUqKzqpE4qyQvdbg 9Jpw== X-Gm-Message-State: AG10YOQ+gt4NK3HTdPafwvop5GRvAbdMZE9yaK7KgkHM9Rl82mqLHa3hdr7lVnTIstJgmQ== X-Received: by 10.66.252.6 with SMTP id zo6mr6347931pac.154.1453486776380; Fri, 22 Jan 2016 10:19:36 -0800 (PST) Received: from tictac.mtv.corp.google.com ([172.22.65.76]) by smtp.gmail.com with ESMTPSA id y86sm11276415pfa.26.2016.01.22.10.19.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 22 Jan 2016 10:19:35 -0800 (PST) From: Douglas Anderson To: John Youn , balbi@ti.com, kever.yang@rock-chips.com Subject: [PATCH v5 07/21] usb: dwc2: hcd: fix split transfer schedule sequence Date: Fri, 22 Jan 2016 10:18:42 -0800 Message-Id: <1453486736-15358-8-git-send-email-dianders@chromium.org> X-Mailer: git-send-email 2.7.0.rc3.207.g0ac5344 In-Reply-To: <1453486736-15358-1-git-send-email-dianders@chromium.org> References: <1453486736-15358-1-git-send-email-dianders@chromium.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160122_101957_158152_8519F08E X-CRM114-Status: GOOD ( 18.78 ) X-Spam-Score: -2.7 (--) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: huangtao@rock-chips.com, gregory.herrero@intel.com, heiko@sntech.de, johnyoun@synopsys.com, gregkh@linuxfoundation.org, ming.lei@canonical.com, linux-usb@vger.kernel.org, Douglas Anderson , linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, yousaf.kaukab@intel.com, stern@rowland.harvard.edu, Yunzhi Li , william.wu@rock-chips.com, Julius Werner , dinguyen@opensource.altera.com MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We're supposed to keep outstanding splits in order. Keep track of a list of the order of splits and process channel interrupts in that order. Without this change and the following setup: * Rockchip rk3288 Chromebook, using port ff540000 -> Pluggable 7-port Hub with Charging (powered) -> Microsoft Wireless Keyboard 2000 in port 1. -> Das Keyboard in port 2. ...I find that I get dropped keys on the Microsoft keyboard (I'm sure there are other combinations that fail, but this documents my test). Specifically I've been typing "hahahahahahaha" on the keyboard and often see keys dropped or repeated. After this change the above setup works properly. This patch is based on a previous patch proposed by Yunzhi Li ("usb: dwc2: hcd: fix periodic transfer schedule sequence") Signed-off-by: Douglas Anderson Signed-off-by: Yunzhi Li Reviewed-by: Kever Yang Tested-by: Kever Yang --- Changes in v5: - Move list maintenance to hcd.c to avoid gadget-only compile error Changes in v4: - fix split transfer schedule sequence new for v4. Changes in v3: None Changes in v2: None drivers/usb/dwc2/core.c | 2 ++ drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/hcd.c | 8 ++++++++ drivers/usb/dwc2/hcd.h | 2 ++ drivers/usb/dwc2/hcd_intr.c | 17 +++++++++++++++++ 5 files changed, 31 insertions(+) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 73f2771b7740..ed73b26818c0 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -1676,6 +1676,8 @@ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan) chan->xfer_started = 0; + list_del_init(&chan->split_order_list_entry); + /* * Clear channel interrupt enables and any unhandled channel interrupt * conditions diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 7fb6434f4639..538cf38af0e4 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -657,6 +657,7 @@ struct dwc2_hregs_backup { * periodic_sched_ready because it must be rescheduled for * the next frame. Otherwise, the item moves to * periodic_sched_inactive. + * @split_order: List keeping track of channels doing splits, in order. * @periodic_usecs: Total bandwidth claimed so far for periodic transfers. * This value is in microseconds per (micro)frame. The * assumption is that all periodic transfers may occur in @@ -780,6 +781,7 @@ struct dwc2_hsotg { struct list_head periodic_sched_ready; struct list_head periodic_sched_assigned; struct list_head periodic_sched_queued; + struct list_head split_order; u16 periodic_usecs; u16 frame_usecs[8]; u16 frame_number; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index d2daaea88d91..87ad5bf2d166 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1045,6 +1045,11 @@ static int dwc2_queue_transaction(struct dwc2_hsotg *hsotg, { int retval = 0; + if (chan->do_split) + /* Put ourselves on the list to keep order straight */ + list_move_tail(&chan->split_order_list_entry, + &hsotg->split_order); + if (hsotg->core_params->dma_enable > 0) { if (hsotg->core_params->dma_desc_enable > 0) { if (!chan->xfer_started || @@ -3151,6 +3156,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) INIT_LIST_HEAD(&hsotg->periodic_sched_assigned); INIT_LIST_HEAD(&hsotg->periodic_sched_queued); + INIT_LIST_HEAD(&hsotg->split_order); + /* * Create a host channel descriptor for each host channel implemented * in the controller. Initialize the channel descriptor array. @@ -3164,6 +3171,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) if (channel == NULL) goto error3; channel->hc_num = i; + INIT_LIST_HEAD(&channel->split_order_list_entry); hsotg->hc_ptr_array[i] = channel; } diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 42f2e4e233da..1b46e2e617cc 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -106,6 +106,7 @@ struct dwc2_qh; * @hc_list_entry: For linking to list of host channels * @desc_list_addr: Current QH's descriptor list DMA address * @desc_list_sz: Current QH's descriptor list size + * @split_order_list_entry: List entry for keeping track of the order of splits * * This structure represents the state of a single host channel when acting in * host mode. It contains the data items needed to transfer packets to an @@ -158,6 +159,7 @@ struct dwc2_host_chan { struct list_head hc_list_entry; dma_addr_t desc_list_addr; u32 desc_list_sz; + struct list_head split_order_list_entry; }; struct dwc2_hcd_pipe_info { diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 2c521c00e5e0..577c91096a51 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -2067,6 +2067,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg) { u32 haint; int i; + struct dwc2_host_chan *chan, *chan_tmp; haint = dwc2_readl(hsotg->regs + HAINT); if (dbg_perio()) { @@ -2075,6 +2076,22 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg) dev_vdbg(hsotg->dev, "HAINT=%08x\n", haint); } + /* + * According to USB 2.0 spec section 11.18.8, a host must + * issue complete-split transactions in a microframe for a + * set of full-/low-speed endpoints in the same relative + * order as the start-splits were issued in a microframe for. + */ + list_for_each_entry_safe(chan, chan_tmp, &hsotg->split_order, + split_order_list_entry) { + int hc_num = chan->hc_num; + + if (haint & (1 << hc_num)) { + dwc2_hc_n_intr(hsotg, hc_num); + haint &= ~(1 << hc_num); + } + } + for (i = 0; i < hsotg->core_params->host_channels; i++) { if (haint & (1 << i)) dwc2_hc_n_intr(hsotg, i);