From patchwork Thu Feb 7 14:59:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 14673 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 22A3823F94 for ; Thu, 7 Feb 2013 15:00:08 +0000 (UTC) Received: from mail-vc0-f176.google.com (mail-vc0-f176.google.com [209.85.220.176]) by fiordland.canonical.com (Postfix) with ESMTP id B5B8FA18A3F for ; Thu, 7 Feb 2013 15:00:07 +0000 (UTC) Received: by mail-vc0-f176.google.com with SMTP id fy27so1627295vcb.7 for ; Thu, 07 Feb 2013 07:00:07 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=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:content-type :content-transfer-encoding:sender:errors-to:x-gm-message-state; bh=lc8mchcDj6kui4WPayQ4hLU8uVx3jpSynuj6NS3gV+0=; b=L9O5Be4yXSiFj18vANyCBbJuuhcFGpBh27QP3qfqOTA7gQgoObBgTHCTIkjnqEV/tG chrtumRAqevDC7cOfWaNJWh+kpL+U+/SQYqI6t0C9g3R5SoK7U39y5I2i0XKE0iDILw5 CyEG2SjghzYYRtCIGiSXqIkeH+rAgVUv44RrhoDLouJOjHRRMh3wh8H1uLQPgITmX93Y uG9C7JNzRNge7z8BQDqDCcMo4lxoI3z3jeO0BxqQxfcoPp+oeeTc9W0CamunytDVjUEI avAeoC13Vx9/xbDpI7Y5s3kWFCfx+nwPbjXoPzQTp86bXe7+Og5CLrd5sWNcutjstzFo daGg== X-Received: by 10.58.232.226 with SMTP id tr2mr1950032vec.48.1360249207121; Thu, 07 Feb 2013 07:00:07 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.252.8 with SMTP id zo8csp94084vec; Thu, 7 Feb 2013 07:00:06 -0800 (PST) X-Received: by 10.14.2.196 with SMTP id 44mr4836716eef.25.1360249204759; Thu, 07 Feb 2013 07:00:04 -0800 (PST) Received: from mombin.canonical.com (mombin.canonical.com. [91.189.95.16]) by mx.google.com with ESMTP id 7si44288223eec.132.2013.02.07.06.59.56; Thu, 07 Feb 2013 07:00:04 -0800 (PST) Received-SPF: neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) client-ip=91.189.95.16; Authentication-Results: mx.google.com; spf=neutral (google.com: 91.189.95.16 is neither permitted nor denied by best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org) smtp.mail=linaro-mm-sig-bounces@lists.linaro.org Received: from localhost ([127.0.0.1] helo=mombin.canonical.com) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U3Sx4-0006lp-8T; Thu, 07 Feb 2013 14:59:50 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by mombin.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1U3Sx2-0006lk-D2 for linaro-mm-sig@lists.linaro.org; Thu, 07 Feb 2013 14:59:49 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MHU00LPVUZF9JV0@mailout4.samsung.com> for linaro-mm-sig@lists.linaro.org; Thu, 07 Feb 2013 23:59:44 +0900 (KST) X-AuditID: cbfee61b-b7fb06d000000f28-b5-5113c160276b Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id D5.09.03880.061C3115; Thu, 07 Feb 2013 23:59:44 +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 <0MHU00EHMUZ9TP80@mmp2.samsung.com> for linaro-mm-sig@lists.linaro.org; Thu, 07 Feb 2013 23:59:44 +0900 (KST) From: Marek Szyprowski To: linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org Date: Thu, 07 Feb 2013 15:59:24 +0100 Message-id: <1360249164-1898-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1359984182-6307-1-git-send-email-m.szyprowski@samsung.com> References: <1359984182-6307-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFnrEJMWRmVeSWpSXmKPExsVy+t9jQd2Eg8KBBiu7xCy+XHnI5MDocfvf Y+YAxigum5TUnMyy1CJ9uwSujJ8dj1gLXmtVLNh2iK2BcbNSFyMnh4SAicS0vUfZIGwxiQv3 1gPZXBxCAtMZJbZ/2ccC4axiktjafA2sik3AUKLrbReYLSLgIfFkxTlmEJtZ4DCTxPQJESC2 sECsxIxvU9lBbBYBVYk1i6+zgNi8Au4SR14eAbI5gLYpSMyZZAMS5gQa8/TURkYQWwio5PLX yawTGHkXMDKsYhRNLUguKE5KzzXSK07MLS7NS9dLzs/dxAj2+TPpHYyrGiwOMQpwMCrx8N5c KhQoxJpYVlyZe4hRgoNZSYRXfr1woBBvSmJlVWpRfnxRaU5q8SFGaQ4WJXFexlNPAoQE0hNL UrNTUwtSi2CyTBycUg2MshfFfafzbp6cWfettfSRm7Oe2Noud9MyC4kE2VOLXpUXvZqdOKnN bKNRf/OBbWdr5O81b7AxtL6RLyPipLaEcfvXyBVbtz/q5T3oesLR6zDz3uVvRFzPvPTtXyOk mWudVNKt03tp4+6C/6JhS5caazT6pR+TPxU8MeXn2nPx75Q7Px3T3z1LiaU4I9FQi7moOBEA baExTvUBAAA= Cc: Russell King - ARM Linux , Arnd Bergmann , Michal Nazarewicz , heesub.shin@samsung.com, Minchan Kim , Kyungmin Park , sj2202.park@samsung.com, lauraa@quicinc.com Subject: [Linaro-mm-sig] [PATCHv3 1/2] ARM: dma-mapping: add support for CMA regions placed in highmem zone X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Unified memory management interest group." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linaro-mm-sig-bounces@lists.linaro.org Errors-To: linaro-mm-sig-bounces@lists.linaro.org X-Gm-Message-State: ALoCoQlRDOh/uEDW45uERq6UpCztUcpOUOQECLe2HWL9Iw7cUbVHI9+EEhZ3XzX/3ORuPMiN3MX+ This patch adds missing pieces to correctly support memory pages served from CMA regions placed in high memory zones. Please note that the default global CMA area is still put into lowmem and is limited by optional architecture specific DMA zone. One can however put device specific CMA regions in high memory zone to reduce lowmem usage. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Acked-by: Michal Nazarewicz --- Changle log: v3: fixed build break for non-MMU builds (thanks to Thierry Reding!) v2: restructured code and made all himem checks positive ('if (PageHighMem(page))' instead of 'if (!PageHighMem(page))') --- arch/arm/mm/dma-mapping.c | 57 +++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index de93ecd..5f79361 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -186,13 +186,24 @@ static u64 get_coherent_dma_mask(struct device *dev) static void __dma_clear_buffer(struct page *page, size_t size) { - void *ptr; /* * Ensure that the allocated pages are zeroed, and that any data * lurking in the kernel direct-mapped region is invalidated. */ - ptr = page_address(page); - if (ptr) { + if (PageHighMem(page)) { + phys_addr_t base = __pfn_to_phys(page_to_pfn(page)); + phys_addr_t end = base + size; + while (size > 0) { + void *ptr = kmap_atomic(page); + memset(ptr, 0, PAGE_SIZE); + dmac_flush_range(ptr, ptr + PAGE_SIZE); + kunmap_atomic(ptr); + page++; + size -= PAGE_SIZE; + } + outer_flush_range(base, end); + } else { + void *ptr = page_address(page); memset(ptr, 0, size); dmac_flush_range(ptr, ptr + size); outer_flush_range(__pa(ptr), __pa(ptr) + size); @@ -243,7 +254,8 @@ static void __dma_free_buffer(struct page *page, size_t size) #endif static void *__alloc_from_contiguous(struct device *dev, size_t size, - pgprot_t prot, struct page **ret_page); + pgprot_t prot, struct page **ret_page, + const void *caller); static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp, pgprot_t prot, struct page **ret_page, @@ -346,10 +358,11 @@ static int __init atomic_pool_init(void) goto no_pages; if (IS_ENABLED(CONFIG_CMA)) - ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page); + ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page, + atomic_pool_init); else ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot, - &page, NULL); + &page, atomic_pool_init); if (ptr) { int i; @@ -542,27 +555,41 @@ static int __free_from_pool(void *start, size_t size) } static void *__alloc_from_contiguous(struct device *dev, size_t size, - pgprot_t prot, struct page **ret_page) + pgprot_t prot, struct page **ret_page, + const void *caller) { unsigned long order = get_order(size); size_t count = size >> PAGE_SHIFT; struct page *page; + void *ptr; page = dma_alloc_from_contiguous(dev, count, order); if (!page) return NULL; __dma_clear_buffer(page, size); - __dma_remap(page, size, prot); + if (PageHighMem(page)) { + ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot, caller); + if (!ptr) { + dma_release_from_contiguous(dev, page, count); + return NULL; + } + } else { + __dma_remap(page, size, prot); + ptr = page_address(page); + } *ret_page = page; - return page_address(page); + return ptr; } static void __free_from_contiguous(struct device *dev, struct page *page, - size_t size) + void *cpu_addr, size_t size) { - __dma_remap(page, size, pgprot_kernel); + if (PageHighMem(page)) + __dma_free_remap(cpu_addr, size); + else + __dma_remap(page, size, pgprot_kernel); dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT); } @@ -583,9 +610,9 @@ static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot) #define __get_dma_pgprot(attrs, prot) __pgprot(0) #define __alloc_remap_buffer(dev, size, gfp, prot, ret, c) NULL #define __alloc_from_pool(size, ret_page) NULL -#define __alloc_from_contiguous(dev, size, prot, ret) NULL +#define __alloc_from_contiguous(dev, size, prot, ret, c) NULL #define __free_from_pool(cpu_addr, size) 0 -#define __free_from_contiguous(dev, page, size) do { } while (0) +#define __free_from_contiguous(dev, page, cpu_addr, size) do { } while (0) #define __dma_free_remap(cpu_addr, size) do { } while (0) #endif /* CONFIG_MMU */ @@ -645,7 +672,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, else if (!IS_ENABLED(CONFIG_CMA)) addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller); else - addr = __alloc_from_contiguous(dev, size, prot, &page); + addr = __alloc_from_contiguous(dev, size, prot, &page, caller); if (addr) *handle = pfn_to_dma(dev, page_to_pfn(page)); @@ -739,7 +766,7 @@ static void __arm_dma_free(struct device *dev, size_t size, void *cpu_addr, * Non-atomic allocations cannot be freed with IRQs disabled */ WARN_ON(irqs_disabled()); - __free_from_contiguous(dev, page, size); + __free_from_contiguous(dev, page, cpu_addr, size); } }