All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: iommu@lists.linux-foundation.org
Cc: Robin Murphy <robin.murphy@arm.com>,
	Vineet Gupta <vgupta@synopsys.com>,
	"Matwey V. Kornilov" <matwey@sai.msu.ru>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	linux-snps-arc@lists.infradead.org,
	Ezequiel Garcia <ezequiel@collabora.com>,
	linux-media@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	dri-devel@lists.freedesktop.org, sparclinux@vger.kernel.org,
	openrisc@lists.librecores.org, linux-parisc@vger.kernel.org,
	linux-mips@vger.kernel.org
Subject: [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat,  8 Dec 2018 09:41:11 -0800	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va == 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) == NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size == 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va == NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) == NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2


WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: iommu@lists.linux-foundation.org
Cc: linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	Vineet Gupta <vgupta@synopsys.com>,
	Robin Murphy <robin.murphy@arm.com>,
	dri-devel@lists.freedesktop.org,
	"Matwey V. Kornilov" <matwey@sai.msu.ru>,
	openrisc@lists.librecores.org,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	sparclinux@vger.kernel.org, linux-snps-arc@lists.infradead.org,
	Ezequiel Garcia <ezequiel@collabora.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-media@vger.kernel.org
Subject: [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat, 08 Dec 2018 17:41:11 +0000	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va = 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) = NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) = NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size = 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va = NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) = NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) = NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2

WARNING: multiple messages have this Message-ID (diff)
From: hch@lst.de (Christoph Hellwig)
To: linux-snps-arc@lists.infradead.org
Subject: [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat,  8 Dec 2018 09:41:11 -0800	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va == 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) == NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size == 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va == NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) == NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2

WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: iommu@lists.linux-foundation.org
Cc: linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	Vineet Gupta <vgupta@synopsys.com>,
	Robin Murphy <robin.murphy@arm.com>,
	dri-devel@lists.freedesktop.org,
	"Matwey V. Kornilov" <matwey@sai.msu.ru>,
	openrisc@lists.librecores.org,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	sparclinux@vger.kernel.org, linux-snps-arc@lists.infradead.org,
	Ezequiel Garcia <ezequiel@collabora.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-media@vger.kernel.org
Subject: [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat,  8 Dec 2018 09:41:11 -0800	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va == 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) == NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size == 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va == NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) == NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2

WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: iommu@lists.linux-foundation.org
Cc: linux-mips@vger.kernel.org, linux-parisc@vger.kernel.org,
	Vineet Gupta <vgupta@synopsys.com>,
	Robin Murphy <robin.murphy@arm.com>,
	dri-devel@lists.freedesktop.org,
	"Matwey V. Kornilov" <matwey@sai.msu.ru>,
	openrisc@lists.librecores.org,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	sparclinux@vger.kernel.org, linux-snps-arc@lists.infradead.org,
	Ezequiel Garcia <ezequiel@collabora.com>,
	linux-arm-kernel@lists.infradead.org,
	linux-media@vger.kernel.org
Subject: [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat,  8 Dec 2018 09:41:11 -0800	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va == 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) == NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size == 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va == NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) == NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: openrisc@lists.librecores.org
Subject: [OpenRISC] [PATCH 2/6] sparc: factor the dma coherent mapping into helper
Date: Sat,  8 Dec 2018 09:41:11 -0800	[thread overview]
Message-ID: <20181208174115.16237-3-hch@lst.de> (raw)
In-Reply-To: <20181208174115.16237-1-hch@lst.de>

Factor the code to remap memory returned from the DMA coherent allocator
into two helpers that can be shared by the IOMMU and direct mapping code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/sparc/kernel/ioport.c | 151 ++++++++++++++++---------------------
 1 file changed, 67 insertions(+), 84 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 4b2167a0ec0b..fd7a41c6d688 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -247,6 +247,53 @@ static void _sparc_free_io(struct resource *res)
 	release_resource(res);
 }
 
+static unsigned long sparc_dma_alloc_resource(struct device *dev, size_t len)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	if (!res)
+		return 0;
+	res->name = dev->of_node->name;
+
+	if (allocate_resource(&_sparc_dvma, res, len, _sparc_dvma.start,
+			_sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("sbus_alloc_consistent: cannot occupy 0x%zx", len);
+		kfree(res);
+		return 0;
+	}
+
+	return res->start;
+}
+
+static bool sparc_dma_free_resource(void *cpu_addr, size_t size)
+{
+	unsigned long addr = (unsigned long)cpu_addr;
+	struct resource *res;
+
+	res = lookup_resource(&_sparc_dvma, addr);
+	if (!res) {
+		printk("%s: cannot free %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	if ((addr & (PAGE_SIZE - 1)) != 0) {
+		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+		return false;
+	}
+
+	size = PAGE_ALIGN(size);
+	if (resource_size(res) != size) {
+		printk("%s: region 0x%lx asked 0x%zx\n",
+			__func__, (long)resource_size(res), size);
+		return false;
+	}
+
+	release_resource(res);
+	kfree(res);
+	return true;
+}
+
 #ifdef CONFIG_SBUS
 
 void sbus_set_sbus64(struct device *dev, int x)
@@ -264,10 +311,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp,
 				 unsigned long attrs)
 {
-	struct platform_device *op = to_platform_device(dev);
 	unsigned long len_total = PAGE_ALIGN(len);
-	unsigned long va;
-	struct resource *res;
+	unsigned long va, addr;
 	int order;
 
 	/* XXX why are some lengths signed, others unsigned? */
@@ -284,32 +329,23 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 	if (va == 0)
 		goto err_nopages;
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL)
+	addr = sparc_dma_alloc_resource(dev, len_total);
+	if (!addr)
 		goto err_nomem;
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
-		goto err_nova;
-	}
-
 	// XXX The sbus_map_dma_area does this for us below, see comments.
 	// srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
 	 * XXX That's where sdev would be used. Currently we load
 	 * all iommu tables with the same translations.
 	 */
-	if (sbus_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
+	if (sbus_map_dma_area(dev, dma_addrp, va, addr, len_total) != 0)
 		goto err_noiommu;
 
-	res->name = op->dev.of_node->name;
-
-	return (void *)(unsigned long)res->start;
+	return (void *)addr;
 
 err_noiommu:
-	release_resource(res);
-err_nova:
-	kfree(res);
+	sparc_dma_free_resource((void *)addr, len_total);
 err_nomem:
 	free_pages(va, order);
 err_nopages:
@@ -319,29 +355,11 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 			       dma_addr_t ba, unsigned long attrs)
 {
-	struct resource *res;
 	struct page *pgv;
 
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)p)) == NULL) {
-		printk("sbus_free_consistent: cannot free %p\n", p);
-		return;
-	}
-
-	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
-		printk("sbus_free_consistent: unaligned va %p\n", p);
-		return;
-	}
-
 	n = PAGE_ALIGN(n);
-	if (resource_size(res) != n) {
-		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
-		    (long)resource_size(res), n);
+	if (!sparc_dma_free_resource(p, n))
 		return;
-	}
-
-	release_resource(res);
-	kfree(res);
 
 	pgv = virt_to_page(p);
 	sbus_unmap_dma_area(dev, ba, n);
@@ -418,45 +436,30 @@ arch_initcall(sparc_register_ioport);
 void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 		gfp_t gfp, unsigned long attrs)
 {
-	unsigned long len_total = PAGE_ALIGN(size);
+	unsigned long addr;
 	void *va;
-	struct resource *res;
-	int order;
 
-	if (size == 0) {
+	if (!size || size > 256 * 1024)	/* __get_free_pages() limit */
 		return NULL;
-	}
-	if (size > 256*1024) {			/* __get_free_pages() limit */
-		return NULL;
-	}
 
-	order = get_order(len_total);
-	va = (void *) __get_free_pages(gfp, order);
-	if (va == NULL) {
-		printk("%s: no %ld pages\n", __func__, len_total>>PAGE_SHIFT);
-		goto err_nopages;
+	size = PAGE_ALIGN(size);
+	va = (void *) __get_free_pages(gfp, get_order(size));
+	if (!va) {
+		printk("%s: no %zd pages\n", __func__, size >> PAGE_SHIFT);
+		return NULL;
 	}
 
-	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		printk("%s: no core\n", __func__);
+	addr = sparc_dma_alloc_resource(dev, size);
+	if (!addr)
 		goto err_nomem;
-	}
 
-	if (allocate_resource(&_sparc_dvma, res, len_total,
-	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
-		printk("%s: cannot occupy 0x%lx", __func__, len_total);
-		goto err_nova;
-	}
-	srmmu_mapiorange(0, virt_to_phys(va), res->start, len_total);
+	srmmu_mapiorange(0, virt_to_phys(va), addr, size);
 
 	*dma_handle = virt_to_phys(va);
-	return (void *) res->start;
+	return (void *)addr;
 
-err_nova:
-	kfree(res);
 err_nomem:
-	free_pages((unsigned long)va, order);
-err_nopages:
+	free_pages((unsigned long)va, get_order(size));
 	return NULL;
 }
 
@@ -471,31 +474,11 @@ void *arch_dma_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	struct resource *res;
-
-	if ((res = lookup_resource(&_sparc_dvma,
-	    (unsigned long)cpu_addr)) == NULL) {
-		printk("%s: cannot free %p\n", __func__, cpu_addr);
-		return;
-	}
-
-	if (((unsigned long)cpu_addr & (PAGE_SIZE-1)) != 0) {
-		printk("%s: unaligned va %p\n", __func__, cpu_addr);
+	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
 		return;
-	}
-
-	size = PAGE_ALIGN(size);
-	if (resource_size(res) != size) {
-		printk("%s: region 0x%lx asked 0x%zx\n", __func__,
-		    (long)resource_size(res), size);
-		return;
-	}
 
 	dma_make_coherent(dma_addr, size);
 	srmmu_unmapiorange((unsigned long)cpu_addr, size);
-
-	release_resource(res);
-	kfree(res);
 	free_pages((unsigned long)phys_to_virt(dma_addr), get_order(size));
 }
 
-- 
2.19.2


  parent reply	other threads:[~2018-12-08 17:41 UTC|newest]

Thread overview: 221+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-08 17:41 make the non-consistent DMA allocator more userful (resend) Christoph Hellwig
2018-12-08 17:41 ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41 ` Christoph Hellwig
2018-12-08 17:41 ` Christoph Hellwig
2018-12-08 17:41 ` Christoph Hellwig
2018-12-08 17:41 ` Christoph Hellwig
2018-12-08 17:41 ` [PATCH 1/6] sparc: remove no needed sbus_dma_ops methods Christoph Hellwig
2018-12-08 17:41   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:57   ` David Miller
2018-12-09  4:57     ` [OpenRISC] " David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-08 17:41 ` Christoph Hellwig [this message]
2018-12-08 17:41   ` [OpenRISC] [PATCH 2/6] sparc: factor the dma coherent mapping into helper Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:57   ` David Miller
2018-12-09  4:57     ` [OpenRISC] " David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-08 17:41 ` [PATCH 3/6] sparc: remove the sparc32_dma_ops indirection Christoph Hellwig
2018-12-08 17:41   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:57   ` David Miller
2018-12-09  4:57     ` [OpenRISC] " David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-15  6:30   ` Guenter Roeck
2018-12-15  6:30     ` [OpenRISC] " Guenter Roeck
2018-12-15  6:30     ` Guenter Roeck
2018-12-15  6:30     ` Guenter Roeck
2018-12-15  6:30     ` Guenter Roeck
2018-12-15  6:30     ` Guenter Roeck
2018-12-15 10:47     ` Christoph Hellwig
2018-12-15 10:47       ` [OpenRISC] " Christoph Hellwig
2018-12-15 10:47       ` Christoph Hellwig
2018-12-15 10:47       ` Christoph Hellwig
2018-12-15 10:47       ` Christoph Hellwig
2018-12-15 10:47       ` Christoph Hellwig
2018-12-15 14:57       ` Guenter Roeck
2018-12-15 14:57         ` [OpenRISC] " Guenter Roeck
2018-12-15 14:57         ` Guenter Roeck
2018-12-15 14:57         ` Guenter Roeck
2018-12-15 14:57         ` Guenter Roeck
2018-12-15 14:57         ` Guenter Roeck
2018-12-08 17:41 ` [PATCH 4/6] sparc: remove not required includes from dma-mapping.h Christoph Hellwig
2018-12-08 17:41   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:57   ` David Miller
2018-12-09  4:57     ` [OpenRISC] " David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-09  4:57     ` David Miller
2018-12-08 17:41 ` [PATCH 5/6] sparc: move the leon PCI memory space comment to <asm/leon.h> Christoph Hellwig
2018-12-08 17:41   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-08 17:41 ` [PATCH 6/6] sparc: merge 32-bit and 64-bit version of pci.h Christoph Hellwig
2018-12-08 17:41   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-08 17:41   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-10 16:32     ` Christoph Hellwig
2018-12-10 16:32       ` [OpenRISC] " Christoph Hellwig
2018-12-10 16:32       ` Christoph Hellwig
2018-12-10 16:32       ` Christoph Hellwig
2018-12-10 16:32       ` Christoph Hellwig
2018-12-10 16:32       ` Christoph Hellwig
2018-12-10 18:10       ` David Miller
2018-12-10 18:10         ` [OpenRISC] " David Miller
2018-12-10 18:10         ` David Miller
2018-12-10 18:10         ` David Miller
2018-12-10 18:10         ` David Miller
2018-12-10 18:10         ` David Miller
2018-12-10 19:22         ` Christoph Hellwig
2018-12-10 19:22           ` [OpenRISC] " Christoph Hellwig
2018-12-10 19:22           ` Christoph Hellwig
2018-12-10 19:22           ` Christoph Hellwig
2018-12-10 19:22           ` Christoph Hellwig
2018-12-10 19:22           ` Christoph Hellwig
2018-12-10 19:33           ` David Miller
2018-12-10 19:33             ` [OpenRISC] " David Miller
2018-12-10 19:33             ` David Miller
2018-12-10 19:33             ` David Miller
2018-12-10 19:33             ` David Miller
2018-12-10 19:33             ` David Miller
2018-12-11 13:46             ` Christoph Hellwig
2018-12-11 13:46               ` [OpenRISC] " Christoph Hellwig
2018-12-11 13:46               ` Christoph Hellwig
2018-12-11 13:46               ` Christoph Hellwig
2018-12-11 13:46               ` Christoph Hellwig
2018-12-11 13:46               ` Christoph Hellwig
  -- strict thread matches above, loose matches on Subject: below --
2018-12-08 17:36 make the non-consistent DMA allocator more userful Christoph Hellwig
2018-12-08 17:36 ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36 ` Christoph Hellwig
2018-12-08 17:36 ` Christoph Hellwig
2018-12-08 17:36 ` Christoph Hellwig
2018-12-08 17:36 ` [PATCH 01/10] dma-direct: provide a generic implementation of DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36 ` [PATCH 02/10] arm64/iommu: don't remap contiguous allocations for coherent devices Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-10 19:19   ` Robin Murphy
2018-12-10 19:19     ` [OpenRISC] " Robin Murphy
2018-12-10 19:19     ` Robin Murphy
2018-12-10 19:19     ` Robin Murphy
2018-12-10 19:19     ` Robin Murphy
2018-12-10 19:25     ` Christoph Hellwig
2018-12-10 19:25       ` [OpenRISC] " Christoph Hellwig
2018-12-10 19:25       ` Christoph Hellwig
2018-12-10 19:25       ` Christoph Hellwig
2018-12-10 19:25       ` Christoph Hellwig
2018-12-08 17:36 ` [PATCH 03/10] arm64/iommu: implement support for DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36 ` [PATCH 04/10] arm: implement DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 22:52   ` Ezequiel Garcia
2018-12-08 22:52     ` [OpenRISC] " Ezequiel Garcia
2018-12-08 22:52     ` Ezequiel Garcia
2018-12-08 22:52     ` Ezequiel Garcia
2018-12-08 22:52     ` Ezequiel Garcia
2018-12-10 19:16     ` Christoph Hellwig
2018-12-10 19:16       ` [OpenRISC] " Christoph Hellwig
2018-12-10 19:16       ` Christoph Hellwig
2018-12-10 19:16       ` Christoph Hellwig
2018-12-10 19:16       ` Christoph Hellwig
2018-12-08 17:36 ` [PATCH 05/10] sparc64/iommu: move code around a bit Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-08 17:36 ` [PATCH 06/10] sparc64/iommu: implement DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-08 17:36 ` [PATCH 07/10] sparc64/pci_sun4v: move code around a bit Christoph Hellwig
2018-12-08 17:36   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-08 17:36   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-08 17:37 ` [PATCH 08/10] sparc64/pci_sun4v: implement DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:37   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-09  4:58   ` David Miller
2018-12-09  4:58     ` [OpenRISC] " David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-09  4:58     ` David Miller
2018-12-08 17:37 ` [PATCH 09/10] dma-mapping: skip declared coherent memory for DMA_ATTR_NON_CONSISTENT Christoph Hellwig
2018-12-08 17:37   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37 ` [PATCH 10/10] Documentation: update the description " Christoph Hellwig
2018-12-08 17:37   ` [OpenRISC] " Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig
2018-12-08 17:37   ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181208174115.16237-3-hch@lst.de \
    --to=hch@lst.de \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=ezequiel@collabora.com \
    --cc=iommu@lists.linux-foundation.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=linux-parisc@vger.kernel.org \
    --cc=linux-snps-arc@lists.infradead.org \
    --cc=matwey@sai.msu.ru \
    --cc=openrisc@lists.librecores.org \
    --cc=robin.murphy@arm.com \
    --cc=sparclinux@vger.kernel.org \
    --cc=vgupta@synopsys.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.