All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area.
@ 2009-11-02 14:28 Kristoffer Glembo
  2009-11-03 22:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific Julian Calaby
                   ` (22 more replies)
  0 siblings, 23 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-02 14:28 UTC (permalink / raw)
  To: sparclinux

Added mmu_inval_dma_area for LEON which flushes dcache if snooping is not enabled
and created LEON specific dma_ops.

Best regards,
Kristoffer Glembo

---
 arch/sparc/kernel/ioport.c |  222 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 218 insertions(+), 4 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 9f61fd8..63aab03 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -48,8 +48,18 @@
 #include <asm/dma.h>
 #include <asm/iommu.h>
 #include <asm/io-unit.h>
+#include <asm/leon.h>
 
+#ifndef CONFIG_SPARC_LEON
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
+#else
+static inline void mmu_inval_dma_area(unsigned long va, unsigned long len)
+{
+	if (!sparc_leon3_snooping_enabled()) {
+                leon_flush_dcache_all();
+        }
+}
+#endif
 
 static struct resource *_sparc_find_resource(struct resource *r,
 					     unsigned long);
@@ -70,6 +80,9 @@ static struct resource _sparc_dvma = {
 	.name = "sparc_iomap", .start = IOBASE_VADDR, .end = IOBASE_END - 1
 };
 
+struct dma_map_ops *dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
 /*
  * Our mini-allocator...
  * Boy this is gross! We need it because we must map I/O for
@@ -403,11 +416,214 @@ struct dma_map_ops sbus_dma_ops = {
 	.sync_sg_for_device	= sbus_sync_sg_for_device,
 };
 
-struct dma_map_ops *dma_ops = &sbus_dma_ops;
-EXPORT_SYMBOL(dma_ops);
+#endif /* CONFIG_SBUS */
+
+#ifdef CONFIG_SPARC_LEON
+
+static void *leon3_alloc_coherent(struct device *dev, size_t len,
+				  dma_addr_t *pba, gfp_t gfp)
+{
+	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	unsigned long va;
+ 	struct resource *res;
+	int order;
+
+	if (len = 0) {
+		return NULL;
+	}
+	if (len > 256*1024) {			/* __get_free_pages() limit */
+		return NULL;
+	}
+
+	order = get_order(len_total);
+	va = __get_free_pages(GFP_KERNEL, order);
+	if (va = 0) {
+		printk("leon3_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
+		return NULL;
+	}
+
+	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) = NULL) {
+		free_pages(va, order);
+		printk("leon3_alloc_consistent: no core\n");
+		return NULL;
+	}
+
+	if (allocate_resource(&_sparc_dvma, res, len_total,
+	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
+		printk("leon3_alloc_consistent: cannot occupy 0x%lx", len_total);
+		free_pages(va, order);
+		kfree(res);
+		return NULL;
+	}
+	mmu_inval_dma_area(va, len_total);
+
+	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
+
+	*pba = virt_to_phys(va);
+	return (void *) res->start;
+}
+
+
+static void leon3_free_coherent(struct device *dev, size_t n, void *p,
+				dma_addr_t ba)
+{
+	struct resource *res;
+	unsigned long pgp;
+
+	if ((res = _sparc_find_resource(&_sparc_dvma,
+	    (unsigned long)p)) = NULL) {
+		printk("leon3_free_consistent: cannot free %p\n", p);
+		return;
+	}
+
+	if (((unsigned long)p & (PAGE_SIZE-1)) != 0) {
+		printk("leon3_free_consistent: unaligned va %p\n", p);
+		return;
+	}
+
+	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	if ((res->end-res->start)+1 != n) {
+		printk("leon3_free_consistent: region 0x%lx asked 0x%lx\n",
+		    (long)((res->end-res->start)+1), (long)n);
+		return;
+	}
+
+	pgp = (unsigned long) phys_to_virt(ba);	/* bus_to_virt actually */
+	mmu_inval_dma_area(pgp, n);
+	sparc_unmapiorange((unsigned long)p, n);
+
+	release_resource(res);
+	kfree(res);
+
+	free_pages(pgp, get_order(n));
+}
+
+static dma_addr_t leon3_map_page(struct device *dev, struct page *page,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction dir,
+				 struct dma_attrs *attrs)
+{
+	/* LEON3 is write-through, not flushing. */
+	return page_to_phys(page) + offset;
+}
+
+static void leon3_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
+                             enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+        if (dir != DMA_TO_DEVICE) {
+		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
+		    (size + PAGE_SIZE-1) & PAGE_MASK);
+	}
+}
+
+static int leon3_map_sg(struct device *device, struct scatterlist *sgl,
+			int nents, enum dma_data_direction dir,
+			struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int n;
+
+	/* LEON3 is write-through, not flushing. */
+	for_each_sg(sgl, sg, nents, n) {
+		BUG_ON(page_address(sg_page(sg)) = NULL);
+		sg->dma_address = virt_to_phys(sg_virt(sg));
+		sg->dma_length = sg->length;
+	}
+	return nents;
+}
+
+static void leon3_unmap_sg(struct device *dev, struct scatterlist *sgl,
+			   int nents, enum dma_data_direction dir,
+			   struct dma_attrs *attrs)
+{
+	struct scatterlist *sg;
+	int n;
+
+	if (dir != DMA_TO_DEVICE) {
+		for_each_sg(sgl, sg, nents, n) {
+			BUG_ON(page_address(sg_page(sg)) = NULL);
+			mmu_inval_dma_area(
+			    (unsigned long) page_address(sg_page(sg)),
+			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+		}
+	}
+}
+
+static void leon3_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
+				      size_t size, enum dma_data_direction dir)
+{
+	if (dir != DMA_TO_DEVICE) {
+		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
+		    (size + PAGE_SIZE-1) & PAGE_MASK);
+	}
+}
+
+static void leon3_sync_single_for_device(struct device *dev, dma_addr_t ba,
+					 size_t size, enum dma_data_direction dir)
+{
+	if (dir != DMA_TO_DEVICE) {
+		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
+		    (size + PAGE_SIZE-1) & PAGE_MASK);
+	}
+}
+
+static void leon3_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
+				  int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int n;
+
+	if (dir != DMA_TO_DEVICE) {
+		for_each_sg(sgl, sg, nents, n) {
+			BUG_ON(page_address(sg_page(sg)) = NULL);
+			mmu_inval_dma_area(
+			    (unsigned long) page_address(sg_page(sg)),
+			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+		}
+	}
+}
+
+static void leon3_sync_sg_for_device(struct device *device, struct scatterlist *sgl,
+				     int nents, enum dma_data_direction dir)
+{
+	struct scatterlist *sg;
+	int n;
+
+	if (dir != DMA_TO_DEVICE) {
+		for_each_sg(sgl, sg, nents, n) {
+			BUG_ON(page_address(sg_page(sg)) = NULL);
+			mmu_inval_dma_area(
+			    (unsigned long) page_address(sg_page(sg)),
+			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+		}
+	}
+}
+
+struct dma_map_ops leon3_dma_ops = {
+	.alloc_coherent		= leon3_alloc_coherent,
+	.free_coherent		= leon3_free_coherent,
+	.map_page		= leon3_map_page,
+	.unmap_page		= leon3_unmap_page,
+	.map_sg			= leon3_map_sg,
+	.unmap_sg		= leon3_unmap_sg,
+        .sync_single_for_cpu    = leon3_sync_single_for_cpu,
+        .sync_single_for_device = leon3_sync_single_for_device,
+	.sync_sg_for_cpu	= leon3_sync_sg_for_cpu,
+	.sync_sg_for_device	= leon3_sync_sg_for_device,
+};
+
+
+
+#endif /* CONFIG_SPARC_LEON */
 
 static int __init sparc_register_ioport(void)
 {
+#ifdef CONFIG_SPARC_LEON
+        dma_ops = &leon3_dma_ops;
+#else
+        dma_ops = &sbus_dma_ops;
+#endif
+
 	register_proc_sparc_ioport();
 
 	return 0;
@@ -415,8 +631,6 @@ static int __init sparc_register_ioport(void)
 
 arch_initcall(sparc_register_ioport);
 
-#endif /* CONFIG_SBUS */
-
 #ifdef CONFIG_PCI
 
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
-- 
1.5.2.2


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-03 22:45 ` Julian Calaby
  2009-11-04 13:39 ` David Miller
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Julian Calaby @ 2009-11-03 22:45 UTC (permalink / raw)
  To: sparclinux

On Tue, Nov 3, 2009 at 01:28, Kristoffer Glembo <kristoffer@gaisler.com> wrote:
> Added mmu_inval_dma_area for LEON which flushes dcache if snooping is not enabled
> and created LEON specific dma_ops.
>
> Best regards,
> Kristoffer Glembo
>
> ---
> diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
> index 9f61fd8..63aab03 100644
> --- a/arch/sparc/kernel/ioport.c
> +++ b/arch/sparc/kernel/ioport.c
> @@ -415,8 +631,6 @@ static int __init sparc_register_ioport(void)
>
>  arch_initcall(sparc_register_ioport);
>
> -#endif /* CONFIG_SBUS */
> -
>  #ifdef CONFIG_PCI
>
>  /* Allocate and map kernel buffer using consistent mode DMA for a device.

Should the arch_initcall() still be protected by the CONFIG_SBUS
ifdefs after this patch?

Thanks,

-- 

Julian Calaby

Email: julian.calaby@gmail.com
.Plan: http://sites.google.com/site/juliancalaby/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
  2009-11-03 22:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific Julian Calaby
@ 2009-11-04 13:39 ` David Miller
  2009-11-04 15:50 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-04 13:39 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon,  2 Nov 2009 15:28:12 +0100

> Added mmu_inval_dma_area for LEON which flushes dcache if snooping
> is not enabled and created LEON specific dma_ops.

This is a lot of code duplication for what you're trying to
accomplish I think.

And now that your drivers will use OpenFirmware driver interfaces
that's yet another difference you no longer have to account for.

I would suggest that you crib the SBUS routines and parameterize
them cleanly for the small differences your LEON cases needs.

Thanks.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area.
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
  2009-11-03 22:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific Julian Calaby
  2009-11-04 13:39 ` David Miller
@ 2009-11-04 15:50 ` Kristoffer Glembo
  2009-11-04 16:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-04 15:50 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:
>
> This is a lot of code duplication for what you're trying to
> accomplish I think.

Yeah I know. The leon3_dma_ops are copied from the pci32_dma_ops.
I think only unmap_page was added basically. Why is there no 
pci32_unmap_page by the way? Maybe I can just add that and use
them as is.

My original thought was that it would be future proof to have separate
versions that might evolve. But I agree and will change it ...

> 
> And now that your drivers will use OpenFirmware driver interfaces
> that's yet another difference you no longer have to account for.
> I would suggest that you crib the SBUS routines and parameterize
> them cleanly for the small differences your LEON cases needs.
> 

The SBUS routines look quite different though. I will use the pci32_dma_ops.

I will modify all the patches according to yours and Julian's feedback
and resend them as soon as possible.

Thanks,
Kristoffer Glembo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (2 preceding siblings ...)
  2009-11-04 15:50 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-04 16:36 ` David Miller
  2009-11-06  9:59 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-04 16:36 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Wed, 04 Nov 2009 16:50:36 +0100

> Yeah I know. The leon3_dma_ops are copied from the pci32_dma_ops.
> I think only unmap_page was added basically. Why is there no
> pci32_unmap_page by the way? Maybe I can just add that and use
> them as is.

Basically because they are buggy and don't get much usage.

They are the worst thing to use as a model for your purposes
since that code gets the least amount of testing,  the SBUS
ones on the other hand get pretty much all of the sparc32
testing.

> The SBUS routines look quite different though. I will use the
> pci32_dma_ops.

I suggested the SBUS ones because they inherit the OpenFirmware
device node name into the resource.  They have also been cleaned
up substantially, the PCI ones are very messy still.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area.
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (3 preceding siblings ...)
  2009-11-04 16:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-11-06  9:59 ` Kristoffer Glembo
  2009-11-06 10:08 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-06  9:59 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:
> 
> I suggested the SBUS ones because they inherit the OpenFirmware
> device node name into the resource.  They have also been cleaned
> up substantially, the PCI ones are very messy still.
> 
> 

Ok I will provide a patch that uses the SBUS versions.

Is it ok if I add sbus_sync_single_for_cpu/device which is a NOP if
SPARC_LEON is not defined?

Best regards,
Kristoffer






^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (4 preceding siblings ...)
  2009-11-06  9:59 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-06 10:08 ` David Miller
  2009-11-16  9:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-06 10:08 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Fri, 06 Nov 2009 10:59:55 +0100

> Is it ok if I add sbus_sync_single_for_cpu/device which is a NOP if
> SPARC_LEON is not defined?

Sure.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area.
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (5 preceding siblings ...)
  2009-11-06 10:08 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-11-16  9:45 ` Kristoffer Glembo
  2009-11-16  9:51 ` Kristoffer Glembo
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-16  9:45 UTC (permalink / raw)
  To: sparclinux

Hi,

David Miller wrote:
> >> The SBUS routines look quite different though. I will use the
>> pci32_dma_ops.
> 
> I suggested the SBUS ones because they inherit the OpenFirmware
> device node name into the resource.  They have also been cleaned
> up substantially, the PCI ones are very messy still.
> 

I finally had the time to look at this again and I'm not sure
how I would do this cleanly using only the SBUS stuff. They
use the IOMMU routines (mm/iommu.c or mm/io-unit.c) and since
we don't currently have an IOMMU I don't want to mess with that.

On LEON system that are not snooping DMA accesses I want to flush
the dcache when unmapping or syncing the buffer. That's it.

I have a suggestion for a patch. It uses sbus_alloc_coherent and
sbus_free_coherent with some added ifdefs and then the PCI
routines for the rest (I've added unmap_page and patched map_page).
At least the code duplication is quite minimal ...

In the somewhat limited testing I have done it works fine.

If you explain what you think is very messy with the PCI routines
maybe I can clean them up further. On LEON we use both the generic
DMA-API and the PCI-API.

I will send the patches separately.

Best regards,
Kristoffer








^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (6 preceding siblings ...)
  2009-11-16  9:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-16  9:51 ` Kristoffer Glembo
  2009-11-16 10:55 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-16  9:51 UTC (permalink / raw)
  To: sparclinux

---
 arch/sparc/kernel/ioport.c |   75 +++++++++++++++++++++++++++++++++++---------
 1 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 3c8c44f..312b7b4 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -50,10 +50,15 @@
 #include <asm/io-unit.h>
 #include <asm/leon.h>
 
-#ifdef CONFIG_SPARC_LEON
-#define mmu_inval_dma_area(p, l) leon_flush_dcache_all()
-#else
+#ifndef CONFIG_SPARC_LEON
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
+#else
+static inline void mmu_inval_dma_area(unsigned long va, unsigned long len)
+{
+	if (!sparc_leon3_snooping_enabled()) {
+		leon_flush_dcache_all();
+	}
+}
 #endif
 
 static struct resource *_sparc_find_resource(struct resource *r,
@@ -281,21 +286,26 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 		goto err_nova;
 	}
 	mmu_inval_dma_area(va, len_total);
+
 	// XXX The mmu_map_dma_area does this for us below, see comments.
 	// sparc_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 (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
-		goto err_noiommu;
-
+#ifdef CONFIG_SPARC_LEON
+	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);	
+	*dma_addrp = virt_to_phys(va);
+#else
+	if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) {
+		release_resource(res);
+		goto err_nova;
+	}
+#endif
 	res->name = op->node->name;
 
 	return (void *)(unsigned long)res->start;
 
-err_noiommu:
-	release_resource(res);
 err_nova:
 	free_pages(va, order);
 err_nomem:
@@ -333,7 +343,12 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 
 	/* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */
 	pgv = virt_to_page(p);
+
+#ifdef CONFIG_SPARC_LEON
+	sparc_unmapiorange((unsigned long)p, n);
+#else
 	mmu_unmap_dma_area(dev, ba, n);
+#endif
 
 	__free_pages(pgv, get_order(n));
 }
@@ -408,9 +423,6 @@ struct dma_map_ops sbus_dma_ops = {
 	.sync_sg_for_device	= sbus_sync_sg_for_device,
 };
 
-struct dma_map_ops *dma_ops = &sbus_dma_ops;
-EXPORT_SYMBOL(dma_ops);
-
 static int __init sparc_register_ioport(void)
 {
 	register_proc_sparc_ioport();
@@ -422,7 +434,7 @@ arch_initcall(sparc_register_ioport);
 
 #endif /* CONFIG_SBUS */
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON)
 
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
  * hwdev should be valid struct pci_dev pointer for PCI devices.
@@ -524,7 +536,16 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
 				 struct dma_attrs *attrs)
 {
 	/* IIep is write-through, not flushing. */
-	return page_to_phys(page) + offset;
+	return virt_to_phys(page_address(page)) + offset;
+}
+
+static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	if (dir != PCI_DMA_TODEVICE) {
+		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
+		    (size + PAGE_SIZE-1) & PAGE_MASK);
+	}
 }
 
 /* Map a set of buffers described by scatterlist in streaming
@@ -649,6 +670,7 @@ struct dma_map_ops pci32_dma_ops = {
 	.alloc_coherent		= pci32_alloc_coherent,
 	.free_coherent		= pci32_free_coherent,
 	.map_page		= pci32_map_page,
+	.unmap_page		= pci32_unmap_page,
 	.map_sg			= pci32_map_sg,
 	.unmap_sg		= pci32_unmap_sg,
 	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
@@ -658,7 +680,30 @@ struct dma_map_ops pci32_dma_ops = {
 };
 EXPORT_SYMBOL(pci32_dma_ops);
 
-#endif /* CONFIG_PCI */
+struct dma_map_ops leon3_dma_ops = {
+	.alloc_coherent		= sbus_alloc_coherent,
+	.free_coherent		= sbus_free_coherent,
+	.map_page		= pci32_map_page,
+	.unmap_page		= pci32_unmap_page,
+	.map_sg			= pci32_map_sg,
+	.unmap_sg		= pci32_unmap_sg,
+	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
+	.sync_single_for_device	= pci32_sync_single_for_device,
+	.sync_sg_for_cpu	= pci32_sync_sg_for_cpu,
+	.sync_sg_for_device	= pci32_sync_sg_for_device,
+};
+
+#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */
+
+#ifdef CONFIG_SPARC_LEON
+struct dma_map_ops *dma_ops = &leon3_dma_ops;
+#else
+struct dma_map_ops *dma_ops = &sbus_dma_ops;
+#endif
+
+#ifdef CONFIG_SBUS
+EXPORT_SYMBOL(dma_ops);
+#endif
 
 /*
  * Return whether the given PCI device DMA address mask can be
@@ -728,7 +773,7 @@ static const struct file_operations sparc_io_proc_fops = {
 static struct resource *_sparc_find_resource(struct resource *root,
 					     unsigned long hit)
 {
-        struct resource *tmp;
+	struct resource *tmp;
 
 	for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
 		if (tmp->start <= hit && tmp->end >= hit)
-- 
1.5.2.2


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (7 preceding siblings ...)
  2009-11-16  9:51 ` Kristoffer Glembo
@ 2009-11-16 10:55 ` David Miller
  2009-11-16 11:03 ` David Miller
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-16 10:55 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon, 16 Nov 2009 10:51:07 +0100

> @@ -524,7 +536,16 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
>  				 struct dma_attrs *attrs)
>  {
>  	/* IIep is write-through, not flushing. */
> -	return page_to_phys(page) + offset;
> +	return virt_to_phys(page_address(page)) + offset;
> +}

What's wrong with page_to_phys()?

page_to_phys() is what must be used, because it is legal to DMA to or
from a highmem page, and for those page_address(page) does not
necessaily evaluate fully.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (8 preceding siblings ...)
  2009-11-16 10:55 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-11-16 11:03 ` David Miller
  2009-11-16 11:06 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-16 11:03 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon, 16 Nov 2009 10:45:40 +0100

> I finally had the time to look at this again and I'm not sure
> how I would do this cleanly using only the SBUS stuff. They
> use the IOMMU routines (mm/iommu.c or mm/io-unit.c) and since
> we don't currently have an IOMMU I don't want to mess with that.
> 
> On LEON system that are not snooping DMA accesses I want to flush
> the dcache when unmapping or syncing the buffer. That's it.
> 
> I have a suggestion for a patch. It uses sbus_alloc_coherent and
> sbus_free_coherent with some added ifdefs and then the PCI
> routines for the rest (I've added unmap_page and patched map_page).
> At least the code duplication is quite minimal ...
> 
> In the somewhat limited testing I have done it works fine.

It looks good from a code sharing perspective, but the
virt_to_phys() change has to be undone as per feedback I
gave to the patch #2 posting.

> If you explain what you think is very messy with the PCI routines
> maybe I can clean them up further. On LEON we use both the generic
> DMA-API and the PCI-API.

Bad coding style, "#if 0" sections, it does things like:

	n = (n + PAGE_SIZE-1) & PAGE_MASK;

when a simple PAGE_ALIGN() would do, etc.

Also, tests like this:

			BUG_ON(page_address(sg_page(sg)) = NULL);

Don't make any sense, because highmem pages are legal to DMA
from/to, and such pages would return NULL here.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (9 preceding siblings ...)
  2009-11-16 11:03 ` David Miller
@ 2009-11-16 11:06 ` Kristoffer Glembo
  2009-11-16 11:21 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-16 11:06 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:
> From: Kristoffer Glembo <kristoffer@gaisler.com>
> Date: Mon, 16 Nov 2009 10:51:07 +0100
> 
>> @@ -524,7 +536,16 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
>>  				 struct dma_attrs *attrs)
>>  {
>>  	/* IIep is write-through, not flushing. */
>> -	return page_to_phys(page) + offset;
>> +	return virt_to_phys(page_address(page)) + offset;
>> +}
> 
> What's wrong with page_to_phys()?
> 
> page_to_phys() is what must be used, because it is legal to DMA to or
> from a highmem page, and for those page_address(page) does not
> necessaily evaluate fully.
> 
> 

After pulling the latest sparc-next dma_map_single began returning
bogus addresses. I just saw that page_address was being used everywhere
else in ioport.c (including sbus_map_page) and switched to that since
page_to_phys was returning incorrect addresses when passed SKB pages.

So if page_address is wrong I will have to investigate what it is that
really is broken.

I will clean up the code according to your other feedback as well.

Thanks,
Kristoffer



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (10 preceding siblings ...)
  2009-11-16 11:06 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-16 11:21 ` David Miller
  2009-11-18  8:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-16 11:21 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon, 16 Nov 2009 12:06:55 +0100

> After pulling the latest sparc-next dma_map_single began returning
> bogus addresses. I just saw that page_address was being used
> everywhere
> else in ioport.c (including sbus_map_page) and switched to that since
> page_to_phys was returning incorrect addresses when passed SKB pages.
> 
> So if page_address is wrong I will have to investigate what it is that
> really is broken.

You really need to investigate why dma_map_single() is not
returning sane addresses.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (11 preceding siblings ...)
  2009-11-16 11:21 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-11-18  8:45 ` Kristoffer Glembo
  2009-11-18  9:32 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-18  8:45 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:

> 
> You really need to investigate why dma_map_single() is not
> returning sane addresses.

I haven't reached a conclusion yet since I'm not so familiar with
the Linux VM subsystem and have not had much time to look at it.

But I noticed that pci_map_single does not work in later kernels.
I guess it stopped working with the patch "sparc: Use
asm-generic/pci-dma-compat" since before the that the physical address
was obtained through virt_to_phys() and after that it goes through
page_to_phys(virt_to_page()) which does not work. Using
page_address(virt_to_page()) works but I understand that this does not
always evaluate properly.

Using page_to_phys(virt_to_page()) results in an address lacking the
phys_base offset. My patch to page_to_phys (adding phys_base) several
weeks ago was done because of this but I thought that the problem then
was that I was using virt_to_page() on an address obtained through
kmalloc which I have read is not really allowed?
The page_to_phys(virt_to_page()) does not even work for memory allocated
with __get_free_page() currently.

I will continue investigating this when I have the time. I just wanted
to give you this feedback. Maybe you understand what is going on ...

Best regards,
Kristoffer







^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (12 preceding siblings ...)
  2009-11-18  8:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-11-18  9:32 ` David Miller
  2009-11-23 12:31 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-11-18  9:32 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Wed, 18 Nov 2009 09:45:41 +0100

> But I noticed that pci_map_single does not work in later kernels.
> I guess it stopped working with the patch "sparc: Use
> asm-generic/pci-dma-compat" since before the that the physical address
> was obtained through virt_to_phys() and after that it goes through
> page_to_phys(virt_to_page()) which does not work. Using
> page_address(virt_to_page()) works but I understand that this does not
> always evaluate properly.

"page_address(virt_to_page())" returns a virtual address, whereas
page_to_phys(virt_to_page()) returns a physical one.

> Using page_to_phys(virt_to_page()) results in an address lacking the
> phys_base offset.

If it's not adding in phys_base, then it's not returning a legal
physical address.  Any idea why we don't add phys_base here?  I feel
like we've discussed this exactly recently, like in the past few
months.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (13 preceding siblings ...)
  2009-11-18  9:32 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-11-23 12:31 ` Kristoffer Glembo
  2009-12-14  4:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-11-23 12:31 UTC (permalink / raw)
  To: sparclinux

Hi,


David Miller wrote:
> From: Kristoffer Glembo <kristoffer@gaisler.com>
> Date: Wed, 18 Nov 2009 09:45:41 +0100
> 
>> But I noticed that pci_map_single does not work in later kernels.
>> I guess it stopped working with the patch "sparc: Use
>> asm-generic/pci-dma-compat" since before the that the physical address
>> was obtained through virt_to_phys() and after that it goes through
>> page_to_phys(virt_to_page()) which does not work. Using
>> page_address(virt_to_page()) works but I understand that this does not
>> always evaluate properly.
> 
> "page_address(virt_to_page())" returns a virtual address, whereas
> page_to_phys(virt_to_page()) returns a physical one.
> 

Yeah, I meant virt_to_phys(page_address(virt_to_page())) ..


>> Using page_to_phys(virt_to_page()) results in an address lacking the
>> phys_base offset.
> 
> If it's not adding in phys_base, then it's not returning a legal
> physical address.  Any idea why we don't add phys_base here?  I feel
> like we've discussed this exactly recently, like in the past few
> months.


We did yes. You said that mem_map is not offset at phys_base and then of
course we don't need to add it in page_to_phys. Is mem_map not offset
because typically sp_banks[].base_addr = 0? In our case we pass in one
sp_banks entry which has base_addr = 0x40000000.


Best regards,
Kristoffer




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (14 preceding siblings ...)
  2009-11-23 12:31 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2009-12-14  4:36 ` David Miller
  2009-12-14  7:57 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2009-12-14  4:36 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon, 23 Nov 2009 13:31:32 +0100

> David Miller wrote:
>> If it's not adding in phys_base, then it's not returning a legal
>> physical address.  Any idea why we don't add phys_base here?  I feel
>> like we've discussed this exactly recently, like in the past few
>> months.
>
> We did yes. You said that mem_map is not offset at phys_base and
> then of course we don't need to add it in page_to_phys. Is mem_map
> not offset because typically sp_banks[].base_addr = 0? In our case
> we pass in one sp_banks entry which has base_addr = 0x40000000.

I'm still trying to find time to address this, just FYI.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (15 preceding siblings ...)
  2009-12-14  4:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2009-12-14  7:57 ` Kristoffer Glembo
  2010-01-12  7:40 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2009-12-14  7:57 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:

>> We did yes. You said that mem_map is not offset at phys_base and
>> then of course we don't need to add it in page_to_phys. Is mem_map
>> not offset because typically sp_banks[].base_addr = 0? In our case
>> we pass in one sp_banks entry which has base_addr = 0x40000000.
> 
> I'm still trying to find time to address this, just FYI.
> 
> 

Thanks. I have been working on non Linux stuff for a while
but in the meantime I have actually used the patch where
phys_base is added in page_to_phys.

I hope to continue Linux development after Christmas.

Happy holidays :)

/Kristoffer

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (16 preceding siblings ...)
  2009-12-14  7:57 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2010-01-12  7:40 ` David Miller
  2010-01-12 10:35 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2010-01-12  7:40 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Mon, 23 Nov 2009 13:31:32 +0100

> We did yes. You said that mem_map is not offset at phys_base and then
> of
> course we don't need to add it in page_to_phys. Is mem_map not offset
> because typically sp_banks[].base_addr = 0? In our case we pass in one
> sp_banks entry which has base_addr = 0x40000000.

Looking at this code, I can't see how virt_to_page() works right
now at all :-)

mem_map[] is offset by pfn_base

This is why __va() and __pa() account for it.

Can you see if your machine boots with the patch at the end of this
email applied?  Others can feel free to test this too :-)

Really, if pfn_base/phys_base are non-zero, it's quite amazing how a
sparc32 machine could sucessfully boot with the code as-is.

Looking more deeply, I guess it could work if you use CONFIG_SLUB.

Or, you use CONFIG_SLAB and SLABs are never destroyed and SLAB
growing never fails (kmem_freepages() uses virt_to_page()).

And I'm guessing that's why using virt_to_page() in the DMA mapping
implementation failed for you Kristoffer, it would be the only common
path it would be used on sparc32.

Anyways, testing of this change by anyone with sparc32 boxes would be
much appreciated.

Thanks!

diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h
index f72080b..156707b 100644
--- a/arch/sparc/include/asm/page_32.h
+++ b/arch/sparc/include/asm/page_32.h
@@ -143,7 +143,7 @@ extern unsigned long pfn_base;
 #define phys_to_virt		__va
 
 #define ARCH_PFN_OFFSET		(pfn_base)
-#define virt_to_page(kaddr)	(mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT)))
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 
 #define pfn_valid(pfn)		(((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr))
 #define virt_addr_valid(kaddr)	((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT) < max_mapnr)

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (17 preceding siblings ...)
  2010-01-12  7:40 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2010-01-12 10:35 ` Kristoffer Glembo
  2010-01-12 10:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2010-01-12 10:35 UTC (permalink / raw)
  To: sparclinux

Hi,

David Miller wrote:
> 
> Looking at this code, I can't see how virt_to_page() works right
> now at all :-)
> 
> mem_map[] is offset by pfn_base
> 
> This is why __va() and __pa() account for it.
> 
> Can you see if your machine boots with the patch at the end of this
> email applied?  Others can feel free to test this too :-)
> 
> Really, if pfn_base/phys_base are non-zero, it's quite amazing how a
> sparc32 machine could sucessfully boot with the code as-is.
> 
> Looking more deeply, I guess it could work if you use CONFIG_SLUB.
> 
> Or, you use CONFIG_SLAB and SLABs are never destroyed and SLAB
> growing never fails (kmem_freepages() uses virt_to_page()).
> 

I was using CONFIG_SLAB without noticing any problems.

But I'm a bit confused. Doesn't this patch generate the exact same code?
Now __pa will add in phys_base but pfn_to_page(__pa()>>PAGE_SHIFT)
will remove it by subtracting ARCH_PFN_OFFSET.


> And I'm guessing that's why using virt_to_page() in the DMA mapping
> implementation failed for you Kristoffer, it would be the only common
> path it would be used on sparc32.
> 

For me it still fails if I'm not adding phys_base in page_to_phys.


Thanks,
Kristoffer

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (18 preceding siblings ...)
  2010-01-12 10:35 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2010-01-12 10:45 ` David Miller
  2010-01-14 10:43 ` David Miller
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2010-01-12 10:45 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Tue, 12 Jan 2010 11:35:59 +0100

> I was using CONFIG_SLAB without noticing any problems.
> 
> But I'm a bit confused. Doesn't this patch generate the exact same code?
> Now __pa will add in phys_base but pfn_to_page(__pa()>>PAGE_SHIFT)
> will remove it by subtracting ARCH_PFN_OFFSET.
 ...
> For me it still fails if I'm not adding phys_base in page_to_phys.

Indeed.

Ok, let me think about this some more.

Thanks for testing and looking at this.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (19 preceding siblings ...)
  2010-01-12 10:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
@ 2010-01-14 10:43 ` David Miller
  2010-01-14 11:05 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
  2010-01-14 11:12 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2010-01-14 10:43 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Tue, 12 Jan 2010 11:35:59 +0100

> David Miller wrote:
>> And I'm guessing that's why using virt_to_page() in the DMA mapping
>> implementation failed for you Kristoffer, it would be the only common
>> path it would be used on sparc32.
>> 
> 
> For me it still fails if I'm not adding phys_base in page_to_phys.

So I did research and this code is the way it is because
of LEON (this commit is from "linux-2.6-history.git") :-)

commit a44032987aaa82d48927b87a0193c7805ec9aade
Author: Keith M. Wesolowski <wesolows@foobazco.org>
Date:   Sat Mar 20 22:43:40 2004 -0800

    [SPARC32]: Support memory starting at physical address other than 0
    
    From: Stefan Holst <mail@s-holst.de>
    
    Allow physical memory to start at almost arbitrary addresses.  LEON
    needs it, so do SPARCstation 10/20 without slot 0 populated.  Although
    Sun do not support this configuration, at least some such systems can
    boot with this patch.
    
    Physical memory starting at or above 0xF4000000 is not supported.

This commit missed updating page_to_phys() appropriately, so
you were right all along I think.

So let's take baby steps, please confirm that you agree with me that
the following patch is correct and that it works on your machine.

If it works I want to reinstate the virt_to_page() change I posted
the other day as well, simply so that we consistently use the
asm-generic/memory-model.h interfaces instead of assuming FLATMEM
memory model all over our headers.

But I am truly mystified how anything works with non-zero phys_base
with this being wrong.  Fundamental operations like
{srmmu,sun4c}_mk_pte() use this.

LEON uses this via SRMMU, so how does it work properly? :-)

Thanks!

diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h
index 93fe21e..679c750 100644
--- a/arch/sparc/include/asm/io_32.h
+++ b/arch/sparc/include/asm/io_32.h
@@ -8,7 +8,7 @@
 #include <asm/page.h>      /* IO address mapping routines need this */
 #include <asm/system.h>
 
-#define page_to_phys(page)	(((page) - mem_map) << PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 static inline u32 flip_dword (u32 l)
 {

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (20 preceding siblings ...)
  2010-01-14 10:43 ` David Miller
@ 2010-01-14 11:05 ` Kristoffer Glembo
  2010-01-14 11:12 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
  22 siblings, 0 replies; 24+ messages in thread
From: Kristoffer Glembo @ 2010-01-14 11:05 UTC (permalink / raw)
  To: sparclinux

David Miller wrote:
> So I did research and this code is the way it is because
> of LEON (this commit is from "linux-2.6-history.git") :-)


Back then I was attending grad school and was blissfully unaware. :-)


> 
> So let's take baby steps, please confirm that you agree with me that
> the following patch is correct and that it works on your machine.


It works fine for me!


> If it works I want to reinstate the virt_to_page() change I posted
> the other day as well, simply so that we consistently use the
> asm-generic/memory-model.h interfaces instead of assuming FLATMEM
> memory model all over our headers.


Yes this change works as well.

> 
> But I am truly mystified how anything works with non-zero phys_base
> with this being wrong.  Fundamental operations like
> {srmmu,sun4c}_mk_pte() use this.
> 
> LEON uses this via SRMMU, so how does it work properly? :-)


Hmm, srmmu_mk_pte() uses page_to_pfn() which accounts for pfn_base?

The only use of page_to_phys below arch/sparc that I find is in pci32_map_page
which is where I got into trouble. :-)

Thanks for looking into this!

Best regards,
Kristoffer

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Added leon3_dma_ops and LEON specific
  2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
                   ` (21 preceding siblings ...)
  2010-01-14 11:05 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
@ 2010-01-14 11:12 ` David Miller
  22 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2010-01-14 11:12 UTC (permalink / raw)
  To: sparclinux

From: Kristoffer Glembo <kristoffer@gaisler.com>
Date: Thu, 14 Jan 2010 12:05:34 +0100

> It works fine for me!
 ...
> Yes this change works as well.

Thanks for testing.

> Hmm, srmmu_mk_pte() uses page_to_pfn() which accounts for pfn_base?

My eyes aren't working, I confused page_to_pfn() with page_to_phys().

Great, now it is all clear.

I'll add the fix to sparc-2.6, thanks again.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2010-01-14 11:12 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-02 14:28 [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-03 22:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific Julian Calaby
2009-11-04 13:39 ` David Miller
2009-11-04 15:50 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-04 16:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-11-06  9:59 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-06 10:08 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-11-16  9:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-16  9:51 ` Kristoffer Glembo
2009-11-16 10:55 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-11-16 11:03 ` David Miller
2009-11-16 11:06 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-16 11:21 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-11-18  8:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-11-18  9:32 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-11-23 12:31 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2009-12-14  4:36 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2009-12-14  7:57 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2010-01-12  7:40 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2010-01-12 10:35 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2010-01-12 10:45 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller
2010-01-14 10:43 ` David Miller
2010-01-14 11:05 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific mmu_inval_dma_area Kristoffer Glembo
2010-01-14 11:12 ` [PATCH 2/2] Added leon3_dma_ops and LEON specific David Miller

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.