From patchwork Tue Aug 26 12:09:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 36012 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ob0-f200.google.com (mail-ob0-f200.google.com [209.85.214.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 35B642054F for ; Tue, 26 Aug 2014 12:14:29 +0000 (UTC) Received: by mail-ob0-f200.google.com with SMTP id va2sf70107018obc.7 for ; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:cc:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version :errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list:content-type :content-transfer-encoding; bh=1UQGdgBgOWf1J0m6qSwSroQETl/1svIFHLUdiENT3OU=; b=TsSyzsSxJ32Mhj5evrAoNyTl1cyMT5xysjHbPYhumcI/yHKXjbA0z5n75ES9NbIGQ9 RVLT6UYcFrTUUU0d+BuGVdFQsEwpWJeYqP+Ewb0LshO4/f4et9w/AXBILnuDdwhsQfuE e360to/oPx4OkKTgRYS6A/mBb8NjB+W2ln9MVGgJmF8lbi5IwN5SH/726HeblfShc8We 4fvsUyUXyoxp2pn6A9CLBUcU/0jkvJayxtqM6nmDv6q26A77eIhk3WCGovsUvT+lW426 U1DI/5MUxGO5XUs9ZYHuybE80pPKvcSVSg9vReZU3V/3bzFRy3Aj0Lor4ZwYjSaa472d wGdg== X-Gm-Message-State: ALoCoQnH1J7npWMc3zfc0Uzupi/ecUBrGLT72hl5BjQmN/dzOIQB9ItTfXyJdHGKg9hZCTLgHZDS X-Received: by 10.182.129.37 with SMTP id nt5mr17795328obb.8.1409055268832; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.90.17 with SMTP id w17ls130551qgd.70.gmail; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-Received: by 10.52.245.101 with SMTP id xn5mr9954942vdc.32.1409055268742; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) Received: from mail-vc0-f171.google.com (mail-vc0-f171.google.com [209.85.220.171]) by mx.google.com with ESMTPS id s6si1250083vdx.72.2014.08.26.05.14.28 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 26 Aug 2014 05:14:28 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.171 as permitted sender) client-ip=209.85.220.171; Received: by mail-vc0-f171.google.com with SMTP id hq11so16709573vcb.16 for ; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-Received: by 10.220.97.5 with SMTP id j5mr23636541vcn.16.1409055268645; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.45.67 with SMTP id uj3csp193592vcb; Tue, 26 Aug 2014 05:14:28 -0700 (PDT) X-Received: by 10.140.102.117 with SMTP id v108mr41591139qge.93.1409055267974; Tue, 26 Aug 2014 05:14:27 -0700 (PDT) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id d30si3497273qga.89.2014.08.26.05.14.27 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 26 Aug 2014 05:14:27 -0700 (PDT) Received-SPF: none (google.com: linaro-mm-sig-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XMFdq-0007EV-9D; Tue, 26 Aug 2014 12:14:26 +0000 Received: from mailout3.w1.samsung.com ([210.118.77.13]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1XMFdO-0007C8-QD for linaro-mm-sig@lists.linaro.org; Tue, 26 Aug 2014 12:13:58 +0000 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout3.w1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0NAW0030HY3VLW40@mailout3.w1.samsung.com> for linaro-mm-sig@lists.linaro.org; Tue, 26 Aug 2014 13:16:43 +0100 (BST) X-AuditID: cbfec7f4-b7f156d0000063c7-81-53fc79ff5e0a Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id BE.48.25543.FF97CF35; Tue, 26 Aug 2014 13:13:51 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0NAW00F45XYW5O50@eusync4.samsung.com>; Tue, 26 Aug 2014 13:13:51 +0100 (BST) From: Marek Szyprowski To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org Date: Tue, 26 Aug 2014 14:09:44 +0200 Message-id: <1409054988-32758-4-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1409054988-32758-1-git-send-email-m.szyprowski@samsung.com> References: <1409054988-32758-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrFLMWRmVeSWpSXmKPExsVy+t/xa7r/K/8EGxzrMLP4O+kYu8WBPzsY LVZ2N7NZ7Fz3jtHibNMbdovtnTPYLb5cechksenxNVaLy7vmsFn0bNjKajHj/D4mi7VH7rJb LDjewmqxfsZrFgc+j9+/JjF6XO7rZfLoenuFyePOtT1sHpuX1Hvc/veY2WPdn1dMHn1bVjF6 fN4kF8AZxWWTkpqTWZZapG+XwJWxbtpatoJjthV9j46wNDCuN+pi5OCQEDCRmPPFu4uRE8gU k7hwbz1bFyMXh5DAUkaJaW9eMUI4fUwSyzffYQepYhMwlOh628UGYosIZEv8+DaZBcRmFljK LDFvlhSILSzgL/Fk6mKwGhYBVYn+3ptgNbwCHhIHXq9igdgmJ/H/5QomkCM4BTwlzk2pBgkL AZVsnP6eZQIj7wJGhlWMoqmlyQXFSem5hnrFibnFpXnpesn5uZsYIeH7ZQfj4mNWhxgFOBiV eHg/lPwOFmJNLCuuzD3EKMHBrCTC+yPpT7AQb0piZVVqUX58UWlOavEhRiYOTqkGxiX/HFY2 nHrULSv0YpfR+c4eVWGmU725Byvvu10JL1xcdGXdDN72i5cNNyZXa+omJM7ruPqvyO5S/67K tymeiySXLdoQdfhrl/Xz/Re8vY+YXP/7WPPoK448O9UDX3S2LZoY/OHIroW6On4r1B+mP+Ra 2/AhS6KzwsNKN9P+28uXE57eN9CtYlFiKc5INNRiLipOBAApUcuUPQIAAA== Cc: Arnd Bergmann , Tomasz Figa , Michal Nazarewicz , linaro-mm-sig@lists.linaro.org, Kyungmin Park , Grant Likely , Joonsoo Kim , Josh Cartwright , linux-media@vger.kernel.org Subject: [Linaro-mm-sig] [PATCH 3/7] drivers: dma-coherent: add initialization from device tree X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-mm-sig-bounces@lists.linaro.org Sender: linaro-mm-sig-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: m.szyprowski@samsung.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.171 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Initialization procedure of dma coherent pool has been split into two parts, so memory pool can now be initialized without assigning to particular struct device. Then initialized region can be assigned to more than one struct device. To protect from concurent allocations from different devices, a spinlock has been added to dma_coherent_mem structure. The last part of this patch adds support for handling 'shared-dma-pool' reserved-memory device tree nodes. Signed-off-by: Marek Szyprowski --- drivers/base/dma-coherent.c | 138 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 7d6e84a51424..4e2dfcc16b70 100644 --- a/drivers/base/dma-coherent.c +++ b/drivers/base/dma-coherent.c @@ -14,11 +14,14 @@ struct dma_coherent_mem { int size; int flags; unsigned long *bitmap; + spinlock_t spinlock; }; -int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, - dma_addr_t device_addr, size_t size, int flags) +static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr, + size_t size, int flags, + struct dma_coherent_mem **mem) { + struct dma_coherent_mem *dma_mem = NULL; void __iomem *mem_base = NULL; int pages = size >> PAGE_SHIFT; int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); @@ -27,27 +30,26 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, goto out; if (!size) goto out; - if (dev->dma_mem) - goto out; - - /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ mem_base = ioremap(phys_addr, size); if (!mem_base) goto out; - dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); - if (!dev->dma_mem) + dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); + if (!dma_mem) goto out; - dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!dev->dma_mem->bitmap) + dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!dma_mem->bitmap) goto free1_out; - dev->dma_mem->virt_base = mem_base; - dev->dma_mem->device_base = device_addr; - dev->dma_mem->pfn_base = PFN_DOWN(phys_addr); - dev->dma_mem->size = pages; - dev->dma_mem->flags = flags; + dma_mem->virt_base = mem_base; + dma_mem->device_base = device_addr; + dma_mem->pfn_base = PFN_DOWN(phys_addr); + dma_mem->size = pages; + dma_mem->flags = flags; + spin_lock_init(&dma_mem->spinlock); + + *mem = dma_mem; if (flags & DMA_MEMORY_MAP) return DMA_MEMORY_MAP; @@ -55,12 +57,51 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, return DMA_MEMORY_IO; free1_out: - kfree(dev->dma_mem); + kfree(dma_mem); out: if (mem_base) iounmap(mem_base); return 0; } + +static void dma_release_coherent_memory(struct dma_coherent_mem *mem) +{ + if (!mem) + return; + iounmap(mem->virt_base); + kfree(mem->bitmap); + kfree(mem); +} + +static int dma_assign_coherent_memory(struct device *dev, + struct dma_coherent_mem *mem) +{ + if (dev->dma_mem) + return -EBUSY; + + dev->dma_mem = mem; + /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ + + return 0; +} + +int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, + dma_addr_t device_addr, size_t size, int flags) +{ + struct dma_coherent_mem *mem; + int ret; + + ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags, + &mem); + if (ret == 0) + return 0; + + if (dma_assign_coherent_memory(dev, mem) == 0) + return ret; + + dma_release_coherent_memory(mem); + return 0; +} EXPORT_SYMBOL(dma_declare_coherent_memory); void dma_release_declared_memory(struct device *dev) @@ -69,10 +110,8 @@ void dma_release_declared_memory(struct device *dev) if (!mem) return; + dma_release_coherent_memory(mem); dev->dma_mem = NULL; - iounmap(mem->virt_base); - kfree(mem->bitmap); - kfree(mem); } EXPORT_SYMBOL(dma_release_declared_memory); @@ -80,6 +119,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev, dma_addr_t device_addr, size_t size) { struct dma_coherent_mem *mem = dev->dma_mem; + unsigned long flags; int pos, err; size += device_addr & ~PAGE_MASK; @@ -87,8 +127,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev, if (!mem) return ERR_PTR(-EINVAL); + spin_lock_irqsave(&mem->spinlock, flags); pos = (device_addr - mem->device_base) >> PAGE_SHIFT; err = bitmap_allocate_region(mem->bitmap, pos, get_order(size)); + spin_unlock_irqrestore(&mem->spinlock, flags); + if (err != 0) return ERR_PTR(err); return mem->virt_base + (pos << PAGE_SHIFT); @@ -115,6 +158,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, { struct dma_coherent_mem *mem; int order = get_order(size); + unsigned long flags; int pageno; if (!dev) @@ -124,6 +168,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, return 0; *ret = NULL; + spin_lock_irqsave(&mem->spinlock, flags); if (unlikely(size > (mem->size << PAGE_SHIFT))) goto err; @@ -138,10 +183,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, *dma_handle = mem->device_base + (pageno << PAGE_SHIFT); *ret = mem->virt_base + (pageno << PAGE_SHIFT); memset(*ret, 0, size); + spin_unlock_irqrestore(&mem->spinlock, flags); return 1; err: + spin_unlock_irqrestore(&mem->spinlock, flags); /* * In the case where the allocation can not be satisfied from the * per-device area, try to fall back to generic memory if the @@ -171,8 +218,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr) if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; + unsigned long flags; + spin_lock_irqsave(&mem->spinlock, flags); bitmap_release_region(mem->bitmap, page, order); + spin_unlock_irqrestore(&mem->spinlock, flags); return 1; } return 0; @@ -218,3 +268,53 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, return 0; } EXPORT_SYMBOL(dma_mmap_from_coherent); + +/* + * Support for reserved memory regions defined in device tree + */ +#ifdef CONFIG_OF_RESERVED_MEM +#include +#include +#include + +static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) +{ + struct dma_coherent_mem *mem = rmem->priv; + if (!mem && + dma_init_coherent_memory(rmem->base, rmem->base, rmem->size, + DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE, + &mem) != DMA_MEMORY_MAP) { + pr_info("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + return -ENODEV; + } + rmem->priv = mem; + dma_assign_coherent_memory(dev, mem); + return 0; +} + +static void rmem_dma_device_release(struct reserved_mem *rmem, + struct device *dev) +{ + dev->dma_mem = NULL; +} + +static const struct reserved_mem_ops rmem_dma_ops = { + .device_init = rmem_dma_device_init, + .device_release = rmem_dma_device_release, +}; + +static int __init rmem_dma_setup(struct reserved_mem *rmem) +{ + unsigned long node = rmem->fdt_node; + + if (of_get_flat_dt_prop(node, "reusable", NULL)) + return -EINVAL; + + rmem->ops = &rmem_dma_ops; + pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n", + &rmem->base, (unsigned long)rmem->size / SZ_1M); + return 0; +} +RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup); +#endif