Patchwork [Q] block / zynq: DMA bouncing

login
register
mail settings
Submitter Guennadi Liakhovetski
Date Jan. 28, 2014, 1:28 p.m.
Message ID <Pine.LNX.4.64.1401281420580.2714@axis700.grange>
Download mbox | patch
Permalink /patch/314724/
State New
Headers show

Comments

Guennadi Liakhovetski - Jan. 28, 2014, 1:28 p.m.
Hi Michal,

(trimmed CC a bit)

On Mon, 27 Jan 2014, Michal Simek wrote:

> On 01/27/2014 06:52 PM, Russell King - ARM Linux wrote:
> > On Mon, Jan 27, 2014 at 06:45:50PM +0100, Michal Simek wrote:
> >> Why 0x4000? IRC Linux for ARM is using space for any purpose.
> >> Russell knows this much better than I.
> > 
> > Probably because as the kernel is loaded at 0x8000, it will place the
> > swapper page table at 0x4000, thus covering from 0x4000 upwards.
> 
> Ah yeah swapper.
> 
> > 
> > Thus, the majority of your un-DMA-able memory will be kernel text or
> > swapper page tables.
> 
> Yes, exactly.
> 0x0 - 0x4000 - reserving not to be used by DMA
> 0x4000 - 0x8000 swapper page table
> 0x8000 - 0x80000 kernel text + up

Maybe you could submit something like the attached patch upstream. I'm not 
sure shom you'd like to put as its original author. I put John Linn there 
as he originally authored commit 5b9f3f2ac8a3e4edae9de7b855f25f757884d84c 
from Xilinx tree with the same description, as the attached patch. 
Unfortunately, that commit didn't have an Sob.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
Guennadi Liakhovetski - Jan. 28, 2014, 1:33 p.m.
On Tue, 28 Jan 2014, Guennadi Liakhovetski wrote:

> Hi Michal,
> 
> (trimmed CC a bit)
> 
> On Mon, 27 Jan 2014, Michal Simek wrote:
> 
> > On 01/27/2014 06:52 PM, Russell King - ARM Linux wrote:
> > > On Mon, Jan 27, 2014 at 06:45:50PM +0100, Michal Simek wrote:
> > >> Why 0x4000? IRC Linux for ARM is using space for any purpose.
> > >> Russell knows this much better than I.
> > > 
> > > Probably because as the kernel is loaded at 0x8000, it will place the
> > > swapper page table at 0x4000, thus covering from 0x4000 upwards.
> > 
> > Ah yeah swapper.
> > 
> > > 
> > > Thus, the majority of your un-DMA-able memory will be kernel text or
> > > swapper page tables.
> > 
> > Yes, exactly.
> > 0x0 - 0x4000 - reserving not to be used by DMA
> > 0x4000 - 0x8000 swapper page table
> > 0x8000 - 0x80000 kernel text + up
> 
> Maybe you could submit something like the attached patch upstream. I'm not 
> sure shom you'd like to put as its original author. I put John Linn there 
> as he originally authored commit 5b9f3f2ac8a3e4edae9de7b855f25f757884d84c 

Sorry, I actually meant commit 83e198c01c381a1d90ba07e241a517d1dabf7c84

Guennadi

> from Xilinx tree with the same description, as the attached patch. 
> Unfortunately, that commit didn't have an Sob.

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
Russell King - ARM Linux - Jan. 28, 2014, 1:48 p.m.
On Tue, Jan 28, 2014 at 02:28:28PM +0100, Guennadi Liakhovetski wrote:
> +static void __init zynq_memory_init(void)
> +{
> +	/*
> +	 * Reserve the 0-0x4000 addresses (before page tables and kernel)
> +	 * which can't be used for DMA
> +	 */
> +	if (!__pa(PAGE_OFFSET))
> +		memblock_reserve(0, 0x4000);

Or maybe this:

	memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));

since that's actually what you mean here.
Michal Simek - Jan. 28, 2014, 1:54 p.m.
On 01/28/2014 02:48 PM, Russell King - ARM Linux wrote:
> On Tue, Jan 28, 2014 at 02:28:28PM +0100, Guennadi Liakhovetski wrote:
>> +static void __init zynq_memory_init(void)
>> +{
>> +	/*
>> +	 * Reserve the 0-0x4000 addresses (before page tables and kernel)
>> +	 * which can't be used for DMA
>> +	 */
>> +	if (!__pa(PAGE_OFFSET))
>> +		memblock_reserve(0, 0x4000);
> 
> Or maybe this:
> 
> 	memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
> 
> since that's actually what you mean here.

yep with that if too.

I will prepare that patch and will send it out.

Thanks,
Michal
Jason Gunthorpe - Jan. 28, 2014, 6:34 p.m.
On Tue, Jan 28, 2014 at 01:48:27PM +0000, Russell King - ARM Linux wrote:
> On Tue, Jan 28, 2014 at 02:28:28PM +0100, Guennadi Liakhovetski wrote:
> > +static void __init zynq_memory_init(void)
> > +{
> > +	/*
> > +	 * Reserve the 0-0x4000 addresses (before page tables and kernel)
> > +	 * which can't be used for DMA
> > +	 */
> > +	if (!__pa(PAGE_OFFSET))
> > +		memblock_reserve(0, 0x4000);
> 
> Or maybe this:
> 
> 	memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
> 
> since that's actually what you mean here.

Can you have a non-zero PAGE_OFFSET and swapper_pg_dir != 0x4000?
Crash dump kernel maybe?

Perhaps:
	if (__pa(PAGE_OFFSET) < 0x8000)
 	   memblock_reserve(__pa(PAGE_OFFSET),
	                    min(__pa(swapper_pg_dir), 0x8000));
?

The Zynq TRM, UG585 pg 115, describes this issue. Physical addresses
below 0x8000 are not accessible to DMA from the AXI interconnect.

Though, how does a crash dump kernel know it needs to bounce buffer
the swapper if it dumps it via DMA?

Regards,
Jason

Patch

From d00684a6d899048938086c11185c89f082b881e0 Mon Sep 17 00:00:00 2001
From: John Linn <john.linn@xilinx.com>
Date: Tue, 28 Jan 2014 14:06:45 +0100
Subject: [PATCH] Xilinx: ARM: BSP: prevent DMA into lower memory

The DMA zone from 2.6.39 is no longer supported such that
a new method was needed. The old method was lost in the
move to 3.0 and USB was seeing failures.

Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---

 arch/arm/mach-zynq/common.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c

index 9a7bd13..2d51453 100644

--- a/arch/arm/mach-zynq/common.c

+++ b/arch/arm/mach-zynq/common.c

@@ -25,6 +25,7 @@ 

 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of.h>
+#include <linux/memblock.h>

 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -39,6 +40,22 @@ 

 
 void __iomem *zynq_scu_base;
 
+/**

+ * zynq_memory_init() - Initialize special memory

+ *

+ * We need to stop things allocating the low memory as DMA can't work in

+ * the 1st 512K of memory.  Using reserve vs remove is not totally clear yet.

+ */

+static void __init zynq_memory_init(void)

+{

+	/*

+	 * Reserve the 0-0x4000 addresses (before page tables and kernel)

+	 * which can't be used for DMA

+	 */

+	if (!__pa(PAGE_OFFSET))

+		memblock_reserve(0, 0x4000);

+}

+

 static struct of_device_id zynq_of_bus_ids[] __initdata = {
 	{ .compatible = "simple-bus", },
 	{}
@@ -113,5 +130,6 @@  DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")

 	.init_machine	= zynq_init_machine,
 	.init_time	= zynq_timer_init,
 	.dt_compat	= zynq_dt_match,
+	.reserve	= zynq_memory_init,

 	.restart	= zynq_system_reset,
 MACHINE_END
-- 

1.7.2.5