Re: [PATCH] [PPC 44x] L2-cache synchronization for ppc44x

2007-11-25 Thread Benjamin Herrenschmidt

On Thu, 2007-11-08 at 02:12 +0300, Yuri Tikhonov wrote:
 This is the updated patch for support synchronization of L2-Cache with the 
 external memory on the ppc44x-based platforms.
 
  Differencies against the previous patch-set:
 - remove L2_CACHE config option;
 - introduce the ppc machdep to invalidate L2 cache lines;
 - some code clean-up.
 
 Signed-off-by: Yuri Tikhonov [EMAIL PROTECTED]
 Signed-off-by: Pavel Kolesnikov [EMAIL PROTECTED]

It's almost right :-0

You want something a bit more details than just a
ppc_md.l2cache_inv_range.

I'd suggest you do a separate extcache_ops structure that contains
callbacks for all 3 directions (flush, flush  invalidate, invalidate),
then fill that up accordingly.

It might be a good idea in the long run to do some tricks to avoid a
branch via function pointer since the cache ops are pretty hot, but if
that ever happens, I'll do that via asm patching tricks I suppose.

Now regarding the line size, I would recommend using the device-tree to
describe the cache instead rather than a config option. The intend is to
be able to build a single binary kernel that can boot multiple variants
of 44x.

I may eventually rewrite your patch around those ideas next week if you
don't feel like doing it -and- I get bored :-)

Cheers,
Ben.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] [PPC 44x] L2-cache synchronization for ppc44x

2007-11-07 Thread Yuri Tikhonov

 This is the updated patch for support synchronization of L2-Cache with the 
external memory on the ppc44x-based platforms.

 Differencies against the previous patch-set:
- remove L2_CACHE config option;
- introduce the ppc machdep to invalidate L2 cache lines;
- some code clean-up.

Signed-off-by: Yuri Tikhonov [EMAIL PROTECTED]
Signed-off-by: Pavel Kolesnikov [EMAIL PROTECTED]

--
diff --git a/arch/powerpc/lib/dma-noncoherent.c 
b/arch/powerpc/lib/dma-noncoherent.c
index 1947380..b06f05c 100644
--- a/arch/powerpc/lib/dma-noncoherent.c
+++ b/arch/powerpc/lib/dma-noncoherent.c
@@ -31,6 +31,7 @@
 #include linux/dma-mapping.h
 
 #include asm/tlbflush.h
+#include asm/machdep.h
 
 /*
  * This address range defaults to a value that is safe for all
@@ -186,6 +187,8 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, gfp_t 
gfp)
unsigned long kaddr = (unsigned long)page_address(page);
memset(page_address(page), 0, size);
flush_dcache_range(kaddr, kaddr + size);
+   if (ppc_md.l2cache_inv_range)
+   ppc_md.l2cache_inv_range(__pa(kaddr), __pa(kaddr + 
size));
}
 
/*
@@ -351,12 +354,16 @@ void __dma_sync(void *vaddr, size_t size, int direction)
BUG();
case DMA_FROM_DEVICE:   /* invalidate only */
invalidate_dcache_range(start, end);
+   if (ppc_md.l2cache_inv_range)
+   ppc_md.l2cache_inv_range(__pa(start), __pa(end));
break;
case DMA_TO_DEVICE: /* writeback only */
clean_dcache_range(start, end);
break;
case DMA_BIDIRECTIONAL: /* writeback and invalidate */
flush_dcache_range(start, end);
+   if (ppc_md.l2cache_inv_range)
+   ppc_md.l2cache_inv_range(__pa(start), __pa(end));
break;
}
 }
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index 46cf8fa..31c9149 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -25,6 +25,10 @@
 #include asm/thread_info.h
 #include asm/asm-offsets.h
 
+#ifdef CONFIG_44x
+#include asm/ibm44x.h
+#endif
+
 #ifdef CONFIG_8xx
 #define ISYNC_8xx isync
 #else
@@ -386,6 +390,35 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
sync/* additional sync needed on g4 */
isync
blr
+
+#if defined(CONFIG_44x)
+/*
+ * Invalidate the Level-2 cache lines corresponded to the address
+ * range.
+ *
+ * invalidate_l2cache_range(unsigned long start, unsigned long stop)
+ */
+_GLOBAL(invalidate_l2cache_range)
+   li  r5,PPC44X_L2_CACHE_BYTES-1  /* align on L2-cache line */
+   andcr3,r3,r5
+   subfr4,r3,r4
+   add r4,r4,r5
+   srwi.   r4,r4,PPC44X_L2_CACHE_SHIFT
+   mtctr   r4
+
+   lis r4, L2C_CMD_INV16
+1: mtdcr   DCRN_L2C0_ADDR,r3   /* write address to invalidate */
+   mtdcr   DCRN_L2C0_CMD,r4/* issue the Invalidate cmd */
+
+2: mfdcr   r5,DCRN_L2C0_SR /* wait for complete */
+   andis.  r5,r5,L2C_CMD_CLR16
+   beq 2b
+
+   addir3,r3,PPC44X_L2_CACHE_BYTES /* next address to invalidate */
+   bdnz1b
+   blr
+#endif
+
 /*
  * Write any modified data cache blocks out to memory.
  * Does not invalidate the corresponding cache lines (especially for
diff --git a/arch/ppc/syslib/ibm440gx_common.c 
b/arch/ppc/syslib/ibm440gx_common.c
index 6b1a801..64c663f 100644
--- a/arch/ppc/syslib/ibm440gx_common.c
+++ b/arch/ppc/syslib/ibm440gx_common.c
@@ -12,6 +12,8 @@
  */
 #include linux/kernel.h
 #include linux/interrupt.h
+#include asm/machdep.h
+#include asm/cacheflush.h
 #include asm/ibm44x.h
 #include asm/mmu.h
 #include asm/processor.h
@@ -201,6 +203,7 @@ void __init ibm440gx_l2c_enable(void){
 
asm volatile (sync; isync ::: memory);
local_irq_restore(flags);
+   ppc_md.l2cache_inv_range = invalidate_l2cache_range;
 }
 
 /* Disable L2 cache */
diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h
index ba667a3..bdebfaa 100644
--- a/include/asm-powerpc/cacheflush.h
+++ b/include/asm-powerpc/cacheflush.h
@@ -49,6 +49,7 @@ extern void flush_dcache_range(unsigned long start, unsigned 
long stop);
 #ifdef CONFIG_PPC32
 extern void clean_dcache_range(unsigned long start, unsigned long stop);
 extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
+extern void invalidate_l2cache_range(unsigned long start, unsigned long stop);
 #endif /* CONFIG_PPC32 */
 #ifdef CONFIG_PPC64
 extern void flush_inval_dcache_range(unsigned long start, unsigned long stop);
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 71c6e7e..754f416 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -201,6 +201,8 @@ struct machdep_calls {
void(*early_serial_map)(void);
void

Re: [PATCH] [PPC 44x] L2-cache synchronization for ppc44x

2007-11-07 Thread Benjamin Herrenschmidt

On Thu, 2007-11-08 at 02:12 +0300, Yuri Tikhonov wrote:
 This is the updated patch for support synchronization of L2-Cache with the 
 external memory on the ppc44x-based platforms.
 
  Differencies against the previous patch-set:
 - remove L2_CACHE config option;
 - introduce the ppc machdep to invalidate L2 cache lines;
 - some code clean-up.

Can you tell me more about how this cache operates ? I don't quite
understand why you would invalidate it on bidirectional DMAs rather than
flush it to memory (unless you get your terminology wrong) and why you
wouldn't flush it on transfers to the device.. Unless it is a
write-through cache ?

Ben.

 Signed-off-by: Yuri Tikhonov [EMAIL PROTECTED]
 Signed-off-by: Pavel Kolesnikov [EMAIL PROTECTED]
 
 --
 diff --git a/arch/powerpc/lib/dma-noncoherent.c 
 b/arch/powerpc/lib/dma-noncoherent.c
 index 1947380..b06f05c 100644
 --- a/arch/powerpc/lib/dma-noncoherent.c
 +++ b/arch/powerpc/lib/dma-noncoherent.c
 @@ -31,6 +31,7 @@
  #include linux/dma-mapping.h
  
  #include asm/tlbflush.h
 +#include asm/machdep.h
  
  /*
   * This address range defaults to a value that is safe for all
 @@ -186,6 +187,8 @@ __dma_alloc_coherent(size_t size, dma_addr_t *handle, 
 gfp_t gfp)
   unsigned long kaddr = (unsigned long)page_address(page);
   memset(page_address(page), 0, size);
   flush_dcache_range(kaddr, kaddr + size);
 + if (ppc_md.l2cache_inv_range)
 + ppc_md.l2cache_inv_range(__pa(kaddr), __pa(kaddr + 
 size));
   }
  
   /*
 @@ -351,12 +354,16 @@ void __dma_sync(void *vaddr, size_t size, int direction)
   BUG();
   case DMA_FROM_DEVICE:   /* invalidate only */
   invalidate_dcache_range(start, end);
 + if (ppc_md.l2cache_inv_range)
 + ppc_md.l2cache_inv_range(__pa(start), __pa(end));
   break;
   case DMA_TO_DEVICE: /* writeback only */
   clean_dcache_range(start, end);
   break;
   case DMA_BIDIRECTIONAL: /* writeback and invalidate */
   flush_dcache_range(start, end);
 + if (ppc_md.l2cache_inv_range)
 + ppc_md.l2cache_inv_range(__pa(start), __pa(end));
   break;
   }
  }
 diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
 index 46cf8fa..31c9149 100644
 --- a/arch/ppc/kernel/misc.S
 +++ b/arch/ppc/kernel/misc.S
 @@ -25,6 +25,10 @@
  #include asm/thread_info.h
  #include asm/asm-offsets.h
  
 +#ifdef CONFIG_44x
 +#include asm/ibm44x.h
 +#endif
 +
  #ifdef CONFIG_8xx
  #define ISYNC_8xx isync
  #else
 @@ -386,6 +390,35 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
   sync/* additional sync needed on g4 */
   isync
   blr
 +
 +#if defined(CONFIG_44x)
 +/*
 + * Invalidate the Level-2 cache lines corresponded to the address
 + * range.
 + *
 + * invalidate_l2cache_range(unsigned long start, unsigned long stop)
 + */
 +_GLOBAL(invalidate_l2cache_range)
 + li  r5,PPC44X_L2_CACHE_BYTES-1  /* align on L2-cache line */
 + andcr3,r3,r5
 + subfr4,r3,r4
 + add r4,r4,r5
 + srwi.   r4,r4,PPC44X_L2_CACHE_SHIFT
 + mtctr   r4
 +
 + lis r4, L2C_CMD_INV16
 +1:   mtdcr   DCRN_L2C0_ADDR,r3   /* write address to invalidate */
 + mtdcr   DCRN_L2C0_CMD,r4/* issue the Invalidate cmd */
 +
 +2:   mfdcr   r5,DCRN_L2C0_SR /* wait for complete */
 + andis.  r5,r5,L2C_CMD_CLR16
 + beq 2b
 +
 + addir3,r3,PPC44X_L2_CACHE_BYTES /* next address to invalidate */
 + bdnz1b
 + blr
 +#endif
 +
  /*
   * Write any modified data cache blocks out to memory.
   * Does not invalidate the corresponding cache lines (especially for
 diff --git a/arch/ppc/syslib/ibm440gx_common.c 
 b/arch/ppc/syslib/ibm440gx_common.c
 index 6b1a801..64c663f 100644
 --- a/arch/ppc/syslib/ibm440gx_common.c
 +++ b/arch/ppc/syslib/ibm440gx_common.c
 @@ -12,6 +12,8 @@
   */
  #include linux/kernel.h
  #include linux/interrupt.h
 +#include asm/machdep.h
 +#include asm/cacheflush.h
  #include asm/ibm44x.h
  #include asm/mmu.h
  #include asm/processor.h
 @@ -201,6 +203,7 @@ void __init ibm440gx_l2c_enable(void){
  
   asm volatile (sync; isync ::: memory);
   local_irq_restore(flags);
 + ppc_md.l2cache_inv_range = invalidate_l2cache_range;
  }
  
  /* Disable L2 cache */
 diff --git a/include/asm-powerpc/cacheflush.h 
 b/include/asm-powerpc/cacheflush.h
 index ba667a3..bdebfaa 100644
 --- a/include/asm-powerpc/cacheflush.h
 +++ b/include/asm-powerpc/cacheflush.h
 @@ -49,6 +49,7 @@ extern void flush_dcache_range(unsigned long start, 
 unsigned long stop);
  #ifdef CONFIG_PPC32
  extern void clean_dcache_range(unsigned long start, unsigned long stop);
  extern void invalidate_dcache_range(unsigned long start, unsigned long stop);
 +extern void invalidate_l2cache_range(unsigned long start, unsigned long 
 stop);
  #endif /* 

Re[2]: [PATCH] [PPC 44x] L2-cache synchronization for ppc44x

2007-11-07 Thread Yuri Tikhonov

 Hi Ben,


On 08.11.2007, 2:19:33 you wrote:
 On Thu, 2007-11-08 at 02:12 +0300, Yuri Tikhonov wrote:
 This is the updated patch for support synchronization of L2-Cache with
 the external memory on the ppc44x-based platforms.
 
  Differencies against the previous patch-set:
 - remove L2_CACHE config option;
 - introduce the ppc machdep to invalidate L2 cache lines;
 - some code clean-up.

 Can you tell me more about how this cache operates ? I don't quite
 understand why you would invalidate it on bidirectional DMAs rather than
 flush it to memory (unless you get your terminology wrong) and why you
 wouldn't flush it on transfers to the device.. Unless it is a
 write-through cache ?

 Yes, the ppc44x Level2 cache has the write-through design, so no need to do 
any kind of l2_flush.

 As far as the DMA_BIDIRECTIONAL case is concerned flush_dcache_range() flushes 
the data over the following path: L1-L2-RAM, but invalidates L1 only, and  L2 
remains invalid. Since in the BIDIRECTIONAL case DMA may update the data in RAM 
- we have to invalidate L2-cache manually, so that CPU may read new data 
transmitted by DMA right from RAM rather than old ones stuck in L2 due to 
flush_dcache().


Regards,
 Yuri 

-- 
Yuri Tikhonov, Senior Software Engineer
Emcraft Systems, www.emcraft.com

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev