From: Vladimir Murzin <vladimir.murzin@arm.com> To: linux-arm-kernel@lists.infradead.org Cc: kbuild-all@01.org, linux-kernel@vger.kernel.org, linux@armlinux.org.uk, akpm@linux-foundation.org, robin.murphy@arm.com, benjamin.gaignard@linaro.org, alexandre.torgue@st.com, sza@esh.hu, Michal Nazarewicz <mina86@mina86.com>, Marek Szyprowski <m.szyprowski@samsung.com>, Roger Quadros <rogerq@ti.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org> Subject: [PATCH v2 3/7] drivers: dma-coherent: Account dma_pfn_offset when used with device tree Date: Tue, 7 Mar 2017 11:12:30 +0000 [thread overview] Message-ID: <1488885154-12429-4-git-send-email-vladimir.murzin@arm.com> (raw) In-Reply-To: <1488885154-12429-1-git-send-email-vladimir.murzin@arm.com> 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 in case memory reservation has been done via device tree; non device tree users continue to use the old scheme. Cc: Michal Nazarewicz <mina86@mina86.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Roger Quadros <rogerq@ti.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> --- drivers/base/dma-coherent.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 640a7e6..99c9695 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -16,8 +16,18 @@ struct dma_coherent_mem { int flags; unsigned long *bitmap; spinlock_t spinlock; + bool use_dev_dma_pfn_offset; }; +static inline dma_addr_t dma_get_device_base(struct device *dev, + struct dma_coherent_mem * mem) +{ + if (mem->use_dev_dma_pfn_offset) + return (mem->pfn_base - dev->dma_pfn_offset) << PAGE_SHIFT; + else + return mem->device_base; +} + 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) @@ -133,7 +143,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 +196,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); @@ -299,6 +309,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) &rmem->base, (unsigned long)rmem->size / SZ_1M); return -ENODEV; } + mem->use_dev_dma_pfn_offset = true; rmem->priv = mem; dma_assign_coherent_memory(dev, mem); return 0; -- 2.0.0
WARNING: multiple messages have this Message-ID (diff)
From: vladimir.murzin@arm.com (Vladimir Murzin) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 3/7] drivers: dma-coherent: Account dma_pfn_offset when used with device tree Date: Tue, 7 Mar 2017 11:12:30 +0000 [thread overview] Message-ID: <1488885154-12429-4-git-send-email-vladimir.murzin@arm.com> (raw) In-Reply-To: <1488885154-12429-1-git-send-email-vladimir.murzin@arm.com> 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 in case memory reservation has been done via device tree; non device tree users continue to use the old scheme. Cc: Michal Nazarewicz <mina86@mina86.com> Cc: Marek Szyprowski <m.szyprowski@samsung.com> Cc: Roger Quadros <rogerq@ti.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> --- drivers/base/dma-coherent.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 640a7e6..99c9695 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -16,8 +16,18 @@ struct dma_coherent_mem { int flags; unsigned long *bitmap; spinlock_t spinlock; + bool use_dev_dma_pfn_offset; }; +static inline dma_addr_t dma_get_device_base(struct device *dev, + struct dma_coherent_mem * mem) +{ + if (mem->use_dev_dma_pfn_offset) + return (mem->pfn_base - dev->dma_pfn_offset) << PAGE_SHIFT; + else + return mem->device_base; +} + 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) @@ -133,7 +143,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 +196,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); @@ -299,6 +309,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) &rmem->base, (unsigned long)rmem->size / SZ_1M); return -ENODEV; } + mem->use_dev_dma_pfn_offset = true; rmem->priv = mem; dma_assign_coherent_memory(dev, mem); return 0; -- 2.0.0
next prev parent reply other threads:[~2017-03-07 12:31 UTC|newest] Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-03-07 11:12 [PATCH v2 0/7] ARM: Fix dma_alloc_coherent() and friends for NOMMU Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-07 11:12 ` [PATCH v2 1/7] dma: Take into account dma_pfn_offset Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-07 11:12 ` [PATCH v2 2/7] dma: Add simple dma_noop_mmap Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin [this message] 2017-03-07 11:12 ` [PATCH v2 3/7] drivers: dma-coherent: Account dma_pfn_offset when used with device tree Vladimir Murzin 2017-03-07 11:12 ` [PATCH v2 4/7] drivers: dma-coherent: Introduce default DMA pool Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-07 11:12 ` [PATCH v2 5/7] ARM: NOMMU: Introduce dma operations for noMMU Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-09 14:06 ` kbuild test robot 2017-03-09 14:06 ` kbuild test robot 2017-03-07 11:12 ` [PATCH v2 6/7] ARM: NOMMU: Set ARM_DMA_MEM_BUFFERABLE for M-class cpus Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin 2017-03-07 11:12 ` [PATCH v2 7/7] ARM: dma-mapping: Remove traces of NOMMU code Vladimir Murzin 2017-03-07 11:12 ` Vladimir Murzin
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1488885154-12429-4-git-send-email-vladimir.murzin@arm.com \ --to=vladimir.murzin@arm.com \ --cc=akpm@linux-foundation.org \ --cc=alexandre.torgue@st.com \ --cc=benjamin.gaignard@linaro.org \ --cc=gregkh@linuxfoundation.org \ --cc=kbuild-all@01.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@armlinux.org.uk \ --cc=m.szyprowski@samsung.com \ --cc=mina86@mina86.com \ --cc=robin.murphy@arm.com \ --cc=rogerq@ti.com \ --cc=sza@esh.hu \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.