From patchwork Fri Feb 3 09:20:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre TORGUE X-Patchwork-Id: 9553653 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9C847604A7 for ; Fri, 3 Feb 2017 09:21:14 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 85DB828511 for ; Fri, 3 Feb 2017 09:21:14 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7A97E28515; Fri, 3 Feb 2017 09:21:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00 autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E73D128511 for ; Fri, 3 Feb 2017 09:21:12 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cZa3L-0002J8-IK; Fri, 03 Feb 2017 09:21:11 +0000 Received: from mx08-00178001.pphosted.com ([91.207.212.93] helo=mx07-00178001.pphosted.com) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cZa3G-00026R-Ku for linux-arm-kernel@lists.infradead.org; Fri, 03 Feb 2017 09:21:09 +0000 Received: from pps.filterd (m0046661.ppops.net [127.0.0.1]) by mx08-00178001.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id v139J5xQ000304; Fri, 3 Feb 2017 10:20:41 +0100 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx08-.pphosted.com with ESMTP id 288k2j6361-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Fri, 03 Feb 2017 10:20:41 +0100 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 0B5263A; Fri, 3 Feb 2017 09:20:36 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag3node2.st.com [10.75.127.8]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id EBC792723; Fri, 3 Feb 2017 09:20:35 +0000 (GMT) Received: from localhost (10.75.127.45) by SFHDAG3NODE2.st.com (10.75.127.8) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Fri, 3 Feb 2017 10:20:35 +0100 From: Alexandre TORGUE To: "M'boumba Cedric Madianga" , Subject: [RFC PATCH v6 3/7] drivers: dma-coherent: Account dma_pfn_offset when used with device tree Date: Fri, 3 Feb 2017 10:20:20 +0100 Message-ID: <1486113624-7494-3-git-send-email-alexandre.torgue@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1486113624-7494-2-git-send-email-alexandre.torgue@st.com> References: <1486113624-7494-2-git-send-email-alexandre.torgue@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.45] X-ClientProxiedBy: SFHDAG7NODE3.st.com (10.75.127.21) To SFHDAG3NODE2.st.com (10.75.127.8) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-02-03_07:, , signatures=0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170203_012107_085689_C8DAEBF9 X-CRM114-Status: GOOD ( 14.63 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vladimir Murzin dma_declare_coherent_memory() and friends are designed to account difference in CPU and device addresses. However, when it is used with reserved memory regions there is assumption that CPU and device have the same view on address space. This assumption gets invalid when reserved memory for coherent DMA allocations is referenced by device with non-empty "dma-range" property. Simply feeding device address as rmem->base + dev->dma_pfn_offset would not work due to reserved memory region can be shared, so this patch turns device address to be expressed with help of CPU address and device's dma_pfn_offset. For the case where device tree is not used and device sees memory different to CPU we explicitly set device's dma_pfn_offset to accomplish such difference. The latter might look controversial, but it seems only a few drivers set device address different to CPU's: - drivers/usb/host/ohci-sm501.c - arch/sh/drivers/pci/fixups-dreamcast.c so they can be screwed only if dma_pfn_offset there is set and not in sync with device address range - we try to catch such cases with WARN_ON. Cc: Michal Nazarewicz Cc: Marek Szyprowski Cc: Alan Stern Cc: Yoshinori Sato Cc: Rich Felker Cc: Roger Quadros Cc: Greg Kroah-Hartman Tested-by: Benjamin Gaignard Tested-by: Andras Szemzo Signed-off-by: Vladimir Murzin --- drivers/base/dma-coherent.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) -- 2.0.0 diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 640a7e6..c59708c 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -18,6 +18,12 @@ struct dma_coherent_mem { spinlock_t spinlock; }; +static inline dma_addr_t dma_get_device_base(struct device *dev, + struct dma_coherent_mem * mem) +{ + return (mem->pfn_base - dev->dma_pfn_offset) << PAGE_SHIFT; +} + static bool dma_init_coherent_memory( phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags, struct dma_coherent_mem **mem) @@ -83,9 +89,16 @@ static void dma_release_coherent_memory(struct dma_coherent_mem *mem) static int dma_assign_coherent_memory(struct device *dev, struct dma_coherent_mem *mem) { + unsigned long dma_pfn_offset = mem->pfn_base - PFN_DOWN(mem->device_base); + if (dev->dma_mem) return -EBUSY; + if (dev->dma_pfn_offset) + WARN_ON(dma_pfn_offset && (dev->dma_pfn_offset != dma_pfn_offset)); + else + dev->dma_pfn_offset = dma_pfn_offset; + dev->dma_mem = mem; /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ @@ -133,7 +146,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev, return ERR_PTR(-EINVAL); spin_lock_irqsave(&mem->spinlock, flags); - pos = (device_addr - mem->device_base) >> PAGE_SHIFT; + pos = PFN_DOWN(device_addr - dma_get_device_base(dev, mem)); err = bitmap_allocate_region(mem->bitmap, pos, get_order(size)); spin_unlock_irqrestore(&mem->spinlock, flags); @@ -186,7 +199,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, /* * Memory was found in the per-device area. */ - *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); + *dma_handle = dma_get_device_base(dev, mem) + (pageno << PAGE_SHIFT); *ret = mem->virt_base + (pageno << PAGE_SHIFT); dma_memory_map = (mem->flags & DMA_MEMORY_MAP); spin_unlock_irqrestore(&mem->spinlock, flags);