From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.5 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SPF_PASS,URIBL_BLOCKED,USER_AGENT_MUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3E5B3C10F14 for ; Fri, 12 Apr 2019 13:17:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 187DC2054F for ; Fri, 12 Apr 2019 13:17:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727057AbfDLNRf (ORCPT ); Fri, 12 Apr 2019 09:17:35 -0400 Received: from foss.arm.com ([217.140.101.70]:60828 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726842AbfDLNRe (ORCPT ); Fri, 12 Apr 2019 09:17:34 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C902015AD; Fri, 12 Apr 2019 06:17:33 -0700 (PDT) Received: from fuggles.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 204E33F68F; Fri, 12 Apr 2019 06:17:29 -0700 (PDT) Date: Fri, 12 Apr 2019 14:17:27 +0100 From: Will Deacon To: Benjamin Herrenschmidt Cc: Linus Torvalds , linux-arch , Linux List Kernel Mailing , "Paul E. McKenney" , Michael Ellerman , Arnd Bergmann , Peter Zijlstra , Andrea Parri , Palmer Dabbelt , Daniel Lustig , David Howells , Alan Stern , "Maciej W. Rozycki" , Paul Burton , Ingo Molnar , Yoshinori Sato , Rich Felker , Tony Luck , Mikulas Patocka , Akira Yokosawa , Luis Chamberlain , Nicholas Piggin Subject: Re: [PATCH v2 01/21] docs/memory-barriers.txt: Rewrite "KERNEL I/O BARRIER EFFECTS" section Message-ID: <20190412131727.GB29218@fuggles.cambridge.arm.com> References: <20190405135936.7266-1-will.deacon@arm.com> <20190405135936.7266-2-will.deacon@arm.com> <080d1ec73e3e29d6ffeeeb50b39b613da28afb37.camel@kernel.crashing.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.11.1+86 (6f28e57d73f2) () Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Apr 12, 2019 at 12:07:09PM +1000, Benjamin Herrenschmidt wrote: > On Thu, 2019-04-11 at 15:34 -0700, Linus Torvalds wrote: > > On Thu, Apr 11, 2019 at 3:13 PM Benjamin Herrenschmidt > > wrote: > > > > > > Minor nit... I would have said "All readX() and writeX() accesses > > > _from > > > the same CPU_ to the same peripheral... and then s/the CPU/this > > > CPU. > > > > Maybe talk about "same thread" rather than "same cpu", with the > > understanding that scheduling/preemption has to include the > > appropriate cross-CPU IO barrier? > > Works for me, but why not spell all this out in the document ? We know, > but others might not. Ok, how about the diff below on top of: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git/log/?h=for-next/mmiowb ? I do plan to investigate ioremap_wc() and friends in the future, but it's been painful enough just dealing with the common case! I'll almost certainly need your help with that too. Will --->8 diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 1660dde75e14..8ce298e09d54 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -2524,26 +2524,30 @@ guarantees: 1. All readX() and writeX() accesses to the same peripheral are ordered with respect to each other. This ensures that MMIO register writes by - the CPU to a particular device will arrive in program order. - - 2. A writeX() by the CPU to the peripheral will first wait for the - completion of all prior CPU writes to memory. This ensures that - writes by the CPU to an outbound DMA buffer allocated by - dma_alloc_coherent() will be visible to a DMA engine when the CPU - writes to its MMIO control register to trigger the transfer. - - 3. A readX() by the CPU from the peripheral will complete before any - subsequent CPU reads from memory can begin. This ensures that reads - by the CPU from an incoming DMA buffer allocated by - dma_alloc_coherent() will not see stale data after reading from the - DMA engine's MMIO status register to establish that the DMA transfer - has completed. - - 4. A readX() by the CPU from the peripheral will complete before any - subsequent delay() loop can begin execution. This ensures that two - MMIO register writes by the CPU to a peripheral will arrive at least - 1us apart if the first write is immediately read back with readX() - and udelay(1) is called prior to the second writeX(): + the same CPU thread to a particular device will arrive in program + order. + + 2. A writeX() by a CPU thread to the peripheral will first wait for the + completion of all prior writes to memory either issued by the thread + or issued while holding a spinlock that was subsequently taken by the + thread. This ensures that writes by the CPU to an outbound DMA + buffer allocated by dma_alloc_coherent() will be visible to a DMA + engine when the CPU writes to its MMIO control register to trigger + the transfer. + + 3. A readX() by a CPU thread from the peripheral will complete before + any subsequent reads from memory by the same thread can begin. This + ensures that reads by the CPU from an incoming DMA buffer allocated + by dma_alloc_coherent() will not see stale data after reading from + the DMA engine's MMIO status register to establish that the DMA + transfer has completed. + + 4. A readX() by a CPU thread from the peripheral will complete before + any subsequent delay() loop can begin execution on the same thread. + This ensures that two MMIO register writes by the CPU to a peripheral + will arrive at least 1us apart if the first write is immediately read + back with readX() and udelay(1) is called prior to the second + writeX(): writel(42, DEVICE_REGISTER_0); // Arrives at the device... readl(DEVICE_REGISTER_0); @@ -2600,8 +2604,10 @@ guarantees: These will perform appropriately for the type of access they're actually doing, be it inX()/outX() or readX()/writeX(). -All of these accessors assume that the underlying peripheral is little-endian, -and will therefore perform byte-swapping operations on big-endian architectures. +With the exception of the string accessors (insX(), outsX(), readsX() and +writesX()), all of the above assume that the underlying peripheral is +little-endian and will therefore perform byte-swapping operations on big-endian +architectures. ========================================