From patchwork Wed Jul 2 10:48:51 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 32967 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f72.google.com (mail-oa0-f72.google.com [209.85.219.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B78A3218C3 for ; Wed, 2 Jul 2014 10:51:22 +0000 (UTC) Received: by mail-oa0-f72.google.com with SMTP id eb12sf67777717oac.7 for ; Wed, 02 Jul 2014 03:51:22 -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:subject:date:message-id :in-reply-to:references:cc:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:mime-version:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:content-type:content-transfer-encoding; bh=V72Vsf8+oA7l4ur3H2kqBiMO6/SRFrB8iY4rVGlvZMs=; b=STYlD0ft4UiMbfLEIKOpQybQAirc1B+bwCDf/daxOhFEsEDNdgUvNQ15bH9gxLm/cU KVpYtMamO7sJMBJcd4iOpIXRAayLa4HE+hZhNpJ5kh0d/TBfq3W9f/xzBxrD2gX/ms7q sjmmWIPPPMplZgac0bGFTT2SAIiOkwrOweTM8jNsgu0OvjlP9d58/fHaRJy7r5ere2c/ 8KqpeSGmr0SJ+viiU3RfUq52cROjZZnb0h8w/8FuY/9fYTigQfraAYM3Y3HxIBumRRzp Eq4Quu9MsxsENsrbiyaXuvo1KRY5cUz2H/Ph/JcjswyTsfJ3lt2LUOn9rbwozd94AWeQ DnRQ== X-Gm-Message-State: ALoCoQklM/JzQSUgnjFX/j4jLL1N8KorgYAQmKPcLGnHztwF0qWt4YO6CK1ox3EPabJFaaA0VRvr X-Received: by 10.43.103.136 with SMTP id di8mr1575819icc.14.1404298282329; Wed, 02 Jul 2014 03:51:22 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.20.23 with SMTP id 23ls466139qgi.26.gmail; Wed, 02 Jul 2014 03:51:22 -0700 (PDT) X-Received: by 10.220.92.193 with SMTP id s1mr99534vcm.34.1404298282241; Wed, 02 Jul 2014 03:51:22 -0700 (PDT) Received: from mail-vc0-f179.google.com (mail-vc0-f179.google.com [209.85.220.179]) by mx.google.com with ESMTPS id ql15si9791990vdb.31.2014.07.02.03.51.22 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 02 Jul 2014 03:51:22 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.179 as permitted sender) client-ip=209.85.220.179; Received: by mail-vc0-f179.google.com with SMTP id id10so10103139vcb.24 for ; Wed, 02 Jul 2014 03:51:22 -0700 (PDT) X-Received: by 10.220.69.72 with SMTP id y8mr49010286vci.21.1404298282142; Wed, 02 Jul 2014 03:51:22 -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.37.5 with SMTP id tc5csp283806vcb; Wed, 2 Jul 2014 03:51:21 -0700 (PDT) X-Received: by 10.68.245.202 with SMTP id xq10mr43780343pbc.109.1404298280712; Wed, 02 Jul 2014 03:51:20 -0700 (PDT) Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id cl5si29908540pad.108.2014.07.02.03.51.20 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 02 Jul 2014 03:51:20 -0700 (PDT) Received-SPF: none (google.com: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org does not designate permitted sender hosts) client-ip=2001:1868:205::9; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X2I6x-0000MK-Fj; Wed, 02 Jul 2014 10:49:59 +0000 Received: from mailout3.w1.samsung.com ([210.118.77.13]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X2I6S-0008Q7-BG for linux-arm-kernel@lists.infradead.org; Wed, 02 Jul 2014 10:49:29 +0000 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) 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 <0N82008Z3ZDP2S90@mailout3.w1.samsung.com> for linux-arm-kernel@lists.infradead.org; Wed, 02 Jul 2014 11:49:02 +0100 (BST) X-AuditID: cbfec7f5-b7f626d000004b39-38-53b3e39e0354 Received: from eusync3.samsung.com ( [203.254.199.213]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id B3.F9.19257.E93E3B35; Wed, 02 Jul 2014 11:49:02 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync3.samsung.com (Oracle Communications Messaging Server 7u4-23.01 (7.0.4.23.0) 64bit (built Aug 10 2011)) with ESMTPA id <0N82004J1ZDILZA0@eusync3.samsung.com>; Wed, 02 Jul 2014 11:49:02 +0100 (BST) From: Marek Szyprowski To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org, devicetree@vger.kernel.org, linux-doc@vger.kernel.org Subject: [PATCH 3/4] drivers: dma-coherent: add initialization from device tree Date: Wed, 02 Jul 2014 12:48:51 +0200 Message-id: <1404298132-6050-4-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1404298132-6050-1-git-send-email-m.szyprowski@samsung.com> References: <1404298132-6050-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAAyWRa0hTcRyG+5+dyzYanJbWQUxCC2SU9+CnVBR0+UNQ0qJQiFq6VPDGlpIS Kabmlk5blGKmrpzlmFpbNm9hytBRmYbXUMvyi5d5wwovm9bct+flfeD98PJ54jrSi5+QfEuu SJYl+tJC8tNmz9DhyimzNGhV6w0VjUYapuYqSXBquxlYysnjwWJtIYIq6xcKiu06Cj44mhHU PbhHg72ogISWhgUEvTl2BiyqMgZ+D/4kwDQ1TIEuv4aEgdYKGuqtEwy8nukkQD/ylYDqnlwK HKU+8HFkhQaj9QUDJaX1JOS9tzLgtJhImO3MJ6GxbI4EXdUPBgytDgQzyzbyxH5srDQivLGu RXjuUQnCA5oiAreUTzC40J5LYZNBRWP1/CCBx4fbaWwr2yDxZJeZxOaaLDy2OcXDg7YcCjc4 Zglc7AyK9IgWHo2VJyakyxWBx68L4+3lT1Gq6dhtTUMtk42qQ9RIwOfYMG4830a4eQ/X/72R ViMhX8zqEfdkVEu6g4bg8gc7GZdFs8Gcel5Nu9iD1SFupXJb4rFFfG66bZV0FbvZC1xh3zzl YpI9yL3R/UUuFrFnuccdGsY958NtzbzanhawmHvZ/mvbEf93rPZFXgkSVaMdBuQpT4tJVd6I SwoJUMqSlGnJcQExKUkm5L73TzPSd0d0IZaPfHeKpgNNUjElS1dmJHUhjs/z9RAVj5qlYlGs LCNTrki5pkhLlCu7EMEXeGWjNLpe5l/jZ9jwl97VjUXUrR4whkZv7TIIWglpz8NSx5lywQxN VJ28H1/lGf5ujRmyFEjGdx1iA1VNdyyx7Lfe9StrbwOCOp5lRtkES+f7rHvDLmdFmiWnzPGT S9USzWfnudr+5dMLxRmXhP3hz4+omi7ua4u4qveTRXbcjPIO9SWV8bJgCU+hlP0DuyrxxbwC AAA= X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140702_034928_550600_D3F0F298 X-CRM114-Status: GOOD ( 20.15 ) X-Spam-Score: -5.0 (-----) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-5.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [210.118.77.13 listed in list.dnswl.org] -0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [210.118.77.13 listed in wl.mailspike.net] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Cc: Mark Rutland , Jon Medhurst , Benjamin Herrenschmidt , Tomasz Figa , Will Deacon , Tomasz Figa , Paul Mackerras , Marek Szyprowski , Arnd Bergmann , Josh Cartwright , Catalin Marinas , Grant Likely , Laura Abbott , Ian Campbell , Pawel Moll , Stephen Warren , Sascha Hauer , Michal Nazarewicz , Marc , Nishanth Peethambaran , Rob Herring , Andrew Morton , "Aneesh Kumar K.V." , Kumar Gala , Olof Johansson , Joonsoo Kim X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.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.179 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 | 137 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 19 deletions(-) diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c index 7d6e84a51424..7185a4f247e1 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,52 @@ 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 void 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; + } + rmem->priv = mem; + dma_assign_coherent_memory(dev, mem); +} + +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