LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Use ppc_md.hpte_insert() in htab_bolt_mapping()
From: Michael Ellerman @ 2006-06-23  8:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

With the ppc_md htab pointers setup earlier, we can use ppc_md.hpte_insert
in htab_bolt_mapping(), rather than deciding which version to call by hand.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/mm/hash_utils_64.c |   34 ++++++----------------------------
 1 file changed, 6 insertions(+), 28 deletions(-)

Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -167,34 +167,12 @@ int htab_bolt_mapping(unsigned long vsta
 		hash = hpt_hash(va, shift);
 		hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-		/* The crap below can be cleaned once ppd_md.probe() can
-		 * set up the hash callbacks, thus we can just used the
-		 * normal insert callback here.
-		 */
-#ifdef CONFIG_PPC_ISERIES
-		if (machine_is(iseries))
-			ret = iSeries_hpte_insert(hpteg, va,
-						  paddr,
-						  tmp_mode,
-						  HPTE_V_BOLTED,
-						  psize);
-		else
-#endif
-#ifdef CONFIG_PPC_PSERIES
-		if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR))
-			ret = pSeries_lpar_hpte_insert(hpteg, va,
-						       paddr,
-						       tmp_mode,
-						       HPTE_V_BOLTED,
-						       psize);
-		else
-#endif
-#ifdef CONFIG_PPC_MULTIPLATFORM
-			ret = native_hpte_insert(hpteg, va,
-						 paddr,
-						 tmp_mode, HPTE_V_BOLTED,
-						 psize);
-#endif
+		DBG("htab_bolt_mapping: calling %p\n", ppc_md.hpte_insert);
+
+		BUG_ON(!ppc_md.hpte_insert);
+		ret = ppc_md.hpte_insert(hpteg, va, paddr,
+				tmp_mode, HPTE_V_BOLTED, psize);
+
 		if (ret < 0)
 			break;
 	}

^ permalink raw reply

* [PATCH 1/2] powerpc: Initialise ppc_md htab pointers earlier
From: Michael Ellerman @ 2006-06-23  8:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

Initialise the ppc_md htab callbacks earlier, in the probe routines. This
allows us to call htab_finish_init() from htab_initialize(), and makes it
private to hash_utils_64.c. Move htab_finish_init() and make_bl() above
htab_initialize() to avoid forward declarations.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/setup_64.c          |    6 --
 arch/powerpc/mm/hash_native_64.c        |    3 -
 arch/powerpc/mm/hash_utils_64.c         |   72 ++++++++++++++++----------------
 arch/powerpc/platforms/cell/setup.c     |   12 ++---
 arch/powerpc/platforms/iseries/htab.c   |    4 -
 arch/powerpc/platforms/iseries/setup.c  |    7 ---
 arch/powerpc/platforms/maple/setup.c    |    7 ---
 arch/powerpc/platforms/powermac/setup.c |    9 ----
 arch/powerpc/platforms/pseries/lpar.c   |    4 -
 arch/powerpc/platforms/pseries/setup.c  |   10 ++--
 include/asm-powerpc/mmu.h               |    1 
 11 files changed, 58 insertions(+), 77 deletions(-)

Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -358,11 +358,7 @@ void __init setup_system(void)
 	 * Fill the ppc64_caches & systemcfg structures with informations
 	 * retrieved from the device-tree. Need to be called before
 	 * finish_device_tree() since the later requires some of the
-	 * informations filled up here to properly parse the interrupt
-	 * tree.
-	 * It also sets up the cache line sizes which allows to call
-	 * routines like flush_icache_range (used by the hash init
-	 * later on).
+	 * informations filled up here to properly parse the interrupt tree.
 	 */
 	initialize_cache_info();
 
Index: to-merge/arch/powerpc/mm/hash_native_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_native_64.c
+++ to-merge/arch/powerpc/mm/hash_native_64.c
@@ -520,7 +520,7 @@ static inline int tlb_batching_enabled(v
 }
 #endif
 
-void hpte_init_native(void)
+void __init hpte_init_native(void)
 {
 	ppc_md.hpte_invalidate	= native_hpte_invalidate;
 	ppc_md.hpte_updatepp	= native_hpte_updatepp;
@@ -530,5 +530,4 @@ void hpte_init_native(void)
 	ppc_md.hpte_clear_all	= native_hpte_clear;
 	if (tlb_batching_enabled())
 		ppc_md.flush_hash_range = native_flush_hash_range;
-	htab_finish_init();
 }
Index: to-merge/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/hash_utils_64.c
+++ to-merge/arch/powerpc/mm/hash_utils_64.c
@@ -413,6 +413,41 @@ void create_section_mapping(unsigned lon
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
+static inline void make_bl(unsigned int *insn_addr, void *func)
+{
+	unsigned long funcp = *((unsigned long *)func);
+	int offset = funcp - (unsigned long)insn_addr;
+
+	*insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
+	flush_icache_range((unsigned long)insn_addr, 4+
+			   (unsigned long)insn_addr);
+}
+
+static void __init htab_finish_init(void)
+{
+	extern unsigned int *htab_call_hpte_insert1;
+	extern unsigned int *htab_call_hpte_insert2;
+	extern unsigned int *htab_call_hpte_remove;
+	extern unsigned int *htab_call_hpte_updatepp;
+
+#ifdef CONFIG_PPC_64K_PAGES
+	extern unsigned int *ht64_call_hpte_insert1;
+	extern unsigned int *ht64_call_hpte_insert2;
+	extern unsigned int *ht64_call_hpte_remove;
+	extern unsigned int *ht64_call_hpte_updatepp;
+
+	make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
+	make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
+	make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
+	make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
+#endif /* CONFIG_PPC_64K_PAGES */
+
+	make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
+	make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
+	make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
+	make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
+}
+
 void __init htab_initialize(void)
 {
 	unsigned long table;
@@ -525,6 +560,8 @@ void __init htab_initialize(void)
 					 mmu_linear_psize));
 	}
 
+	htab_finish_init();
+
 	DBG(" <- htab_initialize()\n");
 }
 #undef KB
@@ -787,16 +824,6 @@ void flush_hash_range(unsigned long numb
 	}
 }
 
-static inline void make_bl(unsigned int *insn_addr, void *func)
-{
-	unsigned long funcp = *((unsigned long *)func);
-	int offset = funcp - (unsigned long)insn_addr;
-
-	*insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc));
-	flush_icache_range((unsigned long)insn_addr, 4+
-			   (unsigned long)insn_addr);
-}
-
 /*
  * low_hash_fault is called when we the low level hash code failed
  * to instert a PTE due to an hypervisor error
@@ -815,28 +842,3 @@ void low_hash_fault(struct pt_regs *regs
 	}
 	bad_page_fault(regs, address, SIGBUS);
 }
-
-void __init htab_finish_init(void)
-{
-	extern unsigned int *htab_call_hpte_insert1;
-	extern unsigned int *htab_call_hpte_insert2;
-	extern unsigned int *htab_call_hpte_remove;
-	extern unsigned int *htab_call_hpte_updatepp;
-
-#ifdef CONFIG_PPC_64K_PAGES
-	extern unsigned int *ht64_call_hpte_insert1;
-	extern unsigned int *ht64_call_hpte_insert2;
-	extern unsigned int *ht64_call_hpte_remove;
-	extern unsigned int *ht64_call_hpte_updatepp;
-
-	make_bl(ht64_call_hpte_insert1, ppc_md.hpte_insert);
-	make_bl(ht64_call_hpte_insert2, ppc_md.hpte_insert);
-	make_bl(ht64_call_hpte_remove, ppc_md.hpte_remove);
-	make_bl(ht64_call_hpte_updatepp, ppc_md.hpte_updatepp);
-#endif /* CONFIG_PPC_64K_PAGES */
-
-	make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert);
-	make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert);
-	make_bl(htab_call_hpte_remove, ppc_md.hpte_remove);
-	make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp);
-}
Index: to-merge/arch/powerpc/platforms/cell/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/cell/setup.c
+++ to-merge/arch/powerpc/platforms/cell/setup.c
@@ -125,8 +125,6 @@ static void __init cell_init_early(void)
 {
 	DBG(" -> cell_init_early()\n");
 
-	hpte_init_native();
-
 	cell_init_iommu();
 
 	ppc64_interrupt_controller = IC_CELL_PIC;
@@ -139,11 +137,13 @@ static int __init cell_probe(void)
 {
 	unsigned long root = of_get_flat_dt_root();
 
-	if (of_flat_dt_is_compatible(root, "IBM,CBEA") ||
-	    of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
-		return 1;
+	if (!of_flat_dt_is_compatible(root, "IBM,CBEA") &&
+	    !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
+		return 0;
+
+	hpte_init_native();
 
-	return 0;
+	return 1;
 }
 
 /*
Index: to-merge/arch/powerpc/platforms/iseries/htab.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/htab.c
+++ to-merge/arch/powerpc/platforms/iseries/htab.c
@@ -242,13 +242,11 @@ static void iSeries_hpte_invalidate(unsi
 	local_irq_restore(flags);
 }
 
-void hpte_init_iSeries(void)
+void __init hpte_init_iSeries(void)
 {
 	ppc_md.hpte_invalidate	= iSeries_hpte_invalidate;
 	ppc_md.hpte_updatepp	= iSeries_hpte_updatepp;
 	ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp;
 	ppc_md.hpte_insert	= iSeries_hpte_insert;
 	ppc_md.hpte_remove	= iSeries_hpte_remove;
-
-	htab_finish_init();
 }
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -319,11 +319,6 @@ static void __init iSeries_init_early(vo
 	iSeries_recal_titan = HvCallXm_loadTod();
 
 	/*
-	 * Initialize the hash table management pointers
-	 */
-	hpte_init_iSeries();
-
-	/*
 	 * Initialize the DMA/TCE management
 	 */
 	iommu_init_early_iSeries();
@@ -671,6 +666,8 @@ static int __init iseries_probe(void)
 	 */
 	virt_irq_max = 255;
 
+	hpte_init_iSeries();
+
 	return 1;
 }
 
Index: to-merge/arch/powerpc/platforms/maple/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/maple/setup.c
+++ to-merge/arch/powerpc/platforms/maple/setup.c
@@ -199,11 +199,6 @@ static void __init maple_init_early(void
 {
 	DBG(" -> maple_init_early\n");
 
-	/* Initialize hash table, from now on, we can take hash faults
-	 * and call ioremap
-	 */
-	hpte_init_native();
-
 	/* Setup interrupt mapping options */
 	ppc64_interrupt_controller = IC_OPEN_PIC;
 
@@ -272,6 +267,8 @@ static int __init maple_probe(void)
 	 */
 	alloc_dart_table();
 
+	hpte_init_native();
+
 	return 1;
 }
 
Index: to-merge/arch/powerpc/platforms/powermac/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/powermac/setup.c
+++ to-merge/arch/powerpc/platforms/powermac/setup.c
@@ -600,13 +600,6 @@ pmac_halt(void)
  */
 static void __init pmac_init_early(void)
 {
-#ifdef CONFIG_PPC64
-	/* Initialize hash table, from now on, we can take hash faults
-	 * and call ioremap
-	 */
-	hpte_init_native();
-#endif
-
 	/* Enable early btext debug if requested */
 	if (strstr(cmd_line, "btextdbg")) {
 		udbg_adb_init_early();
@@ -683,6 +676,8 @@ static int __init pmac_probe(void)
 	 * part of the cacheable linar mapping
 	 */
 	alloc_dart_table();
+
+	hpte_init_native();
 #endif
 
 #ifdef CONFIG_PPC32
Index: to-merge/arch/powerpc/platforms/pseries/lpar.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/lpar.c
+++ to-merge/arch/powerpc/platforms/pseries/lpar.c
@@ -513,7 +513,7 @@ void pSeries_lpar_flush_hash_range(unsig
 		spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
 }
 
-void hpte_init_lpar(void)
+void __init hpte_init_lpar(void)
 {
 	ppc_md.hpte_invalidate	= pSeries_lpar_hpte_invalidate;
 	ppc_md.hpte_updatepp	= pSeries_lpar_hpte_updatepp;
@@ -522,6 +522,4 @@ void hpte_init_lpar(void)
 	ppc_md.hpte_remove	= pSeries_lpar_hpte_remove;
 	ppc_md.flush_hash_range	= pSeries_lpar_flush_hash_range;
 	ppc_md.hpte_clear_all   = pSeries_lpar_hptab_clear;
-
-	htab_finish_init();
 }
Index: to-merge/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/pseries/setup.c
+++ to-merge/arch/powerpc/platforms/pseries/setup.c
@@ -322,11 +322,6 @@ static void __init pSeries_init_early(vo
 	DBG(" -> pSeries_init_early()\n");
 
 	fw_feature_init();
-	
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		hpte_init_lpar();
-	else
-		hpte_init_native();
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		find_udbg_vterm();
@@ -384,6 +379,11 @@ static int __init pSeries_probe_hypertas
 	if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL)
  		powerpc_firmware_features |= FW_FEATURE_LPAR;
 
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		hpte_init_lpar();
+	else
+		hpte_init_native();
+
  	return 1;
 }
 
Index: to-merge/include/asm-powerpc/mmu.h
===================================================================
--- to-merge.orig/include/asm-powerpc/mmu.h
+++ to-merge/include/asm-powerpc/mmu.h
@@ -238,7 +238,6 @@ extern int hash_huge_page(struct mm_stru
 			  unsigned long ea, unsigned long vsid, int local,
 			  unsigned long trap);
 
-extern void htab_finish_init(void);
 extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 			     unsigned long pstart, unsigned long mode,
 			     int psize);

^ permalink raw reply

* [PATCH] Export flat device tree via debugfs for debugging
From: Michael Ellerman @ 2006-06-23  8:16 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

If DEBUG is turned on in prom.c, export the flat device tree via debugfs.
This has been handy on several occasions.

To look at it:
 # mount -t debugfs none /sys/kernel/debug
 # od -a /sys/kernel/debug/powerpc/flat-device-tree
 and/or
 # dtc -fI dtb /sys/kernel/debug/powerpc/flat-device-tree -O dts

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/prom.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

Index: to-merge/arch/powerpc/kernel/prom.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom.c
+++ to-merge/arch/powerpc/kernel/prom.c
@@ -30,6 +30,7 @@
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/kexec.h>
+#include <linux/debugfs.h>
 
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -2148,3 +2149,27 @@ struct device_node *of_get_cpu_node(int 
 	}
 	return NULL;
 }
+
+#ifdef DEBUG
+static struct debugfs_blob_wrapper flat_dt_blob;
+
+static int __init export_flat_device_tree(void)
+{
+	struct dentry *d;
+
+	d = debugfs_create_dir("powerpc", NULL);
+	if (!d)
+		return 1;
+
+	flat_dt_blob.data = initial_boot_params;
+	flat_dt_blob.size = initial_boot_params->totalsize;
+
+	d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
+				d, &flat_dt_blob);
+	if (!d)
+		return 1;
+
+	return 0;
+}
+__initcall(export_flat_device_tree);
+#endif

^ permalink raw reply

* [PATCH] Remove remaining iSeries debugger cruft
From: Michael Ellerman @ 2006-06-23  8:15 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

None of this seems to be necessary, so let's see if can remove it and not
break anything. Booted on iSeries & pSeries here.

NB. we don't remove the hvReleaseData, we just move it down so that the file
reads more clearly.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---

 arch/powerpc/kernel/head_64.S          |   37 ++++++++-------------------------
 arch/powerpc/platforms/iseries/setup.c |   12 ----------
 2 files changed, 9 insertions(+), 40 deletions(-)

Index: to-merge/arch/powerpc/kernel/head_64.S
===================================================================
--- to-merge.orig/arch/powerpc/kernel/head_64.S
+++ to-merge/arch/powerpc/kernel/head_64.S
@@ -85,34 +85,6 @@ END_FTR_SECTION(0, 1)
 	/* Catch branch to 0 in real mode */
 	trap
 
-#ifdef CONFIG_PPC_ISERIES
-	/*
-	 * At offset 0x20, there is a pointer to iSeries LPAR data.
-	 * This is required by the hypervisor
-	 */
-	. = 0x20
-	.llong hvReleaseData-KERNELBASE
-
-	/*
-	 * At offset 0x28 and 0x30 are offsets to the mschunks_map
-	 * array (used by the iSeries LPAR debugger to do translation
-	 * between physical addresses and absolute addresses) and
-	 * to the pidhash table (also used by the debugger)
-	 */
-	.llong mschunks_map-KERNELBASE
-	.llong 0	/* pidhash-KERNELBASE SFRXXX */
-
-	/* Offset 0x38 - Pointer to start of embedded System.map */
-	.globl	embedded_sysmap_start
-embedded_sysmap_start:
-	.llong	0
-	/* Offset 0x40 - Pointer to end of embedded System.map */
-	.globl	embedded_sysmap_end
-embedded_sysmap_end:
-	.llong	0
-
-#endif /* CONFIG_PPC_ISERIES */
-
 	/* Secondary processors spin on this value until it goes to 1. */
 	.globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
@@ -124,6 +96,15 @@ __secondary_hold_spinloop:
 __secondary_hold_acknowledge:
 	.llong	0x0
 
+#ifdef CONFIG_PPC_ISERIES
+	/*
+	 * At offset 0x20, there is a pointer to iSeries LPAR data.
+	 * This is required by the hypervisor
+	 */
+	. = 0x20
+	.llong hvReleaseData-KERNELBASE
+#endif /* CONFIG_PPC_ISERIES */
+
 	. = 0x60
 /*
  * The following code is used on pSeries to hold secondary processors
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -81,8 +81,6 @@ static void iSeries_pci_final_fixup(void
 #endif
 
 extern int rd_size;		/* Defined in drivers/block/rd.c */
-extern unsigned long embedded_sysmap_start;
-extern unsigned long embedded_sysmap_end;
 
 extern unsigned long iSeries_recal_tb;
 extern unsigned long iSeries_recal_titan;
@@ -563,16 +561,6 @@ static void __init iSeries_fixup_klimit(
 	if (naca.xRamDisk)
 		klimit = KERNELBASE + (u64)naca.xRamDisk +
 			(naca.xRamDiskSize * HW_PAGE_SIZE);
-	else {
-		/*
-		 * No ram disk was included - check and see if there
-		 * was an embedded system map.  Change klimit to take
-		 * into account any embedded system map
-		 */
-		if (embedded_sysmap_end)
-			klimit = KERNELBASE + ((embedded_sysmap_end + 4095) &
-					0xfffffffffffff000);
-	}
 }
 
 static int __init iSeries_src_init(void)

^ permalink raw reply

* Help on OHCI USB host present in SM501 chip
From: robinpv @ 2006-06-23  6:48 UTC (permalink / raw)
  To: linuxppc-dev

Hi ,
I am using MPC5200 based board and i have SM501 Mobile Multimedia 
companion chip on the PCI bus.
I am writing OHCI USB host present on the SM501 chip. I wanted to know 
if driver already exists.
I searched in linux ppc,  i could find the driver for the VGA( 
controller present in SM501) but not USB.
Currently i am referring to ohci-sa1111.c as reference.

Thanks in advance
Robin

^ permalink raw reply

* [PATCH] powerpc: kdump: Reserve the existing TCE mappings left by the first kernel
From: Haren Myneni @ 2006-06-23  6:35 UTC (permalink / raw)
  To: Paul Mackerras, Olof Johansson; +Cc: linuxppc-dev

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

Paul, Olof,

tce_union got removed in powerpc.git tree. Hence reposting the patch 
created against this tree. This patch is implemented based on Olof's 
suggestion of reserving TCE entries and use only available ones in the 
kdump boot and tested on P5, P4, JS20 and JS21 machines.

If you are OK with this patch, please send it to upstream.

Thanks
Haren

During kdump boot, noticed some machines checkstop on dma protection 
fault for ongoing DMA left in the first kernel. Instead of initializing 
TCE entries in iommu_init() for the kdump boot, this patch fixes this 
issue by walking through the each TCE table and checks whether the 
entries are in use by the first kernel. If so, reserve those entries by 
setting the corresponding bit in tbl->it_map such that these entries 
will not be available for the kdump boot.

However it could be possible that all TCE entries might be used up due 
to the driver bug that does continuous mapping. My observation is around 
1700 TCE  entries are used on some systems (Ex: P4) at some point of 
time during kdump boot and saving dump (either write into the disk or 
sending to remote machine). Hence, this patch will make sure that 
minimum of 2048 entries will be available such that kdump boot could be 
successful in some cases.

Signed-off-by: Haren Myneni <haren@us.ibm.com>



[-- Attachment #2: ppc64-kdump-checkstop-DMA-fault-fix.patch --]
[-- Type: text/x-patch, Size: 4853 bytes --]

diff -Naurp powerpc.git.orig/arch/powerpc/kernel/iommu.c powerpc.git/arch/powerpc/kernel/iommu.c
--- powerpc.git.orig/arch/powerpc/kernel/iommu.c	2006-06-19 00:54:37.000000000 -0500
+++ powerpc.git/arch/powerpc/kernel/iommu.c	2006-06-19 00:52:31.000000000 -0500
@@ -38,6 +38,7 @@
 #include <asm/iommu.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/kdump.h>
 
 #define DBG(...)
 
@@ -440,8 +441,37 @@ struct iommu_table *iommu_init_table(str
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
 
+#ifdef CONFIG_CRASH_DUMP
+	if (ppc_md.tce_get) {
+		unsigned long index, tceval;
+		unsigned long tcecount = 0;
+
+		/*
+		 * Reserve the existing mappings left by the first kernel.
+		 */
+		for (index = 0; index < tbl->it_size; index++) {
+			tceval = ppc_md.tce_get(tbl, index + tbl->it_offset);
+			/*
+			 * Freed TCE entry contains 0x7fffffffffffffff on JS20
+			 */
+			if (tceval && (tceval != 0x7fffffffffffffffUL)) {
+				__set_bit(index, tbl->it_map);
+				tcecount++;
+			}
+		}
+		if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) {
+			printk(KERN_WARNING "TCE table is full; ");
+			printk(KERN_WARNING "freeing %d entries for the kdump boot\n",
+				KDUMP_MIN_TCE_ENTRIES);
+			for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES;
+				index < tbl->it_size; index++) 
+				__clear_bit(index, tbl->it_map);
+		}
+	}
+#else
 	/* Clear the hardware table in case firmware left allocations in it */
 	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+#endif
 
 	if (!welcomed) {
 		printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
diff -Naurp powerpc.git.orig/arch/powerpc/platforms/pseries/iommu.c powerpc.git/arch/powerpc/platforms/pseries/iommu.c
--- powerpc.git.orig/arch/powerpc/platforms/pseries/iommu.c	2006-06-19 00:54:27.000000000 -0500
+++ powerpc.git/arch/powerpc/platforms/pseries/iommu.c	2006-06-19 00:52:44.000000000 -0500
@@ -92,6 +92,15 @@ static void tce_free_pSeries(struct iomm
 		*(tcep++) = 0;
 }
 
+static unsigned long tce_get_pseries(struct iommu_table *tbl, long index)
+{
+	u64 *tcep;
+
+	index <<= TCE_PAGE_FACTOR;
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	return *tcep;
+}
 
 static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				long npages, unsigned long uaddr,
@@ -235,6 +244,25 @@ static void tce_freemulti_pSeriesLP(stru
 	}
 }
 
+static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
+{
+	u64 rc;
+	unsigned long tce_ret;
+
+	tcenum <<= TCE_PAGE_FACTOR;
+	rc = plpar_tce_get((u64)tbl->it_index, (u64)tcenum << 12, &tce_ret);
+	
+	if (rc && printk_ratelimit()) {
+		printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%ld\n",
+			rc);
+		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
+		printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
+		show_stack(current, (unsigned long *)__get_SP());
+	}
+	
+	return tce_ret;
+}
+
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
 				 struct iommu_table *tbl)
@@ -254,7 +282,10 @@ static void iommu_table_setparms(struct 
 	}
 
 	tbl->it_base = (unsigned long)__va(*basep);
+
+#ifndef CONFIG_CRASH_DUMP
 	memset((void *)tbl->it_base, 0, *sizep);
+#endif
 
 	tbl->it_busno = phb->bus->number;
 
@@ -564,11 +595,13 @@ void iommu_init_early_pSeries(void)
 			ppc_md.tce_build = tce_build_pSeriesLP;
 			ppc_md.tce_free	 = tce_free_pSeriesLP;
 		}
+		ppc_md.tce_get   = tce_get_pSeriesLP;
 		ppc_md.iommu_bus_setup = iommu_bus_setup_pSeriesLP;
 		ppc_md.iommu_dev_setup = iommu_dev_setup_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
+		ppc_md.tce_get   = tce_get_pseries;
 		ppc_md.iommu_bus_setup = iommu_bus_setup_pSeries;
 		ppc_md.iommu_dev_setup = iommu_dev_setup_pSeries;
 	}
diff -Naurp powerpc.git.orig/include/asm-powerpc/kdump.h powerpc.git/include/asm-powerpc/kdump.h
--- powerpc.git.orig/include/asm-powerpc/kdump.h	2006-06-19 00:55:11.000000000 -0500
+++ powerpc.git/include/asm-powerpc/kdump.h	2006-06-22 02:48:15.000000000 -0500
@@ -15,6 +15,8 @@
 #define KDUMP_TRAMPOLINE_START	0x0100
 #define KDUMP_TRAMPOLINE_END	0x3000
 
+#define KDUMP_MIN_TCE_ENTRIES	2048
+
 #else /* !CONFIG_CRASH_DUMP */
 
 #define PHYSICAL_START	0x0
diff -Naurp powerpc.git.orig/include/asm-powerpc/machdep.h powerpc.git/include/asm-powerpc/machdep.h
--- powerpc.git.orig/include/asm-powerpc/machdep.h	2006-06-19 00:54:58.000000000 -0500
+++ powerpc.git/include/asm-powerpc/machdep.h	2006-06-19 00:53:05.000000000 -0500
@@ -82,6 +82,8 @@ struct machdep_calls {
 	void		(*tce_free)(struct iommu_table *tbl,
 				    long index,
 				    long npages);
+	unsigned long	(*tce_get)(struct iommu_table *tbl,
+				    long index);
 	void		(*tce_flush)(struct iommu_table *tbl);
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);

^ permalink raw reply

* Fixed PPC SHA1
From: linux @ 2006-06-23  0:09 UTC (permalink / raw)
  To: git, linuxppc-dev; +Cc: linux
In-Reply-To: <20060619084135.18632.qmail@science.horizon.com>

Okay, here's a tested and working version (the earlier version worked,
too) of a better-scheduled PPC SHA1.  This is about 15% faster that the
current sha1ppc.S on a G4, and 5% faster on a G5 when hashing 10 million
bytes, unaligned.  (The G5 ratio seems to get better as the sizes fall.)

It's also somewhat smaller, due to using load-multiple instructions.

I have a variant that uses load string (lswi) to load the values to be
hashed that is a few percent faster on a G5, but a few percent slower
on a G4.  It's also 52 bytes smaller (out of 4000).

Does anyone have any feeling for the ratio of G4 and G5 machines
out there?  I presume for that small a percentage, run-time processor
detection isn't worth it.  (Cc: to linuxppc-dev for the experts on
this question.)

I've tried using lmw to load the data, and it's faster if the data is
aligned, but it absolutely dies if the data is not.  And due to git's
variable-sized hash prefix, most of git's hashes are of unaligned data.

(No copyright is claimed on the changes to Paul Mackerras' work below.
Enjoy.)

/*
 * SHA-1 implementation for PowerPC.
 *
 * Copyright (C) 2005 Paul Mackerras <paulus@samba.org>
 */

/*
 * PowerPC calling convention:
 * %r0 - volatile temp
 * %r1 - stack pointer.
 * %r2 - reserved
 * %r3-%r12 - Incoming arguments & return values; volatile.
 * %r13-%r31 - Callee-save registers
 * %lr - Return address, volatile
 * %ctr - volatile
 *
 * Register usage in this routine:
 * %r0 - temp
 * %r3 - argument (pointer to 5 words of SHA state)
 * %r4 - argument (pointer to data to hash)
 * %r5 - Contant K in SHA round (initially number of blocks to hash)
 * %r6-%r10 - Working copies of SHA variables A..E (actually E..A order)
 * %r11-%r26 - Data being hashed W[].
 * %r27-%r31 - Previous copies of A..E, for final add back.
 * %ctr - loop count
 */


/*
 * We roll the registers for A, B, C, D, E around on each
 * iteration; E on iteration t is D on iteration t+1, and so on.
 * We use registers 6 - 10 for this.  (Registers 27 - 31 hold
 * the previous values.)
 */
#define RA(t)	(((t)+4)%5+6)
#define RB(t)	(((t)+3)%5+6)
#define RC(t)	(((t)+2)%5+6)
#define RD(t)	(((t)+1)%5+6)
#define RE(t)	(((t)+0)%5+6)

/* We use registers 11 - 26 for the W values */
#define W(t)	((t)%16+11)

/* Register 5 is used for the constant k */

/*
 * The basic SHA-1 round function is:
 * E += ROTL(A,5) + F(B,C,D) + W[i] + K;  B = ROTL(B,30)
 * Then the variables are renamed: (A,B,C,D,E) = (E,A,B,C,D).
 *
 * Every 20 rounds, the function F() and the contant K changes:
 * - 20 rounds of f0(b,c,d) = "bit wise b ? c : d" =  (^b & d) + (b & c)
 * - 20 rounds of f1(b,c,d) = b^c^d = (b^d)^c
 * - 20 rounds of f2(b,c,d) = majority(b,c,d) = (b&d) + ((b^d)&c)
 * - 20 more rounds of f1(b,c,d)
 *
 * These are all scheduled for near-optimal performance on a G4.
 * The G4 is a 3-issue out-of-order machine with 3 ALUs, but it can only
 * *consider* starting the oldest 3 instructions per cycle.  So to get
 * maximum performace out of it, you have to treat it as an in-order
 * machine.  Which means interleaving the computation round t with the
 * computation of W[t+4].
 *
 * The first 16 rounds use W values loaded directly from memory, while the
 * remianing 64 use values computed from those first 16.  We preload
 * 4 values before starting, so there are three kinds of rounds:
 * - The first 12 (all f0) also load the W values from memory.
 * - The next 64 compute W(i+4) in parallel. 8*f0, 20*f1, 20*f2, 16*f1.
 * - The last 4 (all f1) do not do anything with W.
 *
 * Therefore, we have 6 different round functions:
 * STEPD0_LOAD(t,s) - Perform round t and load W(s).  s < 16
 * STEPD0_UPDATE(t,s) - Perform round t and compute W(s).  s >= 16.
 * STEPD1_UPDATE(t,s)
 * STEPD2_UPDATE(t,s)
 * STEPD1(t) - Perform round t with no load or update.
 * 
 * The G5 is more fully out-of-order, and can find the parallelism
 * by itself.  The big limit is that it has a 2-cycle ALU latency, so
 * even though it's 2-way, the code has to be scheduled as if it's
 * 4-way, which can be a limit.  To help it, we try to schedule the
 * read of RA(t) as late as possible so it doesn't stall waiting for
 * the previous round's RE(t-1), and we try to rotate RB(t) as early
 * as possible while reading RC(t) (= RB(t-1)) as late as possible.
 */

/* the initial loads. */
#define LOADW(s) \
	lwz	W(s),(s)*4(%r4)

/*
 * Perform a step with F0, and load W(s).  Uses W(s) as a temporary
 * before loading it.
 * This is actually 10 instructions, which is an awkward fit.
 * It can execute grouped as listed, or delayed one instruction.
 * (If delayed two instructions, there is a stall before the start of the
 * second line.)  Thus, two iterations take 7 cycles, 3.5 cycles per round.
 */
#define STEPD0_LOAD(t,s) \
add RE(t),RE(t),W(t); andc   %r0,RD(t),RB(t);  and    W(s),RC(t),RB(t); \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;      rotlwi RB(t),RB(t),30;   \
add RE(t),RE(t),W(s); add    %r0,%r0,%r5;      lwz    W(s),(s)*4(%r4);  \
add RE(t),RE(t),%r0

/*
 * This is likewise awkward, 13 instructions.  However, it can also
 * execute starting with 2 out of 3 possible moduli, so it does 2 rounds
 * in 9 cycles, 4.5 cycles/round.
 */
#define STEPD0_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); andc   %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r0;  and    %r0,RC(t),RB(t); xor    W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     xor    W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r5;  loadk; rotlwi RB(t),RB(t),30;  rotlwi W(s),W(s),1;     \
add RE(t),RE(t),%r0

/* Nicely optimal.  Conveniently, also the most common. */
#define STEPD1_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); xor    %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r5;  loadk; xor %r0,%r0,RC(t);  xor W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     xor    W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r0;  rotlwi RB(t),RB(t),30;  rotlwi W(s),W(s),1

/*
 * The naked version, no UPDATE, for the last 4 rounds.  3 cycles per.
 * We could use W(s) as a temp register, but we don't need it.
 */
#define STEPD1(t) \
                        add   RE(t),RE(t),W(t); xor    %r0,RD(t),RB(t); \
rotlwi RB(t),RB(t),30;  add   RE(t),RE(t),%r5;  xor    %r0,%r0,RC(t);   \
add    RE(t),RE(t),%r0; rotlwi %r0,RA(t),5;     /* spare slot */        \
add    RE(t),RE(t),%r0

/*
 * 14 instructions, 5 cycles per.  The majority function is a bit
 * awkward to compute.  This can execute with a 1-instruction delay,
 * but it causes a 2-instruction delay, which triggers a stall.
 */
#define STEPD2_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); and    %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r0;  xor    %r0,RD(t),RB(t); xor    W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r5;  loadk; and %r0,%r0,RC(t);  xor W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     rotlwi W(s),W(s),1;             \
add RE(t),RE(t),%r0;  rotlwi RB(t),RB(t),30

#define STEP0_LOAD4(t,s)		\
	STEPD0_LOAD(t,s);		\
	STEPD0_LOAD((t+1),(s)+1);	\
	STEPD0_LOAD((t)+2,(s)+2);	\
	STEPD0_LOAD((t)+3,(s)+3)

#define STEPUP4(fn, t, s, loadk...)		\
	STEP##fn##_UPDATE(t,s,);		\
	STEP##fn##_UPDATE((t)+1,(s)+1,);	\
	STEP##fn##_UPDATE((t)+2,(s)+2,);	\
	STEP##fn##_UPDATE((t)+3,(s)+3,loadk)

#define STEPUP20(fn, t, s, loadk...)	\
	STEPUP4(fn, t, s,);		\
	STEPUP4(fn, (t)+4, (s)+4,);	\
	STEPUP4(fn, (t)+8, (s)+8,);	\
	STEPUP4(fn, (t)+12, (s)+12,);	\
	STEPUP4(fn, (t)+16, (s)+16, loadk)

	.globl	sha1_core
sha1_core:
	stwu	%r1,-80(%r1)
	stmw	%r13,4(%r1)

	/* Load up A - E */
	lmw	%r27,0(%r3)

	mtctr	%r5

1:
	LOADW(0)
	lis	%r5,0x5a82
	mr	RE(0),%r31
	LOADW(1)
	mr	RD(0),%r30
	mr	RC(0),%r29
	LOADW(2)
	ori	%r5,%r5,0x7999	/* K0-19 */
	mr	RB(0),%r28
	LOADW(3)
	mr	RA(0),%r27

	STEP0_LOAD4(0, 4)
	STEP0_LOAD4(4, 8)
	STEP0_LOAD4(8, 12)
	STEPUP4(D0, 12, 16,)
	STEPUP4(D0, 16, 20, lis %r5,0x6ed9)

	ori	%r5,%r5,0xeba1	/* K20-39 */
	STEPUP20(D1, 20, 24, lis %r5,0x8f1b)

	ori	%r5,%r5,0xbcdc	/* K40-59 */
	STEPUP20(D2, 40, 44, lis %r5,0xca62)

	ori	%r5,%r5,0xc1d6	/* K60-79 */
	STEPUP4(D1, 60, 64,)
	STEPUP4(D1, 64, 68,)
	STEPUP4(D1, 68, 72,)
	STEPUP4(D1, 72, 76,)
	addi	%r4,%r4,64
	STEPD1(76)
	STEPD1(77)
	STEPD1(78)
	STEPD1(79)

	/* Add results to original values */
	add	%r31,%r31,RE(0)
	add	%r30,%r30,RD(0)
	add	%r29,%r29,RC(0)
	add	%r28,%r28,RB(0)
	add	%r27,%r27,RA(0)

	bdnz	1b

	/* Save final hash, restore registers, and return */
	stmw	%r27,0(%r3)
	lmw	%r13,4(%r1)
	addi	%r1,%r1,80
	blr

^ permalink raw reply

* Re: Problem for "insmod: unresolved symbol printk"
From: Zhou Rui @ 2006-06-23  3:43 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc-dev
In-Reply-To: <20060622174810.GA16973@pb15.lixom.net>

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

Hi,
    My host machine kernel was 2.4.28 and the PowerPC board was 2.4.25-rthal5. I followed  the Standard Makefile for 2.4(<=) kernels on the page http://kernelnewbies.org/FAQ/LinuxKernelModuleCompile?highlight=%28insmod%29, and do some changes based on my situation:

TARGET := hello
INCLUDE := -I/lib/modules/2.4.25-rthal5/build/include
CFLAGS := -O2 -Wall -DMODULE -D__KERNEL__ -DLINUX
CC := powerpc-linux-gcc

${TARGET}.o: ${TARGET}.c
        $(CC) $(CFLAGS) ${INCLUDE} -c ${TARGET}.c

The problem is still "insmod: unresolved symbol printk". But when I logged in the PowerPC board, and # fgrep 'printk' /proc/ksyms, there was "c0015500 printk_Rdd132261".



Olof Johansson <olof@lixom.net> : On Thu, Jun 22, 2006 at 10:31:56PM +0800, Zhou Rui wrote:
> Hi, all
>     I'm a newbie for linuxppc. I've tried to write a simple hello.c as a kernel module.

Hi,

http://kernelnewbies.org/  should have information on kernel module
basics, and where to find help if you still have problems.


-Olof



Zhou Rui
Distributed & Embedded System Lab
School of Information Science & Engineering
Lanzhou University, P. R. China
http://dslab.lzu.edu.cn/~zr/
 		
---------------------------------
 Mp3疯狂搜-新歌热歌高速下   

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

^ permalink raw reply

* Re: Fixed PPC SHA1
From: linux @ 2006-06-23  0:54 UTC (permalink / raw)
  To: git, linuxppc-dev; +Cc: linux
In-Reply-To: <20060623000908.9370.qmail@science.horizon.com>

Here's the lwsi-based version that's slightly faster on a G5, but slightly
slower on a G4.

/*
 * SHA-1 implementation for PowerPC.
 *
 * Copyright (C) 2005 Paul Mackerras <paulus@samba.org>
 */

/*
 * PowerPC calling convention:
 * %r0 - volatile temp
 * %r1 - stack pointer.
 * %r2 - reserved
 * %r3-%r12 - Incoming arguments & return values; volatile.
 * %r13-%r31 - Callee-save registers
 * %lr - Return address, volatile
 * %ctr - volatile
 *
 * Register usage in this routine:
 * %r0 - temp
 * %r3 - argument (pointer to 5 words of SHA state)
 * %r4 - argument (pointer to data to hash)
 * %r5-%r20 - Data being hashed W[]. (%r5 is initially count of blocks)
 * %r21 - Contant K in SHA round
 * %r22-%r26 - Working copies of SHA variables A..E (actually E..A order) 
 * %r27-%r31 - Previous copies of A..E, for final add back.
 * %ctr - loop count (copied from %r5 argument)
 *
 * It's also worth mentioning that PPC assembly accept a bare
 * number as a register specifier; the "%r" prefix is actually optional.
 * And that number cna be an expression!  That simplifies the
 * loop unrolling significantly.
 */

/*
 * We roll the registers for A, B, C, D, E around on each
 * iteration; E on iteration t is D on iteration t+1, and so on.
 * We use registers 22 - 26 for this.  (Registers 27 - 31 hold
 * the previous values.)
 */
#define RA(t)	(((t)+4)%5+22)
#define RB(t)	(((t)+3)%5+22)
#define RC(t)	(((t)+2)%5+22)
#define RD(t)	(((t)+1)%5+22)
#define RE(t)	(((t)+0)%5+22)

/* Register 21 is used for the constant k */

/* We use registers 5 - 20 for the W values */
#define W(t)	((t)%16+5)

/*
 * The basic SHA-1 round function is:
 * E += ROTL(A,5) + F(B,C,D) + W[i] + K;  B = ROTL(B,30)
 * Then the variables are renamed: (A,B,C,D,E) = (E,A,B,C,D).
 *
 * Every 20 rounds, the function F() and the contant K changes:
 * - 20 rounds of f0(b,c,d) = "bit wise b ? c : d" =  (^b & d) + (b & c)
 * - 20 rounds of f1(b,c,d) = b^c^d = (b^d)^c
 * - 20 rounds of f2(b,c,d) = majority(b,c,d) = (b&d) + ((b^d)&c)
 * - 20 more rounds of f1(b,c,d)
 *
 * These are all scheduled for near-optimal performance on a G4.
 * The G4 is a 3-issue out-of-order machine with 3 ALUs, but it can only
 * *consider* starting the oldest 3 instructions per cycle.  So to get
 * maximum performace out of it, you have to treat it as an in-order
 * machine.  Which means interleaving the computation round t with the
 * computation of W[t+4].
 *
 * The first 16 rounds use W values loaded directly from memory, while the
 * remianing 64 use values computed from those first 16.  We preload
 * 4 values before starting, so there are three kinds of rounds:
 * - The first 12 (all f0) also load the W values from memory.
 * - The next 64 compute W(i+4) in parallel. 8*f0, 20*f1, 20*f2, 16*f1.
 * - The last 4 (all f1) do not do anything with W.
 *
 * Therefore, we have 5 different round functions:
 * STEPD0(t,s) - Perform round t
 * STEPD0_UPDATE(t,s) - Perform round t and compute W(s).  s >= 16.
 * STEPD1_UPDATE(t,s)
 * STEPD2_UPDATE(t,s)
 * STEPD1(t) - Perform round t with no load or update.
 *
 * There's also provision for inserting an instruction to start loading
 * the new K value after it's last used in the given step.
 * 
 * The G5 is more fully out-of-order, and can find the parallelism
 * by itself.  The big limit is that it has a 2-cycle ALU latency, so
 * even though it's 2-way, the code has to be scheduled as if it's
 * 4-way, which can be a limit.  To help it, we try to schedule the
 * read of RA(t) as late as possible so it doesn't stall waiting for
 * the previous round's RE(t-1), and we try to rotate RB(t) as early
 * as possible while reading RC(t) (= RB(t-1)) as late as possible.
 */

/*
 * Okay, we need a naked version of STEPD0.  It's 9 instructions.
 * Can that be done in 3 cycles, WITHOUT using W(s) as a temp?
 * NO.  So we need W(s) as a temp.  That can be arranged with some
 * clever scheduling.
 */
#define STEPD0(t,s) \
/* spare slot */      add RE(t),RE(t),W(t); andc   %r0,RD(t),RB(t); \
add RE(t),RE(t),%r0;  and W(s),RC(t),RB(t); rotlwi %r0,RA(t),5;     \
add RE(t),RE(t),W(s); add %r0,%r0,%r21;     rotlwi RB(t),RB(t),30;  \
add RE(t),RE(t),%r0;

/*
 * This can execute starting with 2 out of 3 possible moduli, so it
 * does 2 rounds in 9 cycles, 4.5 cycles/round.
 */
#define STEPD0_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); andc   %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r0;  and    %r0,RC(t),RB(t); xor    W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     xor    W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r21; loadk; rotlwi RB(t),RB(t),30;  rotlwi W(s),W(s),1;     \
add RE(t),RE(t),%r0

/* Nicely optimal.  Conveniently, also the most common. */
#define STEPD1_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); xor    %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r21; loadk; xor %r0,%r0,RC(t);  xor W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     xor    W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r0;  rotlwi RB(t),RB(t),30;  rotlwi W(s),W(s),1

/*
 * The naked version, no UPDATE, for the last 4 rounds.  3 cycles per.
 * We could use W(s) as a temp register, but we don't need it.
 */
#define STEPD1(t) \
                      add   RE(t),RE(t),W(t); xor    %r0,RD(t),RB(t); \
add RE(t),RE(t),%r21; xor    %r0,%r0,RC(t);   rotlwi RB(t),RB(t),30;  \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     /* spare slot */        \
add RE(t),RE(t),%r0

/* 5 cycles per */
#define STEPD2_UPDATE(t,s,loadk...) \
add RE(t),RE(t),W(t); and    %r0,RD(t),RB(t); xor    W(s),W((s)-16),W((s)-3); \
add RE(t),RE(t),%r0;  xor    %r0,RD(t),RB(t); xor    W(s),W(s),W((s)-8);      \
add RE(t),RE(t),%r21; loadk; and %r0,%r0,RC(t);  xor W(s),W(s),W((s)-14);     \
add RE(t),RE(t),%r0;  rotlwi %r0,RA(t),5;     rotlwi W(s),W(s),1;             \
add RE(t),RE(t),%r0;  rotlwi RB(t),RB(t),30

#define STEP0_LOAD4(t,s)		\
	STEPD0_LOAD(t,s);		\
	STEPD0_LOAD((t+1),(s)+1);	\
	STEPD0_LOAD((t)+2,(s)+2);	\
	STEPD0_LOAD((t)+3,(s)+3);

#define STEP0_4(t,s)		\
	STEPD0(t,s);		\
	STEPD0((t+1),(s)+1);	\
	STEPD0((t)+2,(s)+2);	\
	STEPD0((t)+3,(s)+3);

#define STEP1_4(t)		\
	STEPD1(t);		\
	STEPD1((t+1));		\
	STEPD1((t)+2);		\
	STEPD1((t)+3);

#define STEPUP4(fn, t, s, loadk...)		\
	STEP##fn##_UPDATE(t,s,);		\
	STEP##fn##_UPDATE((t)+1,(s)+1,);	\
	STEP##fn##_UPDATE((t)+2,(s)+2,);	\
	STEP##fn##_UPDATE((t)+3,(s)+3,loadk)

#define STEPUP20(fn, t, s, loadk...)	\
	STEPUP4(fn, t, s,);		\
	STEPUP4(fn, (t)+4, (s)+4,);	\
	STEPUP4(fn, (t)+8, (s)+8,);	\
	STEPUP4(fn, (t)+12, (s)+12,);	\
	STEPUP4(fn, (t)+16, (s)+16, loadk)

	.globl	sha1_core
sha1_core:
	stwu	%r1,-80(%r1)
	stmw	%r13,4(%r1)

	/* Load up A - E */
	lmw	%r27,0(%r3)

	mtctr	%r5

1:
	lswi	W(0),%r4,32
	lis	%r21,0x5a82
	addi	%r4,%r4,32
	mr	RE(0),%r31
	mr	RD(0),%r30
	mr	RC(0),%r29
	ori	%r21,%r21,0x7999	/* K0-19 */
	mr	RB(0),%r28
	mr	RA(0),%r27

	STEP0_4(0, 8)
	STEP0_4(4, 12)
	lswi	W(8),%r4,32
	STEPUP4(D0, 8, 16,)
	STEPUP4(D0, 12, 20,)
	STEPUP4(D0, 16, 24, lis %r21,0x6ed9)

	ori	%r21,%r21,0xeba1	/* K20-39 */
	STEPUP20(D1, 20, 28, lis %r21,0x8f1b)

	ori	%r21,%r21,0xbcdc	/* K40-59 */
	STEPUP20(D2, 40, 48, lis %r21,0xca62)

	ori	%r21,%r21,0xc1d6	/* K60-79 */
	STEPUP4(D1, 60, 68,)
	STEPUP4(D1, 64, 72,)
	STEPUP4(D1, 68, 76,)
	addi	%r4,%r4,32
	STEP1_4(72);
	STEP1_4(76);

	/* Add results to original values */
	add	%r31,%r31,RE(0)
	add	%r30,%r30,RD(0)
	add	%r29,%r29,RC(0)
	add	%r28,%r28,RB(0)
	add	%r27,%r27,RA(0)

	bdnz	1b

	/* Save final hash, restore registers, and return */
	stmw	%r27,0(%r3)
	lmw	%r13,4(%r1)
	addi	%r1,%r1,80
	blr

^ permalink raw reply

* Q about i2c controller on mpc8245
From: Reeve Yang @ 2006-06-23  1:06 UTC (permalink / raw)
  To: linuxppc-dev

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

Hello,

I'm new to this list and wish to get help from it since I'm currently
developing a switch box based on mpc8245, the kernel I'm using is 2.6.14.

Now I'm trying to bring up the I2C controller then I2C devices. Is fsl-i2c
the driver for I2C controller of MPC8245? I enabled that driver and it was
installed, but there is no any device found. Why is it like that? Following
are the dump from sysfs.

/ # systool -b platform -d
Bus = "platform"

  Device = "serial8250"
  Device = "serial8250.0"
  Device = "serial8250.1"

/ # systool -b platform -D
Bus = "platform"

  Driver = "fsl-i2c"

  Driver = "serial8250"
    Devices using "serial8250" are:
      Device = "serial8250"

      Device = "serial8250.0"

      Device = "serial8250.1"

In the booting sequence, I got following error message:

PCI: Probing PCI hardware
PCI: Cannot allocate resource region 1 of device 0000:00:00.0
fsl-i2c.1: failed to claim resource 0
unable to register device 0
fsl-dma.0: failed to claim resource 0
unable to register device 1
fsl-dma.1: failed to claim resource 0
unable to register device 2

Does this error make device undetected? What might be the reason for above
errors? I'd appreciate if you could shed some lights.

Regards,

- Reeve

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

^ permalink raw reply

* Re: [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Segher Boessenkool @ 2006-06-23  0:28 UTC (permalink / raw)
  To: Mike Kravetz
  Cc: Bryan Rosenburg, linuxppc-dev, Nathan Lynch, Arnd Bergmann,
	Christopher Yeoh
In-Reply-To: <20060622225609.GA4877@w-mikek2.ibm.com>

> Statistic files are moved to debugfs, and remain split out by CPU.

Having done some if this myself long ago, I really like to see these
per-cpu statistics.  "Not useful" in real life, but for most testcases
they're invaluable.  It would be useful to also add a "total" column
as well, of course, but it can also be done in userland.


Segher

^ permalink raw reply

* Re: [PATCH] Use IRQ and senses from OF-tree on 8641hpcn.
From: Benjamin Herrenschmidt @ 2006-06-23  0:11 UTC (permalink / raw)
  To: Jon Loeliger; +Cc: linuxppc-dev@ozlabs.org
In-Reply-To: <1150999473.9022.79.camel@cashmere.sps.mot.com>


> -static void __devinit quirk_ali1575(struct pci_dev *dev)
> +static int __init get_pci_irq_from_of(struct pci_controller *hose,
> +				   int slot, int pin)
> +{
> +	struct device_node *node;
> +	unsigned long *interrupt, *interrupt_mask;
> +	int len, mask_len;
> +	int shift, i;
> +	int irq = 0;
> +
> +	if (!hose) {
> +		printk(KERN_ERR "No PCI hose found!\n");
> +		return -EFAULT;
> +	}
> +
> +	node = (struct device_node *)hose->arch_data;
> +	interrupt = (unsigned long *)get_property(node,
> +			"interrupt-map", &len);
> +	interrupt_mask = (unsigned long *)get_property(node,
> +			"interrupt-map-mask", &mask_len);
> +	if (!interrupt || !interrupt_mask) {
> +		printk(KERN_ERR "No PCI interrupt-map or interrupt-map-mask"
> +				"property in OpenFirmware device tree!\n");
> +		return -EFAULT;
> +	}
> +	shift = __ilog2((~interrupt_mask[0] + 1) & 0xffff);

Nice hack :)

But not something mergeable as it strictly relies on the specific format
of the interrupt map on that platform :) I have a generic parser on the
way, it's hot and will be released for public consumption later today or
this week-end along with the rest of the irq patches.

I'll need you guys to help porting the few embedded boards already in
arch/powerpc.

Ben.

> +	/*
> +	 * Find matched irq in interrupt-map node of OF-tree.
> +	 *
> +	 * interrupt-map entries format:
> +	 * <slot>     <pin> <interrupt-parent> <irq#>
> +	 *  8800  0 0   1         40000           3   0
> +	 */
> +	pr_debug("PCI slot %x, pin %d ", slot, pin);
> +	for (i = 0; i < (len / 7); i++)
> +		if (((interrupt[i * 7] & interrupt_mask[0]) == (slot << shift))
> +				&& (interrupt[i * 7 + 3] == pin))
> +			irq = interrupt[i * 7 + 5] & interrupt_mask[3];
> +	pr_debug("irq %d\n", irq);
> +
> +	if (!irq)
> +		printk(KERN_WARNING "PCI Slot %d, Pin %d device "
> +				"has no matched irq!\n", slot, pin);
> +
> +	return irq;
> +}
> +
> +static int __init mpc86xx_irq_fixup(struct pci_dev *dev)
> +{
> +	struct pci_controller *hose = NULL;
> +	int pin, slot;
> +
> +	hose = pci_bus_to_hose(dev->bus->number);
> +	if (!hose) {
> +		printk(KERN_ERR "No PCI hose found!\n");
> +		return -EFAULT;
> +	}
> +
> +	pin = dev->pin;
> +	if (dev->bus->number != hose->first_busno) {
> +		do {
> +			pin = ((pin-1) + PCI_SLOT(dev->devfn)) %4 + 1;
> +			/* Move up the chain of bridges. */
> +			dev = dev->bus->self;
> +		} while (dev->bus->self);
> +		/* The slot is the idsel of the last bridge. */
> +	}
> +	slot = PCI_SLOT(dev->devfn);
> +
> +	return get_pci_irq_from_of(hose, slot, pin);
> +}
> +
> +void __init mpc86xx_pcibios_fixup(void)
> +{
> +	struct pci_dev *dev = NULL;
> +
> +	for_each_pci_dev(dev) {
> +		dev->irq = mpc86xx_irq_fixup(dev);
> +		if (dev->irq < 0)
> +			return;
> +		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
> +	}
> +}
> +
> +enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH};
> +const unsigned char uli1575_irq_route_table[16] = {
> +	0, 	/* 0: Reserved */
> +	0x8, 	/* 1: 0b1000 */
> +	0, 	/* 2: Reserved */
> +	0x2,	/* 3: 0b0010 */
> +	0x4,	/* 4: 0b0100 */
> +	0x5, 	/* 5: 0b0101 */
> +	0x7,	/* 6: 0b0111 */
> +	0x6,	/* 7: 0b0110 */
> +	0, 	/* 8: Reserved */
> +	0x1,	/* 9: 0b0001 */
> +	0x3,	/* 10: 0b0011 */
> +	0x9,	/* 11: 0b1001 */
> +	0xb,	/* 12: 0b1011 */
> +	0, 	/* 13: Reserved */
> +	0xd,	/* 14, 0b1101 */
> +	0xf,	/* 15, 0b1111 */
> +};
> +
> +
> +static void __devinit quirk_uli1575(struct pci_dev *dev)
>  {
>  	unsigned short temp;
> +	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
> +	int i, irq;
> +	unsigned char irq2pin[16];
> +	unsigned long pirq_map_word = 0;
> +
> +	if (!hose) {
> +		printk(KERN_ERR "No PCI hose!\n");
> +		return;
> +	}
>  
>  	/*
> -	 * ALI1575 interrupts route table setup:
> +	 * ULI1575 interrupts route setup
> +	 */
> +	memset(irq2pin, 0, 16); /* Initialize default value 0 */
> +
> +	/*
> +	 * PIRQA -> PIRQD mapping read from OF-tree
> +	 *
> +	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
> +	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
> +	 */
> +	for (i = 0; i < 4; i++){
> +		irq = get_pci_irq_from_of(hose, 17, i + 1);
> +		if (irq >= 0 && irq <= 15)
> +			irq2pin[irq] = PIRQA + i;
> +	}
> +
> +	/*
> +	 * PIRQE -> PIRQF mapping set manually
>  	 *
>  	 * IRQ pin   IRQ#
> -	 * PIRQA ---- 3
> -	 * PIRQB ---- 4
> -	 * PIRQC ---- 5
> -	 * PIRQD ---- 6
>  	 * PIRQE ---- 9
>  	 * PIRQF ---- 10
>  	 * PIRQG ---- 11
>  	 * PIRQH ---- 12
> -	 *
> -	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
> -	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
>  	 */
> -	pci_write_config_dword(dev, 0x48, 0xb9317542);
> +	for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i;
>  
> -	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
> -	pci_write_config_byte(dev, 0x86, 0x0c);
> +	/* Set IRQ-PIRQ Mapping to ULI1575 */
> +	for (i = 0; i < 16; i++)
> +		if (irq2pin[i])
> +			pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
> +				<< ((irq2pin[i] - PIRQA) * 4);
>  
> -	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
> -	pci_write_config_byte(dev, 0x87, 0x0d);
> +	DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n",
> +			pirq_map_word);
> +	pci_write_config_dword(dev, 0x48, pirq_map_word);
>  
> -	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
> -	pci_write_config_byte(dev, 0x88, 0x0f);
> +#define ULI1575_SET_DEV_IRQ(slot, pin, reg) 				\
> +	do { 								\
> +		int irq; 						\
> +		irq = get_pci_irq_from_of(hose, slot, pin); 		\
> +		if (irq >= 0 && irq <=15) 				\
> +			pci_write_config_byte(dev, reg, irq2pin[irq]); 	\
> +	} while(0)
>  
> -	/* USB 2.0 controller, interrupt: PIRQ7 */
> -	pci_write_config_byte(dev, 0x74, 0x06);
> +	/* USB 1.1 OHCI controller 1, slot 28, pin 1 */
> +	ULI1575_SET_DEV_IRQ(28, 1, 0x86);
>  
> -	/* Audio controller, interrupt: PIRQE */
> -	pci_write_config_byte(dev, 0x8a, 0x0c);
> +	/* USB 1.1 OHCI controller 2, slot 28, pin 2 */
> +	ULI1575_SET_DEV_IRQ(28, 2, 0x87);
>  
> -	/* Modem controller, interrupt: PIRQF */
> -	pci_write_config_byte(dev, 0x8b, 0x0d);
> +	/* USB 1.1 OHCI controller 3, slot 28, pin 3 */
> +	ULI1575_SET_DEV_IRQ(28, 3, 0x88);
>  
> -	/* HD audio controller, interrupt: PIRQG */
> -	pci_write_config_byte(dev, 0x8c, 0x0e);
> +	/* USB 2.0 controller, slot 28, pin 4 */
> +	irq = get_pci_irq_from_of(hose, 28, 4);
> +	if (irq >= 0 && irq <=15)
> +		pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
>  
> -	/* Serial ATA interrupt: PIRQD */
> -	pci_write_config_byte(dev, 0x8d, 0x0b);
> +	/* Audio controller, slot 29, pin 1 */
> +	ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
>  
> -	/* SMB interrupt: PIRQH */
> -	pci_write_config_byte(dev, 0x8e, 0x0f);
> +	/* Modem controller, slot 29, pin 2 */
> +	ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
>  
> -	/* PMU ACPI SCI interrupt: PIRQH */
> -	pci_write_config_byte(dev, 0x8f, 0x0f);
> +	/* HD audio controller, slot 29, pin 3 */
> +	ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
> +
> +	/* SMB interrupt: slot 30, pin 1 */
> +	ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
> +
> +	/* PMU ACPI SCI interrupt: slot 30, pin 2 */
> +	ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
> +
> +	/* Serial ATA interrupt: slot 31, pin 1 */
> +	ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
>  
>  	/* Primary PATA IDE IRQ: 14
>  	 * Secondary PATA IDE IRQ: 15
>  	 */
> -	pci_write_config_byte(dev, 0x44, 0x3d);
> -	pci_write_config_byte(dev, 0x75, 0x0f);
> +	pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]);
> +	pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
>  
>  	/* Set IRQ14 and IRQ15 to legacy IRQs */
>  	pci_read_config_word(dev, 0x46, &temp);
> @@ -277,6 +421,8 @@ static void __devinit quirk_ali1575(stru
>  	 */
>  	outb(0xfa, 0x4d0);
>  	outb(0x1e, 0x4d1);
> +
> +#undef ULI1575_SET_DEV_IRQ
>  }
>  
>  static void __devinit quirk_uli5288(struct pci_dev *dev)
> @@ -319,7 +465,7 @@ static void __devinit early_uli5249(stru
>  	dev->class |= 0x1;
>  }
>  
> -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
>  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
>  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
>  DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);

^ permalink raw reply

* [PATCH 3/3] powerpc: Instrument Hypervisor Calls: add debugfs files
From: Mike Kravetz @ 2006-06-22 23:00 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Bryan Rosenburg, Christopher Yeoh, Nathan Lynch, Arnd Bergmann
In-Reply-To: <20060622225609.GA4877@w-mikek2.ibm.com>

Make statistics available via files in debugfs.

--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall_inst.c linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-06-22 23:02:50.000000000 +0000
+++ linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-06-22 23:03:55.000000000 +0000
@@ -217,3 +217,94 @@ long plpar_hcall_9arg_9ret(unsigned long
 	preempt_enable();
 	return rc;
 }
+
+/*
+ * Routines for displaying the statistics in debugfs
+ */
+static void *hc_start(struct seq_file *m, loff_t *pos)
+{
+	if ((int)*pos < MAX_HCALL_OPCODES)
+		return (void *)(unsigned long)(*pos + 1);
+
+	return NULL;
+}
+
+static void *hc_next(struct seq_file *m, void *p, loff_t * pos)
+{
+	++*pos;
+
+	return hc_start(m, pos);
+}
+
+static void hc_stop(struct seq_file *m, void *p)
+{
+}
+
+static int hc_show(struct seq_file *m, void *p)
+{
+	unsigned long h_num = (unsigned long)p;
+	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+
+	if (hs[h_num].num_calls)
+		seq_printf(m, "%lu %lu %lu\n", h_num<<2, hs[h_num].num_calls,
+			   hs[h_num].total_time);
+
+	return 0;
+}
+
+static struct seq_operations hcall_inst_seq_ops = {
+        .start = hc_start,
+        .next  = hc_next,
+        .stop  = hc_stop,
+        .show  = hc_show
+};
+
+static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+{
+	int rc;
+	struct seq_file *seq;
+
+	rc = seq_open(file, &hcall_inst_seq_ops);
+	seq = file->private_data;
+	seq->private = file->f_dentry->d_inode->u.generic_ip;
+
+	return rc;
+}
+
+static struct file_operations hcall_inst_seq_fops = {
+	.open = hcall_inst_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+#define	HCALL_ROOT_DIR		"hcall_inst"
+#define CPU_NAME_BUF_SIZE	32
+
+static int __init hcall_inst_init(void)
+{
+	struct dentry *hcall_root;
+	struct dentry *hcall_file;
+	char cpu_name_buf[CPU_NAME_BUF_SIZE];
+	int cpu;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		return 0;
+
+	hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
+	if (!hcall_root)
+		return -ENOMEM;
+
+	for_each_cpu(cpu) {
+		snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu);
+		hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO,
+						 hcall_root,
+						 per_cpu(hcall_stats, cpu),
+						 &hcall_inst_seq_fops);
+		if (!hcall_file)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+__initcall(hcall_inst_init);

^ permalink raw reply

* [PATCH 0/3] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-06-22 22:56 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Bryan Rosenburg, Christopher Yeoh, Nathan Lynch, Arnd Bergmann

Here is an updated version of the hcall instrumentation patches.
Unfortunately, I have not been able to spend as much time as I
would like on this (and it seems that will continue).  

This version addresses all comments received except Arnd's issue
with an #ifdef for each function in the assembly file.  I like
Jimi's suggestion for creating macros(which could also minimize
the #ifdefs), but have not got around to implementing this.
Suggestions of others way to accomplish this are welcome.

Statistic files are moved to debugfs, and remain split out by CPU.
After some thought, disable/enable of preemption was added around
the statistic gathering(mostly for timing).

-- 
Mike

^ permalink raw reply

* [PATCH 2/3] powerpc: Instrument Hypervisor Calls: add wrappers
From: Mike Kravetz @ 2006-06-22 22:58 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Bryan Rosenburg, Christopher Yeoh, Nathan Lynch, Arnd Bergmann
In-Reply-To: <20060622225609.GA4877@w-mikek2.ibm.com>

Add wrappers which perform the actual hypervisor call instrumentation.

--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr linux-2.6.17.1/arch/powerpc/Kconfig.debug linux-2.6.17.1.work/arch/powerpc/Kconfig.debug
--- linux-2.6.17.1/arch/powerpc/Kconfig.debug	2006-06-20 09:31:55.000000000 +0000
+++ linux-2.6.17.1.work/arch/powerpc/Kconfig.debug	2006-06-22 22:58:58.000000000 +0000
@@ -18,6 +18,19 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
+config HCALL_STATS
+	bool "Hypervisor call instrumentation"
+	depends on PPC_PSERIES && DEBUG_FS
+	help
+	  Adds code to keep track of the number of hypervisor calls made and
+	  the amount of time spent in hypervisor calls.  A directory named
+	  hcall_inst is added at the root of the debugfs filesystem.  Within
+	  the hcall_inst directory are files that contain CPU specific call
+	  statistics.
+
+	  This option will add a small amount of overhead to all hypervisor
+	  calls.
+
 config DEBUGGER
 	bool "Enable debugger hooks"
 	depends on DEBUG_KERNEL
diff -Naupr linux-2.6.17.1/arch/powerpc/platforms/pseries/Makefile linux-2.6.17.1.work/arch/powerpc/platforms/pseries/Makefile
--- linux-2.6.17.1/arch/powerpc/platforms/pseries/Makefile	2006-06-20 09:31:55.000000000 +0000
+++ linux-2.6.17.1.work/arch/powerpc/platforms/pseries/Makefile	2006-06-22 22:58:58.000000000 +0000
@@ -9,3 +9,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
diff -Naupr linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall.S linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall.S
--- linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall.S	2006-06-20 09:31:55.000000000 +0000
+++ linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall.S	2006-06-22 22:58:58.000000000 +0000
@@ -25,7 +25,11 @@
 			unsigned long *out2,		R9
 			unsigned long *out3);		R10
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_base)
+#else
 _GLOBAL(plpar_hcall)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -52,7 +56,19 @@ _GLOBAL(plpar_hcall)
 
 
 /* Simple interface with no output values (other than status) */
+#ifdef CONFIG_HCALL_STATS
+/*
+ * A special 'indirect' call to a C based wrapper if statistics are desired.
+ * See plpar_hcall_norets_C function header for more details.
+ */
+_GLOBAL(plpar_hcall_norets)
+	b	plpar_hcall_norets_C
+
+
+_GLOBAL(plpar_hcall_norets_base)
+#else
 _GLOBAL(plpar_hcall_norets)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -76,7 +92,11 @@ _GLOBAL(plpar_hcall_norets)
 			unsigned long arg8,		112(R1)
 			unsigned long *out1);		120(R1)
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_8arg_2ret_base)
+#else
 _GLOBAL(plpar_hcall_8arg_2ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -102,7 +122,11 @@ _GLOBAL(plpar_hcall_8arg_2ret)
 		 	unsigned long *out3,		R10
 		 	unsigned long *out4);		112(R1)
  */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_4out_base)
+#else
 _GLOBAL(plpar_hcall_4out)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -144,7 +168,11 @@ _GLOBAL(plpar_hcall_4out)
 			 unsigned long *out6,		102(R1)
 			 unsigned long *out7);		100(R1)
 */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_7arg_7ret_base)
+#else
 _GLOBAL(plpar_hcall_7arg_7ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
@@ -193,7 +221,11 @@ _GLOBAL(plpar_hcall_7arg_7ret)
 			 unsigned long *out8,		 94(R1)
 		         unsigned long *out9,            92(R1)
 */
+#ifdef CONFIG_HCALL_STATS
+_GLOBAL(plpar_hcall_9arg_9ret_base)
+#else
 _GLOBAL(plpar_hcall_9arg_9ret)
+#endif
 	HMT_MEDIUM
 
 	mfcr	r0
diff -Naupr linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall_inst.c linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- linux-2.6.17.1/arch/powerpc/platforms/pseries/hvCall_inst.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.17.1.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-06-22 23:00:47.000000000 +0000
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2006 Mike Kravetz IBM Corporation
+ *
+ * Hypervisor Call Instrumentation
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <asm/hvcall.h>
+#include <asm/firmware.h>
+
+DEFINE_PER_CPU(struct hcall_stats[MAX_HCALL_OPCODES+1], hcall_stats);
+
+/*
+ * Common update of the per-CPU/per-hcall statistics
+ */
+static inline void update_stats(unsigned long opcode, unsigned long t_before)
+{
+	unsigned long op_index = opcode >> 2;
+	struct hcall_stats *hs = &__get_cpu_var(hcall_stats[op_index]);
+
+	hs->total_time += (mfspr(SPRN_PURR) - t_before);
+	hs->num_calls++;
+}
+
+/*
+ * plpar_hcall wrapper
+ */
+long plpar_hcall(unsigned long opcode,
+                 unsigned long arg1,
+                 unsigned long arg2,
+                 unsigned long arg3,
+                 unsigned long arg4,
+                 unsigned long *out1,
+                 unsigned long *out2,
+                 unsigned long *out3)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_base(opcode, arg1, arg2, arg3, arg4, out1, out2, out3);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * A C based wrapper for plpar_hcall_norets
+ * The wrapper for plpar_hcall_norets is a special case because the function
+ * takes a variable number of arguments.  It is almost impossible to write a
+ * wrapper for a function that takes a variable number of arguments in C.
+ * Therefore, there is an assembly routine in hvCall.S that simply branches
+ * to this C wrapper.  This 'indirection' takes care of the variable arguments
+ * issue.  This C wrapper has a fixed maximum number of arguments.
+ */
+long plpar_hcall_norets_C(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_norets_base(opcode, arg1, arg2, arg3, arg4, arg5,
+				     arg6);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * plpar_hcall_8arg_2ret wrapper
+ */
+long plpar_hcall_8arg_2ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long arg8,
+                           unsigned long *out1)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_8arg_2ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, arg8, out1);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * plpar_hcall_4out wrapper
+ */
+long plpar_hcall_4out(unsigned long opcode,
+                      unsigned long arg1,
+                      unsigned long arg2,
+                      unsigned long arg3,
+                      unsigned long arg4,
+                      unsigned long *out1,
+                      unsigned long *out2,
+                      unsigned long *out3,
+                      unsigned long *out4)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_4out_base(opcode, arg1, arg2, arg3, arg4, out1,
+				   out2, out3, out4);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * plpar_hcall_7arg_7ret wrapper
+ */
+long plpar_hcall_7arg_7ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long *out1,
+                           unsigned long *out2,
+                           unsigned long *out3,
+                           unsigned long *out4,
+                           unsigned long *out5,
+                           unsigned long *out6,
+                           unsigned long *out7)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_7arg_7ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, out1, out2, out3, out4,
+					out5, out6, out7);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
+
+/*
+ * plpar_hcall_9arg_9ret wrapper
+ */
+long plpar_hcall_9arg_9ret(unsigned long opcode,
+                           unsigned long arg1,
+                           unsigned long arg2,
+                           unsigned long arg3,
+                           unsigned long arg4,
+                           unsigned long arg5,
+                           unsigned long arg6,
+                           unsigned long arg7,
+                           unsigned long arg8,
+                           unsigned long arg9,
+                           unsigned long *out1,
+                           unsigned long *out2,
+                           unsigned long *out3,
+                           unsigned long *out4,
+                           unsigned long *out5,
+                           unsigned long *out6,
+                           unsigned long *out7,
+                           unsigned long *out8,
+                           unsigned long *out9)
+{
+	long rc;
+	unsigned long t_before;
+
+	preempt_disable();
+	t_before = mfspr(SPRN_PURR);
+	rc = plpar_hcall_9arg_9ret_base(opcode, arg1, arg2, arg3, arg4, arg5,
+					arg6, arg7, arg8, arg9, out1, out2,
+					out3, out4, out5, out6, out7, out8,
+					out9);
+
+	update_stats(opcode, t_before);
+	preempt_enable();
+	return rc;
+}
diff -Naupr linux-2.6.17.1/include/asm-powerpc/hvcall.h linux-2.6.17.1.work/include/asm-powerpc/hvcall.h
--- linux-2.6.17.1/include/asm-powerpc/hvcall.h	2006-06-22 22:56:46.000000000 +0000
+++ linux-2.6.17.1.work/include/asm-powerpc/hvcall.h	2006-06-22 22:58:58.000000000 +0000
@@ -292,6 +292,86 @@ long plpar_hcall_9arg_9ret(unsigned long
 			   unsigned long *out8,
 			   unsigned long *out9);
 
+
+/* For hcall instrumentation.  One structure per-hcall, per-CPU */
+struct hcall_stats {
+	unsigned long	num_calls;	/* number of calls (on this CPU) */
+	unsigned long	total_time;	/* total cputime (PURR) of calls. */
+};
+
+/* If Hypervisor call instrumentation is enabled, the assembly routine
+ * names are changed from 'plpar_hcall*' to 'plpar_hcall*_base' and
+ * 'plpar_hcall*' routines become instrumented wrappers.  The following
+ * are declarations for the renamed 'plpar_hcall*_base' routines.
+ */
+long plpar_hcall_base (unsigned long opcode,
+		       unsigned long arg1,
+		       unsigned long arg2,
+		       unsigned long arg3,
+		       unsigned long arg4,
+		       unsigned long *out1,
+		       unsigned long *out2,
+		       unsigned long *out3);
+
+long plpar_hcall_norets_base(unsigned long opcode, ...);
+
+long plpar_hcall_8arg_2ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long arg8,
+				unsigned long *out1);
+
+long plpar_hcall_4out_base(unsigned long opcode,
+			   unsigned long arg1,
+			   unsigned long arg2,
+			   unsigned long arg3,
+			   unsigned long arg4,
+			   unsigned long *out1,
+			   unsigned long *out2,
+			   unsigned long *out3,
+			   unsigned long *out4);
+
+long plpar_hcall_7arg_7ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long *out1,
+				unsigned long *out2,
+				unsigned long *out3,
+				unsigned long *out4,
+				unsigned long *out5,
+				unsigned long *out6,
+				unsigned long *out7);
+
+long plpar_hcall_9arg_9ret_base(unsigned long opcode,
+				unsigned long arg1,
+				unsigned long arg2,
+				unsigned long arg3,
+				unsigned long arg4,
+				unsigned long arg5,
+				unsigned long arg6,
+				unsigned long arg7,
+				unsigned long arg8,
+				unsigned long arg9,
+				unsigned long *out1,
+				unsigned long *out2,
+				unsigned long *out3,
+				unsigned long *out4,
+				unsigned long *out5,
+				unsigned long *out6,
+				unsigned long *out7,
+				unsigned long *out8,
+				unsigned long *out9);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */

^ permalink raw reply

* [PATCH 1/3] powerpc: Instrument Hypervisor Calls: merge headers
From: Mike Kravetz @ 2006-06-22 22:57 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Bryan Rosenburg, Christopher Yeoh, Nathan Lynch, Arnd Bergmann
In-Reply-To: <20060622225609.GA4877@w-mikek2.ibm.com>

Move all the Hypervisor call definitions to to a single header file.

--
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr linux-2.6.17.1/drivers/net/ibmveth.h linux-2.6.17.1.work/drivers/net/ibmveth.h
--- linux-2.6.17.1/drivers/net/ibmveth.h	2006-06-20 09:31:55.000000000 +0000
+++ linux-2.6.17.1.work/drivers/net/ibmveth.h	2006-06-22 22:54:28.000000000 +0000
@@ -41,16 +41,6 @@
 #define IbmVethMcastRemoveFilter     0x2UL
 #define IbmVethMcastClearFilterTable 0x3UL
 
-/* hcall numbers */
-#define H_VIO_SIGNAL             0x104
-#define H_REGISTER_LOGICAL_LAN   0x114
-#define H_FREE_LOGICAL_LAN       0x118
-#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
-#define H_SEND_LOGICAL_LAN       0x120
-#define H_MULTICAST_CTRL         0x130
-#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
-#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
-
 /* hcall macros */
 #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
   plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac)
diff -Naupr linux-2.6.17.1/include/asm-powerpc/hvcall.h linux-2.6.17.1.work/include/asm-powerpc/hvcall.h
--- linux-2.6.17.1/include/asm-powerpc/hvcall.h	2006-06-20 09:31:55.000000000 +0000
+++ linux-2.6.17.1.work/include/asm-powerpc/hvcall.h	2006-06-22 22:54:28.000000000 +0000
@@ -155,9 +155,15 @@
 #define H_VIO_SIGNAL		0x104
 #define H_SEND_CRQ		0x108
 #define H_COPY_RDMA		0x110
+#define H_REGISTER_LOGICAL_LAN	0x114
+#define H_FREE_LOGICAL_LAN	0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
+#define H_SEND_LOGICAL_LAN	0x120
+#define H_MULTICAST_CTRL	0x130
 #define H_SET_XDABR		0x134
 #define H_STUFF_TCE		0x138
 #define H_PUT_TCE_INDIRECT	0x13C
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
 #define H_VTERM_PARTNER_INFO	0x150
 #define H_REGISTER_VTERM	0x154
 #define H_FREE_VTERM		0x158
@@ -187,11 +193,14 @@
 #define H_GET_HCA_INFO          0x1B8
 #define H_GET_PERF_COUNT        0x1BC
 #define H_MANAGE_TRACE          0x1C0
+#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING		0x1D8
 #define H_JOIN			0x298
 #define H_ENABLE_CRQ		0x2B0
 
+#define MAX_HCALL_OPCODES	(H_ENABLE_CRQ >> 2)
+
 #ifndef __ASSEMBLY__
 
 /* plpar_hcall() -- Generic call interface using above opcodes

^ permalink raw reply

* Re: help to run the C code on AMCC PPC 405EP Kit
From: Wolfgang Denk @ 2006-06-22 19:30 UTC (permalink / raw)
  To: Olof Johansson; +Cc: jagadeesh kalisetty, linuxppc-dev
In-Reply-To: <20060622175111.GB16973@pb15.lixom.net>

In message <20060622175111.GB16973@pb15.lixom.net> you wrote:
> 
> >      We are using AMCC PPC 405EP Taihu board, our aim is to run the C code on kit.
> 
> linuxppc-embedded@ozlabs.org is a better list to post your question
> to. Or try contacting AMCC for documentation on how to use their kit,
> since it's pretty basic stuff you're trying to get working.

...and read the DULG, see http://www.denx.de/wiki/DULG/Manual

Best regards,

Wolfgang Denk

-- 
Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
I really hate this damned machine     It never does quite what I want
I wish that they would sell it.              But only what I tell it.

^ permalink raw reply

* Re: [linux-pm] windfarm got signal
From: Pavel Machek @ 2006-06-22 13:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-pm, linuxppc-dev list
In-Reply-To: <1150847482.16662.13.camel@johannes>

Hi!

> after cpu hotplug I decided to write some fake suspend routines for
> ppc64 that always fail to see what all the drivers would say... The
> first thing I saw was during the phase where all threads are stopped,
> that windfarm got a signal!
> 
> Shortly after that, the fans were revved up fully but I guess that's
> expected if the wf control loop exits.
> 
> So now I'm trying to see *why* it got a signal there. Any ideas? Is that
> expected with pm and windfarm just does the wrong thing there by taking
> the signal as a reason to exit the control thread?
> 
> [code in question is windfarm_core.c:wf_thread_func]

See kernel/power/process.c

-- 
64 bytes from 195.113.31.123: icmp_seq=28 ttl=51 time=448769.1 ms         

^ permalink raw reply

* [PATCH] Use IRQ and senses from OF-tree on 8641hpcn.
From: Jon Loeliger @ 2006-06-22 18:04 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org

Signed-off-by: Zhang Wei <wei.zhang@freescale.com>
Signed-off-by: Jon Loeliger <jdl@freescale.com>
---
 arch/powerpc/platforms/86xx/mpc8641_hpcn.h |   11 -
 arch/powerpc/platforms/86xx/mpc86xx.h      |    1 
 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |  118 +---------------
 arch/powerpc/platforms/86xx/pci.c          |  212 ++++++++++++++++++++++++----
 4 files changed, 187 insertions(+), 155 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
index 5042253..747e549 100644
--- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -17,17 +17,6 @@ #define __MPC8641_HPCN_H__
 #include <linux/config.h>
 #include <linux/init.h>
 
-/* PCI interrupt controller */
-#define PIRQA		3
-#define PIRQB		4
-#define PIRQC		5
-#define PIRQD		6
-#define PIRQ7		7
-#define PIRQE		9
-#define PIRQF		10
-#define PIRQG		11
-#define PIRQH		12
-
 /* PCI-Express memory map */
 #define MPC86XX_PCIE_LOWER_IO        0x00000000
 #define MPC86XX_PCIE_UPPER_IO        0x00ffffff
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
index e3c9e4f..96010c6 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx.h
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -16,6 +16,7 @@ #define __MPC86XX_H__
  */
 
 extern int __init add_bridge(struct device_node *dev);
+extern void mpc86xx_pcibios_fixup(void);
 
 extern void __init setup_indirect_pcie(struct pci_controller *hose,
 				       u32 cfg_addr, u32 cfg_data);
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 483c21d..092bca3 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -44,93 +44,24 @@ unsigned long pci_dram_offset = 0;
 #endif
 
 
-/*
- * Internal interrupts are all Level Sensitive, and Positive Polarity
- */
-
-static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: Reserved */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3 transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3 receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3 error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4 transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4 receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4 error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO error/write-port unit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO outbound doorbell */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO inbound doorbell */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO outbound message unit 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO inbound message unit 1 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO outbound message unit 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO inbound message unit 2 */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
-	0x0,						/* External  0: */
-	0x0,						/* External  1: */
-	0x0,						/* External  2: */
-	0x0,						/* External  3: */
-	0x0,						/* External  4: */
-	0x0,						/* External  5: */
-	0x0,						/* External  6: */
-	0x0,						/* External  7: */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis FPGA */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI 8259 INTR Cascade */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad ETH PHY */
-	0x0,						/* External 11: */
-	0x0,
-	0x0,
-	0x0,
-	0x0,
-};
-
-
 void __init
 mpc86xx_hpcn_init_irq(void)
 {
 	struct mpic *mpic1;
 	phys_addr_t openpic_paddr;
+	int irq_count =
+		NR_IRQS - NUM_8259_INTERRUPTS - 4; /* leave room for IPIs */
+	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS - 4];
 
+	prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS - 4);
 	/* Determine the Physical Address of the OpenPIC regs */
 	openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
 
 	/* Alloc mpic structure and per isu has 16 INT entries. */
 	mpic1 = mpic_alloc(openpic_paddr,
 			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
-			16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250,
-			mpc86xx_hpcn_openpic_initsenses,
-			sizeof(mpc86xx_hpcn_openpic_initsenses),
+			16, NUM_8259_INTERRUPTS, irq_count,
+			NR_IRQS - 4, init_senses, irq_count,
 			" MPIC     ");
 	BUG_ON(mpic1 == NULL);
 
@@ -153,40 +84,6 @@ #endif
 
 
 #ifdef CONFIG_PCI
-/*
- * interrupt routing
- */
-
-int
-mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
-	static char pci_irq_table[][4] = {
-		/*
-		 *      PCI IDSEL/INTPIN->INTLINE
-		 *       A      B      C      D
-		 */
-		{PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 17 -- PCI Slot 1 */
-		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 18 -- PCI Slot 2 */
-		{0, 0, 0, 0},			/* IDSEL 19 */
-		{0, 0, 0, 0},			/* IDSEL 20 */
-		{0, 0, 0, 0},			/* IDSEL 21 */
-		{0, 0, 0, 0},			/* IDSEL 22 */
-		{0, 0, 0, 0},			/* IDSEL 23 */
-		{0, 0, 0, 0},			/* IDSEL 24 */
-		{0, 0, 0, 0},			/* IDSEL 25 */
-		{PIRQD, PIRQA, PIRQB, PIRQC},	/* IDSEL 26 -- PCI Bridge*/
-		{PIRQC, 0, 0, 0},		/* IDSEL 27 -- LAN */
-		{PIRQE, PIRQF, PIRQH, PIRQ7},	/* IDSEL 28 -- USB 1.1 */
-		{PIRQE, PIRQF, PIRQG, 0},	/* IDSEL 29 -- Audio & Modem */
-		{PIRQH, 0, 0, 0},		/* IDSEL 30 -- LPC & PMU*/
-		{PIRQD, 0, 0, 0},		/* IDSEL 31 -- ATA */
-	};
-
-	const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4;
-	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
-}
-
-
 int
 mpc86xx_exclude_device(u_char bus, u_char devfn)
 {
@@ -224,8 +121,6 @@ #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
 
-	ppc_md.pci_swizzle = common_swizzle;
-	ppc_md.pci_map_irq = mpc86xx_map_irq;
 	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
 #endif
 
@@ -316,6 +211,7 @@ define_machine(mpc86xx_hpcn) {
 	.name			= "MPC86xx HPCN",
 	.probe			= mpc86xx_hpcn_probe,
 	.setup_arch		= mpc86xx_hpcn_setup_arch,
+	.pcibios_fixup		= mpc86xx_pcibios_fixup,
 	.init_IRQ		= mpc86xx_hpcn_init_irq,
 	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
 	.get_irq		= mpic_get_irq,
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index 5180df7..a03b36f 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -199,63 +199,207 @@ int __init add_bridge(struct device_node
 	return 0;
 }
 
-static void __devinit quirk_ali1575(struct pci_dev *dev)
+static int __init get_pci_irq_from_of(struct pci_controller *hose,
+				   int slot, int pin)
+{
+	struct device_node *node;
+	unsigned long *interrupt, *interrupt_mask;
+	int len, mask_len;
+	int shift, i;
+	int irq = 0;
+
+	if (!hose) {
+		printk(KERN_ERR "No PCI hose found!\n");
+		return -EFAULT;
+	}
+
+	node = (struct device_node *)hose->arch_data;
+	interrupt = (unsigned long *)get_property(node,
+			"interrupt-map", &len);
+	interrupt_mask = (unsigned long *)get_property(node,
+			"interrupt-map-mask", &mask_len);
+	if (!interrupt || !interrupt_mask) {
+		printk(KERN_ERR "No PCI interrupt-map or interrupt-map-mask"
+				"property in OpenFirmware device tree!\n");
+		return -EFAULT;
+	}
+	shift = __ilog2((~interrupt_mask[0] + 1) & 0xffff);
+
+	/*
+	 * Find matched irq in interrupt-map node of OF-tree.
+	 *
+	 * interrupt-map entries format:
+	 * <slot>     <pin> <interrupt-parent> <irq#>
+	 *  8800  0 0   1         40000           3   0
+	 */
+	pr_debug("PCI slot %x, pin %d ", slot, pin);
+	for (i = 0; i < (len / 7); i++)
+		if (((interrupt[i * 7] & interrupt_mask[0]) == (slot << shift))
+				&& (interrupt[i * 7 + 3] == pin))
+			irq = interrupt[i * 7 + 5] & interrupt_mask[3];
+	pr_debug("irq %d\n", irq);
+
+	if (!irq)
+		printk(KERN_WARNING "PCI Slot %d, Pin %d device "
+				"has no matched irq!\n", slot, pin);
+
+	return irq;
+}
+
+static int __init mpc86xx_irq_fixup(struct pci_dev *dev)
+{
+	struct pci_controller *hose = NULL;
+	int pin, slot;
+
+	hose = pci_bus_to_hose(dev->bus->number);
+	if (!hose) {
+		printk(KERN_ERR "No PCI hose found!\n");
+		return -EFAULT;
+	}
+
+	pin = dev->pin;
+	if (dev->bus->number != hose->first_busno) {
+		do {
+			pin = ((pin-1) + PCI_SLOT(dev->devfn)) %4 + 1;
+			/* Move up the chain of bridges. */
+			dev = dev->bus->self;
+		} while (dev->bus->self);
+		/* The slot is the idsel of the last bridge. */
+	}
+	slot = PCI_SLOT(dev->devfn);
+
+	return get_pci_irq_from_of(hose, slot, pin);
+}
+
+void __init mpc86xx_pcibios_fixup(void)
+{
+	struct pci_dev *dev = NULL;
+
+	for_each_pci_dev(dev) {
+		dev->irq = mpc86xx_irq_fixup(dev);
+		if (dev->irq < 0)
+			return;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH};
+const unsigned char uli1575_irq_route_table[16] = {
+	0, 	/* 0: Reserved */
+	0x8, 	/* 1: 0b1000 */
+	0, 	/* 2: Reserved */
+	0x2,	/* 3: 0b0010 */
+	0x4,	/* 4: 0b0100 */
+	0x5, 	/* 5: 0b0101 */
+	0x7,	/* 6: 0b0111 */
+	0x6,	/* 7: 0b0110 */
+	0, 	/* 8: Reserved */
+	0x1,	/* 9: 0b0001 */
+	0x3,	/* 10: 0b0011 */
+	0x9,	/* 11: 0b1001 */
+	0xb,	/* 12: 0b1011 */
+	0, 	/* 13: Reserved */
+	0xd,	/* 14, 0b1101 */
+	0xf,	/* 15, 0b1111 */
+};
+
+
+static void __devinit quirk_uli1575(struct pci_dev *dev)
 {
 	unsigned short temp;
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+	int i, irq;
+	unsigned char irq2pin[16];
+	unsigned long pirq_map_word = 0;
+
+	if (!hose) {
+		printk(KERN_ERR "No PCI hose!\n");
+		return;
+	}
 
 	/*
-	 * ALI1575 interrupts route table setup:
+	 * ULI1575 interrupts route setup
+	 */
+	memset(irq2pin, 0, 16); /* Initialize default value 0 */
+
+	/*
+	 * PIRQA -> PIRQD mapping read from OF-tree
+	 *
+	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
+	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
+	 */
+	for (i = 0; i < 4; i++){
+		irq = get_pci_irq_from_of(hose, 17, i + 1);
+		if (irq >= 0 && irq <= 15)
+			irq2pin[irq] = PIRQA + i;
+	}
+
+	/*
+	 * PIRQE -> PIRQF mapping set manually
 	 *
 	 * IRQ pin   IRQ#
-	 * PIRQA ---- 3
-	 * PIRQB ---- 4
-	 * PIRQC ---- 5
-	 * PIRQD ---- 6
 	 * PIRQE ---- 9
 	 * PIRQF ---- 10
 	 * PIRQG ---- 11
 	 * PIRQH ---- 12
-	 *
-	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
-	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
 	 */
-	pci_write_config_dword(dev, 0x48, 0xb9317542);
+	for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i;
 
-	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
-	pci_write_config_byte(dev, 0x86, 0x0c);
+	/* Set IRQ-PIRQ Mapping to ULI1575 */
+	for (i = 0; i < 16; i++)
+		if (irq2pin[i])
+			pirq_map_word |= (uli1575_irq_route_table[i] & 0xf)
+				<< ((irq2pin[i] - PIRQA) * 4);
 
-	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
-	pci_write_config_byte(dev, 0x87, 0x0d);
+	DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n",
+			pirq_map_word);
+	pci_write_config_dword(dev, 0x48, pirq_map_word);
 
-	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x88, 0x0f);
+#define ULI1575_SET_DEV_IRQ(slot, pin, reg) 				\
+	do { 								\
+		int irq; 						\
+		irq = get_pci_irq_from_of(hose, slot, pin); 		\
+		if (irq >= 0 && irq <=15) 				\
+			pci_write_config_byte(dev, reg, irq2pin[irq]); 	\
+	} while(0)
 
-	/* USB 2.0 controller, interrupt: PIRQ7 */
-	pci_write_config_byte(dev, 0x74, 0x06);
+	/* USB 1.1 OHCI controller 1, slot 28, pin 1 */
+	ULI1575_SET_DEV_IRQ(28, 1, 0x86);
 
-	/* Audio controller, interrupt: PIRQE */
-	pci_write_config_byte(dev, 0x8a, 0x0c);
+	/* USB 1.1 OHCI controller 2, slot 28, pin 2 */
+	ULI1575_SET_DEV_IRQ(28, 2, 0x87);
 
-	/* Modem controller, interrupt: PIRQF */
-	pci_write_config_byte(dev, 0x8b, 0x0d);
+	/* USB 1.1 OHCI controller 3, slot 28, pin 3 */
+	ULI1575_SET_DEV_IRQ(28, 3, 0x88);
 
-	/* HD audio controller, interrupt: PIRQG */
-	pci_write_config_byte(dev, 0x8c, 0x0e);
+	/* USB 2.0 controller, slot 28, pin 4 */
+	irq = get_pci_irq_from_of(hose, 28, 4);
+	if (irq >= 0 && irq <=15)
+		pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]);
 
-	/* Serial ATA interrupt: PIRQD */
-	pci_write_config_byte(dev, 0x8d, 0x0b);
+	/* Audio controller, slot 29, pin 1 */
+	ULI1575_SET_DEV_IRQ(29, 1, 0x8a);
 
-	/* SMB interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x8e, 0x0f);
+	/* Modem controller, slot 29, pin 2 */
+	ULI1575_SET_DEV_IRQ(29, 2, 0x8b);
 
-	/* PMU ACPI SCI interrupt: PIRQH */
-	pci_write_config_byte(dev, 0x8f, 0x0f);
+	/* HD audio controller, slot 29, pin 3 */
+	ULI1575_SET_DEV_IRQ(29, 3, 0x8c);
+
+	/* SMB interrupt: slot 30, pin 1 */
+	ULI1575_SET_DEV_IRQ(30, 1, 0x8e);
+
+	/* PMU ACPI SCI interrupt: slot 30, pin 2 */
+	ULI1575_SET_DEV_IRQ(30, 2, 0x8f);
+
+	/* Serial ATA interrupt: slot 31, pin 1 */
+	ULI1575_SET_DEV_IRQ(31, 1, 0x8d);
 
 	/* Primary PATA IDE IRQ: 14
 	 * Secondary PATA IDE IRQ: 15
 	 */
-	pci_write_config_byte(dev, 0x44, 0x3d);
-	pci_write_config_byte(dev, 0x75, 0x0f);
+	pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]);
+	pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]);
 
 	/* Set IRQ14 and IRQ15 to legacy IRQs */
 	pci_read_config_word(dev, 0x46, &temp);
@@ -277,6 +421,8 @@ static void __devinit quirk_ali1575(stru
 	 */
 	outb(0xfa, 0x4d0);
 	outb(0x1e, 0x4d1);
+
+#undef ULI1575_SET_DEV_IRQ
 }
 
 static void __devinit quirk_uli5288(struct pci_dev *dev)
@@ -319,7 +465,7 @@ static void __devinit early_uli5249(stru
 	dev->class |= 0x1;
 }
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
-- 
2006_06_07.01.gittree_pull-dirty

^ permalink raw reply related

* [PATCH] Remove obsolete #include <linux/config.h>.
From: Jon Loeliger @ 2006-06-22 18:02 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org

Signed-off-by: Jon Loeliger <jdl@freescale.com>
---
 arch/powerpc/platforms/86xx/mpc8641_hpcn.h |    1 -
 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c |    1 -
 arch/powerpc/platforms/86xx/mpc86xx_smp.c  |    1 -
 arch/powerpc/platforms/86xx/pci.c          |    1 -
 include/asm-powerpc/mpc86xx.h              |    1 -
 5 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
index 747e549..d862a9c 100644
--- a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -14,7 +14,6 @@
 #ifndef __MPC8641_HPCN_H__
 #define __MPC8641_HPCN_H__
 
-#include <linux/config.h>
 #include <linux/init.h>
 
 /* PCI-Express memory map */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 092bca3..cf4fd04 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -12,7 +12,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
index 944ec4b..167f040 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_smp.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -10,7 +10,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
index a03b36f..dd7e3bf 100644
--- a/arch/powerpc/platforms/86xx/pci.c
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -12,7 +12,6 @@
  * option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
index d0a6718..1ed72f6 100644
--- a/include/asm-powerpc/mpc86xx.h
+++ b/include/asm-powerpc/mpc86xx.h
@@ -15,7 +15,6 @@ #ifdef __KERNEL__
 #ifndef __ASM_POWERPC_MPC86xx_H__
 #define __ASM_POWERPC_MPC86xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_PPC_86xx
-- 
2006_06_07.01.gittree_pull-dirty

^ permalink raw reply related

* [PATCH] Remove redundant STD_MMU selection.
From: Jon Loeliger @ 2006-06-22 18:01 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org

Signed-off-by: Jon Loeliger <jdl@freescale.com>
---
 arch/powerpc/platforms/86xx/Kconfig |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 3d2b21a..d1ecc0f 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -29,9 +29,4 @@ config PPC_INDIRECT_PCI_BE
 	depends on PPC_86xx
 	default y
 
-config PPC_STD_MMU
-	bool
-	depends on PPC_86xx
-	default y
-
 endmenu
-- 
2006_06_07.01.gittree_pull-dirty

^ permalink raw reply related

* [PATCH] Move I8259 selection under MPC8641HPCN board
From: Jon Loeliger @ 2006-06-22 18:00 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org

Signed-off-by: Jon Loeliger <jdl@freescale.com>
---
 arch/powerpc/Kconfig                |    1 -
 arch/powerpc/platforms/86xx/Kconfig |    1 +
 2 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index cdaa4b1..45043f0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -786,7 +786,6 @@ config GENERIC_ISA_DMA
 
 config PPC_I8259
 	bool
-	default y if MPC8641_HPCN
 	default n
 
 config PPC_INDIRECT_PCI
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
index 3a87863..3d2b21a 100644
--- a/arch/powerpc/platforms/86xx/Kconfig
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -7,6 +7,7 @@ choice
 
 config MPC8641_HPCN
 	bool "Freescale MPC8641 HPCN"
+	select PPC_I8259
 	help
 	  This option enables support for the MPC8641 HPCN board.
 
-- 
2006_06_07.01.gittree_pull-dirty

^ permalink raw reply related

* [PATCH] Remove redundant PPC_86XX check.
From: Jon Loeliger @ 2006-06-22 17:59 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org

Signed-off-by: Jon Loeliger <jdl@freescale.com>
---
 arch/powerpc/platforms/86xx/Makefile |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
index 7be796c..476a6ee 100644
--- a/arch/powerpc/platforms/86xx/Makefile
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -2,9 +2,6 @@ #
 # Makefile for the PowerPC 86xx linux kernel.
 #
 
-
-ifeq ($(CONFIG_PPC_86xx),y)
 obj-$(CONFIG_SMP)		+= mpc86xx_smp.o
-endif
 obj-$(CONFIG_MPC8641_HPCN)	+= mpc86xx_hpcn.o
 obj-$(CONFIG_PCI)		+= pci.o mpc86xx_pcie.o
-- 
2006_06_07.01.gittree_pull-dirty

^ permalink raw reply related

* Re: help to run the C code on AMCC PPC 405EP Kit
From: Olof Johansson @ 2006-06-22 17:51 UTC (permalink / raw)
  To: jagadeesh kalisetty; +Cc: linuxppc-dev
In-Reply-To: <20060622171846.18376.qmail@webmail28.rediffmail.com>

Hi,

On Thu, Jun 22, 2006 at 05:18:46PM -0000, jagadeesh kalisetty wrote:
> Hi
>      We are using AMCC PPC 405EP Taihu board, our aim is to run the C code on kit.

linuxppc-embedded@ozlabs.org is a better list to post your question
to. Or try contacting AMCC for documentation on how to use their kit,
since it's pretty basic stuff you're trying to get working.


Thanks,

Olof

^ permalink raw reply

* Re: Problem for "insmod: unresolved symbol printk"
From: Olof Johansson @ 2006-06-22 17:48 UTC (permalink / raw)
  To: Zhou Rui; +Cc: linuxppc-dev
In-Reply-To: <20060622143156.39031.qmail@web15601.mail.cnb.yahoo.com>

On Thu, Jun 22, 2006 at 10:31:56PM +0800, Zhou Rui wrote:
> Hi, all
>     I'm a newbie for linuxppc. I've tried to write a simple hello.c as a kernel module.

Hi,

http://kernelnewbies.org/  should have information on kernel module
basics, and where to find help if you still have problems.


-Olof

^ 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