From patchwork Mon Apr 3 17:49:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Tomsich X-Patchwork-Id: 746613 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3vxflC62D8z9s83 for ; Tue, 4 Apr 2017 03:50:15 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 78E82C21C80; Mon, 3 Apr 2017 17:50:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 42022C21C2E; Mon, 3 Apr 2017 17:50:09 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C73F5C21C2E; Mon, 3 Apr 2017 17:50:07 +0000 (UTC) Received: from mail.theobroma-systems.com (vegas.theobroma-systems.com [144.76.126.164]) by lists.denx.de (Postfix) with ESMTPS id 78DBFC21C26 for ; Mon, 3 Apr 2017 17:50:07 +0000 (UTC) Received: from [86.59.122.178] (port=38924 helo=android.lan) by mail.theobroma-systems.com with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1cv679-0003Hn-OO; Mon, 03 Apr 2017 19:50:03 +0200 From: Philipp Tomsich To: u-boot@lists.denx.de Date: Mon, 3 Apr 2017 19:49:58 +0200 Message-Id: <1491241798-37084-1-git-send-email-philipp.tomsich@theobroma-systems.com> X-Mailer: git-send-email 1.9.1 Cc: Marek Vasut , Philipp Tomsich , Felipe Balbi , Klaus Goger , Andy Shevchenko Subject: [U-Boot] [PATCH] usb: dwc3: gadget: make cache-maintenance on event buffers more robust X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Merely using dma_alloc_coherent does not ensure that there is no stale data left in the caches for the allocated DMA buffer (i.e. that the affected cacheline may still be dirty). The original code was doing the following (on AArch64, which translates a 'flush' into a 'clean + invalidate'): # during initialisation: 1. allocate buffers via memalign => buffers may still be modified (cached, dirty) # during interrupt processing 2. clean + invalidate buffers => may commit stale data from a modified cacheline 3. read from buffers This could lead to garbage info being written to buffers before reading them during even-processing. To make the event processing more robust, we use the following sequence for the cache-maintenance: # during initialisation: 1. allocate buffers via memalign 2. clean + invalidate buffers (we only need the 'invalidate' part, but dwc3_flush_cache() always performs a 'clean + invalidate') # during interrupt processing 3. read the buffers (we know these lines are not cached, due to the previous invalidation and no other code touching them in-between) 4. clean + invalidate buffers => writes back any modification we may have made during event processing and ensures that the lines are not in the cache the next time we enter interrupt processing Note that with the original sequence, we observe reproducible (depending on the cache state: i.e. running dhcp/usb start before will upset caches to get us around this) issues in the event processing (a fatal synchronous abort in dwc3_gadget_uboot_handle_interrupt on the first time interrupt handling is invoked) when running USB mass storage emulation on our RK3399-Q7 with data-caches on. Signed-off-by: Philipp Tomsich --- drivers/usb/dwc3/core.c | 2 ++ drivers/usb/dwc3/gadget.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b2c7eb1..f58c7ba 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -125,6 +125,8 @@ static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, if (!evt->buf) return ERR_PTR(-ENOMEM); + dwc3_flush_cache((long)evt->buf, evt->length); + return evt; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 1156662..61af71b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2668,11 +2668,12 @@ void dwc3_gadget_uboot_handle_interrupt(struct dwc3 *dwc) int i; struct dwc3_event_buffer *evt; + dwc3_thread_interrupt(0, dwc); + + /* Clean + Invalidate the buffers after touching them */ for (i = 0; i < dwc->num_event_buffers; i++) { evt = dwc->ev_buffs[i]; dwc3_flush_cache((long)evt->buf, evt->length); } - - dwc3_thread_interrupt(0, dwc); } }