From patchwork Thu Apr 11 11:22:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 16041 Return-Path: X-Original-To: linaro@staging.patches.linaro.org Delivered-To: linaro@staging.patches.linaro.org Received: from mail-vc0-f197.google.com (mail-vc0-f197.google.com [209.85.220.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 8C07B238FF for ; Thu, 11 Apr 2013 11:24:22 +0000 (UTC) Received: by mail-vc0-f197.google.com with SMTP id hf12sf1010191vcb.4 for ; Thu, 11 Apr 2013 04:24:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-beenthere:x-received:received-spf:x-received :x-forwarded-to:x-forwarded-for:delivered-to:x-received:received-spf :x-auditid:from:to:date:message-id:x-mailer:in-reply-to:references :x-brightmail-tracker:cc:subject:x-beenthere:x-mailman-version :precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:mime-version:errors-to:sender :x-gm-message-state:x-original-sender :x-original-authentication-results:mailing-list:x-google-group-id :content-type:content-transfer-encoding; bh=adEjYLmBJiqJWQjSllmU6KtcIY/9GXvBy7W8xdJw/P0=; b=Q0yHeqkIMbNksRPiRit3nKAv/AqxBTeOeeeoM12ShL7UAhlu/ERDMofJethTBCgHxa jFBjbl2I1j9ZQ192G70Y+c17tYdKUXl1dsaJ7Q/PIIODVPZkWcu8MIOzAZ4Me4V0Yak0 0HRf5fSVKCwI+Up58SZD1/ACoX0yatlPmly8g8RXdn210FsZ/UBdCOjlRt8D5NFFAoZy ExwikTNYgMxNAk34xlzYPN0JMv3JhWvvpMU/HfgBiY/RxQDxwRSqy2+FlqWmoH/QNDXq uujr1NZHRVzCuRLdrQmbjew91ECX4sh0T5BgzBeWwULVGjblALbEbFFtCRSbQEYaoPWD qh/A== X-Received: by 10.224.178.205 with SMTP id bn13mr19987qab.3.1365679441415; Thu, 11 Apr 2013 04:24:01 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.130.200 with SMTP id og8ls734714qeb.61.gmail; Thu, 11 Apr 2013 04:24:01 -0700 (PDT) X-Received: by 10.58.34.12 with SMTP id v12mr4538305vei.55.1365679441241; Thu, 11 Apr 2013 04:24:01 -0700 (PDT) Received: from mail-vb0-x22b.google.com (mail-vb0-x22b.google.com [2607:f8b0:400c:c02::22b]) by mx.google.com with ESMTPS id x3si3082383vdh.3.2013.04.11.04.24.01 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 11 Apr 2013 04:24:01 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c02::22b is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c02::22b; Received: by mail-vb0-f43.google.com with SMTP id q12so1142835vbe.16 for ; Thu, 11 Apr 2013 04:24:01 -0700 (PDT) X-Received: by 10.221.0.199 with SMTP id nn7mr4717317vcb.14.1365679440860; Thu, 11 Apr 2013 04:24:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.127.98 with SMTP id nf2csp16136veb; Thu, 11 Apr 2013 04:24:00 -0700 (PDT) X-Received: by 10.194.81.71 with SMTP id y7mr9960901wjx.19.1365679439611; Thu, 11 Apr 2013 04:23:59 -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 b4si5533255eef.188.2013.04.11.04.23.58 (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 11 Apr 2013 04:23:59 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) 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 1UQFb9-0007Aa-1P; Thu, 11 Apr 2013 11:23:23 +0000 Received: from mailout1.samsung.com ([203.254.224.24]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1UQFb6-0007AV-Sq for linaro-mm-sig@lists.linaro.org; Thu, 11 Apr 2013 11:23:21 +0000 Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0ML3006RG8ZHGDL0@mailout1.samsung.com> for linaro-mm-sig@lists.linaro.org; Thu, 11 Apr 2013 20:23:48 +0900 (KST) X-AuditID: cbfee61a-b7fa86d0000045ae-e8-51669d435bd1 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 14.A8.17838.34D96615; Thu, 11 Apr 2013 20:23:47 +0900 (KST) Received: from localhost.localdomain ([106.116.147.30]) by mmp2.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0ML3003KM8X0PU50@mmp2.samsung.com>; Thu, 11 Apr 2013 20:23:47 +0900 (KST) From: Marek Szyprowski To: linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org, devicetree-discuss@lists.ozlabs.org Date: Thu, 11 Apr 2013 13:22:09 +0200 Message-id: <1365679330-2514-2-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1365679330-2514-1-git-send-email-m.szyprowski@samsung.com> References: <1365679330-2514-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrBLMWRmVeSWpSXmKPExsVy+t9jQV3nuWmBBrNOG1r8nXSM3eLA7Ies Fq/ObGSzONv0ht1ie+cMdosvVx4yWWx6fI3VYu2Ru+wWG14eZLJYcLyF1eLPdDmLU9c/s1l8 //aNzeLv9k0sFofftLNarJ/xmsVBwOP3r0mMHpf7epk8ds66y+6xeUm9x+1/j5k9zs9YyOhx 5UQTq8e6P6+YPPr/Gnj0bVnF6PHzpU4AdxSXTUpqTmZZapG+XQJXRt9mkYLryRW3vu1ibWA8 G9jFyMkhIWAi8WbOTyYIW0ziwr31bF2MXBxCAtMZJV7Pm8cE4bQzSZx7DJLh5GATMJToetsF ZHNwiAjkS6yexQsSZhZoY5F4sYEFxBYWSJGYsvMBK4jNIqAq8WrJNXYQm1fAXeLp72XMIK0S AgoScybZgJicAh4Sd2Y4g1QIAVXsPNXBOIGRdwEjwypG0dSC5ILipPRcQ73ixNzi0rx0veT8 3E2M4PB+JrWDcWWDxSFGAQ5GJR7eEw2pgUKsiWXFlbmHGCU4mJVEeBlnpwUK8aYkVlalFuXH F5XmpBYfYpTmYFES5z3Qah0oJJCeWJKanZpakFoEk2Xi4JRqYDQzj4qWOjjnhbzrBfMl4g36 pnXzvRbPcRRX9e4v/1HAvG8z5+F4ya+brJen7vQ08PupopbE+0jlKPudatfvoTf+v7qbLC9p dHhTQfjZHpt6l6727fl7Su3WGUeGTRcqvjtlgjozX2moXnJRyYodKn8/xXnF3zW40Hf14amw 3RvP782+PufsLyWW4oxEQy3mouJEAO3ZkbxrAgAA Cc: Arnd Bergmann , Tomasz Figa , Michal Nazarewicz , Grant Likely , Kyungmin Park , Rob Herring , Sylwester Nawrocki , Olof Johansson , Sascha Hauer Subject: [Linaro-mm-sig] [RFC/PATCH v2 1/2] drivers: dma-contiguous: clean source code and prepare for 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-Gm-Message-State: ALoCoQkpcCGCFR3JXiVyXyS62/w2ArzOSb1Io6BEQR4LCsZuhHatCn+ELcMvLQtLeED8nR8A2u/S X-Original-Sender: m.szyprowski@samsung.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c02::22b is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) 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 This patch cleans the initialization of dma contiguous framework. The all-in-one dma_declare_contiguous() function is now separated into dma_contiguous_reserve_area() which only steals the the memory from memblock allocator and dma_contiguous_add_device() function, which assigns given device to the specified reserved memory area. This improves the flexibility in defining contiguous memory areas and assigning device to them, because now it is possible to assign more than one device to the given contiguous memory area. This split in initialization is also required for upcoming device tree support. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park --- drivers/base/dma-contiguous.c | 211 ++++++++++++++++------------------ include/asm-generic/dma-contiguous.h | 2 - include/linux/dma-contiguous.h | 32 +++++- 3 files changed, 129 insertions(+), 116 deletions(-) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 0ca5442..01fe743 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -39,8 +39,15 @@ struct cma { unsigned long *bitmap; }; +static DEFINE_MUTEX(cma_mutex); + +static struct cma cma_areas[MAX_CMA_AREAS]; +static unsigned cma_area_count; + struct cma *dma_contiguous_default_area; +/*****************************************************************************/ + #ifdef CONFIG_CMA_SIZE_MBYTES #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES #else @@ -95,51 +102,20 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void) #endif -/** - * dma_contiguous_reserve() - reserve area for contiguous memory handling - * @limit: End address of the reserved memory (optional, 0 for any). - * - * This function reserves memory from early allocator. It should be - * called by arch specific code once the early allocator (memblock or bootmem) - * has been activated and all other subsystems have already allocated/reserved - * memory. - */ -void __init dma_contiguous_reserve(phys_addr_t limit) -{ - phys_addr_t selected_size = 0; - - pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); - - if (size_cmdline != -1) { - selected_size = size_cmdline; - } else { -#ifdef CONFIG_CMA_SIZE_SEL_MBYTES - selected_size = size_bytes; -#elif defined(CONFIG_CMA_SIZE_SEL_PERCENTAGE) - selected_size = cma_early_percent_memory(); -#elif defined(CONFIG_CMA_SIZE_SEL_MIN) - selected_size = min(size_bytes, cma_early_percent_memory()); -#elif defined(CONFIG_CMA_SIZE_SEL_MAX) - selected_size = max(size_bytes, cma_early_percent_memory()); -#endif - } - - if (selected_size) { - pr_debug("%s: reserving %ld MiB for global area\n", __func__, - (unsigned long)selected_size / SZ_1M); - - dma_declare_contiguous(NULL, selected_size, 0, limit); - } -}; - -static DEFINE_MUTEX(cma_mutex); +/*************************************************************************/ -static __init int cma_activate_area(unsigned long base_pfn, unsigned long count) +static __init int cma_activate_area(struct cma *cma) { - unsigned long pfn = base_pfn; - unsigned i = count >> pageblock_order; + int bitmap_size = BITS_TO_LONGS(cma->count) * sizeof(long); + unsigned long base_pfn = cma->base_pfn, pfn = base_pfn; + unsigned i = cma->count >> pageblock_order; struct zone *zone; + cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); + + if (!cma->bitmap) + return -ENOMEM; + WARN_ON_ONCE(!pfn_valid(pfn)); zone = page_zone(pfn_to_page(pfn)); @@ -153,92 +129,74 @@ static __init int cma_activate_area(unsigned long base_pfn, unsigned long count) } init_cma_reserved_pageblock(pfn_to_page(base_pfn)); } while (--i); + return 0; } -static __init struct cma *cma_create_area(unsigned long base_pfn, - unsigned long count) +/** + * dma_contiguous_reserve() - reserve area(s) for contiguous memory handling + * @limit: End address of the reserved memory (optional, 0 for any). + * + * This function reserves memory from early allocator. It should be + * called by arch specific code once the early allocator (memblock or bootmem) + * has been activated and all other subsystems have already allocated/reserved + * memory. It reserves contiguous areas for global, device independent + * allocations and (optionally) all areas defined in device tree structures. + */ +void __init dma_contiguous_reserve(phys_addr_t limit) { - int bitmap_size = BITS_TO_LONGS(count) * sizeof(long); - struct cma *cma; - int ret = -ENOMEM; - - pr_debug("%s(base %08lx, count %lx)\n", __func__, base_pfn, count); - - cma = kmalloc(sizeof *cma, GFP_KERNEL); - if (!cma) - return ERR_PTR(-ENOMEM); + phys_addr_t sel_size = 0; - cma->base_pfn = base_pfn; - cma->count = count; - cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - - if (!cma->bitmap) - goto no_mem; - - ret = cma_activate_area(base_pfn, count); - if (ret) - goto error; - - pr_debug("%s: returned %p\n", __func__, (void *)cma); - return cma; - -error: - kfree(cma->bitmap); -no_mem: - kfree(cma); - return ERR_PTR(ret); -} - -static struct cma_reserved { - phys_addr_t start; - unsigned long size; - struct device *dev; -} cma_reserved[MAX_CMA_AREAS] __initdata; -static unsigned cma_reserved_count __initdata; + pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit); -static int __init cma_init_reserved_areas(void) -{ - struct cma_reserved *r = cma_reserved; - unsigned i = cma_reserved_count; + if (size_cmdline != -1) { + sel_size = size_cmdline; + } else { +#ifdef CONFIG_CMA_SIZE_SEL_MBYTES + sel_size = size_bytes; +#elif defined(CONFIG_CMA_SIZE_SEL_PERCENTAGE) + sel_size = cma_early_percent_memory(); +#elif defined(CONFIG_CMA_SIZE_SEL_MIN) + sel_size = min(size_bytes, cma_early_percent_memory()); +#elif defined(CONFIG_CMA_SIZE_SEL_MAX) + sel_size = max(size_bytes, cma_early_percent_memory()); +#endif + } - pr_debug("%s()\n", __func__); + if (sel_size && !dma_contiguous_default_area) { + pr_debug("%s: reserving %ld MiB for global area\n", __func__, + (unsigned long)sel_size / SZ_1M); - for (; i; --i, ++r) { - struct cma *cma; - cma = cma_create_area(PFN_DOWN(r->start), - r->size >> PAGE_SHIFT); - if (!IS_ERR(cma)) - dev_set_cma_area(r->dev, cma); + dma_contiguous_reserve_area(sel_size, 0, limit, + &dma_contiguous_default_area); } - return 0; -} -core_initcall(cma_init_reserved_areas); +}; /** - * dma_declare_contiguous() - reserve area for contiguous memory handling - * for particular device - * @dev: Pointer to device structure. - * @size: Size of the reserved memory. - * @base: Start address of the reserved memory (optional, 0 for any). + * dma_contiguous_reserve_area() - reserve custom contiguous area + * @size: Size of the reserved area (in bytes), + * @base: Base address of the reserved area optional, use 0 for any * @limit: End address of the reserved memory (optional, 0 for any). + * @res_cma: Pointer to store the created cma region. * - * This function reserves memory for specified device. It should be - * called by board specific code when early allocator (memblock or bootmem) - * is still activate. + * This function reserves memory from early allocator. It should be + * called by arch specific code once the early allocator (memblock or bootmem) + * has been activated and all other subsystems have already allocated/reserved + * memory. This function allows to create custom reserved areas for specific + * devices. */ -int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, - phys_addr_t base, phys_addr_t limit) +int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, + phys_addr_t limit, struct cma **res_cma) { - struct cma_reserved *r = &cma_reserved[cma_reserved_count]; phys_addr_t alignment; + int ret = 0; pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__, (unsigned long)size, (unsigned long)base, (unsigned long)limit); /* Sanity checks */ - if (cma_reserved_count == ARRAY_SIZE(cma_reserved)) { + if (cma_area_count == ARRAY_SIZE(cma_areas)) { pr_err("Not enough slots for CMA reserved regions!\n"); return -ENOSPC; } @@ -256,7 +214,7 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, if (base) { if (memblock_is_region_reserved(base, size) || memblock_reserve(base, size) < 0) { - base = -EBUSY; + ret = -EBUSY; goto err; } } else { @@ -266,7 +224,7 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, */ phys_addr_t addr = __memblock_alloc_base(size, alignment, limit); if (!addr) { - base = -ENOMEM; + ret = -ENOMEM; goto err; } else { base = addr; @@ -277,10 +235,11 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, * Each reserved area must be initialised later, when more kernel * subsystems (like slab allocator) are available. */ - r->start = base; - r->size = size; - r->dev = dev; - cma_reserved_count++; + cma_areas[cma_area_count].base_pfn = PFN_DOWN(base); + cma_areas[cma_area_count].count = size >> PAGE_SHIFT; + *res_cma = &cma_areas[cma_area_count]; + cma_area_count++; + pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M, (unsigned long)base); @@ -289,10 +248,38 @@ int __init dma_declare_contiguous(struct device *dev, phys_addr_t size, return 0; err: pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M); - return base; + return ret; } /** + * dma_contiguous_add_device() - add device to custom contiguous reserved area + * @dev: Pointer to device structure. + * @cma: Pointer to the cma structure for the reserved area + * + * This function assigns the given device to the contiguous memory area + * reserved earlier by dma_contiguous_reserve_area() function. + */ +int __init dma_contiguous_add_device(struct device *dev, struct cma *cma) +{ + dev_set_cma_area(dev, cma); + return 0; +} + +static int __init cma_init_reserved_areas(void) +{ + int i; + + for (i = 0; i < cma_area_count; i++) { + int ret = cma_activate_area(&cma_areas[i]); + if (ret) + return ret; + } + + return 0; +} +core_initcall(cma_init_reserved_areas); + +/** * dma_alloc_from_contiguous() - allocate pages from contiguous area * @dev: Pointer to device for which the allocation is performed. * @count: Requested number of pages. diff --git a/include/asm-generic/dma-contiguous.h b/include/asm-generic/dma-contiguous.h index 294b1e7..8979f86 100644 --- a/include/asm-generic/dma-contiguous.h +++ b/include/asm-generic/dma-contiguous.h @@ -18,8 +18,6 @@ static inline void dev_set_cma_area(struct device *dev, struct cma *cma) { if (dev) dev->cma_area = cma; - if (!dev && !dma_contiguous_default_area) - dma_contiguous_default_area = cma; } #endif diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h index 01b5c84..28c31fe 100644 --- a/include/linux/dma-contiguous.h +++ b/include/linux/dma-contiguous.h @@ -68,8 +68,36 @@ struct device; extern struct cma *dma_contiguous_default_area; void dma_contiguous_reserve(phys_addr_t addr_limit); -int dma_declare_contiguous(struct device *dev, phys_addr_t size, - phys_addr_t base, phys_addr_t limit); + +int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, + phys_addr_t limit, struct cma **res_cma); + +int dma_contiguous_add_device(struct device *dev, struct cma *cma); + +/** + * dma_declare_contiguous() - reserve area for contiguous memory handling + * for particular device + * @dev: Pointer to device structure. + * @size: Size of the reserved memory. + * @base: Start address of the reserved memory (optional, 0 for any). + * @limit: End address of the reserved memory (optional, 0 for any). + * + * This function reserves memory for specified device. It should be + * called by board specific code when early allocator (memblock or bootmem) + * is still activate. + */ + +static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size, + phys_addr_t base, phys_addr_t limit) +{ + struct cma *cma; + int ret; + ret = dma_contiguous_reserve_area(size, base, limit, &cma); + if (ret == 0) + dma_contiguous_add_device(dev, cma); + + return ret; +} struct page *dma_alloc_from_contiguous(struct device *dev, int count, unsigned int order);