From patchwork Mon Oct 15 14:03:52 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 1697461 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 650E83FCA5 for ; Mon, 5 Nov 2012 13:51:26 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TVN2i-00068j-6j; Mon, 05 Nov 2012 13:48:44 +0000 Received: from mailout4.samsung.com ([203.254.224.34]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TNlIE-0002SQ-Jf for linux-arm-kernel@lists.infradead.org; Mon, 15 Oct 2012 14:05:20 +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 <0MBX005OYTRLG0A0@mailout4.samsung.com> for linux-arm-kernel@lists.infradead.org; Mon, 15 Oct 2012 23:04:33 +0900 (KST) X-AuditID: cbfee61b-b7fd46d0000046e0-fc-507c17f165da Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id ED.6A.18144.1F71C705; Mon, 15 Oct 2012 23:04:33 +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 <0MBX00JMCTQOCL70@mmp1.samsung.com> for linux-arm-kernel@lists.infradead.org; Mon, 15 Oct 2012 23:04:33 +0900 (KST) From: Marek Szyprowski To: linux-arm-kernel@lists.infradead.org, linaro-mm-sig@lists.linaro.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [RFC 2/2] ARM: dma-mapping: add support for DMA_ATTR_FORCE_CONTIGUOUS attribute Date: Mon, 15 Oct 2012 16:03:52 +0200 Message-id: <1350309832-18461-3-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.7.9.5 In-reply-to: <1350309832-18461-1-git-send-email-m.szyprowski@samsung.com> References: <1350309832-18461-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrHJMWRmVeSWpSXmKPExsVy+t9jAd2P4jUBBk8+SFpsenyN1YHRY/OS +gDGKC6blNSczLLUIn27BK6Mnz8/MxZ8kKiYv16ugXGaSBcjJ4eEgInE5fnLWSBsMYkL99az dTFycQgJLGKUODH9PpSzgUmie/MTZpAqNgFDia63XUAJDg4RgRqJeTMYQWqYBV4zSszauRks LiwQJbHvayZIOYuAqsSLO79YQMK8Ah4SLzeCVUgIKEjMmWQDUsEp4Cnx9OFcRhBbCKhiXuNu 5gmMvAsYGVYxiqYWJBcUJ6XnGukVJ+YWl+al6yXn525iBPv6mfQOxlUNFocYBTgYlXh4f3pV BwixJpYVV+YeYpTgYFYS4X32CCjEm5JYWZValB9fVJqTWnyIUZqDRUmct9kjJUBIID2xJDU7 NbUgtQgmy8TBKdXAWHT/74MPwvPnPXM7yJBWxZnddNf623wv5Xk3Wk5usVhbeu8lh92SmQZX Fn3WVNA8WXX4O5Phq11LpZpUAoOjXidzhu97Ee4Tv4kh7tel3ckydxd+/85/0zXM8/rbu38t i7y4JboMvvUt57+RHiB9vVItZXL4TsdtXC4KGme368VzyfLXC72ZrsRSnJFoqMVcVJwIAPe+ 5U3xAQAA X-Bad-Reply: References and In-Reply-To but no 'Re:' in Subject. X-Spam-Note: CRM114 invocation failed X-Spam-Score: -7.3 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [203.254.224.34 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.4 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Mailman-Approved-At: Mon, 05 Nov 2012 08:45:43 -0500 Cc: Russell King - ARM Linux , Arnd Bergmann , Inki Dae , Kyungmin Park , Rob Clark , Marek Szyprowski X-BeenThere: linux-arm-kernel@lists.infradead.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 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This patch adds support for DMA_ATTR_FORCE_CONTIGUOUS attribute for dma_alloc_attrs() in IOMMU-aware implementation. For allocating physically contiguous buffers Contiguous Memory Allocator is used. Signed-off-by: Marek Szyprowski --- arch/arm/mm/dma-mapping.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 477a2d2..583a302 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1036,7 +1036,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping, spin_unlock_irqrestore(&mapping->lock, flags); } -static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp) +static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, + gfp_t gfp, struct dma_attrs *attrs) { struct page **pages; int count = size >> PAGE_SHIFT; @@ -1050,6 +1051,23 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t if (!pages) return NULL; + if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) + { + unsigned long order = get_order(size); + struct page *page; + + page = dma_alloc_from_contiguous(dev, count, order); + if (!page) + goto error; + + __dma_clear_buffer(page, size); + + for (i = 0; i < count; i++) + pages[i] = page + i; + + return pages; + } + while (count) { int j, order = __fls(count); @@ -1083,14 +1101,21 @@ error: return NULL; } -static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size) +static int __iommu_free_buffer(struct device *dev, struct page **pages, + size_t size, struct dma_attrs *attrs) { int count = size >> PAGE_SHIFT; int array_size = count * sizeof(struct page *); int i; - for (i = 0; i < count; i++) - if (pages[i]) - __free_pages(pages[i], 0); + + if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) { + dma_release_from_contiguous(dev, pages[0], count); + } else { + for (i = 0; i < count; i++) + if (pages[i]) + __free_pages(pages[i], 0); + } + if (array_size <= PAGE_SIZE) kfree(pages); else @@ -1252,7 +1277,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, if (gfp & GFP_ATOMIC) return __iommu_alloc_atomic(dev, size, handle); - pages = __iommu_alloc_buffer(dev, size, gfp); + pages = __iommu_alloc_buffer(dev, size, gfp, attrs); if (!pages) return NULL; @@ -1273,7 +1298,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size, err_mapping: __iommu_remove_mapping(dev, *handle, size); err_buffer: - __iommu_free_buffer(dev, pages, size); + __iommu_free_buffer(dev, pages, size, attrs); return NULL; } @@ -1329,7 +1354,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr, } __iommu_remove_mapping(dev, handle, size); - __iommu_free_buffer(dev, pages, size); + __iommu_free_buffer(dev, pages, size, attrs); } static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,