LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2]: powerpc: Cleanup CPU inits
From: Olof Johansson @ 2006-08-11  5:07 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20060811050159.GA5879@pb15.lixom.net>

Cleanup CPU inits a bit more, Geoff Levand already did some earlier.

* Move CPU state save to cpu_setup, since cpu_setup is only ever done
  on cpu 0 on 64-bit and save is never done more than once.
* Rename __restore_cpu_setup to __restore_cpu_ppc970 and add
  function pointers to the cputable to use instead. Powermac always
  has 970 so no need to check there.
* Rename __970_cpu_preinit to __cpu_preinit_ppc970 and check PVR before
  calling it instead of in it, it's too early to use cputable.
* Rename pSeries_secondary_smp_init to generic_secondary_smp_init since
  everyone but powermac and iSeries use it.


Signed-off-by: Olof Johansson <olof@lixom.net>


Index: linux-2.6/arch/powerpc/kernel/cpu_setup_ppc970.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ linux-2.6/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -16,27 +16,12 @@
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
-_GLOBAL(__970_cpu_preinit)
-	/*
-	 * Do nothing if not running in HV mode
-	 */
+_GLOBAL(__cpu_preinit_ppc970)
+	/* Do nothing if not running in HV mode */
 	mfmsr	r0
 	rldicl.	r0,r0,4,63
 	beqlr
 
-	/*
-	 * Deal only with PPC970 and PPC970FX.
-	 */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bnelr
-1:
-
 	/* Make sure HID4:rm_ci is off before MMU is turned off, that large
 	 * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
 	 * HID5:DCBZ32_ill
@@ -72,21 +57,6 @@ _GLOBAL(__970_cpu_preinit)
 	isync
 	blr
 
-_GLOBAL(__setup_cpu_ppc970)
-	mfspr	r0,SPRN_HID0
-	li	r11,5			/* clear DOZE and SLEEP */
-	rldimi	r0,r11,52,8		/* set NAP and DPM */
-	mtspr	SPRN_HID0,r0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	sync
-	isync
-	blr
-
 /* Definitions for the table use to save CPU states */
 #define CS_HID0		0
 #define CS_HID1		8
@@ -101,33 +71,28 @@ cpu_state_storage:
 	.balign	L1_CACHE_BYTES,0
 	.text
 
-/* Called in normal context to backup CPU 0 state. This
- * does not include cache settings. This function is also
- * called for machine sleep. This does not include the MMU
- * setup, BATs, etc... but rather the "special" registers
- * like HID0, HID1, HID4, etc...
- */
-_GLOBAL(__save_cpu_setup)
-	/* Some CR fields are volatile, we back it up all */
-	mfcr	r7
-
-	/* Get storage ptr */
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
-
-	/* We only deal with 970 for now */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bne	2f
 
-1:	/* skip if not running in HV mode */
+_GLOBAL(__setup_cpu_ppc970)
+	/* Do nothing if not running in HV mode */
 	mfmsr	r0
 	rldicl.	r0,r0,4,63
-	beq	2f
+	beqlr
+
+	mfspr	r0,SPRN_HID0
+	li	r11,5			/* clear DOZE and SLEEP */
+	rldimi	r0,r11,52,8		/* set NAP and DPM */
+	mtspr	SPRN_HID0,r0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	sync
+	isync
+
+	/* Save away cpu state */
+	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
 
 	/* Save HID0,1,4 and 5 */
 	mfspr	r3,SPRN_HID0
@@ -139,35 +104,19 @@ _GLOBAL(__save_cpu_setup)
 	mfspr	r3,SPRN_HID5
 	std	r3,CS_HID5(r5)
 
-2:
-	mtcr	r7
 	blr
 
 /* Called with no MMU context (typically MSR:IR/DR off) to
  * restore CPU state as backed up by the previous
  * function. This does not include cache setting
  */
-_GLOBAL(__restore_cpu_setup)
-	/* Get storage ptr (FIXME when using anton reloc as we
-	 * are running with translation disabled here
-	 */
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
-
-	/* We only deal with 970 for now */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bnelr
-
-1:	/* skip if not running in HV mode */
+_GLOBAL(__restore_cpu_ppc970)
+	/* Do nothing if not running in HV mode */
 	mfmsr	r0
 	rldicl.	r0,r0,4,63
 	beqlr
 
+	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
 	/* Before accessing memory, we make sure rm_ci is clear */
 	li	r0,0
 	mfspr	r3,SPRN_HID4
Index: linux-2.6/arch/powerpc/kernel/head_64.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/head_64.S
+++ linux-2.6/arch/powerpc/kernel/head_64.S
@@ -132,7 +132,7 @@ _GLOBAL(__secondary_hold)
 	bne	100b
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
-	LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
+	LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
 	mtctr	r4
 	mr	r3,r24
 	bctr
@@ -1484,19 +1484,17 @@ fwnmi_data_area:
         . = 0x8000
 
 /*
- * On pSeries, secondary processors spin in the following code.
+ * On pSeries and most other platforms, secondary processors spin
+ * in the following code.
  * At entry, r3 = this processor's number (physical cpu id)
  */
-_GLOBAL(pSeries_secondary_smp_init)
+_GLOBAL(generic_secondary_smp_init)
 	mr	r24,r3
 	
 	/* turn on 64-bit mode */
 	bl	.enable_64b_mode
 	isync
 
-	/* Copy some CPU settings from CPU 0 */
-	bl	.__restore_cpu_setup
-
 	/* Set up a paca value for this processor. Since we have the
 	 * physical cpu id in r24, we need to search the pacas to find
 	 * which logical id maps to our physical one.
@@ -1522,15 +1520,28 @@ _GLOBAL(pSeries_secondary_smp_init)
 					/* start.			 */
 	sync
 
-	/* Create a temp kernel stack for use before relocation is on.	*/
+#ifndef CONFIG_SMP
+	b	3b			/* Never go on non-SMP		 */
+#else
+	cmpwi	0,r23,0
+	beq	3b			/* Loop until told to go	 */
+
+	/* See if we need to call a cpu state restore handler */
+	LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
+	ld	r23,0(r23)
+	ld	r23,CPU_SPEC_RESTORE(r23)
+	cmpdi	0,r23,0
+	beq	4f
+	ld	r23,0(r23)
+	mtctr	r23
+	bctrl
+
+4:	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
 	subi	r1,r1,STACK_FRAME_OVERHEAD
 
-	cmpwi	0,r23,0
-#ifdef CONFIG_SMP
-	bne	.__secondary_start
+	b	.__secondary_start
 #endif
-	b 	3b			/* Loop until told to go	 */
 
 #ifdef CONFIG_PPC_ISERIES
 _STATIC(__start_initialization_iSeries)
@@ -1611,7 +1622,16 @@ _GLOBAL(__start_initialization_multiplat
 	bl	.enable_64b_mode
 
 	/* Setup some critical 970 SPRs before switching MMU off */
-	bl	.__970_cpu_preinit
+	mfspr	r0,SPRN_PVR
+	srwi	r0,r0,16
+	cmpwi	r0,0x39		/* 970 */
+	beq	1f
+	cmpwi	r0,0x3c		/* 970FX */
+	beq	1f
+	cmpwi	r0,0x44		/* 970MP */
+	bne	2f
+1:	bl	.__cpu_preinit_ppc970
+2:
 
 	/* Switch off MMU if not already */
 	LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
@@ -1782,7 +1802,7 @@ _GLOBAL(pmac_secondary_start)
 	isync
 
 	/* Copy some CPU settings from CPU 0 */
-	bl	.__restore_cpu_setup
+	bl	.__restore_cpu_ppc970
 
 	/* pSeries do that early though I don't think we really need it */
 	mfmsr	r3
@@ -1932,12 +1952,6 @@ _STATIC(start_here_multiplatform)
 	mr	r5,r26
 	bl	.identify_cpu
 
-	/* Save some low level config HIDs of CPU0 to be copied to
-	 * other CPUs later on, or used for suspend/resume
-	 */
-	bl	.__save_cpu_setup
-	sync
-
 	/* Do very early kernel initializations, including initial hash table,
 	 * stab and slb setup before we turn on relocation.	*/
 
Index: linux-2.6/arch/powerpc/platforms/cell/smp.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/cell/smp.c
+++ linux-2.6/arch/powerpc/platforms/cell/smp.c
@@ -57,7 +57,7 @@
  */
 static cpumask_t of_spin_map;
 
-extern void pSeries_secondary_smp_init(unsigned long);
+extern void generic_secondary_smp_init(unsigned long);
 
 /**
  * smp_startup_cpu() - start the given cpu
@@ -74,7 +74,7 @@ static inline int __devinit smp_startup_
 {
 	int status;
 	unsigned long start_here = __pa((u32)*((unsigned long *)
-					       pSeries_secondary_smp_init));
+					       generic_secondary_smp_init));
 	unsigned int pcpu;
 	int start_cpu;
 
Index: linux-2.6/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- linux-2.6.orig/arch/powerpc/platforms/pseries/smp.c
+++ linux-2.6/arch/powerpc/platforms/pseries/smp.c
@@ -62,7 +62,7 @@
  */
 static cpumask_t of_spin_map;
 
-extern void pSeries_secondary_smp_init(unsigned long);
+extern void generic_secondary_smp_init(unsigned long);
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -270,7 +270,7 @@ static inline int __devinit smp_startup_
 {
 	int status;
 	unsigned long start_here = __pa((u32)*((unsigned long *)
-					       pSeries_secondary_smp_init));
+					       generic_secondary_smp_init));
 	unsigned int pcpu;
 	int start_cpu;
 
Index: linux-2.6/arch/powerpc/kernel/asm-offsets.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-2.6/arch/powerpc/kernel/asm-offsets.c
@@ -241,6 +241,7 @@ int main(void)
 	DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
 	DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+	DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
 
 #ifndef CONFIG_PPC64
 	DEFINE(pbe_address, offsetof(struct pbe, address));
Index: linux-2.6/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/cputable.c
+++ linux-2.6/arch/powerpc/kernel/cputable.c
@@ -39,7 +39,10 @@ extern void __setup_cpu_7400(unsigned lo
 extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
 #endif /* CONFIG_PPC32 */
+#ifdef CONFIG_PPC64
 extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
+extern void __restore_cpu_ppc970(void);
+#endif /* CONFIG_PPC64 */
 
 /* This table only contains "desktop" CPUs, it need to be filled with embedded
  * ones as well...
@@ -184,6 +187,7 @@ struct cpu_spec	cpu_specs[] = {
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
 		.cpu_setup		= __setup_cpu_ppc970,
+		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
@@ -199,6 +203,7 @@ struct cpu_spec	cpu_specs[] = {
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
 		.cpu_setup		= __setup_cpu_ppc970,
+		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
@@ -214,6 +219,7 @@ struct cpu_spec	cpu_specs[] = {
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
 		.cpu_setup		= __setup_cpu_ppc970,
+		.cpu_restore		= __restore_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
Index: linux-2.6/include/asm-powerpc/cputable.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/cputable.h
+++ linux-2.6/include/asm-powerpc/cputable.h
@@ -36,6 +36,7 @@
 struct cpu_spec;
 
 typedef	void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec);
+typedef	void (*cpu_restore_t)(void);
 
 enum powerpc_oprofile_type {
 	PPC_OPROFILE_INVALID = 0,
@@ -65,6 +66,8 @@ struct cpu_spec {
 	 * BHT, SPD, etc... from head.S before branching to identify_machine
 	 */
 	cpu_setup_t	cpu_setup;
+	/* Used to restore cpu setup on secondary processors and at resume */
+	cpu_restore_t	cpu_restore;
 
 	/* Used by oprofile userspace to select the right counters */
 	char		*oprofile_cpu_type;

^ permalink raw reply

* [PATCH 1/2] powerpc: Rename cpu_setup_power4.S to cpu_setup_ppc970.S
From: Olof Johansson @ 2006-08-11  5:03 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev
In-Reply-To: <20060811050159.GA5879@pb15.lixom.net>

Rename cpu_setup_power4.S to cpu_setup_ppc970.S, since that's
really what it is.

No functional or other changes.


Signed-off-by: Olof Johansson <olof@lixom.net>

Index: linux-2.6/arch/powerpc/kernel/cpu_setup_power4.S
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/cpu_setup_power4.S
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * This file contains low level CPU setup functions.
- *    Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/cache.h>
-
-_GLOBAL(__970_cpu_preinit)
-	/*
-	 * Do nothing if not running in HV mode
-	 */
-	mfmsr	r0
-	rldicl.	r0,r0,4,63
-	beqlr
-
-	/*
-	 * Deal only with PPC970 and PPC970FX.
-	 */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bnelr
-1:
-
-	/* Make sure HID4:rm_ci is off before MMU is turned off, that large
-	 * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
-	 * HID5:DCBZ32_ill
-	 */
-	li	r0,0
-	mfspr	r3,SPRN_HID4
-	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */
-	rldimi	r3,r0,2,61	/* clear bit 61 (lg_pg_en) */
-	sync
-	mtspr	SPRN_HID4,r3
-	isync
-	sync
-	mfspr	r3,SPRN_HID5
-	rldimi	r3,r0,6,56	/* clear bits 56 & 57 (DCBZ*) */
-	sync
-	mtspr	SPRN_HID5,r3
-	isync
-	sync
-
-	/* Setup some basic HID1 features */
-	mfspr	r0,SPRN_HID1
-	li	r3,0x1200		/* enable i-fetch cacheability */
-	sldi	r3,r3,44		/* and prefetch */
-	or	r0,r0,r3
-	mtspr	SPRN_HID1,r0
-	mtspr	SPRN_HID1,r0
-	isync
-
-	/* Clear HIOR */
-	li	r0,0
-	sync
-	mtspr	SPRN_HIOR,0		/* Clear interrupt prefix */
-	isync
-	blr
-
-_GLOBAL(__setup_cpu_ppc970)
-	mfspr	r0,SPRN_HID0
-	li	r11,5			/* clear DOZE and SLEEP */
-	rldimi	r0,r11,52,8		/* set NAP and DPM */
-	mtspr	SPRN_HID0,r0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	mfspr	r0,SPRN_HID0
-	sync
-	isync
-	blr
-
-/* Definitions for the table use to save CPU states */
-#define CS_HID0		0
-#define CS_HID1		8
-#define	CS_HID4		16
-#define CS_HID5		24
-#define CS_SIZE		32
-
-	.data
-	.balign	L1_CACHE_BYTES,0
-cpu_state_storage:
-	.space	CS_SIZE
-	.balign	L1_CACHE_BYTES,0
-	.text
-
-/* Called in normal context to backup CPU 0 state. This
- * does not include cache settings. This function is also
- * called for machine sleep. This does not include the MMU
- * setup, BATs, etc... but rather the "special" registers
- * like HID0, HID1, HID4, etc...
- */
-_GLOBAL(__save_cpu_setup)
-	/* Some CR fields are volatile, we back it up all */
-	mfcr	r7
-
-	/* Get storage ptr */
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
-
-	/* We only deal with 970 for now */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bne	2f
-
-1:	/* skip if not running in HV mode */
-	mfmsr	r0
-	rldicl.	r0,r0,4,63
-	beq	2f
-
-	/* Save HID0,1,4 and 5 */
-	mfspr	r3,SPRN_HID0
-	std	r3,CS_HID0(r5)
-	mfspr	r3,SPRN_HID1
-	std	r3,CS_HID1(r5)
-	mfspr	r3,SPRN_HID4
-	std	r3,CS_HID4(r5)
-	mfspr	r3,SPRN_HID5
-	std	r3,CS_HID5(r5)
-
-2:
-	mtcr	r7
-	blr
-
-/* Called with no MMU context (typically MSR:IR/DR off) to
- * restore CPU state as backed up by the previous
- * function. This does not include cache setting
- */
-_GLOBAL(__restore_cpu_setup)
-	/* Get storage ptr (FIXME when using anton reloc as we
-	 * are running with translation disabled here
-	 */
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
-
-	/* We only deal with 970 for now */
-	mfspr	r0,SPRN_PVR
-	srwi	r0,r0,16
-	cmpwi	r0,0x39
-	beq	1f
-	cmpwi	r0,0x3c
-	beq	1f
-	cmpwi	r0,0x44
-	bnelr
-
-1:	/* skip if not running in HV mode */
-	mfmsr	r0
-	rldicl.	r0,r0,4,63
-	beqlr
-
-	/* Before accessing memory, we make sure rm_ci is clear */
-	li	r0,0
-	mfspr	r3,SPRN_HID4
-	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */
-	sync
-	mtspr	SPRN_HID4,r3
-	isync
-	sync
-
-	/* Clear interrupt prefix */
-	li	r0,0
-	sync
-	mtspr	SPRN_HIOR,0
-	isync
-
-	/* Restore HID0 */
-	ld	r3,CS_HID0(r5)
-	sync
-	isync
-	mtspr	SPRN_HID0,r3
-	mfspr	r3,SPRN_HID0
-	mfspr	r3,SPRN_HID0
-	mfspr	r3,SPRN_HID0
-	mfspr	r3,SPRN_HID0
-	mfspr	r3,SPRN_HID0
-	mfspr	r3,SPRN_HID0
-	sync
-	isync
-
-	/* Restore HID1 */
-	ld	r3,CS_HID1(r5)
-	sync
-	isync
-	mtspr	SPRN_HID1,r3
-	mtspr	SPRN_HID1,r3
-	sync
-	isync
-
-	/* Restore HID4 */
-	ld	r3,CS_HID4(r5)
-	sync
-	isync
-	mtspr	SPRN_HID4,r3
-	sync
-	isync
-
-	/* Restore HID5 */
-	ld	r3,CS_HID5(r5)
-	sync
-	isync
-	mtspr	SPRN_HID5,r3
-	sync
-	isync
-	blr
-
Index: linux-2.6/arch/powerpc/kernel/cpu_setup_ppc970.S
===================================================================
--- /dev/null
+++ linux-2.6/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -0,0 +1,225 @@
+/*
+ * This file contains low level CPU setup functions.
+ *    Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/cache.h>
+
+_GLOBAL(__970_cpu_preinit)
+	/*
+	 * Do nothing if not running in HV mode
+	 */
+	mfmsr	r0
+	rldicl.	r0,r0,4,63
+	beqlr
+
+	/*
+	 * Deal only with PPC970 and PPC970FX.
+	 */
+	mfspr	r0,SPRN_PVR
+	srwi	r0,r0,16
+	cmpwi	r0,0x39
+	beq	1f
+	cmpwi	r0,0x3c
+	beq	1f
+	cmpwi	r0,0x44
+	bnelr
+1:
+
+	/* Make sure HID4:rm_ci is off before MMU is turned off, that large
+	 * pages are enabled with HID4:61 and clear HID5:DCBZ_size and
+	 * HID5:DCBZ32_ill
+	 */
+	li	r0,0
+	mfspr	r3,SPRN_HID4
+	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */
+	rldimi	r3,r0,2,61	/* clear bit 61 (lg_pg_en) */
+	sync
+	mtspr	SPRN_HID4,r3
+	isync
+	sync
+	mfspr	r3,SPRN_HID5
+	rldimi	r3,r0,6,56	/* clear bits 56 & 57 (DCBZ*) */
+	sync
+	mtspr	SPRN_HID5,r3
+	isync
+	sync
+
+	/* Setup some basic HID1 features */
+	mfspr	r0,SPRN_HID1
+	li	r3,0x1200		/* enable i-fetch cacheability */
+	sldi	r3,r3,44		/* and prefetch */
+	or	r0,r0,r3
+	mtspr	SPRN_HID1,r0
+	mtspr	SPRN_HID1,r0
+	isync
+
+	/* Clear HIOR */
+	li	r0,0
+	sync
+	mtspr	SPRN_HIOR,0		/* Clear interrupt prefix */
+	isync
+	blr
+
+_GLOBAL(__setup_cpu_ppc970)
+	mfspr	r0,SPRN_HID0
+	li	r11,5			/* clear DOZE and SLEEP */
+	rldimi	r0,r11,52,8		/* set NAP and DPM */
+	mtspr	SPRN_HID0,r0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	mfspr	r0,SPRN_HID0
+	sync
+	isync
+	blr
+
+/* Definitions for the table use to save CPU states */
+#define CS_HID0		0
+#define CS_HID1		8
+#define	CS_HID4		16
+#define CS_HID5		24
+#define CS_SIZE		32
+
+	.data
+	.balign	L1_CACHE_BYTES,0
+cpu_state_storage:
+	.space	CS_SIZE
+	.balign	L1_CACHE_BYTES,0
+	.text
+
+/* Called in normal context to backup CPU 0 state. This
+ * does not include cache settings. This function is also
+ * called for machine sleep. This does not include the MMU
+ * setup, BATs, etc... but rather the "special" registers
+ * like HID0, HID1, HID4, etc...
+ */
+_GLOBAL(__save_cpu_setup)
+	/* Some CR fields are volatile, we back it up all */
+	mfcr	r7
+
+	/* Get storage ptr */
+	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+
+	/* We only deal with 970 for now */
+	mfspr	r0,SPRN_PVR
+	srwi	r0,r0,16
+	cmpwi	r0,0x39
+	beq	1f
+	cmpwi	r0,0x3c
+	beq	1f
+	cmpwi	r0,0x44
+	bne	2f
+
+1:	/* skip if not running in HV mode */
+	mfmsr	r0
+	rldicl.	r0,r0,4,63
+	beq	2f
+
+	/* Save HID0,1,4 and 5 */
+	mfspr	r3,SPRN_HID0
+	std	r3,CS_HID0(r5)
+	mfspr	r3,SPRN_HID1
+	std	r3,CS_HID1(r5)
+	mfspr	r3,SPRN_HID4
+	std	r3,CS_HID4(r5)
+	mfspr	r3,SPRN_HID5
+	std	r3,CS_HID5(r5)
+
+2:
+	mtcr	r7
+	blr
+
+/* Called with no MMU context (typically MSR:IR/DR off) to
+ * restore CPU state as backed up by the previous
+ * function. This does not include cache setting
+ */
+_GLOBAL(__restore_cpu_setup)
+	/* Get storage ptr (FIXME when using anton reloc as we
+	 * are running with translation disabled here
+	 */
+	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+
+	/* We only deal with 970 for now */
+	mfspr	r0,SPRN_PVR
+	srwi	r0,r0,16
+	cmpwi	r0,0x39
+	beq	1f
+	cmpwi	r0,0x3c
+	beq	1f
+	cmpwi	r0,0x44
+	bnelr
+
+1:	/* skip if not running in HV mode */
+	mfmsr	r0
+	rldicl.	r0,r0,4,63
+	beqlr
+
+	/* Before accessing memory, we make sure rm_ci is clear */
+	li	r0,0
+	mfspr	r3,SPRN_HID4
+	rldimi	r3,r0,40,23	/* clear bit 23 (rm_ci) */
+	sync
+	mtspr	SPRN_HID4,r3
+	isync
+	sync
+
+	/* Clear interrupt prefix */
+	li	r0,0
+	sync
+	mtspr	SPRN_HIOR,0
+	isync
+
+	/* Restore HID0 */
+	ld	r3,CS_HID0(r5)
+	sync
+	isync
+	mtspr	SPRN_HID0,r3
+	mfspr	r3,SPRN_HID0
+	mfspr	r3,SPRN_HID0
+	mfspr	r3,SPRN_HID0
+	mfspr	r3,SPRN_HID0
+	mfspr	r3,SPRN_HID0
+	mfspr	r3,SPRN_HID0
+	sync
+	isync
+
+	/* Restore HID1 */
+	ld	r3,CS_HID1(r5)
+	sync
+	isync
+	mtspr	SPRN_HID1,r3
+	mtspr	SPRN_HID1,r3
+	sync
+	isync
+
+	/* Restore HID4 */
+	ld	r3,CS_HID4(r5)
+	sync
+	isync
+	mtspr	SPRN_HID4,r3
+	sync
+	isync
+
+	/* Restore HID5 */
+	ld	r3,CS_HID5(r5)
+	sync
+	isync
+	mtspr	SPRN_HID5,r3
+	sync
+	isync
+	blr
+
Index: linux-2.6/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/Makefile
+++ linux-2.6/arch/powerpc/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y				:= semaphore.o cputable.o ptrac
 obj-y				+= vdso32/
 obj-$(CONFIG_PPC64)		+= setup_64.o binfmt_elf32.o sys_ppc32.o \
 				   signal_64.o ptrace32.o \
-				   paca.o cpu_setup_power4.o \
+				   paca.o cpu_setup_ppc970.o \
 				   firmware.o sysfs.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o

^ permalink raw reply

* [PATCH 0/2]: powerpc: Cpu init cleanups
From: Olof Johansson @ 2006-08-11  5:01 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev

Hi,

Attached are two patches to cleanup the cpu inits a bit. First one just
renames cpu_setup_power4.S to cpu_setup_ppc970.S, since that's really
what it contains. No functional changes at all in there to simplify
review.

Second patch renames some of the setup functions, and make the restore
functions come of the cputable instead of being hardcoded. Current setup
makes it awkward to add new cpus without editing the ppc970 setup/restore
functions or add more PVR checks in the assembly, which would be nice
to avoid. Only the really early one is still needed in assembly, since
cputables have not yet been setup at that point.

Earlier patch submission was all baked together, which makes it harder
to review and tell what is new and not.

Boot tested on PowerMac and POWER5. Please consider for 2.6.19 merge
window.


Thanks,

Olof

^ permalink raw reply

* Re: [RFC] consolidated libdt proposal
From: Milton Miller @ 2006-08-11  4:55 UTC (permalink / raw)
  To: Mark A. Greer
  Cc: hollisb, pantelis, xen-ppc-devel, linuxppc-dev, linuxppc-embedded
In-Reply-To: <20060810185514.GA12848@mag.az.mvista.com>

On Aug 10, 2006, at 1:55 PM, Mark A. Greer wrote:
> On Thu, Aug 10, 2006 at 11:51:30AM -0500, Milton Miller wrote:
>> On Tue Aug  8 2006 01:04:08 PM CDT, Mark A. Greer wrote:
>>> If we're going to allow cmdline editing in the bootwrapper, we would
>>> need to extend the size of a property.
...
>> We already have replace the command line merged (it's why my patches
>> don't apply).
> That's different.
...

Yes, but it still requires changing the size or inserting a
property, which is the real requirement we were discussing.

Yes, editing at command line would require an input function.

milton

^ permalink raw reply

* Re: Gianfar eth driver on 8540 ppc - for 2.4 and 2.6 : different outputs
From: Kumar Gala @ 2006-08-11  4:10 UTC (permalink / raw)
  To: Prashant Yendigeri; +Cc: linuxppc-embedded
In-Reply-To: <OF403D77BC.13F5C3B5-ON652571C6.003D5A1C-652571C6.003E28AE@lntinfotech.com>


On Aug 10, 2006, at 6:18 AM, Prashant Yendigeri wrote:

>
> Hi,
>
> The gianfar driver of 2.6.12 and 2.4.20 give different outputs on  
> the same PPC 8540 board.
>
> What could be the reason ?
>
> Output on 2.4.20 :
> /root # ifconfig eth0 172.28.8.254 up
> eth0: PHY is Marvell 88E1011S (1410c62)
> eth0: Auto-negotiation done
> eth0: Half Duplex
> eth0: Speed 10BT
> eth0: Link is up
>
> Output on 2.6.12
> / # ifconfig eth0 172.28.8.254 up
>  eth0: PHY is Generic MII (ffffffff)

It looks like your 2.6.12 kernel isn't handling the PHY correctly.   
I'd recommend upgrading to something newer which has the phylib  
(can't remember which 2.6 that went into).

- kumar

^ permalink raw reply

* [RFC PATCH 0/4]  powerpc 2.6.16-rt17: to port rt patch to powerpc
From: Tsutomu OWA @ 2006-08-11  2:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, mingo, tglx


Hi, I'm trying to port realtime-preempt patch to powerpc.  The primary
purpose to post an experimental work is for review and to see if I'm on
the right track.  The same material is placed on CE Linux Forum's wiki
page;
http://tree.celinuxforum.org/CelfPubWiki/RTPatchForPowerPC

This series of patches adds support to make rt patch work on powerpc64
targets. Currently two platforms (powermac and cell) are tested.

These patches apply to 2.6.16 kernel with realtime preempt patch
(patch-2.6.16-rt17) by Ingo Molnar at
http://people.redhat.com/mingo/realtime-preempt/.

Compile tested for both powermac and cell w/ and w/o PREEMPT_RT.

Boot tested for powermac w/ and w/o PREEMPT_RT on a Dual Power Mac
G5. (boots on initrd and CONFIG_BLK_DEV_IDE_PMAC is disabled (or with a
work around included in the patch) for PREEMPT_RT, see *1).

Boot tested for cell w/ and w/o PREEMPT_RT on the systemsim simulator
provided by IBM. Note that "iommu=off" command line option is applied.

[RFC PATCH 1/4] powerpc 2.6.16-rt17: to build on powerpc w/ RT
[RFC PATCH 2/4] powerpc 2.6.16-rt17: to boot on powerpc w/ RT
[RFC PATCH 3/4] powerpc 2.6.16-rt17: to support CONFIG_MCOUNT
[RFC PATCH 4/4] powerpc 2.6.16-rt29: to fix network driver (workaround)

These patches are provided under GNU GPL.

Comments and suggestions are welcome.

Thanks in advance.

*1: There seem to be some flaw(s) which make(s) some devices unavailable
 (namely a cdrom drive and a SATA drive so far) when PREEMPT_HARDIRQS is
 enabled. "hda: lost interrupt" and/or "ata1: command 0x50 host_stat
 0x4" show up. Other devices such as network, keyboard etc. seem to work
 fine. I've looked into this for a couple of weeks in vain. 

-- owa
Software Engineering Center, TOSHIBA.

^ permalink raw reply

* [RFC PATCH 4/4] powerpc 2.6.16-rt29: to fix network driver (workaround)
From: Tsutomu OWA @ 2006-08-11  2:04 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, mingo, tglx


  To make network driver available for rt29 (actually rt21 and later).
When doing "ping -f", the network driver seems to hang without this 
workaround for rt version 29.

-- owa
# I suppose this should be fixed in other way in future but for now...

--- rt29/kernel/irq/manage.c	2006-07-10 09:01:21.000000000 +0900
+++ rt-powerpc/kernel/irq/manage.c	2006-07-21 20:17:50.000000000 +0900
@@ -723,15 +723,24 @@ static int do_irqd(void * __desc)
 		set_current_state(TASK_INTERRUPTIBLE);
 		do_hardirq(desc);
 		cond_resched_all();
+#ifndef CONFIG_PPC_PMAC64 /* work around: to revert to patch-2.6.16-rt20 version */
 		local_irq_disable();
+#endif /* !CONFIG_PPC_PMAC64 */
 		__do_softirq();
 		local_irq_enable();
 #ifdef CONFIG_SMP
 		/*
 		 * Did IRQ affinities change?
 		 */
+#ifdef CONFIG_PPC_PMAC64 /* work around; revert to patch-2.6.16-rt20 version */
+		if (!cpu_isset(smp_processor_id(), irq_affinity[irq])) {
+			mask = cpumask_of_cpu(any_online_cpu(irq_affinity[irq]));
+			set_cpus_allowed(current, mask);
+		}
+#else
 		if (!cpus_equal(current->cpus_allowed, irq_affinity[irq]))
 			set_cpus_allowed(current, irq_affinity[irq]);
+#endif /* CONFIG_PPC_PMAC64 */
 #endif
 		schedule();
 	}

^ permalink raw reply

* [RFC PATCH 2/4] powerpc 2.6.16-rt17: to boot on powerpc w/ RT
From: Tsutomu OWA @ 2006-08-11  2:02 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, mingo, tglx


  To boot on powermac and cell.

---
with PREEMPT_RT
BUG: using smp_processor_id() in preemptible [00000000] code: init/1
caller is .hpte_update+0x4c/0x250
Call Trace:
[C000000001467850] [C00000000000F250] .show_stack+0x68/0x1b4
(unreliable)
[C000000001467900] [C00000000014C4A4] .debug_smp_processor_id+0xc4/0xf4
[C000000001467990] [C00000000002BEC0] .hpte_update+0x4c/0x250
[C000000001467A40] [C00000000008C670] .do_wp_page+0x474/0x618
[C000000001467B10] [C00000000008DC30] .__handle_mm_fault+0xd50/0xe68
[C000000001467C20] [C000000000029EFC] .do_page_fault+0x48c/0x674
[C000000001467E30] [C000000000004760] .handle_page_fault+0x20/0x54

o to enable drivers.
  powermac/low_i2c.c:
    struct semaphore -> struct compat_semaphore
    spinlock_t -> raw_spinlock_t
  drivers/net/sungem.c: transmit_tx_frame(). try_spinlock_irqsave()
  make spinlock_t to raw_spinlock_t for mpic and native_tlbie_lock.
  make struct semaphore to struct compat_semaphore for kw2_i2c.

* to boot on cell
  o port systemsim bogus disk and console.  (not included in this patch)
with PREEMPT_RT
BUG: swapper:0 task might have lost a preemption check!
Call Trace:
[C0000000002FFC40] [C00000000000F250] .show_stack+0x68/0x1b4
(unreliable)
[C0000000002FFCF0] [C0000000000425F8]
.preempt_enable_no_resched+0x68/0x80
[C0000000002FFD70] [C000000000032EC0] .cbe_idle+0x168/0x184
[C0000000002FFE00] [C000000000018DD0] .cpu_idle+0x4c/0x60
[C0000000002FFE70] [C000000000009290] .rest_init+0x60/0x78
[C0000000002FFEF0] [C0000000002CE890] .start_kernel+0x310/0x330
[C0000000002FFF90] [C000000000008574] .start_here_common+0x88/0x114

--
BUG: using smp_processor_id() in preemptible [00000000] code: init/1
caller is .hpte_update+0x4c/0x250
Call Trace:
[C000000001467850] [C00000000000F250] .show_stack+0x68/0x1b4
(unreliable)
[C000000001467900] [C00000000014C4A4] .debug_smp_processor_id+0xc4/0xf4
[C000000001467990] [C00000000002BEC0] .hpte_update+0x4c/0x250
[C000000001467A40] [C00000000008C670] .do_wp_page+0x474/0x618
[C000000001467B10] [C00000000008DC30] .__handle_mm_fault+0xd50/0xe68
[C000000001467C20] [C000000000029EFC] .do_page_fault+0x48c/0x674
[C000000001467E30] [C000000000004760] .handle_page_fault+0x20/0x54
-- owa

diff -rup -x CVS 2.6.16-rt17/arch/powerpc/mm/hash_native_64.c rt-powerpc/arch/powerpc/mm/hash_native_64.c
--- 2.6.16-rt17/arch/powerpc/mm/hash_native_64.c	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/arch/powerpc/mm/hash_native_64.c	2006-07-12 14:38:24.000000000 +0900
@@ -35,7 +35,10 @@
 
 #define HPTE_LOCK_BIT 3
 
-static DEFINE_SPINLOCK(native_tlbie_lock);
+/*
+ * to avoid "BUG: scheduling while atomic at native_flush_hash_range.
+ */
+static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
 
 static inline void __tlbie(unsigned long va, unsigned int psize)
 {
diff -rup -x CVS 2.6.16-rt17/arch/powerpc/mm/tlb_64.c rt-powerpc/arch/powerpc/mm/tlb_64.c
--- 2.6.16-rt17/arch/powerpc/mm/tlb_64.c	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/arch/powerpc/mm/tlb_64.c	2006-07-12 13:47:32.000000000 +0900
@@ -95,9 +95,15 @@ static void pte_free_submit(struct pte_f
 
 void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
 {
+#ifndef CONFIG_PREEMPT_RT
 	/* This is safe since tlb_gather_mmu has disabled preemption */
         cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
 	struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+#else
+        cpumask_t local_cpumask = cpumask_of_cpu(raw_smp_processor_id());
+	struct pte_freelist_batch **batchp = &get_cpu_var(pte_freelist_cur);
+	put_cpu_var(pte_freelist_cur);
+#endif /* !CONFIG_PREEMPT_RT */
 
 	if (atomic_read(&tlb->mm->mm_users) < 2 ||
 	    cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
diff -rup -x CVS 2.6.16-rt17/arch/powerpc/platforms/cell/pervasive.c rt-powerpc/arch/powerpc/platforms/cell/pervasive.c
--- 2.6.16-rt17/arch/powerpc/platforms/cell/pervasive.c	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/arch/powerpc/platforms/cell/pervasive.c	2006-07-12 13:48:09.000000000 +0900
@@ -136,8 +136,8 @@ static void cbe_idle(void)
 		 */
 		ppc64_runlatch_on();
 
-		preempt_enable_no_resched();
-		schedule();
+		__preempt_enable_no_resched();
+		__schedule();
 		preempt_disable();
 	}
 }
diff -rup -x CVS 2.6.16-rt17/arch/powerpc/platforms/powermac/low_i2c.c rt-powerpc/arch/powerpc/platforms/powermac/low_i2c.c
--- 2.6.16-rt17/arch/powerpc/platforms/powermac/low_i2c.c	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/arch/powerpc/platforms/powermac/low_i2c.c	2006-07-12 13:49:09.000000000 +0900
@@ -85,7 +85,7 @@ struct pmac_i2c_bus
 	void			*hostdata;
 	int			channel;	/* some hosts have multiple */
 	int			mode;		/* current mode */
-	struct semaphore	sem;
+	struct compat_semaphore	sem;
 	int			opened;
 	int			polled;		/* open mode */
 	struct platform_device	*platform_dev;
@@ -105,7 +105,7 @@ static LIST_HEAD(pmac_i2c_busses);
 
 struct pmac_i2c_host_kw
 {
-	struct semaphore	mutex;		/* Access mutex for use by
+	struct compat_semaphore	mutex;		/* Access mutex for use by
 						 * i2c-keywest */
 	void __iomem		*base;		/* register base address */
 	int			bsteps;		/* register stepping */
@@ -119,6 +119,9 @@ struct pmac_i2c_host_kw
 	int			result;
 	struct completion	complete;
 	spinlock_t		lock;
+		/* "BUG: scheduling while at atomic" at del_timer() called
+		 * from kw_i2c_irq() if raw_spinlock_t.
+		 */
 	struct timer_list	timeout_timer;
 };
 
diff -rup -x CVS 2.6.16-rt17/arch/powerpc/sysdev/mpic.c rt-powerpc/arch/powerpc/sysdev/mpic.c
--- 2.6.16-rt17/arch/powerpc/sysdev/mpic.c	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/arch/powerpc/sysdev/mpic.c	2006-07-11 16:19:06.000000000 +0900
@@ -45,7 +45,7 @@
 
 static struct mpic *mpics;
 static struct mpic *mpic_primary;
-static DEFINE_SPINLOCK(mpic_lock);
+static DEFINE_RAW_SPINLOCK(mpic_lock);
 
 #ifdef CONFIG_PPC32	/* XXX for now */
 #ifdef CONFIG_IRQ_ALL_CPUS
@@ -1009,13 +1009,13 @@ void mpic_request_ipis(void)
 	printk("requesting IPIs ... \n");
 
 	/* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
-	request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+	request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT | SA_NODELAY,
 		    "IPI0 (call function)", mpic);
-	request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+	request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT | SA_NODELAY,
 		   "IPI1 (reschedule)", mpic);
-	request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+	request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT | SA_NODELAY,
 		   "IPI2 (unused)", mpic);
-	request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+	request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT | SA_NODELAY,
 		   "IPI3 (debugger break)", mpic);
 
 	printk("IPIs requested... \n");
diff -rup -x CVS 2.6.16-rt17/drivers/ide/ide-io.c rt-powerpc/drivers/ide/ide-io.c
--- 2.6.16-rt17/drivers/ide/ide-io.c	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/drivers/ide/ide-io.c	2006-07-12 13:50:47.000000000 +0900
@@ -1560,8 +1560,10 @@ irqreturn_t ide_intr (int irq, void *dev
 	del_timer(&hwgroup->timer);
 	spin_unlock(&ide_lock);
 
+#if !defined(CONFIG_PREEMPT_HARDIRQS) || !defined(CONFIG_PPC_PMAC64)
 	if (drive->unmask)
 		local_irq_enable_nort();
+#endif /* !(CONFIG_PREEMPT_HARDIRQS && CONFIG_PPC_PMAC64) */
 	/* service this interrupt, may set handler for next interrupt */
 	startstop = handler(drive);
 	spin_lock_irq(&ide_lock);
diff -rup -x CVS 2.6.16-rt17/drivers/ide/ide-probe.c rt-powerpc/drivers/ide/ide-probe.c
--- 2.6.16-rt17/drivers/ide/ide-probe.c	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/drivers/ide/ide-probe.c	2006-07-12 14:07:23.000000000 +0900
@@ -51,6 +51,7 @@
 #include <linux/spinlock.h>
 #include <linux/kmod.h>
 #include <linux/pci.h>
+#include <linux/irq.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -1088,6 +1089,10 @@ static int init_irq (ide_hwif_t *hwif)
 		sa = SA_SHIRQ;
 #endif /* __mc68000__ || CONFIG_APUS */
 
+#if defined(CONFIG_PREEMPT_HARDIRQS) && defined(CONFIG_PPC_PMAC64)
+		sa |= SA_NODELAY | SA_INTERRUPT;
+#endif /* (CONFIG_PREEMPT_HARDIRQS && CONFIG_PPC_PMAC64) */
+
 		if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
 			sa = SA_SHIRQ;
 #ifndef CONFIG_IDEPCI_SHARE_IRQ
diff -rup -x CVS 2.6.16-rt17/drivers/net/sungem.c rt-powerpc/drivers/net/sungem.c
--- 2.6.16-rt17/drivers/net/sungem.c	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/drivers/net/sungem.c	2006-07-11 17:07:43.000000000 +0900
@@ -1036,10 +1036,8 @@ static int gem_start_xmit(struct sk_buff
 			(csum_stuff_off << 21));
 	}
 
-	local_irq_save(flags);
-	if (!spin_trylock(&gp->tx_lock)) {
+	if (!spin_trylock_irqsave(&gp->tx_lock, flags)) {
 		/* Tell upper layer to requeue */
-		local_irq_restore(flags);
 		return NETDEV_TX_LOCKED;
 	}
 	/* We raced with gem_do_stop() */
diff -rup -x CVS 2.6.16-rt17/include/asm-powerpc/mpic.h rt-powerpc/include/asm-powerpc/mpic.h
--- 2.6.16-rt17/include/asm-powerpc/mpic.h	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/include/asm-powerpc/mpic.h	2006-05-19 20:48:49.000000000 +0900
@@ -160,7 +160,7 @@ struct mpic
 #ifdef CONFIG_MPIC_BROKEN_U3
 	/* The fixup table */
 	struct mpic_irq_fixup	*fixups;
-	spinlock_t		fixup_lock;
+	raw_spinlock_t		fixup_lock;
 #endif
 
 	/* The various ioremap'ed bases */
diff -rup -x CVS 2.6.16-rt17/kernel/latency.c rt-powerpc/kernel/latency.c
--- 2.6.16-rt17/kernel/latency.c	2006-04-26 18:24:29.000000000 +0900
+++ rt-powerpc/kernel/latency.c	2006-07-12 13:57:31.000000000 +0900
@@ -1787,7 +1787,12 @@ void notrace add_preempt_count(unsigned 
 #endif
 
 	preempt_count() += val;
+
 #ifdef CONFIG_PREEMPT_TRACE
+#if 1 /* FIXME: somehow current is NULL. why? */
+	if (!current) 
+		return;
+#endif
 	

^ permalink raw reply

* [RFC PATCH 1/4] powerpc 2.6.16-rt17: to build on powerpc w/ RT
From: Tsutomu OWA @ 2006-08-11  2:01 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, mingo, tglx


To fix following compile errors for powermac and cell.

--- 
with PREEMPT_NONE
o arch/powerpc/kernel/head_64.S
  include/asm-generic/bug.h: Assembler messages:
  include/asm-generic/bug.h:19: Error: Unrecognized opcode: `extern'

o missing percpu related macros
  arch/powerpc/mm/mem.c
  In file included from include/asm/tlb.h:53,
                 from arch/powerpc/mm/mem.c:45:
  include/asm-generic/tlb.h:50: error: parse error before "mmu_gathers"
  include/asm-generic/tlb.h:50: warning: type defaults to `int' in
  declaration of `DECLARE_PER_CPU_LOCKED'
  etc.

o kernel/time/clockevents.c:82: error: conflicting types for
 'timer_interrupt'
  include/asm/hw_irq.h:14: error: previous declaration of
  'timer_interrupt' was here
  kernel/time/clockevents.c:82: error: conflicting types for
  'timer_interrupt'
  include/asm/hw_irq.h:14: error: previous declaration of
  'timer_interrupt' was here

o kernel/built-in.o: In function `do_gettimeofday':
    : multiple definition of `do_gettimeofday'
  arch/powerpc/kernel/built-in.o:: first defined here
  kernel/built-in.o: In function `.do_gettimeofday':
    : multiple definition of `.do_gettimeofday'
  arch/powerpc/kernel/built-in.o:: first defined here
  /usr/local/sti/SDK0.29/bin/pu64-ld: Warning: size of symbol
  `.do_gettimeofday' changed from 120 in arch/powerpc/kernel/built-in.o
    to 372 in kernel/built-in.o
  arch/powerpc/kernel/built-in.o: In function `.do_gettimeofday':

o arch/powerpc/kernel/built-in.o: In function `.do_gettimeofday':
  : undefined reference to `.SCALE_XSEC'

with PREEMPT_RT

o arch/powerpc/platforms/powermac/.tmp_feature.o
  arch/powerpc/platforms/powermac/feature.c
  arch/powerpc/platforms/powermac/feature.c:65: error: conflicting types
  for 'feature_lock'
  include/asm/pmac_feature.h:381: error: previous declaration of
    'feature_lock' was here
  arch/powerpc/platforms/powermac/feature.c:65: error: conflicting types
    for 'feature_lock'
  include/asm/pmac_feature.h:381: error: previous declaration of
    'feature_lock' was here

diff -rup -x CVS 2.6.16-rt17/arch/powerpc/kernel/time.c rt-powerpc/arch/powerpc/kernel/time.c
--- 2.6.16-rt17/arch/powerpc/kernel/time.c	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/arch/powerpc/kernel/time.c	2006-07-12 13:45:31.000000000 +0900
@@ -200,6 +200,7 @@ void udelay(unsigned long usecs)
 }
 EXPORT_SYMBOL(udelay);
 
+#ifndef CONFIG_GENERIC_TIME
 /*
  * This version of gettimeofday has microsecond resolution.
  */
@@ -223,6 +224,7 @@ static inline void __do_gettimeofday(str
 	xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs);
 	sec = xsec / XSEC_PER_SEC;
 	usec = (unsigned long)xsec & (XSEC_PER_SEC - 1);
+#define SCALE_XSEC(xsec, max)  (((xsec) * max) / XSEC_PER_SEC)
 	usec = SCALE_XSEC(usec, 1000000);
 
 	tv->tv_sec = sec;
@@ -254,6 +256,7 @@ void do_gettimeofday(struct timeval *tv)
 }
 
 EXPORT_SYMBOL(do_gettimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
 
 /*
  * There are two copies of tb_to_xs and stamp_xsec so that no
diff -rup -x CVS 2.6.16-rt17/include/asm-generic/bug.h rt-powerpc/include/asm-generic/bug.h
--- 2.6.16-rt17/include/asm-generic/bug.h	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/include/asm-generic/bug.h	2006-06-08 17:18:06.000000000 +0900
@@ -16,7 +16,9 @@
 #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #endif
 
+#ifndef __ASSEMBLY__
 extern void __WARN_ON(const char *func, const char *file, const int line);
+#endif /* __ASSEMBLY__ */
 
 #ifndef HAVE_ARCH_WARN_ON
 #define WARN_ON(condition) do { \
diff -rup -x CVS 2.6.16-rt17/include/asm-powerpc/hardirq.h rt-powerpc/include/asm-powerpc/hardirq.h
--- 2.6.16-rt17/include/asm-powerpc/hardirq.h	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/include/asm-powerpc/hardirq.h	2006-06-08 17:18:42.000000000 +0900
@@ -11,7 +11,7 @@
  * for uniformity.
  */
 typedef struct {
-	unsigned int __softirq_pending;	/* set_bit is used on this */
+	unsigned int __softirq_pending;	/* set_bit is not used on this */
 	unsigned int __last_jiffy_stamp;
 } ____cacheline_aligned irq_cpustat_t;
 
diff -rup -x CVS 2.6.16-rt17/include/asm-powerpc/hw_irq.h rt-powerpc/include/asm-powerpc/hw_irq.h
--- 2.6.16-rt17/include/asm-powerpc/hw_irq.h	2006-04-26 18:24:28.000000000 +0900
+++ rt-powerpc/include/asm-powerpc/hw_irq.h	2006-07-12 13:55:15.000000000 +0900
@@ -11,7 +11,11 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
-extern void timer_interrupt(struct pt_regs *);
+/*
+ * this conflicts w/ the declaration of 'timer_interrupt' in
+ * kernel/time/clockevents.c
+ */
+/* extern void timer_interrupt(struct pt_regs *); */
 
 #ifdef CONFIG_PPC_ISERIES
 
diff -rup -x CVS 2.6.16-rt17/include/asm-powerpc/percpu.h rt-powerpc/include/asm-powerpc/percpu.h
--- 2.6.16-rt17/include/asm-powerpc/percpu.h	2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/include/asm-powerpc/percpu.h	2006-06-08 21:03:28.000000000 +0900
@@ -18,11 +18,23 @@
 /* Separate out the type, so (int[3], foo) works. */
 #define DEFINE_PER_CPU(type, name) \
     __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
+#define DEFINE_PER_CPU_LOCKED(type, name) \
+    __attribute__((__section__(".data.percpu"))) spinlock_t per_cpu_lock__##name##_locked = SPIN_LOCK_UNLOCKED; \
+    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name##_locked
 
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
 
+#define per_cpu_lock(var, cpu) \
+        (*RELOC_HIDE(&per_cpu_lock__##var##_locked, __per_cpu_offset(cpu)))
+#define per_cpu_var_locked(var, cpu) \
+	(*RELOC_HIDE(&per_cpu__##var##_locked, __per_cpu_offset(cpu)))
+#define __get_cpu_lock(var, cpu) \
+	per_cpu_lock(var, cpu)
+#define __get_cpu_var_locked(var, cpu) \
+	per_cpu_var_locked(var, cpu)
+
 /* A macro to avoid #include hell... */
 #define percpu_modcopy(pcpudst, src, size)			\
 do {								\
@@ -39,16 +51,27 @@ extern void setup_per_cpu_areas(void);
 
 #define DEFINE_PER_CPU(type, name) \
     __typeof__(type) per_cpu__##name
+#define DEFINE_PER_CPU_LOCKED(type, name) \
+    spinlock_t per_cpu_lock__##name##_locked = SPIN_LOCK_UNLOCKED; \
+    __typeof__(type) per_cpu__##name##_locked
 
 #define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
+#define per_cpu_var_locked(var, cpu)                   (*((void)(cpu), &per_cpu__##var##_locked))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __get_cpu_lock(var, cpu)                per_cpu_lock__##var##_locked
+#define __get_cpu_var_locked(var, cpu)          per_cpu__##var##_locked
 
 #endif	/* SMP */
 
 #define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
+#define DECLARE_PER_CPU_LOCKED(type, name) \
+    extern spinlock_t per_cpu_lock__##name##_locked; \
+    extern __typeof__(type) per_cpu__##name##_locked
 
 #define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
 #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
+#define EXPORT_PER_CPU_LOCKED_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu_lock__##var##_locked); EXPORT_SYMBOL_GPL(per_cpu__##var##_locked)
+
 
 #else
 #include <asm-generic/percpu.h>
diff -rup -x CVS 2.6.16-rt17/include/asm-powerpc/pmac_feature.h rt-powerpc/include/asm-powerpc/pmac_feature.h
--- 2.6.16-rt17/include/asm-powerpc/pmac_feature.h      2006-03-20 14:53:29.000000000 +0900
+++ rt-powerpc/include/asm-powerpc/pmac_feature.h       2006-05-10 13:52:58.000000000 +0900
@@ -378,7 +378,7 @@ extern struct macio_chip* macio_find(str
  * Those are exported by pmac feature for internal use by arch code
  * only like the platform function callbacks, do not use directly in drivers
  */
-extern spinlock_t feature_lock;
+extern raw_spinlock_t feature_lock;
 extern struct device_node *uninorth_node;
 extern u32 __iomem *uninorth_base;

diff -rup -x CVS 2.6.16-rt17/kernel/time/clockevents.c rt-powerpc/kernel/time/clockevents.c
--- 2.6.16-rt17/kernel/time/clockevents.c	2006-04-26 18:24:29.000000000 +0900
+++ rt-powerpc/kernel/time/clockevents.c	2006-07-12 13:58:28.000000000 +0900
@@ -29,6 +29,8 @@
 #include <linux/percpu.h>
 #include <linux/sysdev.h>
 #include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
 
 #define MAX_CLOCK_EVENTS	4

^ permalink raw reply

* RE: PCI driver on EB8347
From: Liu Dave-r63238 @ 2006-08-11  3:40 UTC (permalink / raw)
  To: rajan rai, Gala Kumar K.-galak; +Cc: linuxppc-embedded
In-Reply-To: <4DA89577C33E194ABEBC978921E858541B8E38@exchange.ingenient.net>


Rajan>        I have written PCI driver which works fine along with
MPC8347 and two PCI
Rajan> card connected in a single PCI bus. When I try to communicate
same PCI card
Rajan> using PCI bridge ( PCI2050B ), Linux does detect PCI card on
Secondary bus=20
Rajan> but same driver doesn't work !!!!

PCI interrupt for secondary bus set up properly?
     =20
Rajan>        Do I need to enable support for second PCI host controller
at kernel level to=20
Rajan>make it work? Or I need to do something else ? I tried compiling
PPC-linux kernel
Rajan> after enabling CONFIG_85xx_PCI2 kernel doesn't compile it gives
me error while=20
Rajan>compiling "arch/ppc/syslib/ppc83xx_setup.c" Kernel version I'm
using is 2.6.13.

Why you enable CONFIG_85xx_PCI2 in kernel? It is for 85xx, but you are
using 8347 processor.

<snip>

Dave

^ permalink raw reply

* [RFC PATCH 3/4] powerpc 2.6.16-rt17: to support CONFIG_MCOUNT
From: Tsutomu OWA @ 2006-08-11  2:17 UTC (permalink / raw)
  To: linux-kernel; +Cc: linuxppc-dev, mingo, tglx
In-Reply-To: <yyilkpwhvwh.wl@forest.swc.toshiba.co.jp>


Please read the previous mail's subject as [RFC PATCH 3/4] powerpc 2.6.16-rt17: to support CONFIG_MCOUNT.

Sorry about that.

thanks.
-- owa
Software Engineering Center, TOSHIBA.

^ permalink raw reply

* Realtime preemption patch on PPC
From: Ben Weintraub @ 2006-08-11  0:55 UTC (permalink / raw)
  To: linuxppc-dev

(Sorry for those of you who see this message twice, it was originally  
posted in the linuxppc-embedded list, but Mark Greer suggested  
posting it here too)

Howdy,

I'm wondering if anyone has had success getting Ingo Molnar's realtime
preemption patch (the one here:
http://people.redhat.com/mingo/realtime-preempt/ ) working on the ppc
arch.

I'm working with patch-2.6.17-rt8 (the latest) and linux-2.6.17.  The
realtime-preempt patch seems to include the generic timeofday patch, but
with no support for the ppc arch, only powerpc, so I've hacked in
support for ppc by basically replicating the powerpc arch-specific stuff
found here:
http://sr71.net/~jstultz/tod/archive/linux-2.6.17-rc3_timekeeping_C2/ 
broken-out/linux-2.6.17-rc3_timeofday-arch-ppc_C2.patch

I can attach my patch if anyone would like, but for all I know it could
be wildly inaccurate.

Anyhow, when I boot on an MPC8555 with my hack, I get an endless stream
of:

BUG: sleeping function called from invalid context init(1) at
arch/powerpc/math-emu/math.c:226
in_atomic():0 [00000000], irqs_disabled():1
Call Trace:
[A0BB3E90] [A000934C] show_stack+0x48/0x194 (unreliable)
[A0BB3EC0] [A001B7DC] __might_sleep+0xe8/0xf4
[A0BB3EE0] [A00136C0] do_mathemu+0x30/0x8c8
[A0BB3F00] [A00036AC] program_check_exception+0x1ac/0x514
[A0BB3F40] [A0002A08] ret_from_except_full+0x0/0x4c

Line 226 in arch/powerpc/math-emu/math.c is part of the do_mathemu()
function, and contains a call to get_user(), which calls
__might_sleep(), causing this problem.

I did find this message in the LKML archives describing a very similar
problem:
http://lkml.org/lkml/2006/2/23/312

And so tried putting a call to local_irq_enable() before the call to
do_mathemu() in program_check_excpetion(), but this causes a hard lockup
with no messages printed when I try to bring up my network interface.  I
assume this means I've done something Very Bad with interrupts by adding
in local_irq_enable() at the wrong spot.  I also tried adding it at the
exact same spot as the patch given by Paul in his reply, but in this
case I still get the endless stream of BUG messages.

Can anyone offer some guidance or advice?

Thanks so much,
Ben

^ permalink raw reply

* Re: Realtime preemption patch on PPC
From: Lee Revell @ 2006-08-11  1:38 UTC (permalink / raw)
  To: Ben Weintraub; +Cc: linuxppc-embedded
In-Reply-To: <1155251072.5950.80.camel@localhost>

On Thu, 2006-08-10 at 16:04 -0700, Ben Weintraub wrote:
> Howdy,
> 
> I'm wondering if anyone has had success getting Ingo Molnar's realtime
> preemption patch (the one here:
> http://people.redhat.com/mingo/realtime-preempt/ ) working on the ppc
> arch.  
> 

This is probably a better question for the -rt people and LKML than this
list.

Lee

^ permalink raw reply

* PCI driver on EB8347
From: rajan rai @ 2006-08-11  0:49 UTC (permalink / raw)
  To: kumar.gala; +Cc: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 2322 bytes --]



        I have written PCI driver which works fine along with MPC8347 and two PCI card connected in a single PCI bus. When I try to communicate same PCI card using PCI bridge ( PCI2050B ), Linux does detect PCI card on Secondary bus but same driver doesn't work !!!!
       
                 Do I need to enable support for second PCI host controller at kernel level to make it work? Or I need to do something else ? I tried compiling PPC-linux kernel after enabling CONFIG_85xx_PCI2 kernel doesn't compile it gives me error while compiling "arch/ppc/syslib/ppc83xx_setup.c" Kernel version I'm using is 2.6.13.


****** Board along with which PCI card works ************
lspci -v
/demo # lspci -v
00:1b.0 Non-VGA unclassified device: Texas Instruments: Unknown device 9065 (rev 01)
        Flags: bus master, medium devsel, latency 128, IRQ 21
        Memory at 9fc00000 (32-bit, prefetchable) [size=4M]
        Memory at 9f000000 (32-bit, non-prefetchable) [size=8M]
        I/O ports at 3ffffff0 [size=16]
        Capabilities: [40] Power Management version 2

00:1c.0 Non-VGA unclassified device: Texas Instruments: Unknown device 9065 (rev 01)
        Flags: bus master, medium devsel, latency 128, IRQ 18
        Memory at 9ec00000 (32-bit, prefetchable) [size=4M]
        Memory at 9e000000 (32-bit, non-prefetchable) [size=8M]
        I/O ports at 3fffffe0 [size=16]
        Capabilities: [40] Power Management version 2


****** Board along with which PCI card doesn't work ************
lspci -v
PCI devices found:
  Bus  0, device  17, function  0:
    Class 0604: PCI device 104c:ac28 (rev 2).
  Bus  1, device   1, function  0:
    Class 0000: PCI device 104c:9065 (rev 1).
      Master Capable.  Latency=128.
      Prefetchable 32 bit memory at 0x9fc00000 [0x9fffffff].
      Non-prefetchable 32 bit memory at 0x9f000000 [0x9f7fffff].
      I/O at 0xfff0 [0xffff].
  Bus  1, device   2, function  0:
    Class 0000: PCI device 104c:9065 (rev 1).
      Master Capable.  Latency=128.
      Prefetchable 32 bit memory at 0x9ec00000 [0x9effffff].
      Non-prefetchable 32 bit memory at 0x9e000000 [0x9e7fffff].
      I/O at 0xffe0 [0xffef].

                     Any help would be appreciated I'm running out of ideas what to do next !!!!!!!!

Regards,
-Rajan Rai

[-- Attachment #2: Type: text/html, Size: 3795 bytes --]

^ permalink raw reply

* Problem with SCC uart in UART mode on mpc8270 w/ Linux-2.6.17.6
From: Vipin.Malik @ 2006-08-11  0:55 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

I'm trying to use the SCC1 in uart mode on a MPC8270 under 2.6.17.4 from
kernel.org

I've turned on all SCC uarts and I can send and rx data but have an
issue:
The first time I open the port (ttyCPM2) by "cat /dev/ttyCPM2" and "cat
>/dev/ttyCPM2"
I can tx and rx fine.

The problem occurs when I close the first cat session and open it again.

This time, my TX has some sort of threshold in it. It seems that only
after a few 10's of bytes have been sent to the port (the fifo size?
Need to
check) does the scc actually send the data. After that it's all ok.

However, my rx never works after the 1st port open.

Console is on SMC1 and works fine all the time.

I'm using non-platform mode (whatever I tried to do in platform mode, my
SMC1 console stopped working/board stopped working. I would not get any
output after u-boot starts the kernel- not even the Linux version
string).

Any ideas?

TIA

Vipin
P.S. I had to hack the compat code to get the BRG's wired properly for
the SCC's, but the SCC works the 1st time and tx works (besides the
threshold
 issue)- so I don't think that is the cause.

I also tried to get platform code working, but not luck. Is there any
 document or email anywhere I can read that explains that setup?

^ permalink raw reply

* Re: [PATCH 3/6] ehea: queue management
From: Michael Neuling @ 2006-08-11  0:46 UTC (permalink / raw)
  To: Alexey Dobriyan
  Cc: Thomas Klein, netdev, linux-kernel, Christoph Raisch,
	linuxppc-dev, Marcus Eder
In-Reply-To: <20060811003204.GA6935@martell.zuzino.mipt.ru>

> > > +static inline u32 map_swqe_size(u8 swqe_enc_size)
> > > +{
> > > +	return 128 << swqe_enc_size;
> > > +}		      ^
> > > +		      |
> > > +static inline u32|map_rwqe_size(u8 rwqe_enc_size)
> > > +{		      |
> > > +	return 128 << rwqe_enc_size;
> 		      ^
> > > +}		      |
> >		      |
> > Snap!  These are ide|tical...
> 		      |
> No, they aren't. -----+

Functionally identical.

Mikey

^ permalink raw reply

* Re: [PATCH 3/6] ehea: queue management
From: Alexey Dobriyan @ 2006-08-11  0:32 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Thomas Klein, netdev, linux-kernel, Christoph Raisch,
	linuxppc-dev, Marcus Eder
In-Reply-To: <20060811000540.200CE67B6B@ozlabs.org>

> > +static inline u32 map_swqe_size(u8 swqe_enc_size)
> > +{
> > +	return 128 << swqe_enc_size;
> > +}		      ^
> > +		      |
> > +static inline u32|map_rwqe_size(u8 rwqe_enc_size)
> > +{		      |
> > +	return 128 << rwqe_enc_size;
		      ^
> > +}		      |
>		      |
> Snap!  These are ide|tical...
		      |
No, they aren't. -----+

> Name the function after what it does, not after the functions you expect
> to call it.

^ permalink raw reply

* Re: [PATCH 3/6] ehea: queue management
From: Michael Neuling @ 2006-08-11  0:05 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, netdev, linux-kernel, linux-ppc, Christoph Raisch,
	Marcus Eder
In-Reply-To: <44D99F38.8010306@de.ibm.com>

Please add comments to make the code more readable, especially at the
start of functions/structures to describe what they do.  A large readme
at the start of ehea_main.c which gave an overview of the driver design
would be really useful.

Comments inline below... 

> +static void *ipz_qpageit_get_inc(struct ipz_queue *queue)
> +{
> +	void *retvalue = ipz_qeit_get(queue);
> +	queue->current_q_offset += queue->pagesize;
> +	if (queue->current_q_offset > queue->queue_length) {
> +		queue->current_q_offset -= queue->pagesize;
> +		retvalue = NULL;
> +	}
> +	else if ((((u64) retvalue) & (EHEA_PAGESIZE-1)) != 0) {
> +		EDEB(4, "ERROR!! not at PAGE-Boundary");
> +		return NULL;
> +	}
> +	EDEB(7, "queue=%p retvalue=%p", queue, retvalue);

Don't redefine these debugging macros, but if so, what is EDEB?

> +	return retvalue;
> +}
> +
> +static int ipz_queue_ctor(struct ipz_queue *queue,
> +			  const u32 nr_of_pages,
> +			  const u32 pagesize, const u32 qe_size,
> +			  const u32 nr_of_sg)
> +{
> +	int f;
> +	EDEB_EN(7, "nr_of_pages=%x pagesize=%x qe_size=%x",
> +		nr_of_pages, pagesize, qe_size);
> +	queue->queue_length = nr_of_pages * pagesize;
> +	queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *));

> +	if (!queue->queue_pages) {
> +		EDEB(4, "ERROR!! didn't get the memory");
> +		return 0;
> +	}
> +	memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *));
> +
> +	for (f = 0; f < nr_of_pages; f++) {
> +		(queue->queue_pages)[f] =
> +		    (struct ipz_page *)get_zeroed_page(GFP_KERNEL);
> +		if (!(queue->queue_pages)[f]) {
> +			break;
> +		}
> +	}
> +	if (f < nr_of_pages) {
> +		int g;
> +		EDEB_ERR(4, "couldn't get 0ed pages queue=%p f=%x "
> +			 "nr_of_pages=%x", queue, f, nr_of_pages);
> +		for (g = 0; g < f; g++) {
> +			free_page((unsigned long)(queue->queue_pages)[g]);
> +		}
> +		return 0;

If you return here when calling from ehea_create_eq, I think you are
leaking the queue->queue_pages allocation (the pages they point to are
freed correctly).

Either way these allocations/deallocations seem too complicated.  Can
you write to dtor so it can be called to free the structure in any state?

> +	}
> +	queue->current_q_offset = 0;
> +	queue->qe_size = qe_size;
> +	queue->act_nr_of_sg = nr_of_sg;
> +	queue->pagesize = pagesize;
> +	queue->toggle_state = 1;
> +	EDEB_EX(7, "queue_length=%x queue_pages=%p qe_size=%x"
> +		" act_nr_of_sg=%x", queue->queue_length, queue->queue_pages,
> +		queue->qe_size, queue->act_nr_of_sg);
> +	return 1;
> +}
> +
> +static int ipz_queue_dtor(struct ipz_queue *queue)
> +{
> +	int g;
> +	EDEB_EN(7, "ipz_queue pointer=%p", queue);
> +	if (!queue) {
> +		return 0;
> +	}
> +	if (!queue->queue_pages) {
> +		return 0;
> +	}

if (!queue || !queue->queue_pages) 
      return 0;

> +	EDEB(7, "destructing a queue with the following properties:\n"
> +	     "queue_length=%x act_nr_of_sg=%x pagesize=%x qe_size=%x",
> +	     queue->queue_length, queue->act_nr_of_sg, queue->pagesize,
> +	     queue->qe_size);
> +	for (g = 0; g < (queue->queue_length / queue->pagesize); g++) {
> +		free_page((unsigned long)(queue->queue_pages)[g]);
> +	}
> +	vfree(queue->queue_pages);
> +
> +	EDEB_EX(7, "queue freed!");
> +	return 1;
> +}
> +
> +struct ehea_cq *ehea_cq_new(void)
> +{
> +	struct ehea_cq *cq = vmalloc(sizeof(*cq));
> +	if (cq)
> +		memset(cq, 0, sizeof(*cq));
> +	return cq;
> +}
> +
> +void ehea_cq_delete(struct ehea_cq *cq)
> +{
> +	vfree(cq);
> +}

This is used in only two places.  Do we need it?  

If we do... can we static inline?

> +struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
> +			       int nr_of_cqe, u64 eq_handle, u32 cq_token)
> +{
> +	struct ehea_cq *cq = NULL;
> +	struct h_galpa gal;
> +
> +	u64 *cq_handle_ref;
> +	u32 act_nr_of_entries;
> +	u32 act_pages;
> +	u64 hret = H_HARDWARE;
> +	int ipz_rc;
> +	u32 counter;
> +	void *vpage = NULL;
> +	u64 rpage = 0;
> +
> +	EDEB_EN(7, "adapter=%p nr_of_cqe=%x , eq_handle: %016lX",
> +		adapter, nr_of_cqe, eq_handle);
> +
> +	cq = ehea_cq_new();
> +	if (!cq) {
> +		cq = NULL;
> +		EDEB_ERR(4, "ehea_create_cq ret=%p (-ENOMEM)", cq);
> +		goto create_cq_exit0;
> +	}
> +
> +	cq->attr.max_nr_of_cqes = nr_of_cqe;
> +	cq->attr.cq_token = cq_token;
> +	cq->attr.eq_handle = eq_handle;
> +
> +	cq->adapter = adapter;
> +
> +	cq_handle_ref = &cq->ipz_cq_handle;
> +	act_nr_of_entries = 0;
> +	act_pages = 0;
> +
> +	hret = ehea_h_alloc_resource_cq(adapter->handle,
> +					cq,
> +					&cq->attr,
> +					&cq->ipz_cq_handle, &cq->galpas);

hret set twice...



> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "ehea_h_alloc_resource_cq failed. hret=%lx", hret);
> +		goto create_cq_exit1;
> +	}
> +
> +	ipz_rc = ipz_queue_ctor(&cq->ipz_queue, cq->attr.nr_pages,
> +				EHEA_PAGESIZE, sizeof(struct ehea_cqe), 0);
> +	if (!ipz_rc)
> +		goto create_cq_exit2;
> +
> +	hret = H_SUCCESS;
> +
> +	for (counter = 0; counter < cq->attr.nr_pages; counter++) {
> +		vpage = ipz_qpageit_get_inc(&cq->ipz_queue);

vpga set twice...

> +		if (!vpage) {
> +			EDEB_ERR(4, "ipz_qpageit_get_inc() "
> +				 "returns NULL adapter=%p", adapter);
> +			goto create_cq_exit3;
> +		}
> +
> +		rpage = virt_to_abs(vpage);
> +
> +		hret = ehea_h_register_rpage_cq(adapter->handle,
> +						cq->ipz_cq_handle,
> +						0,
> +						HIPZ_CQ_REGISTER_ORIG,
> +						rpage, 1, cq->galpas.kernel);
> +
> +		if (hret < H_SUCCESS) {
> +			EDEB_ERR(4, "ehea_h_register_rpage_cq() failed "
> +				 "ehea_cq=%p hret=%lx "
> +				 "counter=%i act_pages=%i",
> +				 cq, hret, counter, cq->attr.nr_pages);
> +			goto create_cq_exit3;
> +		}
> +
> +		if (counter == (cq->attr.nr_pages - 1)) {
> +			vpage = ipz_qpageit_get_inc(&cq->ipz_queue);
> +
> +			if ((hret != H_SUCCESS) || (vpage)) {
> +				EDEB_ERR(4, "Registration of pages not "
> +					 "complete ehea_cq=%p hret=%lx",
> +					 cq, hret)
> +				goto create_cq_exit3;
> +			}
> +		} else {
> +			if ((hret != H_PAGE_REGISTERED) || (vpage == 0)) {
> +				EDEB_ERR(4, "Registration of page failed "
> +					 "ehea_cq=%p hret=%lx"
> +					 "counter=%i act_pages=%i",
> +					 cq, hret, counter, cq->attr.nr_pages);
> +				goto create_cq_exit3;
> +			}
> +		}
> +	}
> +
> +	ipz_qeit_reset(&cq->ipz_queue);
> +	gal = cq->galpas.kernel;
> +	ehea_reset_cq_ep(cq);
> +	ehea_reset_cq_n1(cq);
> +
> +	EDEB_EX(7, "ret=%p ", cq);
> +	return cq;
> +
> +create_cq_exit3:
> +	ipz_queue_dtor(&cq->ipz_queue);
> +
> +create_cq_exit2:
> +	hret = ehea_h_destroy_cq(adapter->handle, cq, cq->ipz_cq_handle,
> +				 &cq->galpas);
> +	EDEB(7, "return code of ehea_cq_destroy=%lx", hret);
> +
> +create_cq_exit1:
> +	ehea_cq_delete(cq);
> +
> +create_cq_exit0:
> +	EDEB_EX(7, "ret=NULL");
> +	return NULL;
> +}
> +
> +int ehea_destroy_cq(struct ehea_cq *cq)
> +{
> +	int ret = 0;
> +	u64 adapter_handle;
> +	u64 hret = H_HARDWARE;
> +
> +	adapter_handle = cq->adapter->handle;
> +	EDEB_EN(7, "adapter=%p cq=%p", cq->adapter, cq);
> +
> +	/* deregister all previous registered pages */
> +	hret = ehea_h_destroy_cq(adapter_handle, cq, cq->ipz_cq_handle,
> +				 &cq->galpas);
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "destroy CQ failed!");
> +		return -EINVAL;
> +	}
> +	ipz_queue_dtor(&cq->ipz_queue);
> +	ehea_cq_delete(cq);
> +
> +	EDEB_EX(7, "ret=%x ", ret);
> +	return ret;
> +}
> +
> +struct ehea_eq *ehea_eq_new(void)
> +{
> +	struct ehea_eq *eq = vmalloc(sizeof(*eq));
> +	if (eq)
> +		memset(eq, 0, sizeof(*eq));
> +	return eq;
> +}
> +
> +void ehea_eq_delete(struct ehea_eq *eq)
> +{
> +	vfree(eq);
> +}

Again, is this really needed and what about static inline?

> +struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
> +			       const enum ehea_eq_type type,
> +			       const u32 max_nr_of_eqes, const u8 eqe_gen)
> +{
> +	u64 hret = H_HARDWARE;
> +	int ret = 0;
> +	u32 i;
> +	void *vpage = NULL;
> +	struct ehea_eq *eq;
> +
> +	EDEB_EN(7, "adapter=%p, max_nr_of_eqes=%x", adapter, max_nr_of_eqes);
> +
> +	eq = ehea_eq_new();
> +	if (!eq)
> +		return NULL;
> +
> +	eq->adapter = adapter;
> +	eq->attr.type = type;
> +	eq->attr.max_nr_of_eqes = max_nr_of_eqes;
> +	eq->attr.eqe_gen = eqe_gen;
> +	spin_lock_init(&eq->spinlock);
> +
> +	hret = ehea_h_alloc_resource_eq(adapter->handle,
> +					eq, &eq->attr, &eq->ipz_eq_handle);
> +
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "ehea_h_alloc_resource_eq failed. hret=%lx", hret);
> +		goto free_eq_mem;
> +	}
> +
> +	ret = ipz_queue_ctor(&eq->ipz_queue, eq->attr.nr_pages,
> +			      EHEA_PAGESIZE, sizeof(struct ehea_eqe), 0);
> +	if (!ret) {
> +		EDEB_ERR(4, "can't allocate EQ pages");
> +		goto alloc_pages_failed;
> +	}
> +
> +	for (i = 0; i < eq->attr.nr_pages; i++) {
> +		u64 rpage;
> +
> +		if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) {
> +			hret = H_RESOURCE;
> +			goto register_page_failed;
> +		}
> +
> +		rpage = virt_to_abs(vpage);
> +
> +		hret = ehea_h_register_rpage_eq(adapter->handle,
> +						eq->ipz_eq_handle,
> +						0,
> +						HIPZ_EQ_REGISTER_ORIG,
> +						rpage, 1);
> +
> +		if (i == (eq->attr.nr_pages - 1)) {
> +			/* last page */
> +			vpage = ipz_qpageit_get_inc(&eq->ipz_queue);
> +			if ((hret != H_SUCCESS) || (vpage)) {
> +				goto register_page_failed;
> +			}
> +		} else {
> +			if ((hret != H_PAGE_REGISTERED) || (!vpage)) {
> +				goto register_page_failed;
> +			}
> +		}
> +	}
> +
> +	ipz_qeit_reset(&eq->ipz_queue);
> +
> +	EDEB_EX(7, "hret=%lx", hret);
> +	return eq;
> +
> +register_page_failed:
> +	ipz_queue_dtor(&eq->ipz_queue);
> +
> +alloc_pages_failed:
> +	ehea_h_destroy_eq(adapter->handle, eq, eq->ipz_eq_handle, &eq->galpas);
> +free_eq_mem:
> +	ehea_eq_delete(eq);
> +
> +	EDEB_EX(7, "return with error hret=%lx", hret);
> +	return NULL;
> +}
> +
> +void *ehea_poll_eq(struct ehea_eq *eq)
> +{
> +	void *eqe = NULL;
> +	unsigned long flags = 0;
> +
> +	EDEB_EN(7, "adapter=%p  eq=%p", eq->adapter, eq);
> +
> +	spin_lock_irqsave(&eq->spinlock, flags);
> +	eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue);
> +	spin_unlock_irqrestore(&eq->spinlock, flags);
> +
> +	EDEB_EX(7, "eqe=%p", eqe);
> +
> +	return eqe;
> +}
> +
> +int ehea_destroy_eq(struct ehea_eq *eq)
> +{
> +	unsigned long flags = 0;
> +	u64 hret = H_HARDWARE;
> +
> +	EDEB_EN(7, "adapter=%p  eq=%p", eq->adapter, eq);
> +
> +	spin_lock_irqsave(&eq->spinlock, flags);
> +
> +	hret = ehea_h_destroy_eq(eq->adapter->handle, eq, eq->ipz_eq_handle,
> +				 &eq->galpas);
> +	spin_unlock_irqrestore(&eq->spinlock, flags);
> +
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "Failed freeing EQ resources. hret=%lx", hret);
> +		return -EINVAL;
> +	}
> +	ipz_queue_dtor(&eq->ipz_queue);
> +	ehea_eq_delete(eq);
> +	EDEB_EX(7, "");
> +
> +	return 0;
> +}
> +
> +struct ehea_qp *ehea_qp_new(void) {
> +	struct ehea_qp *qp = vmalloc(sizeof(*qp));
> +	if (qp != 0) {

if (qp) ??

> +		memset(qp, 0, sizeof(*qp));
> +	}
> +	return qp;
> +}
> +
> +void ehea_qp_delete(struct ehea_qp *qp)
> +{
> +	vfree(qp);
> +}
> +
> +/**
> + * allocates memory for a queue and registers pages in phyp
> + */
> +int ehea_qp_alloc_register(struct ehea_qp *qp,
> +			   struct ipz_queue *ipz_queue,
> +			   int nr_pages,
> +			   int wqe_size,
> +			   int act_nr_sges,
> +			   struct ehea_adapter *adapter, int h_call_q_selector)
> +{
> +	u64 hret = H_HARDWARE;
> +	u64 rpage = 0;
> +	int iret = 0;
> +	int cnt = 0;
> +	void *vpage = NULL;
> +
> +	iret = ipz_queue_ctor(ipz_queue,
> +			      nr_pages, EHEA_PAGESIZE, wqe_size, act_nr_sges);
> +	if (!iret) {
> +		EDEB_ERR(4, "Cannot allocate page for queue. iret=%x", iret);
> +		return -ENOMEM;
> +	}
> +
> +	EDEB(7, "queue_size=%x, alloc_len=%x, toggle_state=%d",
> +	     ipz_queue->qe_size,
> +	     ipz_queue->queue_length, ipz_queue->toggle_state);
> +
> +	for (cnt = 0; cnt < nr_pages; cnt++) {
> +		vpage = ipz_qpageit_get_inc(ipz_queue);
> +		if (!vpage) {
> +			EDEB_ERR(4, "SQ ipz_qpageit_get_inc() "
> +				 "failed p_vpage= %p", vpage);
> +			goto qp_alloc_register_exit0;
> +		}
> +		rpage = virt_to_abs(vpage);
> +
> +		hret = ehea_h_register_rpage_qp(adapter->handle,
> +						qp->ipz_qp_handle,
> +						0,
> +						h_call_q_selector,
> +						rpage,
> +						1, qp->galpas.kernel);
> +
> +		if (hret < H_SUCCESS) {
> +			EDEB_ERR(4, "ehea_h_register_rpage_qp failed. hret=%lx"
,
> +				 hret);
> +			goto qp_alloc_register_exit0;
> +		}
> +	}
> +	ipz_qeit_reset(ipz_queue);
> +
> +	return 0;
> +
> +qp_alloc_register_exit0:
> +	ipz_queue_dtor(ipz_queue);
> +	return -EINVAL;
> +}
> +
> +static inline u32 map_swqe_size(u8 swqe_enc_size)
> +{
> +	return 128 << swqe_enc_size;
> +}
> +
> +static inline u32 map_rwqe_size(u8 rwqe_enc_size)
> +{
> +	return 128 << rwqe_enc_size;
> +}

Snap!  These are identical...

Name the function after what it does, not after the functions you expect
to call it.  

> +
> +struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter,
> +			       u32 pd, struct ehea_qp_init_attr *init_attr)
> +{
> +	struct ehea_qp *qp;
> +	u64 hret = H_HARDWARE;
> +
> +	u32 wqe_size_in_bytes_sq = 0;
> +	u32 wqe_size_in_bytes_rq1 = 0;
> +	u32 wqe_size_in_bytes_rq2 = 0;
> +	u32 wqe_size_in_bytes_rq3 = 0;
> +
> +	int ret = -1;
> +
> +	EDEB_EN(7, "init_attr=%p", init_attr);
> +
> +	qp = ehea_qp_new();
> +
> +	if (!qp) {
> +		EDEB_ERR(4, "pd=%X not enough memory to alloc qp", pd);
> +		return NULL;
> +	}
> +	qp->adapter = adapter;
> +
> +	EDEB(7, "send_ehea_cq->ipz_cq_handle=0x%lX"
> +	     "recv_ehea_cq->ipz_cq_handle=0x%lX", init_attr->send_cq_handle,
> +	     init_attr->recv_cq_handle);
> +
> +
> +	hret = ehea_h_alloc_resource_qp(adapter->handle, qp,
> +					init_attr,
> +					pd,
> +					&qp->ipz_qp_handle,
> +					&qp->galpas);
> +
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "ehea_h_alloc_resource_qp failed. hret=%lx", hret);
> +		goto create_qp_exit1;
> +	}
> +
> +	wqe_size_in_bytes_sq = map_swqe_size(init_attr->act_wqe_size_enc_sq);
> +	EDEB(7, "SWQE SG %d", init_attr->wqe_size_enc_sq);
> +
> +	wqe_size_in_bytes_rq1 = map_rwqe_size(init_attr->act_wqe_size_enc_rq1);
> +	wqe_size_in_bytes_rq2 = map_rwqe_size(init_attr->act_wqe_size_enc_rq2);
> +	wqe_size_in_bytes_rq3 = map_rwqe_size(init_attr->act_wqe_size_enc_rq3);
> +
> +	EDEB(7, "SQ pages: %d, SQ WQE size:%d, max SWQE size enc: %d",
> +	     init_attr->nr_sq_pages,
> +	     wqe_size_in_bytes_sq, init_attr->act_wqe_size_enc_sq);
> +
> +	EDEB(7, "RQ1 pages: %d, RQ1 WQE size:%d, max RWQE size enc: %d",
> +	     init_attr->nr_rq1_pages,
> +	     wqe_size_in_bytes_rq1, init_attr->act_wqe_size_enc_rq1);
> +
> +	EDEB(7, "RQ2 pages: %d, RQ2 WQE size:%d, max RWQE size enc: %d",
> +	     init_attr->nr_rq2_pages,
> +	     wqe_size_in_bytes_rq2, init_attr->act_wqe_size_enc_rq2);
> +
> +	EDEB(7, "RQ3 pages: %d, RQ3 WQE size:%d, max RWQE size enc: %d",
> +	     init_attr->nr_rq3_pages,
> +	     wqe_size_in_bytes_rq3, init_attr->act_wqe_size_enc_rq3);
> +
> +	ret = ehea_qp_alloc_register(qp,
> +				     &qp->ipz_squeue,
> +				     init_attr->nr_sq_pages,
> +				     wqe_size_in_bytes_sq,
> +				     init_attr->act_wqe_size_enc_sq, adapter,
> +				     0);
> +	if (ret < H_SUCCESS) {
> +		EDEB_ERR(4, "can't register for sq hret=%x", ret);
> +		goto create_qp_exit2;
> +	}
> +
> +	ret = ehea_qp_alloc_register(qp,
> +				     &qp->ipz_rqueue1,
> +				     init_attr->nr_rq1_pages,
> +				     wqe_size_in_bytes_rq1,
> +				     init_attr->act_wqe_size_enc_rq1,
> +				     adapter, 1);
> +
> +	if (ret < 0) {
> +		EDEB_ERR(4, "can't register for rq1 hret=%x", ret);
> +		goto create_qp_exit3;
> +	}
> +
> +	if (init_attr->rq_count > 1) {
> +		ret = ehea_qp_alloc_register(qp,
> +					     &qp->ipz_rqueue2,
> +					     init_attr->nr_rq2_pages,
> +					     wqe_size_in_bytes_rq2,
> +					     init_attr->act_wqe_size_enc_rq2,
> +					     adapter, 2);
> +
> +		if (ret < 0) {
> +			EDEB_ERR(4, "can't register for rq2 hret=%x", ret);
> +			goto create_qp_exit4;
> +		}
> +	}
> +
> +	if (init_attr->rq_count > 2) {
> +		ret = ehea_qp_alloc_register(qp,
> +					     &qp->ipz_rqueue3,
> +					     init_attr->nr_rq3_pages,
> +					     wqe_size_in_bytes_rq3,
> +					     init_attr->act_wqe_size_enc_rq3,
> +					     adapter, 3);
> +
> +		if (ret != 0) {
> +			EDEB_ERR(4, "can't register for rq3 hret=%x", ret);
> +			goto create_qp_exit5;
> +		}
> +	}
> +
> +	qp->init_attr = *init_attr;
> +
> +	EDEB_EX(7, "");
> +	return qp;
> +
> +create_qp_exit5:
> +	ipz_queue_dtor(&qp->ipz_rqueue2);
> +
> +create_qp_exit4:
> +	ipz_queue_dtor(&qp->ipz_rqueue1);
> +
> +create_qp_exit3:
> +	ipz_queue_dtor(&qp->ipz_squeue);
> +
> +create_qp_exit2:
> +	hret = ehea_h_destroy_qp(adapter->handle, qp, qp->ipz_qp_handle,
> +				 &qp->galpas);
> +
> +create_qp_exit1:
> +	ehea_qp_delete(qp);
> +
> +	EDEB_EX(7, "hret=NULL");
> +	return NULL;
> +
> +}
> +
> +int ehea_destroy_qp(struct ehea_qp *qp)
> +{
> +	int ret = 0;
> +	u64 hret = H_HARDWARE;
> +	struct ehea_qp_init_attr *qp_attr = &qp->init_attr;
> +	EDEB_EX(7, "");
> +
> +	hret = ehea_h_destroy_qp(qp->adapter->handle, qp, qp->ipz_qp_handle,
> +				 &qp->galpas);
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "destroy QP failed!");
> +		ret = -EINVAL;
> +	}
> +
> +	ipz_queue_dtor(&qp->ipz_squeue);
> +	ipz_queue_dtor(&qp->ipz_rqueue1);
> +
> +   	if(qp_attr->rq_count > 1)
> +		ipz_queue_dtor(&qp->ipz_rqueue2);
> +   	if(qp_attr->rq_count > 2)
> +		ipz_queue_dtor(&qp->ipz_rqueue3);
> +	ehea_qp_delete(qp);
> +
> +	EDEB_EX(7, "hret=%lx", hret);
> +
> +	return ret;
> +}
> +
> +int ehea_reg_mr_adapter(struct ehea_adapter *adapter)
> +{
> +	int i = 0;
> +	int k = 0;
> +	u64 hret = H_HARDWARE;
> +	u64 start = KERNELBASE;
> +	u64 end = (u64) high_memory;
> +	u64 nr_pages = (end - start) / PAGE_SIZE;
> +	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
> +	u64 pt_abs = 0;
> +	u64 *pt;
> +
> +	EDEB_EN(7, "adapter=%p", adapter);
> +	pt =  kzalloc(PAGE_SIZE, GFP_KERNEL);
> +	if (!pt) {
> +		EDEB_ERR(4, "allocating page failed");
> +		return -EINVAL;
> +	}
> +	pt_abs = virt_to_abs(pt);
> +
> +	hret = ehea_h_alloc_resource_mr(adapter->handle,
> +					start,
> +					end - start,
> +					acc_ctrl,
> +					adapter->pd,
> +					&adapter->mr.handle,
> +					&adapter->mr.lkey);
> +	if (hret != H_SUCCESS) {
> +		EDEB_EX(4, "Error: hret=%lX\n", hret);
> +		return -EINVAL;
> +	}
> +
> +	adapter->mr.vaddr = KERNELBASE;
> +
> +	while (nr_pages > 0) {
> +		if (nr_pages > 1) {
> +			u64 num_pages = min(nr_pages, (u64)512);
> +			for (i = 0; i < num_pages; i++)
> +				pt[i] = virt_to_abs((void *)(((u64)start)
> +							     + ((k++) *
> +								PAGE_SIZE)));
> +
> +			hret = ehea_h_register_rpage_mr(adapter->handle,
> +							adapter->mr.handle,
> +							0,
> +							0,
> +							(u64)pt_abs,
> +							num_pages);

They probably don't all need their own line.

> +			nr_pages -= num_pages;
> +		} else {
> +			u64 abs_adr = virt_to_abs((void *)(((u64)start)
> +							   + (k * PAGE_SIZE)));
> +			hret = ehea_h_register_rpage_mr(adapter->handle,
> +							adapter->mr.handle,
> +							0,
> +							0,
> +							abs_adr,
> +							1);

Ditto.

> +			nr_pages--;
> +		}
> +
> +		if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) {
> +			ehea_h_free_resource_mr(adapter->handle,
> +						adapter->mr.handle);
> +			EDEB_EX(4, " register rpage_mr: hret=%lX\n", hret);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	if (hret != H_SUCCESS) {
> +		ehea_h_free_resource_mr(adapter->handle, adapter->mr.handle);
> +		EDEB_EX(4, " register rpage_mr failed for last page: hret=%lX",
> +			hret);
> +		return -EINVAL;
> +	}
> +
> +	EDEB_EX(7, "lkey=0x%X, mr_handle=0x%lX", adapter->mr.lkey,
> +		adapter->mr.handle);
> +	return 0;
> +}
> +
> +int ehea_reg_mr_pages(struct ehea_adapter *adapter,
> +		      struct ehea_mr *mr,
> +		      u64 start, u64 *pt, int nr_pages)
> +{
> +	u64 hret = H_HARDWARE;
> +	u32 acc_ctrl = EHEA_MR_ACC_CTRL;
> +
> +	u64 pt_abs = virt_to_abs(pt);
> +	u64 first_page = pt[0];
> +
> +	hret = ehea_h_alloc_resource_mr(adapter->handle,
> +					start,
> +					PAGE_SIZE * nr_pages,
> +					acc_ctrl,
> +					adapter->pd,
> +					&mr->handle,
> +					&mr->lkey);
> +	if (hret != H_SUCCESS) {
> +		EDEB_EX(4, "Error: hret=%lX\n", hret);
> +		return -EINVAL;
> +	}
> +
> +	if (nr_pages > 1)
> +		hret = ehea_h_register_rpage_mr(adapter->handle,
> +						mr->handle,
> +						0,
> +						0,
> +						(u64)pt_abs,
> +						nr_pages);
> +	else
> +		hret = ehea_h_register_rpage_mr(adapter->handle,
> +						mr->handle,
> +						0,
> +						0,
> +						first_page,
> +						1);

hret = ehea_h_register_rpage_mr(adapter->handle, mr->handle, 0,
				0, (nr_pages > 1)?(u64)pt_abs:first_page,
				nr_pages);
Simpler?

Or get ehea_h_register_rpage_mr to do this for you?  You seem to do this
same decode twice?


> +
> +	if (hret != H_SUCCESS) {
> +		ehea_h_free_resource_mr(adapter->handle, mr->handle);
> +		EDEB_EX(4, " register rpage_mr failed for last page:"
> +			"hret=%lX\n", hret);
> +		return -EINVAL;
> +	}
> +	mr->vaddr = start;
> +
> +	EDEB_EX(7, "");
> +	return 0;
> +}
> +
> +
> +
> +int ehea_dereg_mr_adapter(struct ehea_adapter *adapter)
> +{
> +	u64 hret = H_HARDWARE;
> +	EDEB_EN(7, "adapter=%p", adapter);
> +	hret = ehea_h_free_resource_mr(adapter->handle, adapter->mr.handle);
> +	if (hret != H_SUCCESS) {
> +		EDEB_EX(4, "deregistering memory region failed");
> +		return -EINVAL;
> +	}
> +	EDEB_EX(7, "");
> +	return 0;
> +}
> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea_qmr.h	1969-12-31 16:00:00.000
000000 -0800
> +++ kernel/drivers/net/ehea/ehea_qmr.h	2006-08-08 23:59:38.108463416 -
0700
> @@ -0,0 +1,381 @@
> +/*
> + *  linux/drivers/net/ehea/ehea_qmr.h
> + *
> + *  eHEA ethernet device driver for IBM eServer System p
> + *
> + *  (C) Copyright IBM Corp. 2006
> + *
> + *  Authors:
> + *       Christoph Raisch <raisch@de.ibm.com>
> + *       Jan-Bernd Themann <themann@de.ibm.com>
> + *       Heiko-Joerg Schick <schickhj@de.ibm.com>
> + *       Thomas Klein <tklein@de.ibm.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2, or (at your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#ifndef __EHEA_QMR_H__
> +#define __EHEA_QMR_H__
> +
> +#include "ehea.h"
> +#include "ehea_hw.h"
> +
> +/* Use of WR_ID field for EHEA */
> +#define EHEA_WR_ID_COUNT   EHEA_BMASK_IBM(0, 19)
> +#define EHEA_WR_ID_TYPE    EHEA_BMASK_IBM(20, 23)
> +#define EHEA_SWQE2_TYPE    0x1
> +#define EHEA_SWQE3_TYPE    0x2
> +#define EHEA_RWQE2_TYPE    0x3	/* RQ2  */
> +#define EHEA_RWQE3_TYPE    0x4	/* RQ3  */
> +#define EHEA_WR_ID_INDEX   EHEA_BMASK_IBM(24, 47)
> +#define EHEA_WR_ID_REFILL  EHEA_BMASK_IBM(48, 63)
> +
> +struct ehea_vsgentry {
> +	u64 vaddr;
> +	u32 l_key;
> +	u32 len;
> +};
> +
> +/* maximum number of sg entries allowed in a WQE */
> +#define EHEA_MAX_WQE_SG_ENTRIES  252
> +#define SWQE2_MAX_IMM            (0xD0 - 0x30)	/* (160-14) ? */
> +#define SWQE3_MAX_IMM            224
> +
> +/* tx control flags for swqe */
> +#define EHEA_SWQE_CRC                    0x8000
> +#define EHEA_SWQE_IP_CHECKSUM            0x4000
> +#define EHEA_SWQE_TCP_CHECKSUM           0x2000
> +#define EHEA_SWQE_TSO                    0x1000
> +#define EHEA_SWQE_SIGNALLED_COMPLETION   0x0800
> +#define EHEA_SWQE_VLAN_INSERT            0x0400
> +#define EHEA_SWQE_IMM_DATA_PRESENT 	 0x0200
> +#define EHEA_SWQE_DESCRIPTORS_PRESENT    0x0100
> +#define EHEA_SWQE_WRAP_CTL_REC           0x0080
> +#define EHEA_SWQE_WRAP_CTL_FORCE         0x0040
> +#define EHEA_SWQE_BIND                   0x0020
> +#define EHEA_SWQE_PURGE                  0x0010
> +
> +#define SWQE_HEADER_SIZE 32

This is never used...  

Would be nice to document some of the names here.  What are SWQE, RWQE,
WQE, CQE, IPZ etc?

> +
> +struct ehea_swqe {
> +	u64 wr_id;
> +	u16 tx_control;
> +	u16 vlan_tag;
> +	u8 reserved1;
> +	u8 ip_start;
> +	u8 ip_end;
> +	u8 immediate_data_length;
> +	u8 tcp_offset;
> +	u8 reserved2;
> +	u16 tcp_end;
> +	u8 wrap_tag;
> +	u8 descriptors;		/* number of valid descriptors in WQE */
> +	u16 reserved3;
> +	u16 reserved4;
> +	u16 mss;
> +	u32 reserved5;
> +	union {
> +		/*  Send WQE Format 1 */
> +		struct {
> +			struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES];
> +		} no_immediate_data;
> +
> +		/*  Send WQE Format 2 */
> +		struct {
> +			struct ehea_vsgentry sg_entry;
> +			/* 0x30 */
> +			u8 immediate_data[SWQE2_MAX_IMM];
> +			/* 0xd0 */
> +			struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES-1]
;
> +		} immdata_desc __attribute__ ((packed));
> +
> +		/*  Send WQE Format 3 */
> +		struct {
> +			u8 immediate_data[SWQE3_MAX_IMM];
> +		} immdata_nodesc;
> +	} u;
> +};
> +
> +struct ehea_rwqe {
> +	u64 wr_id;		/* work request ID */
> +	u8 reserved1[5];
> +	u8 data_segments;
> +	u16 reserved2;
> +	u64 reserved3;
> +	u64 reserved4;
> +	struct ehea_vsgentry sg_list[EHEA_MAX_WQE_SG_ENTRIES];
> +};
> +
> +#define EHEA_CQE_VLAN_TAG_XTRACT  0x0400
> +
> +#define EHEA_CQE_TYPE_RQ          0x60
> +#define EHEA_CQE_STAT_ERR_MASK    0x7300
> +#define EHEA_CQE_STAT_ERR_TCP     0x4000
> +
> +struct ehea_cqe {
> +	u64 wr_id;		/* work request ID from WQE */
> +	u8 type;
> +	u8 valid;
> +	u16 status;
> +	u16 reserved1;
> +	u16 num_bytes_transfered;
> +	u16 vlan_tag;
> +	u16 inet_checksum_value;
> +	u8 reserved2;
> +	u8 header_length;
> +	u16 reserved3;
> +	u16 page_offset;
> +	u16 wqe_count;
> +	u32 qp_token;
> +	u32 timestamp;
> +	u32 reserved4;
> +	u64 reserved5[3];
> +};
> +
> +#define EHEA_EQE_VALID           EHEA_BMASK_IBM(0, 0)
> +#define EHEA_EQE_IS_CQE          EHEA_BMASK_IBM(1, 1)
> +#define EHEA_EQE_IDENTIFIER      EHEA_BMASK_IBM(2, 7)
> +#define EHEA_EQE_QP_CQ_NUMBER    EHEA_BMASK_IBM(8, 31)
> +#define EHEA_EQE_QP_TOKEN        EHEA_BMASK_IBM(32, 63)
> +#define EHEA_EQE_CQ_TOKEN        EHEA_BMASK_IBM(32, 63)
> +#define EHEA_EQE_KEY             EHEA_BMASK_IBM(32, 63)

3 the same here?

> +#define EHEA_EQE_PORT_NUMBER     EHEA_BMASK_IBM(56, 63)
> +#define EHEA_EQE_EQ_NUMBER       EHEA_BMASK_IBM(48, 63)
> +#define EHEA_EQE_SM_ID           EHEA_BMASK_IBM(48, 63)

2 the same here?

> +#define EHEA_EQE_SM_MECH_NUMBER  EHEA_BMASK_IBM(48, 55)
> +#define EHEA_EQE_SM_PORT_NUMBER  EHEA_BMASK_IBM(56, 63)
> +
> +struct ehea_eqe {
> +	u64 entry;
> +};

ehea_ege.. what is that and why a struct if only 1 item?  Comments
please.  

In ehea_main.c you use this with a ehea_poll_eq which returns a void *
Mostly you cast to a (struct ehea_eqe *) but you don't need to.


> +
> +static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset)
> +{
> +	struct ipz_page *current_page = NULL;
> +	if (q_offset >= queue->queue_length)
> +		q_offset -= queue->queue_length;
> +	current_page = (queue->queue_pages)[q_offset >> EHEA_PAGESHIFT];
> +	return &current_page->entries[q_offset & (EHEA_PAGESIZE - 1)];
> +}
> +
> +static inline void *ipz_qeit_get(struct ipz_queue *queue)
> +{
> +	return ipz_qeit_calc(queue, queue->current_q_offset);
> +}
> +
> +static inline void ipz_qeit_inc(struct ipz_queue *queue)
> +{
> +	queue->current_q_offset += queue->qe_size;
> +	if (queue->current_q_offset >= queue->queue_length) {
> +		queue->current_q_offset = 0;
> +		/* toggle the valid flag */
> +		queue->toggle_state = (~queue->toggle_state) & 1;
> +	}
> +}
> +
> +static inline void *ipz_qeit_get_inc(struct ipz_queue *queue)
> +{
> +	void *retvalue = ipz_qeit_get(queue);
> +	ipz_qeit_inc(queue);
> +	EDEB(8, "queue=%p retvalue=%p new current_q_addr=%lx qe_size=%x",
> +	     queue, retvalue, queue->current_q_offset, queue->qe_size);
> +
> +	return retvalue;
> +}
> +
> +static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue)
> +{
> +	struct ehea_cqe *retvalue = ipz_qeit_get(queue);
> +	void *pref;
> +	u8 valid = retvalue->valid;
> +	if ((valid >> 7) == (queue->toggle_state & 1)) {
> +		/* this is a good one */
> +		ipz_qeit_inc(queue);
> +		pref = ipz_qeit_calc(queue, queue->current_q_offset);
> +		prefetch(pref);
> +		prefetch(pref + 128);
> +	} else
> +		retvalue = NULL;
> +	return retvalue;
> +}
> +
> +static inline void *ipz_qeit_get_valid(struct ipz_queue *queue)
> +{
> +	u8 valid = 0;
> +
> +	struct ehea_cqe *retvalue = ipz_qeit_get(queue);
> +	void *pref;
> +	pref = ipz_qeit_calc(queue, queue->current_q_offset);
> +	prefetch(pref);
> +	prefetch(pref + 128);
> +	prefetch(pref + 256);
> +	valid = retvalue->valid;
> +	if (!((valid >> 7) == (queue->toggle_state & 1)))
> +		retvalue = NULL;
> +	return retvalue;
> +}
> +
> +static inline void *ipz_qeit_reset(struct ipz_queue *queue)
> +{
> +	queue->current_q_offset = 0;
> +	return ipz_qeit_get(queue);
> +}
> +
> +static inline void *ipz_qeit_eq_get_inc(struct ipz_queue *queue)
> +{
> +	void *retvalue = NULL;
> +	u64 last_entry_in_q = queue->queue_length - queue->qe_size;
> +
> +	retvalue = ipz_qeit_get(queue);
> +	queue->current_q_offset += queue->qe_size;
> +	if (queue->current_q_offset > last_entry_in_q) {
> +		queue->current_q_offset = 0;
> +		queue->toggle_state = (~queue->toggle_state) & 1;
> +	}
> +
> +	EDEB(7, "queue=%p retvalue=%p new current_q_offset=%lx qe_size=%x",
> +	     queue, retvalue, queue->current_q_offset, queue->qe_size);
> +
> +	return retvalue;
> +}
> +
> +static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue)
> +{
> +	void *retvalue = ipz_qeit_get(queue);
> +	u32 qe = *(u8 *) retvalue;
> +	EDEB(7, "ipz_eqit_eq_get_inc_valid qe=%x", qe);
> +	if ((qe >> 7) == (queue->toggle_state & 1))
> +		ipz_qeit_eq_get_inc(queue);
> +	else
> +		retvalue = NULL;
> +	return retvalue;
> +}
> +
> +static inline struct ehea_rwqe *ehea_get_next_rwqe(struct ehea_qp *qp,
> +						   int rq_nr)
> +{
> +
> +	struct ehea_rwqe *wqe_p = NULL;
> +	struct ipz_queue *queue = NULL;
> +	struct ehea_qp *my_qp = qp;
> +	EDEB_EN(8, "QP=%p, RQ_nr=%d", qp, rq_nr);
> +
> +	if (rq_nr == 1)
> +		queue = &my_qp->ipz_rqueue1;
> +	else if (rq_nr == 2)
> +		queue = &my_qp->ipz_rqueue2;
> +	else
> +		queue = &my_qp->ipz_rqueue3;
> +	wqe_p = (struct ehea_rwqe *)ipz_qeit_get_inc(queue);
> +
> +	EDEB_EX(8, "&RWQE=%p, queue=%p", wqe_p, queue);
> +	return wqe_p;
> +}
> +
> +static inline struct ehea_swqe *ehea_get_swqe(struct ehea_qp *my_qp,
> +					      int *wqe_index)
> +{
> +	struct ipz_queue *queue = &my_qp->ipz_squeue;
> +	struct ehea_swqe *wqe_p = NULL;
> +	EDEB_EN(7, "QP=%p, queue=%p", my_qp, &my_qp->ipz_squeue);
> +	*wqe_index = (queue->current_q_offset) >> (7 + EHEA_SG_SQ);
> +	wqe_p = (struct ehea_swqe *)ipz_qeit_get_inc(&my_qp->ipz_squeue);
> +	EDEB_EX(7, "");
> +	return wqe_p;
> +}
> +
> +static inline void ehea_post_swqe(struct ehea_qp *my_qp, struct ehea_swqe *s
wqe)
> +{
> +
> +	EDEB_EN(7, "QP=%p, SWQE=%p", my_qp, swqe);
> +	EDEB(6, "SWQE workreqid = 0x%lX, imm_data_len=%d, descriptors=%d",
> +	     (u64) swqe->wr_id, swqe->immediate_data_length, swqe->descriptors)
;
> +	iosync();
> +	ehea_update_sqa(my_qp, 1);
> +	EDEB_EX(7, "");
> +}
> +
> +static inline struct ehea_cqe *ehea_poll_rq1(struct ehea_qp *qp, int *wqe_in
dex)
> +{
> +	struct ipz_queue *queue = &qp->ipz_rqueue1;
> +	struct ehea_cqe *cqe = NULL;
> +
> +	EDEB_EN(7, "QP=%p, RQ1 toggle state = %d, current_q_offset=%lx", qp,
> +		queue->toggle_state, queue->current_q_offset);
> +	*wqe_index = (queue->current_q_offset) >> (7 + EHEA_SG_RQ1);
> +	cqe = (struct ehea_cqe *)ipz_qeit_get_valid(queue);
> +	EDEB_EX(7, "cqe=%p, new toggle state %d, wqe_index = %d",
> +		cqe, queue->toggle_state, *wqe_index);
> +	return cqe;
> +}
> +
> +static inline void ehea_inc_rq1(struct ehea_qp *qp)
> +{
> +	struct ipz_queue *queue = &qp->ipz_rqueue1;
> +	ipz_qeit_inc(queue);
> +}
> +
> +static inline struct ehea_cqe *ehea_poll_cq(struct ehea_cq *my_cq)
> +{
> +
> +	struct ehea_cqe *wqe_p = NULL;
> +	EDEB_EN(7, "CQ=%p", my_cq);
> +
> +	EDEB(7, "queue_element_size=%x, alloc_len=%x, queue=%p",
> +	     my_cq->ipz_queue.qe_size,
> +	     my_cq->ipz_queue.queue_length, &my_cq->ipz_queue);
> +	wqe_p = (struct ehea_cqe *)ipz_qeit_get_inc_valid(&my_cq->ipz_queue);
> +
> +	EDEB_EX(7, "wqe_p=%p", wqe_p);
> +	return wqe_p;
> +};

Can we stick all these functions in the .c and put only the prototypes here?

> +
> +#define HIPZ_CQ_REGISTER_ORIG 0
> +#define HIPZ_EQ_REGISTER_ORIG 0
> +
> +enum ehea_eq_type {
> +	EHEA_EQ = 0,		/* event queue              */
> +	EHEA_NEQ		/* notification event queue */
> +};
> +
> +struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
> +			       enum ehea_eq_type type,
> +			       const u32 length, const u8 eqe_gen);
> +
> +int ehea_destroy_eq(struct ehea_eq *eq);
> +
> +void *ehea_poll_eq(struct ehea_eq *eq);
> +
> +struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, int cqe,
> +			       u64 eq_handle, u32 cq_token);
> +
> +int ehea_destroy_cq(struct ehea_cq *cq);
> +
> +
> +struct ehea_qp *ehea_create_qp(struct ehea_adapter * adapter,
> +			       u32 pd,
> +			       struct ehea_qp_init_attr *init_attr);
> +
> +int ehea_destroy_qp(struct ehea_qp *qp);
> +
> +int ehea_reg_mr_adapter(struct ehea_adapter *adapter);
> +int ehea_dereg_mr_adapter(struct ehea_adapter *adapter);
> +
> +int ehea_reg_mr_pages(struct ehea_adapter *adapter,
> +		      struct ehea_mr *mr,
> +		      u64 start, u64 *pt, int nr_pages);
> +
> +#endif	/* __EHEA_QMR_H__ */
> --- linux-2.6.18-rc4-orig/drivers/net/ehea/ehea_ethtool.c	1969-12-31 16:0
0:00.000000000 -0800
> +++ kernel/drivers/net/ehea/ehea_ethtool.c	2006-08-08 23:59:38.092465848 -
0700

Why is the ethtool stuff in the queue management patch?

> @@ -0,0 +1,325 @@
> +/*
> + *  linux/drivers/net/ehea/ehea_ethtool.c
> + *
> + *  eHEA ethernet device driver for IBM eServer System p
> + *
> + *  (C) Copyright IBM Corp. 2006
> + *
> + *  Authors:
> + *       Christoph Raisch <raisch@de.ibm.com>
> + *       Jan-Bernd Themann <themann@de.ibm.com>
> + *       Heiko-Joerg Schick <schickhj@de.ibm.com>
> + *       Thomas Klein <tklein@de.ibm.com>
> + *
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2, or (at your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#include "ehea.h"
> +#include "ehea_phyp.h"
> +
> +
> +static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *c
md)
> +{
> +	u64 hret = H_HARDWARE;
> +	struct ehea_port *port = (struct ehea_port*)dev->priv;
> +	struct ehea_adapter *adapter = port->adapter;
> +	struct hcp_query_ehea_port_cb_4 *cb4 = NULL;
> +
> +	EDEB_EN(7, "net_device=%p", dev);
> +
> +	cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
> +	if(!cb4) {
> +		EDEB_ERR(4, "No memory for cb4");
> +		goto get_settings_exit;
> +	}
> +
> +	hret = ehea_h_query_ehea_port(adapter->handle,
> +				      port->logical_port_id,
> +				      H_PORT_CB4,
> +				      H_PORT_CB4_ALL,
> +				      cb4);

As mpe noted as well... hret is set twice..

> +
> +	if (hret != H_SUCCESS) {
> +		EDEB_ERR(4, "query_ehea_port failed for cb4");
> +		kfree(cb4);
> +		goto get_settings_exit;
> +	}
> +
> +	EDEB_DMP(7, (u8*)cb4,
> +		 sizeof(struct hcp_query_ehea_port_cb_4), "After HCALL");
> +
> +	if (netif_carrier_ok(dev)) {
> +		switch(cb4->port_speed){
> +		case H_PORT_SPEED_10M_H:
> +			cmd->speed = SPEED_10;
> +			cmd->duplex = DUPLEX_HALF;
> +			break;
> +		case H_PORT_SPEED_10M_F:
> +			cmd->speed = SPEED_10;
> +			cmd->duplex = DUPLEX_FULL;
> +			break;
> +		case H_PORT_SPEED_100M_H:
> +			cmd->speed = SPEED_100;
> +			cmd->duplex = DUPLEX_HALF;
> +			break;
> +		case H_PORT_SPEED_100M_F:
> +			cmd->speed = SPEED_100;
> +			cmd->duplex = DUPLEX_FULL;
> +			break;
> +		case H_PORT_SPEED_1G_F:
> +			cmd->speed = SPEED_1000;
> +			cmd->duplex = DUPLEX_FULL;
> +			break;
> +		case H_PORT_SPEED_10G_F:
> +			cmd->speed = SPEED_10000;
> +			cmd->duplex = DUPLEX_FULL;
> +			break;
> +		}
> +	} else {
> +		cmd->speed = -1;
> +		cmd->duplex = -1;
> +	}
> +
> +	cmd->supported =
> +	    (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full
> +	     | SUPPORTED_100baseT_Full |  SUPPORTED_100baseT_Half
> +	     | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half
> +	     | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
> +	cmd->advertising =
> +	    (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg
> +	     | ADVERTISED_FIBRE);
> +	cmd->port = PORT_FIBRE;
> +	cmd->autoneg = AUTONEG_ENABLE;
> +
> +	kfree(cb4);
> +	return 0;
> +
> +get_settings_exit:
> +	EDEB_EX(7, "");
> +	return 1;
> +}
> +
> +static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *c
md)
> +{
> +	printk("set settings\n");
> +	return 0;
> +}
> +
> +static void netdev_get_drvinfo(struct net_device *dev,
> +			       struct ethtool_drvinfo *info)
> +{
> +	printk("get drvinfo\n");
> +	strncpy(info->driver, EHEA_DRIVER_NAME, sizeof(info->driver) - 1);
> +	strncpy(info->version, EHEA_DRIVER_VERSION, sizeof(info->version) - 1);
> +}
> +
> +static u32 netdev_get_msglevel(struct net_device *dev)
> +{
> +	EDEB(7, "");
> +	return (u32)ehea_trace_level;
> +}
> +
> +static void netdev_set_msglevel(struct net_device *dev, u32 value)
> +{
> +	EDEB(7, "trace level set to %x", value);
> +	ehea_trace_level = (int)value;
> +}
> +
> +static int netdev_nway_reset(struct net_device *dev)
> +{
> +	printk("nway reset\n");
> +	return 0;
> +}
> +
> +static void netdev_get_pauseparam(struct net_device *dev,
> +				  struct ethtool_pauseparam *pauseparam)
> +{
> +	printk("get pauseparam\n");
> +}
> +
> +static int netdev_set_pauseparam(struct net_device *dev,
> +				 struct ethtool_pauseparam *pauseparam)
> +{
> +	printk("set pauseparam\n");
> +	return 0;
> +}
> +
> +static u32 netdev_get_rx_csum(struct net_device *dev)
> +{
> +	printk("set rx_csum\n");
> +	return 0;
> +}
> +
> +static int netdev_set_rx_csum(struct net_device *dev, u32 value)
> +{
> +	printk("set rx_csum\n");
> +	return 0;
> +}
> +
> +static int netdev_self_test_count(struct net_device *dev)
> +{
> +	printk("self test count\n");
> +	return 0;
> +}
> +
> +static void netdev_self_test(struct net_device *dev, struct ethtool_test *te
st,
> +			     u64 *value)
> +{
> +	printk("self test\n");
> +}
> +
> +static int netdev_phys_id(struct net_device *dev, u32 value)
> +{
> +	printk("physical id\n");
> +	return 0;
> +}

These are yet to be done?


> +
> +static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
> +	{"poll_max_processed"},
> +	{"queue_stopped"},
> +	{"min_swqe_avail"},
> +	{"poll_receive_err"},
> +	{"pkt_send"},
> +	{"pkt_xmit"},
> +	{"send_tasklet"},
> +	{"ehea_poll"},
> +	{"nwqe"},
> +	{"swqe_available_0"},
> +	{"rxo"},
> +	{"rx64"},
> +	{"rx65"},
> +	{"rx128"},
> +	{"rx256"},
> +	{"rx512"},
> +	{"rx1024"},
> +	{"txo"},
> +	{"tx64"},
> +	{"tx65"},
> +	{"tx128"},
> +	{"tx256"},
> +	{"tx512"},
> +	{"tx1024"},
> +};
> +
> +static void netdev_get_strings(struct net_device *dev,
> +				     u32 stringset, u8 * data)
> +{
> +	switch (stringset) {
> +	case ETH_SS_TEST:
> +		break;
> +	case ETH_SS_STATS:
> +		memcpy(data, &ehea_ethtool_stats_keys,
> +		       sizeof(ehea_ethtool_stats_keys));
> +	}
> +}
> +
> +static int netdev_get_stats_count(struct net_device *dev)
> +{
> +	return ARRAY_SIZE(ehea_ethtool_stats_keys);
> +}
> +
> +
> +static void netdev_get_ethtool_stats(struct net_device *dev,
> +				     struct ethtool_stats *stats, u64 *data)
> +{
> +	int i = 0;
> +	u64 hret = H_HARDWARE;
> +	struct ehea_port *port = (struct ehea_port*)dev->priv;
> +	struct ehea_adapter *adapter = port->adapter;
> +	struct ehea_port_res *pr = &port->port_res[0];
> +	struct port_state *p_state = &pr->p_state;
> +	struct hcp_query_ehea_port_cb_6 *cb6 = NULL;
> +
> +	EDEB_EN(7, "net_device=%p", dev);
> +
> +	cb6 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
> +	if(!cb6) {
> +		EDEB_ERR(4, "No memory for cb6");
> +		goto stats_exit;
> +	}
> +
> +	hret = ehea_h_query_ehea_port(adapter->handle,
> +				      port->logical_port_id,
> +				      H_PORT_CB6,
> +				      H_PORT_CB6_ALL,
> +				      cb6);
> +
> +	if (hret != H_SUCCESS)
> +		EDEB_ERR(4, "query_ehea_port failed for cb6");
> +
> +	EDEB_DMP(7, (u8*)cb6,
> +		 sizeof(struct hcp_query_ehea_port_cb_6), "After HCALL");
> +	data[i++] = p_state->poll_max_processed;
> +	data[i++] = p_state->queue_stopped;
> +	data[i++] = p_state->min_swqe_avail;
> +	data[i++] = p_state->poll_receive_errors;
> +	data[i++] = p_state->pkt_send;
> +	data[i++] = p_state->pkt_xmit;
> +	data[i++] = p_state->send_tasklet;
> +	data[i++] = p_state->ehea_poll;
> +	data[i++] = p_state->nwqe;
> +	data[i++] = atomic_read(&port->port_res[0].swqe_avail);
> +
> +	data[i++] = cb6->rxo;
> +	data[i++] = cb6->rx64;
> +	data[i++] = cb6->rx65;
> +	data[i++] = cb6->rx128;
> +	data[i++] = cb6->rx256;
> +	data[i++] = cb6->rx512;
> +	data[i++] = cb6->rx1024;
> +	data[i++] = cb6->txo;
> +	data[i++] = cb6->tx64;
> +	data[i++] = cb6->tx65;
> +	data[i++] = cb6->tx128;
> +	data[i++] = cb6->tx256;
> +	data[i++] = cb6->tx512;
> +	data[i++] = cb6->tx1024;
> +
> +	kfree(cb6);
> +stats_exit:
> +	EDEB_EX(7, "");
> +}
> +
> +struct ethtool_ops ehea_ethtool_ops = {
> +	.get_settings = netdev_get_settings,
> +	.set_settings = netdev_set_settings,
> +	.get_drvinfo = netdev_get_drvinfo,
> +	.get_msglevel = netdev_get_msglevel,
> +	.set_msglevel = netdev_set_msglevel,
> +	.nway_reset = netdev_nway_reset,
> +	.get_link = ethtool_op_get_link,
> +	.get_pauseparam = netdev_get_pauseparam,
> +	.set_pauseparam = netdev_set_pauseparam,
> +	.get_rx_csum = netdev_get_rx_csum,
> +	.set_rx_csum = netdev_set_rx_csum,
> +	.get_tx_csum = ethtool_op_get_tx_csum,
> +	.set_tx_csum = ethtool_op_set_tx_csum,
> +	.get_sg = ethtool_op_get_sg,
> +	.set_sg = ethtool_op_set_sg,
> +	.get_tso = ethtool_op_get_tso,
> +	.set_tso = ethtool_op_set_tso,
> +	.self_test_count = netdev_self_test_count,
> +	.self_test = netdev_self_test,
> +	.get_strings = netdev_get_strings,
> +	.phys_id = netdev_phys_id,
> +	.get_stats_count = netdev_get_stats_count,
> +	.get_ethtool_stats = netdev_get_ethtool_stats
> +};
> +
> +void ehea_set_ethtool_ops(struct net_device *netdev)
> +{
> +	SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops);
> +}
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

I hope this helps...

Mikey

^ permalink raw reply

* Re: latest git: compile error: arch/powerpc/kernel/built-in.o
From: Michael Ellerman @ 2006-08-10 23:48 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linux-ppc
In-Reply-To: <20060810232102.GB3668@localhost>

On Fri, 2006-08-11 at 01:21 +0200, Wolfgang Pfeiffer wrote:
> On Thu, Aug 10, 2006 at 02:14:46PM -0700, Haren Myneni wrote:
> > Wolfgang Pfeiffer wrote:
> > 
> > A couple of Michael's patches are needed. I am able to build with your 
> > config file.
> > 
> > http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024271.html
> > http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024272.html
> 
> Yes. Works. Although I could take the patches on the pages above from the
> the corresponding messages that are still in my mail folder ... :)
> 
> Strange tho' - for me at least - that these patches from about 5 weeks (!)
> ago still don't seem to have made it into the current git tree ...

Hmm, yeah. My fault for not chasing them up :)

Paul, any objection to these two?

cheers

-- 
Michael Ellerman
IBM OzLabs

email: michaele@au.ibm.com
stime: ellerman@au1.ibm.com
notes: Michael Ellerman/Australia/IBM
phone: +61 2 6212 1183 (tie line 70 21183)

We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person

^ permalink raw reply

* Realtime preemption patch on PPC
From: Ben Weintraub @ 2006-08-10 23:04 UTC (permalink / raw)
  To: linuxppc-embedded

Howdy,

I'm wondering if anyone has had success getting Ingo Molnar's realtime
preemption patch (the one here:
http://people.redhat.com/mingo/realtime-preempt/ ) working on the ppc
arch.  

I'm working with patch-2.6.17-rt8 (the latest) and linux-2.6.17.  The
realtime-preempt patch seems to include the generic timeofday patch, but
with no support for the ppc arch, only powerpc, so I've hacked in
support for ppc by basically replicating the powerpc arch-specific stuff
found here:
http://sr71.net/~jstultz/tod/archive/linux-2.6.17-rc3_timekeeping_C2/broken-out/linux-2.6.17-rc3_timeofday-arch-ppc_C2.patch

I can attach my patch if anyone would like, but for all I know it could
be wildly inaccurate.  

Anyhow, when I boot on an MPC8555 with my hack, I get an endless stream
of:

BUG: sleeping function called from invalid context init(1) at
arch/powerpc/math-emu/math.c:226
in_atomic():0 [00000000], irqs_disabled():1
Call Trace:
[A0BB3E90] [A000934C] show_stack+0x48/0x194 (unreliable)
[A0BB3EC0] [A001B7DC] __might_sleep+0xe8/0xf4
[A0BB3EE0] [A00136C0] do_mathemu+0x30/0x8c8
[A0BB3F00] [A00036AC] program_check_exception+0x1ac/0x514
[A0BB3F40] [A0002A08] ret_from_except_full+0x0/0x4c

Line 226 in arch/powerpc/math-emu/math.c is part of the do_mathemu()
function, and contains a call to get_user(), which calls
__might_sleep(), causing this problem.  

I did find this message in the LKML archives describing a very similar
problem:
http://lkml.org/lkml/2006/2/23/312

And so tried putting a call to local_irq_enable() before the call to
do_mathemu() in program_check_excpetion(), but this causes a hard lockup
with no messages printed when I try to bring up my network interface.  I
assume this means I've done something Very Bad with interrupts by adding
in local_irq_enable() at the wrong spot.  I also tried adding it at the
exact same spot as the patch given by Paul in his reply, but in this
case I still get the endless stream of BUG messages.

Can anyone offer some guidance or advice?

Thanks so much,
Ben 

^ permalink raw reply

* Re: latest git: compile error: arch/powerpc/kernel/built-in.o
From: Wolfgang Pfeiffer @ 2006-08-10 23:21 UTC (permalink / raw)
  To: Haren Myneni; +Cc: linux-ppc, ellerman
In-Reply-To: <44DBA1C6.2020902@us.ibm.com>

On Thu, Aug 10, 2006 at 02:14:46PM -0700, Haren Myneni wrote:
> Wolfgang Pfeiffer wrote:
> 
> A couple of Michael's patches are needed. I am able to build with your 
> config file.
> 
> http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024271.html
> http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024272.html

Yes. Works. Although I could take the patches on the pages above from the
the corresponding messages that are still in my mail folder ... :)

Strange tho' - for me at least - that these patches from about 5 weeks (!)
ago still don't seem to have made it into the current git tree ...

> 
> Thanks
> Haren

Ditto: Thanks. To Michael Ellerman, too :)

Best Regards
Wolfgang

> 
> >Hi All
> >
> >I'm trying to compile a fresh git kernel, with latest sources pulled today,
> >Aug. 10. To no avail so far. 

            [ ... ]

-- 
Wolfgang Pfeiffer: /ICQ: 286585973/ + + +  /AIM: crashinglinux/
http://profiles.yahoo.com/wolfgangpfeiffer

Key ID: E3037113
http://keyserver.mine.nu/pks/lookup?search=0xE3037113&fingerprint=on

^ permalink raw reply

* Re: Which is better for Wireless Network Support, 2.6 or 2.4?
From: Lee Revell @ 2006-08-10 22:04 UTC (permalink / raw)
  To: wei.li4; +Cc: linuxppc-embedded
In-Reply-To: <20060810132251.ycxgkqik5csw0gc0@webmail.mcgill.ca>

On Thu, 2006-08-10 at 13:22 -0400, wei.li4@elf.mcgill.ca wrote:
> Hi All,
> 
> I am working on wireless data application via MPC875 host USB, is there 
> any difference to use Linux 2.6.x or Linux 2.4.x? Is it Linux 2.6 more 
> like RTOS? Thanks.
> 

Yes, absolutely.  Recent Linux 2.6 kernels (since 2.6.14 or so) have
much better RT performance if PREEMPT is enabled than any 2.4 kernel.

Lee

^ permalink raw reply

* Re: latest git: compile error: arch/powerpc/kernel/built-in.o
From: Haren Myneni @ 2006-08-10 21:14 UTC (permalink / raw)
  To: Wolfgang Pfeiffer; +Cc: linux-ppc, ellerman
In-Reply-To: <20060810181154.GA3668@localhost>

Wolfgang Pfeiffer wrote:

A couple of Michael's patches are needed. I am able to build with your 
config file.

http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024271.html
http://ozlabs.org/pipermail/linuxppc-dev/2006-July/024272.html

Thanks
Haren

>Hi All
>
>I'm trying to compile a fresh git kernel, with latest sources pulled today,
>Aug. 10. To no avail so far. 
>
>OS is Debian/unstable, last time I upgraded the system as far as the
>dependencies allowed doing that was yesterday, Aug. 10.
>
>---------------------
>$ cat /proc/cpuinfo 
>processor       : 0
>cpu             : 7447A, altivec supported
>clock           : 833.333000MHz
>revision        : 0.5 (pvr 8003 0105)
>bogomips        : 16.57
>timebase        : 8320000
>platform        : PowerMac
>machine         : PowerBook5,8
>motherboard     : PowerBook5,8 MacRISC3 Power Macintosh 
>detected as     : 287 (PowerBook G4 15")
>pmac flags      : 00000019
>L2 cache        : 512K unified
>pmac-generation : NewWorld
>-----------------------------
>
>Here's the config I used:
>
>http://wolfgangpfeiffer.com/config.060810.txt
>
>The compile messages:
>
>--------------------------------
>time MAKEFLAGS="CC=gcc-4.1"  fakeroot make-kpkg --append-to-version=-060810 kernel_image
>
>results in [excerpts]:
>
>  CC      lib/sha1.o
>  CC      lib/string.o
>  CC      lib/vsprintf.o
>  AR      lib/lib.a
>  GEN     .version
>  CHK     include/linux/compile.h
>  UPD     include/linux/compile.h
>  CC      init/version.o
>  LD      init/built-in.o
>  LD      .tmp_vmlinux1
>arch/powerpc/kernel/built-in.o: In function `__restore_cpu_setup':
>(.text+0xcd34): undefined reference to `kexec_sr_activated'
>arch/powerpc/kernel/built-in.o: In function `__restore_cpu_setup':
>(.text+0xcd44): undefined reference to `crash_kexec_secondary'
>arch/powerpc/kernel/built-in.o: In function `early_init_devtree':
>(.init.text+0x1cdc): undefined reference to `reserve_crashkernel'
>arch/powerpc/kernel/built-in.o: In function `early_init_devtree':
>(.init.text+0x1e1c): undefined reference to `overlaps_crashkernel'
>make[1]: *** [.tmp_vmlinux1] Error 1
>make[1]: Leaving directory `/home/shorty/kernel-factory/git.08102006/linux-2.6'
>make: *** [debian/stamp-build-kernel] Error 2
>
>real    9m39.089s
>user    8m21.904s
>sys     0m59.167s
>
>------------------------------------------------------------
>
>and with gcc-4.0 the same:
>
>time MAKEFLAGS="CC=gcc-4.0"  fakeroot make-kpkg --append-to-version=-060810 kernel_image
>
>results in [excerpts]:
>
>  CC      lib/vsprintf.o
>  AR      lib/lib.a
>  GEN     .version
>  CHK     include/linux/compile.h
>  UPD     include/linux/compile.h
>  CC      init/version.o
>  LD      init/built-in.o
>  LD      .tmp_vmlinux1
>arch/powerpc/kernel/built-in.o: In function `__restore_cpu_setup':
>(.text+0xcccc): undefined reference to `kexec_sr_activated'
>arch/powerpc/kernel/built-in.o: In function `__restore_cpu_setup':
>(.text+0xccdc): undefined reference to `crash_kexec_secondary'
>arch/powerpc/kernel/built-in.o: In function `early_init_devtree':
>(.init.text+0x15d0): undefined reference to `reserve_crashkernel'
>arch/powerpc/kernel/built-in.o: In function `early_init_devtree':
>(.init.text+0x1710): undefined reference to `overlaps_crashkernel'
>make[1]: *** [.tmp_vmlinux1] Error 1
>make[1]: Leaving directory `/home/shorty/kernel-factory/git.08102006/linux-2.6'
>make: *** [debian/stamp-build-kernel] Error 2
>
>--------------------------------------
>
>Please let me know if you need more details.
>
>Thanks in anticipation
>
>Best Regards
>Wolfgang Pfeiffer
>
>  
>

^ permalink raw reply

* kernel panic: BUG in cascade at kernel/timer.c
From: Bizhan Gholikhamseh (bgholikh) @ 2006-08-10 21:12 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1535 bytes --]

Hi All,
We have developed our own custom board based on MPC8541 board running
linux 2.6.11
During stress testing the system we get following kernel panic which
related to timer cascase.
Any hints greatly apprieciated. Many thanks in advance:
 
kernel BUG in cascade at kernel/timer.c:416!
Oops: Exception in kernel mode, sig: 5 [#1]
PREEMPT 
NIP: C0023AB4 LR: C0023CC8 SP: C02DDDF0 REGS: c02ddd40 TRAP: 0700
Tainted: P    
MSR: 00021200 EE: 0 PR: 0 FP: 0 ME: 1 IR/DR: 00
TASK = c02bb730[0] 'swapper' THREAD: c02dc000
Last syscall: 120 

File timer.c line 416 :
    401 static int cascade(tvec_base_t *base, tvec_t *tv, int index)
    402 {
    403         /* cascade all the timers from tv up one level */
    404         struct list_head *head, *curr;
    405 
    406         head = tv->vec + index;
    407         curr = head->next;
    408         /*
    409          * We are removing _all_ timers from the list, so we
don't  have
         to
    410          * detach them individually, just clear the list
afterwards.
    411          */ 
    412         while (curr != head) {
    413                 struct timer_list *tmp;
    414         
    415                 tmp = list_entry(curr, struct timer_list,
entry);
    416                 BUG_ON(tmp->base != base);
    417                 curr = curr->next;
    418                 internal_add_timer(base, tmp);
    419         }
    420         INIT_LIST_HEAD(head);
    421 
    422         return index;

 
Regards,
Bizhan

[-- Attachment #2: Type: text/html, Size: 4369 bytes --]

^ permalink raw reply

* RE: Debugging with no serial port
From: Ben Warren @ 2006-08-10 20:53 UTC (permalink / raw)
  To: Martin, Tim; +Cc: linuxppc-embedded
In-Reply-To: <821B2170E9E7F04FA38DF7EC21DE487105FD14A0@VCAEXCH01.hq.corp.viasat.com>

Martin,

On Thu, 2006-08-10 at 13:12 -0700, Martin, Tim wrote:

> 	
> I tried this as well and have the same GDB synchronization problem e.g.
> 
> break log_stuff
> commands
>    silent
>    if (variable_logging_enabled)
>       printf "(%d,%d)\n",stuff1_variable,stuff2_variable
>    end
>    cont
> end
> 
That's too bad.  I wonder if you could run gdb from expect or some other
auto-scripting language and have it issue the 'cont' once all data is
printed (Have your code spit out a special 'end of data' delimiter). 

Just a thought - no idea if it would work.  

I'm not 100% certain how BDI-2000/gdb works, but I guess the gdb server
is running on the box, in which case you probably don't have much
control over how it works, and thus can't control if the output stream
is buffered or not.  My BDI-2000 book doesn't have much on configuring
the gdb part.

Anyway, sorry for rambling.

regards,
Ben

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox