From patchwork Wed Jul 31 12:51:56 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 18688 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-gh0-f197.google.com (mail-gh0-f197.google.com [209.85.160.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 76EDE246CC for ; Wed, 31 Jul 2013 12:52:35 +0000 (UTC) Received: by mail-gh0-f197.google.com with SMTP id r20sf760393ghr.0 for ; Wed, 31 Jul 2013 05:52:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-beenthere:x-forwarded-to:x-forwarded-for:delivered-to: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-removed-original-auth:x-original-sender :x-original-authentication-results:mailing-list:x-google-group-id :content-type:content-transfer-encoding; bh=8XuxxPTysSw221l2Kg32oRQAUAkslWKL6rIvo0kUEW0=; b=aXrmUTmhF+e3gWJ+k5hWomyjRKI8rEcZjgikaeJzNlapwBcD6z5imRNfmdNVc6k+0S 20yko237LNJJ570vWOyBGRQf4+re7rKMz8xqfHyHWOtq1H8GzsU0JcAk+cGQGQihwwez TKsVQ4pDLq6uTSrLO4b6FNtSbm5ighS4OfV36OjjPxWofkeHSxLhmKMf1hPDnWYYlxv6 6ML47kyKIuGQsRmNrnfQR/MvIFKE6h67das0UvOs7upgtm1dBLrCFkcfTFIMoFKJMNeE 4IXIFIelkjF/J0/0DD0OWZYq0IoZTSCuvGTmB2Yaw8xHDR9sH8/BiR4nBWdauCle4JvQ 5U7A== X-Received: by 10.236.113.77 with SMTP id z53mr28959667yhg.47.1375275155293; Wed, 31 Jul 2013 05:52:35 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.71.231 with SMTP id y7ls595565qeu.39.gmail; Wed, 31 Jul 2013 05:52:35 -0700 (PDT) X-Received: by 10.58.249.236 with SMTP id yx12mr28615752vec.25.1375275155120; Wed, 31 Jul 2013 05:52:35 -0700 (PDT) Received: from mail-ve0-f173.google.com (mail-ve0-f173.google.com [209.85.128.173]) by mx.google.com with ESMTPS id x9si261714vec.80.2013.07.31.05.52.35 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 31 Jul 2013 05:52:35 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.173; Received: by mail-ve0-f173.google.com with SMTP id cy12so406195veb.4 for ; Wed, 31 Jul 2013 05:52:35 -0700 (PDT) X-Received: by 10.52.109.69 with SMTP id hq5mr10524039vdb.85.1375275154964; Wed, 31 Jul 2013 05:52:34 -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.221.11.8 with SMTP id pc8csp235040vcb; Wed, 31 Jul 2013 05:52:34 -0700 (PDT) X-Received: by 10.194.76.68 with SMTP id i4mr3424586wjw.50.1375275149247; Wed, 31 Jul 2013 05:52:29 -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 lv10si687913wjb.158.2013.07.31.05.52.28 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Wed, 31 Jul 2013 05:52:29 -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 1V4Vt6-00043S-Ow; Wed, 31 Jul 2013 12:52:20 +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 1V4Vt4-000434-OB for linaro-mm-sig@lists.linaro.org; Wed, 31 Jul 2013 12:52:19 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MQS00GABX3472V0@mailout1.samsung.com> for linaro-mm-sig@lists.linaro.org; Wed, 31 Jul 2013 21:52:17 +0900 (KST) X-AuditID: cbfee61b-b7efe6d000007b11-07-51f908812d3a Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 60.0A.31505.18809F15; Wed, 31 Jul 2013 21:52:17 +0900 (KST) Received: from localhost.localdomain ([106.116.147.30]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MQS004JJX2O1G70@mmp1.samsung.com>; Wed, 31 Jul 2013 21:52:17 +0900 (KST) From: Marek Szyprowski To: linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org, devicetree-discuss@lists.ozlabs.org Date: Wed, 31 Jul 2013 14:51:56 +0200 Message-id: <1375275119-12787-2-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1375275119-12787-1-git-send-email-m.szyprowski@samsung.com> References: <1375275119-12787-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrOLMWRmVeSWpSXmKPExsVy+t9jAd1Gjp+BBps/S1v8nXSM3eLA7Ies Fq/ObGSzONv0ht1ie+cMdosvVx4yWWx6fI3VYu2Ru+wWG14eZLJYcLyF1eLPdDmLU9c/s1l8 //aNzeLv9k0sFofftLNarJ/xmsVBwOP3r0mMHpf7epk8ds66y+6xeUm9x+1/j5k9zs9YyOhx 5UQTq8e6P6+YPPr/Gnj0bVnF6PHzpU4AdxSXTUpqTmZZapG+XQJXxrQ5egWXIiueTdjK3MB4 x6OLkZNDQsBE4sLWuUwQtpjEhXvr2UBsIYFFjBIvr6d0MXIB2e1MEh//9oEVsQkYSnS97QIq 4uAQEciXWD2LFyTMLNDGIvFiAwtIWFggQeLNTzuQMIuAqsT0/VsZQWxeAQ+J43c/sIOUSAgo SMyZZAMS5hTwlDj4cw/UVg+JY3Mnsk1g5F3AyLCKUTS1ILmgOCk910ivODG3uDQvXS85P3cT Izi4n0nvYFzVYHGIUYCDUYmHd8al74FCrIllxZW5hxglOJiVRHj3sP4MFOJNSaysSi3Kjy8q zUktPsQozcGiJM57sNU6UEggPbEkNTs1tSC1CCbLxMEp1cBYabrgwG3B6YJ3Phy99+pW3bem GwmWa9fa/9Ncbu6xe67vIgUmbYED7+84HA1WkM1MyDT9+rxRhXuqqsn/J8nRu5ZWbxOLkc0F Rn7Q6V3bItcf4FB/aiQidX47r3hubJ/T9FU9NWcbJBON5p0tC68oFj0861y0dd8RFatlaRNV vlsnW6s8OaDEUpyRaKjFXFScCADeiOJ8agIAAA== Cc: Arnd Bergmann , Tomasz Figa , Michal Nazarewicz , Grant Likely , Kyungmin Park , Rob Herring , Sylwester Nawrocki , Olof Johansson , Sascha Hauer Subject: [Linaro-mm-sig] [PATCH v4 1/4] 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: ALoCoQkPCIuGQ88SsXWX+91kG/Ujedu9u6egSHj86quQyNHTMptVZrC2sw1KnHHGxT9xLd03HSkP X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: m.szyprowski@samsung.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.173 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. Such split in initialization procedure is also required for upcoming device tree support. Signed-off-by: Marek Szyprowski Acked-by: Kyungmin Park --- drivers/base/dma-contiguous.c | 147 +++++++++++++++++----------------- include/asm-generic/dma-contiguous.h | 2 - include/linux/dma-contiguous.h | 49 +++++++++++- 3 files changed, 119 insertions(+), 79 deletions(-) diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 0ca5442..2cc9c77 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -96,7 +96,7 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void) #endif /** - * dma_contiguous_reserve() - reserve area for contiguous memory handling + * 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 @@ -124,22 +124,29 @@ void __init dma_contiguous_reserve(phys_addr_t limit) #endif } - if (selected_size) { + if (selected_size && !dma_contiguous_default_area) { 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); + dma_contiguous_reserve_area(selected_size, 0, limit, + &dma_contiguous_default_area); } }; 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 +160,53 @@ 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) -{ - 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); - 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); + return 0; } -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; +static struct cma cma_areas[MAX_CMA_AREAS]; +static unsigned cma_area_count; static int __init cma_init_reserved_areas(void) { - struct cma_reserved *r = cma_reserved; - unsigned i = cma_reserved_count; - - pr_debug("%s()\n", __func__); + int i; - 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); + 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_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]; + struct cma *cma = &cma_areas[cma_area_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 +224,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 +234,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 +245,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->base_pfn = PFN_DOWN(base); + cma->count = size >> PAGE_SHIFT; + *res_cma = cma; + cma_area_count++; + pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M, (unsigned long)base); @@ -289,9 +258,37 @@ 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; +} + +/** + * dma_contiguous_set_default_area() - set global contiguous reserved area + * @cma: Pointer to the cma structure for the reserved area + * + * This function sets global, device independent contiguous memory area to + * the area created earlier by dma_contiguous_reserve_area() function. + */ +int __init dma_contiguous_set_default_area(struct cma *cma) +{ + dma_contiguous_default_area = cma; + return 0; } + /** * dma_alloc_from_contiguous() - allocate pages from contiguous area * @dev: Pointer to device for which the allocation is performed. 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..9c807c2 100644 --- a/include/linux/dma-contiguous.h +++ b/include/linux/dma-contiguous.h @@ -68,8 +68,37 @@ 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); +int dma_contiguous_set_default_area(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); @@ -82,6 +111,22 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, static inline void dma_contiguous_reserve(phys_addr_t limit) { } +static inline int dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base, + phys_addr_t limit, struct cma **res_cma) { + return -ENOSYS; +} + +static inline int dma_contiguous_add_device(struct device *dev, struct cma *cma) +{ + return -ENOSYS; +} + +static inline int dma_contiguous_set_default_area(struct cma *cma) +{ + return -ENOSYS; +} + + static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size, phys_addr_t base, phys_addr_t limit)