aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2005-09-03 02:44:09 -0400
committerLen Brown <len.brown@intel.com>2005-09-03 02:44:09 -0400
commit129521dcc94f781890f8f668219ab79f0073ff9f (patch)
tree9f70707c88da65577f38814fe37b24c4b4957d64 /arch
parent824b558bbe2c298b165cdb54c33718994dda30bb (diff)
parentf505380ba7b98ec97bf25300c2a58aeae903530b (diff)
Merge linux-2.6 into linux-acpi-2.6 test
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig4
-rw-r--r--arch/arm/common/gic.c1
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S4
-rw-r--r--arch/arm/kernel/sys_arm.c10
-rw-r--r--arch/arm/kernel/time.c10
-rw-r--r--arch/arm/mach-ixp4xx/common.c155
-rw-r--r--arch/arm/mach-ixp4xx/coyote-pci.c7
-rw-r--r--arch/arm/mach-ixp4xx/coyote-setup.c9
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-pci.c28
-rw-r--r--arch/arm/mach-ixp4xx/gtwx5715-setup.c8
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-pci.c12
-rw-r--r--arch/arm/mach-ixp4xx/ixdp425-setup.c13
-rw-r--r--arch/arm/mach-ixp4xx/ixdpg425-pci.c4
-rw-r--r--arch/arm/mach-pxa/time.c58
-rw-r--r--arch/arm/mach-s3c2410/clock.c9
-rw-r--r--arch/arm/mach-s3c2410/s3c2440-clock.c6
-rw-r--r--arch/arm/mach-sa1100/time.c68
-rw-r--r--arch/arm/mm/alignment.c70
-rw-r--r--arch/arm/mm/mm-armv.c30
-rw-r--r--arch/i386/pci/common.c1
-rw-r--r--arch/i386/pci/i386.c49
-rw-r--r--arch/ia64/Kconfig6
-rw-r--r--arch/ia64/hp/sim/boot/fw-emu.c11
-rw-r--r--arch/ia64/ia32/ia32_signal.c1
-rw-r--r--arch/ia64/kernel/Makefile1
-rw-r--r--arch/ia64/kernel/cpufreq/Kconfig29
-rw-r--r--arch/ia64/kernel/cpufreq/Makefile1
-rw-r--r--arch/ia64/kernel/cpufreq/acpi-cpufreq.c499
-rw-r--r--arch/ia64/kernel/sys_ia64.c2
-rw-r--r--arch/ia64/kernel/uncached.c4
-rw-r--r--arch/ia64/lib/Makefile2
-rw-r--r--arch/ia64/lib/swiotlb.c5
-rw-r--r--arch/ia64/mm/hugetlbpage.c8
-rw-r--r--arch/ia64/pci/pci.c1
-rw-r--r--arch/ia64/sn/include/tio.h6
-rw-r--r--arch/ia64/sn/include/xtalk/hubdev.h11
-rw-r--r--arch/ia64/sn/kernel/bte.c83
-rw-r--r--arch/ia64/sn/kernel/huberror.c2
-rw-r--r--arch/ia64/sn/kernel/io_init.c35
-rw-r--r--arch/ia64/sn/kernel/irq.c75
-rw-r--r--arch/ia64/sn/kernel/setup.c7
-rw-r--r--arch/ia64/sn/kernel/sn2/ptc_deadlock.S13
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c256
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_hwperf.c313
-rw-r--r--arch/ia64/sn/kernel/sn2/sn_proc_fs.c4
-rw-r--r--arch/ia64/sn/kernel/sn2/timer_interrupt.c22
-rw-r--r--arch/ia64/sn/pci/Makefile2
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_dma.c60
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c40
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c7
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c771
-rw-r--r--arch/m68knommu/Kconfig66
-rw-r--r--arch/m68knommu/Makefile5
-rw-r--r--arch/m68knommu/defconfig452
-rw-r--r--arch/m68knommu/kernel/setup.c25
-rw-r--r--arch/m68knommu/kernel/traps.c20
-rw-r--r--arch/m68knommu/kernel/vmlinux.lds.S23
-rw-r--r--arch/m68knommu/platform/523x/config.c82
-rw-r--r--arch/m68knommu/platform/5307/head.S15
-rw-r--r--arch/m68knommu/platform/68328/entry.S4
-rw-r--r--arch/m68knommu/platform/68360/entry.S2
-rw-r--r--arch/ppc/Makefile11
-rw-r--r--arch/ppc/boot/utils/addRamDisk.c203
-rw-r--r--arch/ppc/kernel/cpu_setup_6xx.S5
-rw-r--r--arch/ppc/kernel/l2cr.S31
-rw-r--r--arch/ppc/syslib/m8xx_setup.c6
-rw-r--r--arch/ppc64/Kconfig74
-rw-r--r--arch/ppc64/Makefile9
-rw-r--r--arch/ppc64/boot/Makefile4
-rw-r--r--arch/ppc64/boot/addnote.c4
-rw-r--r--arch/ppc64/boot/crt0.S2
-rw-r--r--arch/ppc64/boot/div64.S2
-rw-r--r--arch/ppc64/boot/elf.h149
-rw-r--r--arch/ppc64/boot/main.c55
-rw-r--r--arch/ppc64/boot/page.h34
-rw-r--r--arch/ppc64/boot/ppc32-types.h36
-rw-r--r--arch/ppc64/boot/ppc_asm.h62
-rw-r--r--arch/ppc64/boot/prom.c196
-rw-r--r--arch/ppc64/boot/prom.h18
-rw-r--r--arch/ppc64/boot/stdio.h16
-rw-r--r--arch/ppc64/boot/string.S2
-rw-r--r--arch/ppc64/boot/string.h16
-rw-r--r--arch/ppc64/boot/zlib.c2
-rw-r--r--arch/ppc64/configs/g5_defconfig6
-rw-r--r--arch/ppc64/configs/iSeries_defconfig7
-rw-r--r--arch/ppc64/configs/maple_defconfig6
-rw-r--r--arch/ppc64/configs/pSeries_defconfig6
-rw-r--r--arch/ppc64/defconfig6
-rw-r--r--arch/ppc64/kernel/LparData.c37
-rw-r--r--arch/ppc64/kernel/Makefile7
-rw-r--r--arch/ppc64/kernel/asm-offsets.c3
-rw-r--r--arch/ppc64/kernel/cputable.c40
-rw-r--r--arch/ppc64/kernel/firmware.c47
-rw-r--r--arch/ppc64/kernel/head.S523
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c5
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c30
-rw-r--r--arch/ppc64/kernel/iSeries_vio.c155
-rw-r--r--arch/ppc64/kernel/lmb.c151
-rw-r--r--arch/ppc64/kernel/lparcfg.c7
-rw-r--r--arch/ppc64/kernel/misc.S98
-rw-r--r--arch/ppc64/kernel/of_device.c2
-rw-r--r--arch/ppc64/kernel/pSeries_iommu.c3
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c4
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c39
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c3
-rw-r--r--arch/ppc64/kernel/pSeries_vio.c273
-rw-r--r--arch/ppc64/kernel/pacaData.c4
-rw-r--r--arch/ppc64/kernel/pmac_setup.c2
-rw-r--r--arch/ppc64/kernel/pmc.c21
-rw-r--r--arch/ppc64/kernel/process.c12
-rw-r--r--arch/ppc64/kernel/prom.c184
-rw-r--r--arch/ppc64/kernel/prom_init.c93
-rw-r--r--arch/ppc64/kernel/rtas_pci.c19
-rw-r--r--arch/ppc64/kernel/setup.c28
-rw-r--r--arch/ppc64/kernel/sysfs.c57
-rw-r--r--arch/ppc64/kernel/time.c7
-rw-r--r--arch/ppc64/kernel/vio.c444
-rw-r--r--arch/ppc64/mm/hash_low.S4
-rw-r--r--arch/ppc64/mm/hash_native.c3
-rw-r--r--arch/ppc64/mm/hash_utils.c4
-rw-r--r--arch/ppc64/mm/hugetlbpage.c388
-rw-r--r--arch/ppc64/mm/imalloc.c2
-rw-r--r--arch/ppc64/mm/init.c96
-rw-r--r--arch/ppc64/mm/numa.c2
-rw-r--r--arch/ppc64/mm/slb_low.S35
-rw-r--r--arch/ppc64/mm/tlb.c95
-rw-r--r--arch/ppc64/oprofile/common.c1
-rw-r--r--arch/ppc64/xmon/start.c2
-rw-r--r--arch/ppc64/xmon/xmon.c28
-rw-r--r--arch/sparc/kernel/setup.c1
-rw-r--r--arch/sparc/kernel/tick14.c1
-rw-r--r--arch/sparc/kernel/time.c1
-rw-r--r--arch/sparc/mm/fault.c1
-rw-r--r--arch/sparc/mm/init.c1
-rw-r--r--arch/sparc64/kernel/entry.S293
-rw-r--r--arch/sparc64/kernel/pci_iommu.c2
-rw-r--r--arch/sparc64/kernel/process.c2
-rw-r--r--arch/sparc64/kernel/sbus.c2
-rw-r--r--arch/sparc64/kernel/setup.c1
-rw-r--r--arch/sparc64/kernel/signal32.c22
-rw-r--r--arch/sparc64/kernel/smp.c30
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c32
-rw-r--r--arch/sparc64/kernel/traps.c269
-rw-r--r--arch/sparc64/kernel/ttable.S27
-rw-r--r--arch/sparc64/kernel/unaligned.c18
-rw-r--r--arch/sparc64/kernel/winfixup.S6
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/debuglocks.c56
-rw-r--r--arch/sparc64/lib/mb.S73
-rw-r--r--arch/sparc64/solaris/misc.c6
-rw-r--r--arch/v850/configs/rte-ma1-cb_defconfig108
-rw-r--r--arch/v850/configs/rte-me2-cb_defconfig21
-rw-r--r--arch/v850/configs/sim_defconfig21
-rw-r--r--arch/v850/kernel/setup.c44
155 files changed, 5541 insertions, 2954 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4bf0e8737e1f..68dfdba71d74 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -365,8 +365,8 @@ config NO_IDLE_HZ
365 365
366 Please note that dynamic tick may affect the accuracy of 366 Please note that dynamic tick may affect the accuracy of
367 timekeeping on some platforms depending on the implementation. 367 timekeeping on some platforms depending on the implementation.
368 Currently at least OMAP platform is known to have accurate 368 Currently at least OMAP, PXA2xx and SA11x0 platforms are known
369 timekeeping with dynamic tick. 369 to have accurate timekeeping with dynamic tick.
370 370
371config ARCH_DISCONTIGMEM_ENABLE 371config ARCH_DISCONTIGMEM_ENABLE
372 bool 372 bool
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 51dbf5489b6b..d74990717559 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -24,6 +24,7 @@
24#include <linux/kernel.h> 24#include <linux/kernel.h>
25#include <linux/list.h> 25#include <linux/list.h>
26#include <linux/smp.h> 26#include <linux/smp.h>
27#include <linux/cpumask.h>
27 28
28#include <asm/irq.h> 29#include <asm/irq.h>
29#include <asm/io.h> 30#include <asm/io.h>
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 2b6b4c786e65..db07ce42b3b2 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -284,7 +284,7 @@ __syscall_start:
284 .long sys_fstatfs64 284 .long sys_fstatfs64
285 .long sys_tgkill 285 .long sys_tgkill
286 .long sys_utimes 286 .long sys_utimes
287/* 270 */ .long sys_fadvise64_64 287/* 270 */ .long sys_arm_fadvise64_64_wrapper
288 .long sys_pciconfig_iobase 288 .long sys_pciconfig_iobase
289 .long sys_pciconfig_read 289 .long sys_pciconfig_read
290 .long sys_pciconfig_write 290 .long sys_pciconfig_write
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3f8d0e3aefab..6281d488ac97 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -265,6 +265,10 @@ sys_futex_wrapper:
265 str r5, [sp, #4] @ push sixth arg 265 str r5, [sp, #4] @ push sixth arg
266 b sys_futex 266 b sys_futex
267 267
268sys_arm_fadvise64_64_wrapper:
269 str r5, [sp, #4] @ push r5 to stack
270 b sys_arm_fadvise64_64
271
268/* 272/*
269 * Note: off_4k (r5) is always units of 4K. If we can't do the requested 273 * Note: off_4k (r5) is always units of 4K. If we can't do the requested
270 * offset, we return EINVAL. 274 * offset, we return EINVAL.
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index f897ce2ccf0d..42629ff84f5a 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
311 return ret; 311 return ret;
312} 312}
313EXPORT_SYMBOL(execve); 313EXPORT_SYMBOL(execve);
314
315/*
316 * Since loff_t is a 64 bit type we avoid a lot of ABI hastle
317 * with a different argument ordering.
318 */
319asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
320 loff_t offset, loff_t len)
321{
322 return sys_fadvise64_64(fd, offset, len, advice);
323}
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 1b7fcd50c3e2..8880482dcbff 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -433,10 +433,12 @@ void timer_dyn_reprogram(void)
433{ 433{
434 struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; 434 struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
435 435
436 write_seqlock(&xtime_lock); 436 if (dyn_tick) {
437 if (dyn_tick->state & DYN_TICK_ENABLED) 437 write_seqlock(&xtime_lock);
438 dyn_tick->reprogram(next_timer_interrupt() - jiffies); 438 if (dyn_tick->state & DYN_TICK_ENABLED)
439 write_sequnlock(&xtime_lock); 439 dyn_tick->reprogram(next_timer_interrupt() - jiffies);
440 write_sequnlock(&xtime_lock);
441 }
440} 442}
441 443
442static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) 444static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 04490a9f8f6e..0422e906cc9a 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -38,90 +38,6 @@
38#include <asm/mach/irq.h> 38#include <asm/mach/irq.h>
39#include <asm/mach/time.h> 39#include <asm/mach/time.h>
40 40
41enum ixp4xx_irq_type {
42 IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
43};
44static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
45
46/*************************************************************************
47 * GPIO acces functions
48 *************************************************************************/
49
50/*
51 * Configure GPIO line for input, interrupt, or output operation
52 *
53 * TODO: Enable/disable the irq_desc based on interrupt or output mode.
54 * TODO: Should these be named ixp4xx_gpio_?
55 */
56void gpio_line_config(u8 line, u32 style)
57{
58 static const int gpio2irq[] = {
59 6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
60 };
61 u32 enable;
62 volatile u32 *int_reg;
63 u32 int_style;
64 enum ixp4xx_irq_type irq_type;
65
66 enable = *IXP4XX_GPIO_GPOER;
67
68 if (style & IXP4XX_GPIO_OUT) {
69 enable &= ~((1) << line);
70 } else if (style & IXP4XX_GPIO_IN) {
71 enable |= ((1) << line);
72
73 switch (style & IXP4XX_GPIO_INTSTYLE_MASK)
74 {
75 case (IXP4XX_GPIO_ACTIVE_HIGH):
76 int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
77 irq_type = IXP4XX_IRQ_LEVEL;
78 break;
79 case (IXP4XX_GPIO_ACTIVE_LOW):
80 int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
81 irq_type = IXP4XX_IRQ_LEVEL;
82 break;
83 case (IXP4XX_GPIO_RISING_EDGE):
84 int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
85 irq_type = IXP4XX_IRQ_EDGE;
86 break;
87 case (IXP4XX_GPIO_FALLING_EDGE):
88 int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
89 irq_type = IXP4XX_IRQ_EDGE;
90 break;
91 case (IXP4XX_GPIO_TRANSITIONAL):
92 int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
93 irq_type = IXP4XX_IRQ_EDGE;
94 break;
95 default:
96 int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
97 irq_type = IXP4XX_IRQ_LEVEL;
98 break;
99 }
100
101 if (style & IXP4XX_GPIO_INTSTYLE_MASK)
102 ixp4xx_config_irq(gpio2irq[line], irq_type);
103
104 if (line >= 8) { /* pins 8-15 */
105 line -= 8;
106 int_reg = IXP4XX_GPIO_GPIT2R;
107 }
108 else { /* pins 0-7 */
109 int_reg = IXP4XX_GPIO_GPIT1R;
110 }
111
112 /* Clear the style for the appropriate pin */
113 *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
114 (line * IXP4XX_GPIO_STYLE_SIZE));
115
116 /* Set the new style */
117 *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
118 }
119
120 *IXP4XX_GPIO_GPOER = enable;
121}
122
123EXPORT_SYMBOL(gpio_line_config);
124
125/************************************************************************* 41/*************************************************************************
126 * IXP4xx chipset I/O mapping 42 * IXP4xx chipset I/O mapping
127 *************************************************************************/ 43 *************************************************************************/
@@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void)
165 * (be it PCI or something else) configures that GPIO line 81 * (be it PCI or something else) configures that GPIO line
166 * as an IRQ. 82 * as an IRQ.
167 **************************************************************************/ 83 **************************************************************************/
84enum ixp4xx_irq_type {
85 IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
86};
87
88static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
89
90/*
91 * IRQ -> GPIO mapping table
92 */
93static int irq2gpio[32] = {
94 -1, -1, -1, -1, -1, -1, 0, 1,
95 -1, -1, -1, -1, -1, -1, -1, -1,
96 -1, -1, -1, 2, 3, 4, 5, 6,
97 7, 8, 9, 10, 11, 12, -1, -1,
98};
99
100static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
101{
102 int line = irq2gpio[irq];
103 u32 int_style;
104 enum ixp4xx_irq_type irq_type;
105 volatile u32 *int_reg;
106
107 /*
108 * Only for GPIO IRQs
109 */
110 if (line < 0)
111 return -EINVAL;
112
113 if (type & IRQT_BOTHEDGE) {
114 int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
115 irq_type = IXP4XX_IRQ_EDGE;
116 } else if (type & IRQT_RISING) {
117 int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
118 irq_type = IXP4XX_IRQ_EDGE;
119 } else if (type & IRQT_FALLING) {
120 int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
121 irq_type = IXP4XX_IRQ_EDGE;
122 } else if (type & IRQT_HIGH) {
123 int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
124 irq_type = IXP4XX_IRQ_LEVEL;
125 } else if (type & IRQT_LOW) {
126 int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
127 irq_type = IXP4XX_IRQ_LEVEL;
128 }
129
130 ixp4xx_config_irq(irq, irq_type);
131
132 if (line >= 8) { /* pins 8-15 */
133 line -= 8;
134 int_reg = IXP4XX_GPIO_GPIT2R;
135 } else { /* pins 0-7 */
136 int_reg = IXP4XX_GPIO_GPIT1R;
137 }
138
139 /* Clear the style for the appropriate pin */
140 *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
141 (line * IXP4XX_GPIO_STYLE_SIZE));
142
143 /* Set the new style */
144 *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
145}
146
168static void ixp4xx_irq_mask(unsigned int irq) 147static void ixp4xx_irq_mask(unsigned int irq)
169{ 148{
170 if (cpu_is_ixp46x() && irq >= 32) 149 if (cpu_is_ixp46x() && irq >= 32)
@@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq)
183 162
184static void ixp4xx_irq_ack(unsigned int irq) 163static void ixp4xx_irq_ack(unsigned int irq)
185{ 164{
186 static int irq2gpio[32] = {
187 -1, -1, -1, -1, -1, -1, 0, 1,
188 -1, -1, -1, -1, -1, -1, -1, -1,
189 -1, -1, -1, 2, 3, 4, 5, 6,
190 7, 8, 9, 10, 11, 12, -1, -1,
191 };
192 int line = (irq < 32) ? irq2gpio[irq] : -1; 165 int line = (irq < 32) ? irq2gpio[irq] : -1;
193 166
194 if (line >= 0) 167 if (line >= 0)
@@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = {
209 .ack = ixp4xx_irq_mask, 182 .ack = ixp4xx_irq_mask,
210 .mask = ixp4xx_irq_mask, 183 .mask = ixp4xx_irq_mask,
211 .unmask = ixp4xx_irq_level_unmask, 184 .unmask = ixp4xx_irq_level_unmask,
185 .type = ixp4xx_set_irq_type
212}; 186};
213 187
214static struct irqchip ixp4xx_irq_edge_chip = { 188static struct irqchip ixp4xx_irq_edge_chip = {
215 .ack = ixp4xx_irq_ack, 189 .ack = ixp4xx_irq_ack,
216 .mask = ixp4xx_irq_mask, 190 .mask = ixp4xx_irq_mask,
217 .unmask = ixp4xx_irq_unmask, 191 .unmask = ixp4xx_irq_unmask,
192 .type = ixp4xx_set_irq_type
218}; 193};
219 194
220static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) 195static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c
index afafb42ae129..60de8a94cff5 100644
--- a/arch/arm/mach-ixp4xx/coyote-pci.c
+++ b/arch/arm/mach-ixp4xx/coyote-pci.c
@@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
30 30
31void __init coyote_pci_preinit(void) 31void __init coyote_pci_preinit(void)
32{ 32{
33 gpio_line_config(COYOTE_PCI_SLOT0_PIN, 33 set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
34 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); 34 set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
35
36 gpio_line_config(COYOTE_PCI_SLOT1_PIN,
37 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
38 35
39 gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN); 36 gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
40 gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN); 37 gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 411ea9996190..8b2f25322452 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -24,11 +24,6 @@
24#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
25#include <asm/mach/flash.h> 25#include <asm/mach/flash.h>
26 26
27void __init coyote_map_io(void)
28{
29 ixp4xx_map_io();
30}
31
32static struct flash_platform_data coyote_flash_data = { 27static struct flash_platform_data coyote_flash_data = {
33 .map_name = "cfi_probe", 28 .map_name = "cfi_probe",
34 .width = 2, 29 .width = 2,
@@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
107 .phys_ram = PHYS_OFFSET, 102 .phys_ram = PHYS_OFFSET,
108 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 103 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
109 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 104 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
110 .map_io = coyote_map_io, 105 .map_io = ixp4xx_map_io,
111 .init_irq = ixp4xx_init_irq, 106 .init_irq = ixp4xx_init_irq,
112 .timer = &ixp4xx_timer, 107 .timer = &ixp4xx_timer,
113 .boot_params = 0x0100, 108 .boot_params = 0x0100,
@@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
125 .phys_ram = PHYS_OFFSET, 120 .phys_ram = PHYS_OFFSET,
126 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 121 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
127 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 122 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
128 .map_io = coyote_map_io, 123 .map_io = ixp4xx_map_io,
129 .init_irq = ixp4xx_init_irq, 124 .init_irq = ixp4xx_init_irq,
130 .timer = &ixp4xx_timer, 125 .timer = &ixp4xx_timer,
131 .boot_params = 0x0100, 126 .boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
index b18035824e3e..a66484b63d36 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c
@@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void);
35extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); 35extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
36extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); 36extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
37 37
38 /*
39 * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
40 * Slot 0 isn't actually populated with a card connector but
41 * we initialize it anyway in case a future version has the
42 * slot populated or someone with good soldering skills has
43 * some free time.
44 */
45
46
47static void gtwx5715_init_gpio(u8 pin, u32 style)
48{
49 gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW);
50
51 if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin);
52}
53 38
39/*
40 * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
41 * Slot 0 isn't actually populated with a card connector but
42 * we initialize it anyway in case a future version has the
43 * slot populated or someone with good soldering skills has
44 * some free time.
45 */
54void __init gtwx5715_pci_preinit(void) 46void __init gtwx5715_pci_preinit(void)
55{ 47{
56 gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN); 48 set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
57 gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN); 49 set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
50 set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
51 set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
58 52
59 ixp4xx_pci_preinit(); 53 ixp4xx_pci_preinit();
60} 54}
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 333459d6aa46..3fd92c5cbaa8 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = {
101 .resource = gtwx5715_uart_resources, 101 .resource = gtwx5715_uart_resources,
102}; 102};
103 103
104
105void __init gtwx5715_map_io(void)
106{
107 ixp4xx_map_io();
108}
109
110static struct flash_platform_data gtwx5715_flash_data = { 104static struct flash_platform_data gtwx5715_flash_data = {
111 .map_name = "cfi_probe", 105 .map_name = "cfi_probe",
112 .width = 2, 106 .width = 2,
@@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
144 .phys_ram = PHYS_OFFSET, 138 .phys_ram = PHYS_OFFSET,
145 .phys_io = IXP4XX_UART2_BASE_PHYS, 139 .phys_io = IXP4XX_UART2_BASE_PHYS,
146 .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, 140 .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
147 .map_io = gtwx5715_map_io, 141 .map_io = ixp4xx_map_io,
148 .init_irq = ixp4xx_init_irq, 142 .init_irq = ixp4xx_init_irq,
149 .timer = &ixp4xx_timer, 143 .timer = &ixp4xx_timer,
150 .boot_params = 0x0100, 144 .boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c
index c2ab9ebb5980..f9a1d3e7d692 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c
@@ -27,14 +27,10 @@
27 27
28void __init ixdp425_pci_preinit(void) 28void __init ixdp425_pci_preinit(void)
29{ 29{
30 gpio_line_config(IXDP425_PCI_INTA_PIN, 30 set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
31 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); 31 set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
32 gpio_line_config(IXDP425_PCI_INTB_PIN, 32 set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
33 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); 33 set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
34 gpio_line_config(IXDP425_PCI_INTC_PIN,
35 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
36 gpio_line_config(IXDP425_PCI_INTD_PIN,
37 IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
38 34
39 gpio_line_isr_clear(IXDP425_PCI_INTA_PIN); 35 gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
40 gpio_line_isr_clear(IXDP425_PCI_INTB_PIN); 36 gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index fa0646c8693b..6c14ff3c23a0 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -24,11 +24,6 @@
24#include <asm/mach/arch.h> 24#include <asm/mach/arch.h>
25#include <asm/mach/flash.h> 25#include <asm/mach/flash.h>
26 26
27void __init ixdp425_map_io(void)
28{
29 ixp4xx_map_io();
30}
31
32static struct flash_platform_data ixdp425_flash_data = { 27static struct flash_platform_data ixdp425_flash_data = {
33 .map_name = "cfi_probe", 28 .map_name = "cfi_probe",
34 .width = 2, 29 .width = 2,
@@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
133 .phys_ram = PHYS_OFFSET, 128 .phys_ram = PHYS_OFFSET,
134 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 129 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
135 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 130 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
136 .map_io = ixdp425_map_io, 131 .map_io = ixp4xx_map_io,
137 .init_irq = ixp4xx_init_irq, 132 .init_irq = ixp4xx_init_irq,
138 .timer = &ixp4xx_timer, 133 .timer = &ixp4xx_timer,
139 .boot_params = 0x0100, 134 .boot_params = 0x0100,
@@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
145 .phys_ram = PHYS_OFFSET, 140 .phys_ram = PHYS_OFFSET,
146 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 141 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
147 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 142 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
148 .map_io = ixdp425_map_io, 143 .map_io = ixp4xx_map_io,
149 .init_irq = ixp4xx_init_irq, 144 .init_irq = ixp4xx_init_irq,
150 .timer = &ixp4xx_timer, 145 .timer = &ixp4xx_timer,
151 .boot_params = 0x0100, 146 .boot_params = 0x0100,
@@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
157 .phys_ram = PHYS_OFFSET, 152 .phys_ram = PHYS_OFFSET,
158 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 153 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
159 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 154 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
160 .map_io = ixdp425_map_io, 155 .map_io = ixp4xx_map_io,
161 .init_irq = ixp4xx_init_irq, 156 .init_irq = ixp4xx_init_irq,
162 .timer = &ixp4xx_timer, 157 .timer = &ixp4xx_timer,
163 .boot_params = 0x0100, 158 .boot_params = 0x0100,
@@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
176 .phys_ram = PHYS_OFFSET, 171 .phys_ram = PHYS_OFFSET,
177 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, 172 .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
178 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, 173 .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
179 .map_io = ixdp425_map_io, 174 .map_io = ixp4xx_map_io,
180 .init_irq = ixp4xx_init_irq, 175 .init_irq = ixp4xx_init_irq,
181 .timer = &ixp4xx_timer, 176 .timer = &ixp4xx_timer,
182 .boot_params = 0x0100, 177 .boot_params = 0x0100,
diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
index ce4563f00676..fe5e7660de1d 100644
--- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c
+++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c
@@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
29 29
30void __init ixdpg425_pci_preinit(void) 30void __init ixdpg425_pci_preinit(void)
31{ 31{
32 gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); 32 set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
33 gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); 33 set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
34 34
35 gpio_line_isr_clear(6); 35 gpio_line_isr_clear(6);
36 gpio_line_isr_clear(7); 36 gpio_line_isr_clear(7);
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 6e5202154f91..7dad3f1465e0 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
70 return usec; 70 return usec;
71} 71}
72 72
73#ifdef CONFIG_NO_IDLE_HZ
74static unsigned long initial_match;
75static int match_posponed;
76#endif
77
73static irqreturn_t 78static irqreturn_t
74pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 79pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
75{ 80{
@@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
77 82
78 write_seqlock(&xtime_lock); 83 write_seqlock(&xtime_lock);
79 84
85#ifdef CONFIG_NO_IDLE_HZ
86 if (match_posponed) {
87 match_posponed = 0;
88 OSMR0 = initial_match;
89 }
90#endif
91
80 /* Loop until we get ahead of the free running timer. 92 /* Loop until we get ahead of the free running timer.
81 * This ensures an exact clock tick count and time accuracy. 93 * This ensures an exact clock tick count and time accuracy.
82 * IRQs are disabled inside the loop to ensure coherence between 94 * Since IRQs are disabled at this point, coherence between
83 * lost_ticks (updated in do_timer()) and the match reg value, so we 95 * lost_ticks(updated in do_timer()) and the match reg value is
84 * can use do_gettimeofday() from interrupt handlers. 96 * ensured, hence we can use do_gettimeofday() from interrupt
97 * handlers.
85 * 98 *
86 * HACK ALERT: it seems that the PXA timer regs aren't updated right 99 * HACK ALERT: it seems that the PXA timer regs aren't updated right
87 * away in all cases when a write occurs. We therefore compare with 100 * away in all cases when a write occurs. We therefore compare with
@@ -126,6 +139,42 @@ static void __init pxa_timer_init(void)
126 OSCR = 0; /* initialize free-running timer, force first match */ 139 OSCR = 0; /* initialize free-running timer, force first match */
127} 140}
128 141
142#ifdef CONFIG_NO_IDLE_HZ
143static int pxa_dyn_tick_enable_disable(void)
144{
145 /* nothing to do */
146 return 0;
147}
148
149static void pxa_dyn_tick_reprogram(unsigned long ticks)
150{
151 if (ticks > 1) {
152 initial_match = OSMR0;
153 OSMR0 = initial_match + ticks * LATCH;
154 match_posponed = 1;
155 }
156}
157
158static irqreturn_t
159pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
160{
161 if (match_posponed) {
162 match_posponed = 0;
163 OSMR0 = initial_match;
164 if ( (signed long)(initial_match - OSCR) <= 8 )
165 return pxa_timer_interrupt(irq, dev_id, regs);
166 }
167 return IRQ_NONE;
168}
169
170static struct dyn_tick_timer pxa_dyn_tick = {
171 .enable = pxa_dyn_tick_enable_disable,
172 .disable = pxa_dyn_tick_enable_disable,
173 .reprogram = pxa_dyn_tick_reprogram,
174 .handler = pxa_dyn_tick_handler,
175};
176#endif
177
129#ifdef CONFIG_PM 178#ifdef CONFIG_PM
130static unsigned long osmr[4], oier; 179static unsigned long osmr[4], oier;
131 180
@@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
161 .suspend = pxa_timer_suspend, 210 .suspend = pxa_timer_suspend,
162 .resume = pxa_timer_resume, 211 .resume = pxa_timer_resume,
163 .offset = pxa_gettimeoffset, 212 .offset = pxa_gettimeoffset,
213#ifdef CONFIG_NO_IDLE_HZ
214 .dyn_tick = &pxa_dyn_tick,
215#endif
164}; 216};
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 9a66050e887d..f59608268751 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
388 unsigned long hclk, 388 unsigned long hclk,
389 unsigned long pclk) 389 unsigned long pclk)
390{ 390{
391 unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
391 struct clk *clkp = init_clocks; 392 struct clk *clkp = init_clocks;
392 int ptr; 393 int ptr;
393 int ret; 394 int ret;
@@ -446,5 +447,13 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
446 } 447 }
447 } 448 }
448 449
450 /* show the clock-slow value */
451
452 printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
453 print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
454 (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
455 (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
456 (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
457
449 return 0; 458 return 0;
450} 459}
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index b018a1f680ce..c67e0979aec3 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = {
68static int s3c2440_clk_add(struct sys_device *sysdev) 68static int s3c2440_clk_add(struct sys_device *sysdev)
69{ 69{
70 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); 70 unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
71 unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
71 struct clk *clk_h; 72 struct clk *clk_h;
72 struct clk *clk_p; 73 struct clk *clk_p;
73 struct clk *clk_xtal; 74 struct clk *clk_xtal;
@@ -80,8 +81,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
80 81
81 s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate); 82 s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
82 83
83 printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n", 84 printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n",
84 print_mhz(s3c2440_clk_upll.rate)); 85 print_mhz(s3c2440_clk_upll.rate),
86 (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
85 87
86 clk_p = clk_get(NULL, "pclk"); 88 clk_p = clk_get(NULL, "pclk");
87 clk_h = clk_get(NULL, "hclk"); 89 clk_h = clk_get(NULL, "hclk");
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 0eeb3616ffea..47e0420623fc 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void)
70 return usec; 70 return usec;
71} 71}
72 72
73/* 73#ifdef CONFIG_NO_IDLE_HZ
74 * We will be entered with IRQs enabled. 74static unsigned long initial_match;
75 * 75static int match_posponed;
76 * Loop until we get ahead of the free running timer. 76#endif
77 * This ensures an exact clock tick count and time accuracy. 77
78 * IRQs are disabled inside the loop to ensure coherence between
79 * lost_ticks (updated in do_timer()) and the match reg value, so we
80 * can use do_gettimeofday() from interrupt handlers.
81 */
82static irqreturn_t 78static irqreturn_t
83sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 79sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
84{ 80{
@@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
86 82
87 write_seqlock(&xtime_lock); 83 write_seqlock(&xtime_lock);
88 84
85#ifdef CONFIG_NO_IDLE_HZ
86 if (match_posponed) {
87 match_posponed = 0;
88 OSMR0 = initial_match;
89 }
90#endif
91
92 /*
93 * Loop until we get ahead of the free running timer.
94 * This ensures an exact clock tick count and time accuracy.
95 * Since IRQs are disabled at this point, coherence between
96 * lost_ticks(updated in do_timer()) and the match reg value is
97 * ensured, hence we can use do_gettimeofday() from interrupt
98 * handlers.
99 */
89 do { 100 do {
90 timer_tick(regs); 101 timer_tick(regs);
91 OSSR = OSSR_M0; /* Clear match on timer 0 */ 102 OSSR = OSSR_M0; /* Clear match on timer 0 */
@@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void)
120 OSCR = 0; /* initialize free-running timer, force first match */ 131 OSCR = 0; /* initialize free-running timer, force first match */
121} 132}
122 133
134#ifdef CONFIG_NO_IDLE_HZ
135static int sa1100_dyn_tick_enable_disable(void)
136{
137 /* nothing to do */
138 return 0;
139}
140
141static void sa1100_dyn_tick_reprogram(unsigned long ticks)
142{
143 if (ticks > 1) {
144 initial_match = OSMR0;
145 OSMR0 = initial_match + ticks * LATCH;
146 match_posponed = 1;
147 }
148}
149
150static irqreturn_t
151sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
152{
153 if (match_posponed) {
154 match_posponed = 0;
155 OSMR0 = initial_match;
156 if ((signed long)(initial_match - OSCR) <= 0)
157 return sa1100_timer_interrupt(irq, dev_id, regs);
158 }
159 return IRQ_NONE;
160}
161
162static struct dyn_tick_timer sa1100_dyn_tick = {
163 .enable = sa1100_dyn_tick_enable_disable,
164 .disable = sa1100_dyn_tick_enable_disable,
165 .reprogram = sa1100_dyn_tick_reprogram,
166 .handler = sa1100_dyn_tick_handler,
167};
168#endif
169
123#ifdef CONFIG_PM 170#ifdef CONFIG_PM
124unsigned long osmr[4], oier; 171unsigned long osmr[4], oier;
125 172
@@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
156 .suspend = sa1100_timer_suspend, 203 .suspend = sa1100_timer_suspend,
157 .resume = sa1100_timer_resume, 204 .resume = sa1100_timer_resume,
158 .offset = sa1100_gettimeoffset, 205 .offset = sa1100_gettimeoffset,
206#ifdef CONFIG_NO_IDLE_HZ
207 .dyn_tick = &sa1100_dyn_tick,
208#endif
159}; 209};
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 81f4a8a2d34b..4b39d867ac14 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -45,7 +45,7 @@
45 45
46#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) 46#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
47 47
48#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ 48#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */
49#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ 49#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
50 50
51#define RN_BITS(i) ((i >> 16) & 15) /* Rn */ 51#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
@@ -68,6 +68,7 @@ static unsigned long ai_sys;
68static unsigned long ai_skipped; 68static unsigned long ai_skipped;
69static unsigned long ai_half; 69static unsigned long ai_half;
70static unsigned long ai_word; 70static unsigned long ai_word;
71static unsigned long ai_dword;
71static unsigned long ai_multi; 72static unsigned long ai_multi;
72static int ai_usermode; 73static int ai_usermode;
73 74
@@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
93 p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); 94 p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
94 p += sprintf(p, "Half:\t\t%lu\n", ai_half); 95 p += sprintf(p, "Half:\t\t%lu\n", ai_half);
95 p += sprintf(p, "Word:\t\t%lu\n", ai_word); 96 p += sprintf(p, "Word:\t\t%lu\n", ai_word);
97 if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
98 p += sprintf(p, "DWord:\t\t%lu\n", ai_dword);
96 p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); 99 p += sprintf(p, "Multi:\t\t%lu\n", ai_multi);
97 p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, 100 p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
98 usermode_action[ai_usermode]); 101 usermode_action[ai_usermode]);
@@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
283{ 286{
284 unsigned int rd = RD_BITS(instr); 287 unsigned int rd = RD_BITS(instr);
285 288
286 if ((instr & 0x01f00ff0) == 0x01000090)
287 goto swp;
288
289 if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
290 goto bad;
291
292 ai_half += 1; 289 ai_half += 1;
293 290
294 if (user_mode(regs)) 291 if (user_mode(regs))
@@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
323 320
324 return TYPE_LDST; 321 return TYPE_LDST;
325 322
326 swp: 323 fault:
327 printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); 324 return TYPE_FAULT;
328 bad: 325}
329 return TYPE_ERROR; 326
327static int
328do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
329 struct pt_regs *regs)
330{
331 unsigned int rd = RD_BITS(instr);
332
333 ai_dword += 1;
334
335 if (user_mode(regs))
336 goto user;
337
338 if ((instr & 0xf0) == 0xd0) {
339 unsigned long val;
340 get32_unaligned_check(val, addr);
341 regs->uregs[rd] = val;
342 get32_unaligned_check(val, addr+4);
343 regs->uregs[rd+1] = val;
344 } else {
345 put32_unaligned_check(regs->uregs[rd], addr);
346 put32_unaligned_check(regs->uregs[rd+1], addr+4);
347 }
348
349 return TYPE_LDST;
350
351 user:
352 if ((instr & 0xf0) == 0xd0) {
353 unsigned long val;
354 get32t_unaligned_check(val, addr);
355 regs->uregs[rd] = val;
356 get32t_unaligned_check(val, addr+4);
357 regs->uregs[rd+1] = val;
358 } else {
359 put32t_unaligned_check(regs->uregs[rd], addr);
360 put32t_unaligned_check(regs->uregs[rd+1], addr+4);
361 }
362
363 return TYPE_LDST;
330 364
331 fault: 365 fault:
332 return TYPE_FAULT; 366 return TYPE_FAULT;
@@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
617 regs->ARM_pc += thumb_mode(regs) ? 2 : 4; 651 regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
618 652
619 switch (CODING_BITS(instr)) { 653 switch (CODING_BITS(instr)) {
620 case 0x00000000: /* ldrh or strh */ 654 case 0x00000000: /* 3.13.4 load/store instruction extensions */
621 if (LDSTH_I_BIT(instr)) 655 if (LDSTHD_I_BIT(instr))
622 offset.un = (instr & 0xf00) >> 4 | (instr & 15); 656 offset.un = (instr & 0xf00) >> 4 | (instr & 15);
623 else 657 else
624 offset.un = regs->uregs[RM_BITS(instr)]; 658 offset.un = regs->uregs[RM_BITS(instr)];
625 handler = do_alignment_ldrhstrh; 659
660 if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
661 (instr & 0x001000f0) == 0x001000f0) /* LDRSH */
662 handler = do_alignment_ldrhstrh;
663 else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
664 (instr & 0x001000f0) == 0x000000f0) /* STRD */
665 handler = do_alignment_ldrdstrd;
666 else
667 goto bad;
626 break; 668 break;
627 669
628 case 0x04000000: /* ldr or str immediate */ 670 case 0x04000000: /* ldr or str immediate */
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 3c655c54e231..d125a3dc061c 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
275 int i; 275 int i;
276 276
277 for (i = 0; i < 16; i += 1) { 277 for (i = 0; i < 16; i += 1) {
278 alloc_init_section(virt, phys & SUPERSECTION_MASK, 278 alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
279 prot | PMD_SECT_SUPER);
280 279
281 virt += (PGDIR_SIZE / 2); 280 virt += (PGDIR_SIZE / 2);
282 phys += (PGDIR_SIZE / 2);
283 } 281 }
284} 282}
285 283
@@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
297 pte_t *ptep; 295 pte_t *ptep;
298 296
299 if (pmd_none(*pmdp)) { 297 if (pmd_none(*pmdp)) {
300 unsigned long pmdval;
301 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * 298 ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
302 sizeof(pte_t)); 299 sizeof(pte_t));
303 300
304 pmdval = __pa(ptep) | prot_l1; 301 __pmd_populate(pmdp, __pa(ptep) | prot_l1);
305 pmdp[0] = __pmd(pmdval);
306 pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
307 flush_pmd_entry(pmdp);
308 } 302 }
309 ptep = pte_offset_kernel(pmdp, virt); 303 ptep = pte_offset_kernel(pmdp, virt);
310 304
@@ -459,7 +453,7 @@ static void __init build_mem_type_table(void)
459 453
460 for (i = 0; i < 16; i++) { 454 for (i = 0; i < 16; i++) {
461 unsigned long v = pgprot_val(protection_map[i]); 455 unsigned long v = pgprot_val(protection_map[i]);
462 v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; 456 v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
463 protection_map[i] = __pgprot(v); 457 protection_map[i] = __pgprot(v);
464 } 458 }
465 459
@@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
583 */ 577 */
584void setup_mm_for_reboot(char mode) 578void setup_mm_for_reboot(char mode)
585{ 579{
586 unsigned long pmdval; 580 unsigned long base_pmdval;
587 pgd_t *pgd; 581 pgd_t *pgd;
588 pmd_t *pmd;
589 int i; 582 int i;
590 int cpu_arch = cpu_architecture();
591 583
592 if (current->mm && current->mm->pgd) 584 if (current->mm && current->mm->pgd)
593 pgd = current->mm->pgd; 585 pgd = current->mm->pgd;
594 else 586 else
595 pgd = init_mm.pgd; 587 pgd = init_mm.pgd;
596 588
597 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { 589 base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
598 pmdval = (i << PGDIR_SHIFT) | 590 if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
599 PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | 591 base_pmdval |= PMD_BIT4;
600 PMD_TYPE_SECT; 592
601 if (cpu_arch <= CPU_ARCH_ARMv5TEJ) 593 for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
602 pmdval |= PMD_BIT4; 594 unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
595 pmd_t *pmd;
596
603 pmd = pmd_off(pgd, i << PGDIR_SHIFT); 597 pmd = pmd_off(pgd, i << PGDIR_SHIFT);
604 pmd[0] = __pmd(pmdval); 598 pmd[0] = __pmd(pmdval);
605 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); 599 pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index ade5bc57c34c..c96bea14b98f 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -165,7 +165,6 @@ static int __init pcibios_init(void)
165 if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) 165 if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
166 pcibios_sort(); 166 pcibios_sort();
167#endif 167#endif
168 pci_assign_unassigned_resources();
169 return 0; 168 return 0;
170} 169}
171 170
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index 93a364c82150..3cc480998a47 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -170,43 +170,26 @@ static void __init pcibios_allocate_resources(int pass)
170static int __init pcibios_assign_resources(void) 170static int __init pcibios_assign_resources(void)
171{ 171{
172 struct pci_dev *dev = NULL; 172 struct pci_dev *dev = NULL;
173 int idx; 173 struct resource *r, *pr;
174 struct resource *r;
175
176 for_each_pci_dev(dev) {
177 int class = dev->class >> 8;
178
179 /* Don't touch classless devices and host bridges */
180 if (!class || class == PCI_CLASS_BRIDGE_HOST)
181 continue;
182
183 for(idx=0; idx<6; idx++) {
184 r = &dev->resource[idx];
185
186 /*
187 * Don't touch IDE controllers and I/O ports of video cards!
188 */
189 if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
190 (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
191 continue;
192
193 /*
194 * We shall assign a new address to this resource, either because
195 * the BIOS forgot to do so or because we have decided the old
196 * address was unusable for some reason.
197 */
198 if (!r->start && r->end)
199 pci_assign_resource(dev, idx);
200 }
201 174
202 if (pci_probe & PCI_ASSIGN_ROMS) { 175 if (!(pci_probe & PCI_ASSIGN_ROMS)) {
176 /* Try to use BIOS settings for ROMs, otherwise let
177 pci_assign_unassigned_resources() allocate the new
178 addresses. */
179 for_each_pci_dev(dev) {
203 r = &dev->resource[PCI_ROM_RESOURCE]; 180 r = &dev->resource[PCI_ROM_RESOURCE];
204 r->end -= r->start; 181 if (!r->flags || !r->start)
205 r->start = 0; 182 continue;
206 if (r->end) 183 pr = pci_find_parent_resource(dev, r);
207 pci_assign_resource(dev, PCI_ROM_RESOURCE); 184 if (!pr || request_resource(pr, r) < 0) {
185 r->end -= r->start;
186 r->start = 0;
187 }
208 } 188 }
209 } 189 }
190
191 pci_assign_unassigned_resources();
192
210 return 0; 193 return 0;
211} 194}
212 195
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index addf07393ef4..e1c9ea03f31f 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -357,6 +357,12 @@ source "kernel/power/Kconfig"
357 357
358source "drivers/acpi/Kconfig" 358source "drivers/acpi/Kconfig"
359 359
360if PM
361
362source "arch/ia64/kernel/cpufreq/Kconfig"
363
364endif
365
360endmenu 366endmenu
361 367
362if !IA64_HP_SIM 368if !IA64_HP_SIM
diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c
index 5c46928e3dc6..30fdfb1d0a53 100644
--- a/arch/ia64/hp/sim/boot/fw-emu.c
+++ b/arch/ia64/hp/sim/boot/fw-emu.c
@@ -237,17 +237,6 @@ sal_emulator (long index, unsigned long in1, unsigned long in2,
237 return ((struct sal_ret_values) {status, r9, r10, r11}); 237 return ((struct sal_ret_values) {status, r9, r10, r11});
238} 238}
239 239
240
241/*
242 * This is here to work around a bug in egcs-1.1.1b that causes the
243 * compiler to crash (seems like a bug in the new alias analysis code.
244 */
245void *
246id (long addr)
247{
248 return (void *) addr;
249}
250
251struct ia64_boot_param * 240struct ia64_boot_param *
252sys_fw_init (const char *args, int arglen) 241sys_fw_init (const char *args, int arglen)
253{ 242{
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index ebb89be2aa2d..aa891c9bc9b6 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -29,7 +29,6 @@
29#include <asm/uaccess.h> 29#include <asm/uaccess.h>
30#include <asm/rse.h> 30#include <asm/rse.h>
31#include <asm/sigcontext.h> 31#include <asm/sigcontext.h>
32#include <asm/segment.h>
33 32
34#include "ia32priv.h" 33#include "ia32priv.h"
35 34
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index e1fb68ddec26..b242594be55b 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o domain.o
20obj-$(CONFIG_NUMA) += numa.o 20obj-$(CONFIG_NUMA) += numa.o
21obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o 21obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o
22obj-$(CONFIG_IA64_CYCLONE) += cyclone.o 22obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
23obj-$(CONFIG_CPU_FREQ) += cpufreq/
23obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o 24obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
24obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o 25obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
25obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o 26obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
diff --git a/arch/ia64/kernel/cpufreq/Kconfig b/arch/ia64/kernel/cpufreq/Kconfig
new file mode 100644
index 000000000000..2d9d5279b981
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/Kconfig
@@ -0,0 +1,29 @@
1
2#
3# CPU Frequency scaling
4#
5
6menu "CPU Frequency scaling"
7
8source "drivers/cpufreq/Kconfig"
9
10if CPU_FREQ
11
12comment "CPUFreq processor drivers"
13
14config IA64_ACPI_CPUFREQ
15 tristate "ACPI Processor P-States driver"
16 select CPU_FREQ_TABLE
17 depends on ACPI_PROCESSOR
18 help
19 This driver adds a CPUFreq driver which utilizes the ACPI
20 Processor Performance States.
21
22 For details, take a look at <file:Documentation/cpu-freq/>.
23
24 If in doubt, say N.
25
26endif # CPU_FREQ
27
28endmenu
29
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile
new file mode 100644
index 000000000000..f748d34c02f0
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
new file mode 100644
index 000000000000..da4d5cf80a48
--- /dev/null
+++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
@@ -0,0 +1,499 @@
1/*
2 * arch/ia64/kernel/cpufreq/acpi-cpufreq.c
3 * This file provides the ACPI based P-state support. This
4 * module works with generic cpufreq infrastructure. Most of
5 * the code is based on i386 version
6 * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
7 *
8 * Copyright (C) 2005 Intel Corp
9 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/cpufreq.h>
17#include <linux/proc_fs.h>
18#include <linux/seq_file.h>
19#include <asm/io.h>
20#include <asm/uaccess.h>
21#include <asm/pal.h>
22
23#include <linux/acpi.h>
24#include <acpi/processor.h>
25
26#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg)
27
28MODULE_AUTHOR("Venkatesh Pallipadi");
29MODULE_DESCRIPTION("ACPI Processor P-States Driver");
30MODULE_LICENSE("GPL");
31
32
33struct cpufreq_acpi_io {
34 struct acpi_processor_performance acpi_data;
35 struct cpufreq_frequency_table *freq_table;
36 unsigned int resume;
37};
38
39static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS];
40
41static struct cpufreq_driver acpi_cpufreq_driver;
42
43
44static int
45processor_set_pstate (
46 u32 value)
47{
48 s64 retval;
49
50 dprintk("processor_set_pstate\n");
51
52 retval = ia64_pal_set_pstate((u64)value);
53
54 if (retval) {
55 dprintk("Failed to set freq to 0x%x, with error 0x%x\n",
56 value, retval);
57 return -ENODEV;
58 }
59 return (int)retval;
60}
61
62
63static int
64processor_get_pstate (
65 u32 *value)
66{
67 u64 pstate_index = 0;
68 s64 retval;
69
70 dprintk("processor_get_pstate\n");
71
72 retval = ia64_pal_get_pstate(&pstate_index);
73 *value = (u32) pstate_index;
74
75 if (retval)
76 dprintk("Failed to get current freq with "
77 "error 0x%x, idx 0x%x\n", retval, *value);
78
79 return (int)retval;
80}
81
82
83/* To be used only after data->acpi_data is initialized */
84static unsigned
85extract_clock (
86 struct cpufreq_acpi_io *data,
87 unsigned value,
88 unsigned int cpu)
89{
90 unsigned long i;
91
92 dprintk("extract_clock\n");
93
94 for (i = 0; i < data->acpi_data.state_count; i++) {
95 if (value >= data->acpi_data.states[i].control)
96 return data->acpi_data.states[i].core_frequency;
97 }
98 return data->acpi_data.states[i-1].core_frequency;
99}
100
101
102static unsigned int
103processor_get_freq (
104 struct cpufreq_acpi_io *data,
105 unsigned int cpu)
106{
107 int ret = 0;
108 u32 value = 0;
109 cpumask_t saved_mask;
110 unsigned long clock_freq;
111
112 dprintk("processor_get_freq\n");
113
114 saved_mask = current->cpus_allowed;
115 set_cpus_allowed(current, cpumask_of_cpu(cpu));
116 if (smp_processor_id() != cpu) {
117 ret = -EAGAIN;
118 goto migrate_end;
119 }
120
121 /*
122 * processor_get_pstate gets the average frequency since the
123 * last get. So, do two PAL_get_freq()...
124 */
125 ret = processor_get_pstate(&value);
126 ret = processor_get_pstate(&value);
127
128 if (ret) {
129 set_cpus_allowed(current, saved_mask);
130 printk(KERN_WARNING "get performance failed with error %d\n",
131 ret);
132 ret = -EAGAIN;
133 goto migrate_end;
134 }
135 clock_freq = extract_clock(data, value, cpu);
136 ret = (clock_freq*1000);
137
138migrate_end:
139 set_cpus_allowed(current, saved_mask);
140 return ret;
141}
142
143
144static int
145processor_set_freq (
146 struct cpufreq_acpi_io *data,
147 unsigned int cpu,
148 int state)
149{
150 int ret = 0;
151 u32 value = 0;
152 struct cpufreq_freqs cpufreq_freqs;
153 cpumask_t saved_mask;
154 int retval;
155
156 dprintk("processor_set_freq\n");
157
158 saved_mask = current->cpus_allowed;
159 set_cpus_allowed(current, cpumask_of_cpu(cpu));
160 if (smp_processor_id() != cpu) {
161 retval = -EAGAIN;
162 goto migrate_end;
163 }
164
165 if (state == data->acpi_data.state) {
166 if (unlikely(data->resume)) {
167 dprintk("Called after resume, resetting to P%d\n", state);
168 data->resume = 0;
169 } else {
170 dprintk("Already at target state (P%d)\n", state);
171 retval = 0;
172 goto migrate_end;
173 }
174 }
175
176 dprintk("Transitioning from P%d to P%d\n",
177 data->acpi_data.state, state);
178
179 /* cpufreq frequency struct */
180 cpufreq_freqs.cpu = cpu;
181 cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
182 cpufreq_freqs.new = data->freq_table[state].frequency;
183
184 /* notify cpufreq */
185 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
186
187 /*
188 * First we write the target state's 'control' value to the
189 * control_register.
190 */
191
192 value = (u32) data->acpi_data.states[state].control;
193
194 dprintk("Transitioning to state: 0x%08x\n", value);
195
196 ret = processor_set_pstate(value);
197 if (ret) {
198 unsigned int tmp = cpufreq_freqs.new;
199 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
200 cpufreq_freqs.new = cpufreq_freqs.old;
201 cpufreq_freqs.old = tmp;
202 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
203 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
204 printk(KERN_WARNING "Transition failed with error %d\n", ret);
205 retval = -ENODEV;
206 goto migrate_end;
207 }
208
209 cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
210
211 data->acpi_data.state = state;
212
213 retval = 0;
214
215migrate_end:
216 set_cpus_allowed(current, saved_mask);
217 return (retval);
218}
219
220
221static unsigned int
222acpi_cpufreq_get (
223 unsigned int cpu)
224{
225 struct cpufreq_acpi_io *data = acpi_io_data[cpu];
226
227 dprintk("acpi_cpufreq_get\n");
228
229 return processor_get_freq(data, cpu);
230}
231
232
233static int
234acpi_cpufreq_target (
235 struct cpufreq_policy *policy,
236 unsigned int target_freq,
237 unsigned int relation)
238{
239 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
240 unsigned int next_state = 0;
241 unsigned int result = 0;
242
243 dprintk("acpi_cpufreq_setpolicy\n");
244
245 result = cpufreq_frequency_table_target(policy,
246 data->freq_table, target_freq, relation, &next_state);
247 if (result)
248 return (result);
249
250 result = processor_set_freq(data, policy->cpu, next_state);
251
252 return (result);
253}
254
255
256static int
257acpi_cpufreq_verify (
258 struct cpufreq_policy *policy)
259{
260 unsigned int result = 0;
261 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
262
263 dprintk("acpi_cpufreq_verify\n");
264
265 result = cpufreq_frequency_table_verify(policy,
266 data->freq_table);
267
268 return (result);
269}
270
271
272/*
273 * processor_init_pdc - let BIOS know about the SMP capabilities
274 * of this driver
275 * @perf: processor-specific acpi_io_data struct
276 * @cpu: CPU being initialized
277 *
278 * To avoid issues with legacy OSes, some BIOSes require to be informed of
279 * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC
280 * accordingly. Actual call to _PDC is done in driver/acpi/processor.c
281 */
282static void
283processor_init_pdc (
284 struct acpi_processor_performance *perf,
285 unsigned int cpu,
286 struct acpi_object_list *obj_list
287 )
288{
289 union acpi_object *obj;
290 u32 *buf;
291
292 dprintk("processor_init_pdc\n");
293
294 perf->pdc = NULL;
295 /* Initialize pdc. It will be used later. */
296 if (!obj_list)
297 return;
298
299 if (!(obj_list->count && obj_list->pointer))
300 return;
301
302 obj = obj_list->pointer;
303 if ((obj->buffer.length == 12) && obj->buffer.pointer) {
304 buf = (u32 *)obj->buffer.pointer;
305 buf[0] = ACPI_PDC_REVISION_ID;
306 buf[1] = 1;
307 buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
308 perf->pdc = obj_list;
309 }
310 return;
311}
312
313
314static int
315acpi_cpufreq_cpu_init (
316 struct cpufreq_policy *policy)
317{
318 unsigned int i;
319 unsigned int cpu = policy->cpu;
320 struct cpufreq_acpi_io *data;
321 unsigned int result = 0;
322
323 union acpi_object arg0 = {ACPI_TYPE_BUFFER};
324 u32 arg0_buf[3];
325 struct acpi_object_list arg_list = {1, &arg0};
326
327 dprintk("acpi_cpufreq_cpu_init\n");
328 /* setup arg_list for _PDC settings */
329 arg0.buffer.length = 12;
330 arg0.buffer.pointer = (u8 *) arg0_buf;
331
332 data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
333 if (!data)
334 return (-ENOMEM);
335
336 memset(data, 0, sizeof(struct cpufreq_acpi_io));
337
338 acpi_io_data[cpu] = data;
339
340 processor_init_pdc(&data->acpi_data, cpu, &arg_list);
341 result = acpi_processor_register_performance(&data->acpi_data, cpu);
342 data->acpi_data.pdc = NULL;
343
344 if (result)
345 goto err_free;
346
347 /* capability check */
348 if (data->acpi_data.state_count <= 1) {
349 dprintk("No P-States\n");
350 result = -ENODEV;
351 goto err_unreg;
352 }
353
354 if ((data->acpi_data.control_register.space_id !=
355 ACPI_ADR_SPACE_FIXED_HARDWARE) ||
356 (data->acpi_data.status_register.space_id !=
357 ACPI_ADR_SPACE_FIXED_HARDWARE)) {
358 dprintk("Unsupported address space [%d, %d]\n",
359 (u32) (data->acpi_data.control_register.space_id),
360 (u32) (data->acpi_data.status_register.space_id));
361 result = -ENODEV;
362 goto err_unreg;
363 }
364
365 /* alloc freq_table */
366 data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
367 (data->acpi_data.state_count + 1),
368 GFP_KERNEL);
369 if (!data->freq_table) {
370 result = -ENOMEM;
371 goto err_unreg;
372 }
373
374 /* detect transition latency */
375 policy->cpuinfo.transition_latency = 0;
376 for (i=0; i<data->acpi_data.state_count; i++) {
377 if ((data->acpi_data.states[i].transition_latency * 1000) >
378 policy->cpuinfo.transition_latency) {
379 policy->cpuinfo.transition_latency =
380 data->acpi_data.states[i].transition_latency * 1000;
381 }
382 }
383 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
384
385 policy->cur = processor_get_freq(data, policy->cpu);
386
387 /* table init */
388 for (i = 0; i <= data->acpi_data.state_count; i++)
389 {
390 data->freq_table[i].index = i;
391 if (i < data->acpi_data.state_count) {
392 data->freq_table[i].frequency =
393 data->acpi_data.states[i].core_frequency * 1000;
394 } else {
395 data->freq_table[i].frequency = CPUFREQ_TABLE_END;
396 }
397 }
398
399 result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
400 if (result) {
401 goto err_freqfree;
402 }
403
404 /* notify BIOS that we exist */
405 acpi_processor_notify_smm(THIS_MODULE);
406
407 printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management "
408 "activated.\n", cpu);
409
410 for (i = 0; i < data->acpi_data.state_count; i++)
411 dprintk(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
412 (i == data->acpi_data.state?'*':' '), i,
413 (u32) data->acpi_data.states[i].core_frequency,
414 (u32) data->acpi_data.states[i].power,
415 (u32) data->acpi_data.states[i].transition_latency,
416 (u32) data->acpi_data.states[i].bus_master_latency,
417 (u32) data->acpi_data.states[i].status,
418 (u32) data->acpi_data.states[i].control);
419
420 cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
421
422 /* the first call to ->target() should result in us actually
423 * writing something to the appropriate registers. */
424 data->resume = 1;
425
426 return (result);
427
428 err_freqfree:
429 kfree(data->freq_table);
430 err_unreg:
431 acpi_processor_unregister_performance(&data->acpi_data, cpu);
432 err_free:
433 kfree(data);
434 acpi_io_data[cpu] = NULL;
435
436 return (result);
437}
438
439
440static int
441acpi_cpufreq_cpu_exit (
442 struct cpufreq_policy *policy)
443{
444 struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
445
446 dprintk("acpi_cpufreq_cpu_exit\n");
447
448 if (data) {
449 cpufreq_frequency_table_put_attr(policy->cpu);
450 acpi_io_data[policy->cpu] = NULL;
451 acpi_processor_unregister_performance(&data->acpi_data,
452 policy->cpu);
453 kfree(data);
454 }
455
456 return (0);
457}
458
459
460static struct freq_attr* acpi_cpufreq_attr[] = {
461 &cpufreq_freq_attr_scaling_available_freqs,
462 NULL,
463};
464
465
466static struct cpufreq_driver acpi_cpufreq_driver = {
467 .verify = acpi_cpufreq_verify,
468 .target = acpi_cpufreq_target,
469 .get = acpi_cpufreq_get,
470 .init = acpi_cpufreq_cpu_init,
471 .exit = acpi_cpufreq_cpu_exit,
472 .name = "acpi-cpufreq",
473 .owner = THIS_MODULE,
474 .attr = acpi_cpufreq_attr,
475};
476
477
478static int __init
479acpi_cpufreq_init (void)
480{
481 dprintk("acpi_cpufreq_init\n");
482
483 return cpufreq_register_driver(&acpi_cpufreq_driver);
484}
485
486
487static void __exit
488acpi_cpufreq_exit (void)
489{
490 dprintk("acpi_cpufreq_exit\n");
491
492 cpufreq_unregister_driver(&acpi_cpufreq_driver);
493 return;
494}
495
496
497late_initcall(acpi_cpufreq_init);
498module_exit(acpi_cpufreq_exit);
499
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 770fab37928e..f2dbcd1db0d4 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -35,7 +35,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
35 return -ENOMEM; 35 return -ENOMEM;
36 36
37#ifdef CONFIG_HUGETLB_PAGE 37#ifdef CONFIG_HUGETLB_PAGE
38 if (REGION_NUMBER(addr) == REGION_HPAGE) 38 if (REGION_NUMBER(addr) == RGN_HPAGE)
39 addr = 0; 39 addr = 0;
40#endif 40#endif
41 if (!addr) 41 if (!addr)
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index 490dfc9ab47f..4e9d06c48a8b 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -184,7 +184,7 @@ uncached_free_page(unsigned long maddr)
184{ 184{
185 int node; 185 int node;
186 186
187 node = nasid_to_cnodeid(NASID_GET(maddr)); 187 node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET);
188 188
189 dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node); 189 dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
190 190
@@ -217,7 +217,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
217 217
218 memset((char *)vstart, 0, length); 218 memset((char *)vstart, 0, length);
219 219
220 node = nasid_to_cnodeid(NASID_GET(start)); 220 node = paddr_to_nid(start);
221 221
222 for (; vstart < vend ; vstart += PAGE_SIZE) { 222 for (; vstart < vend ; vstart += PAGE_SIZE) {
223 dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart); 223 dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
index 1902c3c2ef92..799407e7726f 100644
--- a/arch/ia64/lib/Makefile
+++ b/arch/ia64/lib/Makefile
@@ -6,7 +6,7 @@ obj-y := io.o
6 6
7lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ 7lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
8 __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ 8 __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \
9 bitop.o checksum.o clear_page.o csum_partial_copy.o copy_page.o \ 9 bitop.o checksum.o clear_page.o csum_partial_copy.o \
10 clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ 10 clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \
11 flush.o ip_fast_csum.o do_csum.o \ 11 flush.o ip_fast_csum.o do_csum.o \
12 memset.o strlen.o swiotlb.o 12 memset.o strlen.o swiotlb.o
diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
index ab7b3ad99a7f..dbc0b3e449c5 100644
--- a/arch/ia64/lib/swiotlb.c
+++ b/arch/ia64/lib/swiotlb.c
@@ -93,8 +93,7 @@ static int __init
93setup_io_tlb_npages(char *str) 93setup_io_tlb_npages(char *str)
94{ 94{
95 if (isdigit(*str)) { 95 if (isdigit(*str)) {
96 io_tlb_nslabs = simple_strtoul(str, &str, 0) << 96 io_tlb_nslabs = simple_strtoul(str, &str, 0);
97 (PAGE_SHIFT - IO_TLB_SHIFT);
98 /* avoid tail segment of size < IO_TLB_SEGSIZE */ 97 /* avoid tail segment of size < IO_TLB_SEGSIZE */
99 io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); 98 io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
100 } 99 }
@@ -117,7 +116,7 @@ swiotlb_init_with_default_size (size_t default_size)
117 unsigned long i; 116 unsigned long i;
118 117
119 if (!io_tlb_nslabs) { 118 if (!io_tlb_nslabs) {
120 io_tlb_nslabs = (default_size >> PAGE_SHIFT); 119 io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
121 io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); 120 io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
122 } 121 }
123 122
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index e0a776a3044c..2d13889d0a99 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -76,7 +76,7 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
76 return -EINVAL; 76 return -EINVAL;
77 if (addr & ~HPAGE_MASK) 77 if (addr & ~HPAGE_MASK)
78 return -EINVAL; 78 return -EINVAL;
79 if (REGION_NUMBER(addr) != REGION_HPAGE) 79 if (REGION_NUMBER(addr) != RGN_HPAGE)
80 return -EINVAL; 80 return -EINVAL;
81 81
82 return 0; 82 return 0;
@@ -87,7 +87,7 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int writ
87 struct page *page; 87 struct page *page;
88 pte_t *ptep; 88 pte_t *ptep;
89 89
90 if (REGION_NUMBER(addr) != REGION_HPAGE) 90 if (REGION_NUMBER(addr) != RGN_HPAGE)
91 return ERR_PTR(-EINVAL); 91 return ERR_PTR(-EINVAL);
92 92
93 ptep = huge_pte_offset(mm, addr); 93 ptep = huge_pte_offset(mm, addr);
@@ -142,8 +142,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u
142 return -ENOMEM; 142 return -ENOMEM;
143 if (len & ~HPAGE_MASK) 143 if (len & ~HPAGE_MASK)
144 return -EINVAL; 144 return -EINVAL;
145 /* This code assumes that REGION_HPAGE != 0. */ 145 /* This code assumes that RGN_HPAGE != 0. */
146 if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) 146 if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1)))
147 addr = HPAGE_REGION_BASE; 147 addr = HPAGE_REGION_BASE;
148 else 148 else
149 addr = ALIGN(addr, HPAGE_SIZE); 149 addr = ALIGN(addr, HPAGE_SIZE);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index f9472c50ab42..9977c122e9fa 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -24,7 +24,6 @@
24 24
25#include <asm/machvec.h> 25#include <asm/machvec.h>
26#include <asm/page.h> 26#include <asm/page.h>
27#include <asm/segment.h>
28#include <asm/system.h> 27#include <asm/system.h>
29#include <asm/io.h> 28#include <asm/io.h>
30#include <asm/sal.h> 29#include <asm/sal.h>
diff --git a/arch/ia64/sn/include/tio.h b/arch/ia64/sn/include/tio.h
index 0139124dd54a..6b2e7b75eb19 100644
--- a/arch/ia64/sn/include/tio.h
+++ b/arch/ia64/sn/include/tio.h
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8 8
9#ifndef _ASM_IA64_SN_TIO_H 9#ifndef _ASM_IA64_SN_TIO_H
@@ -26,6 +26,10 @@
26#define TIO_ITTE_VALID_MASK 0x1 26#define TIO_ITTE_VALID_MASK 0x1
27#define TIO_ITTE_VALID_SHIFT 16 27#define TIO_ITTE_VALID_SHIFT 16
28 28
29#define TIO_ITTE_WIDGET(itte) \
30 (((itte) >> TIO_ITTE_WIDGET_SHIFT) & TIO_ITTE_WIDGET_MASK)
31#define TIO_ITTE_VALID(itte) \
32 (((itte) >> TIO_ITTE_VALID_SHIFT) & TIO_ITTE_VALID_MASK)
29 33
30#define TIO_ITTE_PUT(nasid, bigwin, widget, addr, valid) \ 34#define TIO_ITTE_PUT(nasid, bigwin, widget, addr, valid) \
31 REMOTE_HUB_S((nasid), TIO_ITTE(bigwin), \ 35 REMOTE_HUB_S((nasid), TIO_ITTE(bigwin), \
diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h
index 580a1c0403a7..71c2b271b4c6 100644
--- a/arch/ia64/sn/include/xtalk/hubdev.h
+++ b/arch/ia64/sn/include/xtalk/hubdev.h
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8#ifndef _ASM_IA64_SN_XTALK_HUBDEV_H 8#ifndef _ASM_IA64_SN_XTALK_HUBDEV_H
9#define _ASM_IA64_SN_XTALK_HUBDEV_H 9#define _ASM_IA64_SN_XTALK_HUBDEV_H
@@ -16,6 +16,9 @@
16#define IIO_ITTE_WIDGET_MASK ((1<<IIO_ITTE_WIDGET_BITS)-1) 16#define IIO_ITTE_WIDGET_MASK ((1<<IIO_ITTE_WIDGET_BITS)-1)
17#define IIO_ITTE_WIDGET_SHIFT 8 17#define IIO_ITTE_WIDGET_SHIFT 8
18 18
19#define IIO_ITTE_WIDGET(itte) \
20 (((itte) >> IIO_ITTE_WIDGET_SHIFT) & IIO_ITTE_WIDGET_MASK)
21
19/* 22/*
20 * Use the top big window as a surrogate for the first small window 23 * Use the top big window as a surrogate for the first small window
21 */ 24 */
@@ -34,7 +37,8 @@ struct sn_flush_device_list {
34 unsigned long sfdl_force_int_addr; 37 unsigned long sfdl_force_int_addr;
35 unsigned long sfdl_flush_value; 38 unsigned long sfdl_flush_value;
36 volatile unsigned long *sfdl_flush_addr; 39 volatile unsigned long *sfdl_flush_addr;
37 uint64_t sfdl_persistent_busnum; 40 uint32_t sfdl_persistent_busnum;
41 uint32_t sfdl_persistent_segment;
38 struct pcibus_info *sfdl_pcibus_info; 42 struct pcibus_info *sfdl_pcibus_info;
39 spinlock_t sfdl_flush_lock; 43 spinlock_t sfdl_flush_lock;
40}; 44};
@@ -58,7 +62,8 @@ struct hubdev_info {
58 62
59 void *hdi_nodepda; 63 void *hdi_nodepda;
60 void *hdi_node_vertex; 64 void *hdi_node_vertex;
61 void *hdi_xtalk_vertex; 65 uint32_t max_segment_number;
66 uint32_t max_pcibus_number;
62}; 67};
63 68
64extern void hubdev_init_node(nodepda_t *, cnodeid_t); 69extern void hubdev_init_node(nodepda_t *, cnodeid_t);
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 647deae9bfcd..45854c637e9c 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -29,16 +29,30 @@
29 29
30/* two interfaces on two btes */ 30/* two interfaces on two btes */
31#define MAX_INTERFACES_TO_TRY 4 31#define MAX_INTERFACES_TO_TRY 4
32#define MAX_NODES_TO_TRY 2
32 33
33static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface) 34static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface)
34{ 35{
35 nodepda_t *tmp_nodepda; 36 nodepda_t *tmp_nodepda;
36 37
38 if (nasid_to_cnodeid(nasid) == -1)
39 return (struct bteinfo_s *)NULL;;
40
37 tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid)); 41 tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid));
38 return &tmp_nodepda->bte_if[interface]; 42 return &tmp_nodepda->bte_if[interface];
39 43
40} 44}
41 45
46static inline void bte_start_transfer(struct bteinfo_s *bte, u64 len, u64 mode)
47{
48 if (is_shub2()) {
49 BTE_CTRL_STORE(bte, (IBLS_BUSY | ((len) | (mode) << 24)));
50 } else {
51 BTE_LNSTAT_STORE(bte, len);
52 BTE_CTRL_STORE(bte, mode);
53 }
54}
55
42/************************************************************************ 56/************************************************************************
43 * Block Transfer Engine copy related functions. 57 * Block Transfer Engine copy related functions.
44 * 58 *
@@ -67,13 +81,15 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
67{ 81{
68 u64 transfer_size; 82 u64 transfer_size;
69 u64 transfer_stat; 83 u64 transfer_stat;
84 u64 notif_phys_addr;
70 struct bteinfo_s *bte; 85 struct bteinfo_s *bte;
71 bte_result_t bte_status; 86 bte_result_t bte_status;
72 unsigned long irq_flags; 87 unsigned long irq_flags;
73 unsigned long itc_end = 0; 88 unsigned long itc_end = 0;
74 struct bteinfo_s *btes_to_try[MAX_INTERFACES_TO_TRY]; 89 int nasid_to_try[MAX_NODES_TO_TRY];
75 int bte_if_index; 90 int my_nasid = get_nasid();
76 int bte_pri, bte_sec; 91 int bte_if_index, nasid_index;
92 int bte_first, btes_per_node = BTES_PER_NODE;
77 93
78 BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n", 94 BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n",
79 src, dest, len, mode, notification)); 95 src, dest, len, mode, notification));
@@ -86,36 +102,26 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
86 (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK)); 102 (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK));
87 BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT))); 103 BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)));
88 104
89 /* CPU 0 (per node) tries bte0 first, CPU 1 try bte1 first */ 105 /*
90 if (cpuid_to_subnode(smp_processor_id()) == 0) { 106 * Start with interface corresponding to cpu number
91 bte_pri = 0; 107 */
92 bte_sec = 1; 108 bte_first = raw_smp_processor_id() % btes_per_node;
93 } else {
94 bte_pri = 1;
95 bte_sec = 0;
96 }
97 109
98 if (mode & BTE_USE_DEST) { 110 if (mode & BTE_USE_DEST) {
99 /* try remote then local */ 111 /* try remote then local */
100 btes_to_try[0] = bte_if_on_node(NASID_GET(dest), bte_pri); 112 nasid_to_try[0] = NASID_GET(dest);
101 btes_to_try[1] = bte_if_on_node(NASID_GET(dest), bte_sec);
102 if (mode & BTE_USE_ANY) { 113 if (mode & BTE_USE_ANY) {
103 btes_to_try[2] = bte_if_on_node(get_nasid(), bte_pri); 114 nasid_to_try[1] = my_nasid;
104 btes_to_try[3] = bte_if_on_node(get_nasid(), bte_sec);
105 } else { 115 } else {
106 btes_to_try[2] = NULL; 116 nasid_to_try[1] = (int)NULL;
107 btes_to_try[3] = NULL;
108 } 117 }
109 } else { 118 } else {
110 /* try local then remote */ 119 /* try local then remote */
111 btes_to_try[0] = bte_if_on_node(get_nasid(), bte_pri); 120 nasid_to_try[0] = my_nasid;
112 btes_to_try[1] = bte_if_on_node(get_nasid(), bte_sec);
113 if (mode & BTE_USE_ANY) { 121 if (mode & BTE_USE_ANY) {
114 btes_to_try[2] = bte_if_on_node(NASID_GET(dest), bte_pri); 122 nasid_to_try[1] = NASID_GET(dest);
115 btes_to_try[3] = bte_if_on_node(NASID_GET(dest), bte_sec);
116 } else { 123 } else {
117 btes_to_try[2] = NULL; 124 nasid_to_try[1] = (int)NULL;
118 btes_to_try[3] = NULL;
119 } 125 }
120 } 126 }
121 127
@@ -123,11 +129,12 @@ retry_bteop:
123 do { 129 do {
124 local_irq_save(irq_flags); 130 local_irq_save(irq_flags);
125 131
126 bte_if_index = 0; 132 bte_if_index = bte_first;
133 nasid_index = 0;
127 134
128 /* Attempt to lock one of the BTE interfaces. */ 135 /* Attempt to lock one of the BTE interfaces. */
129 while (bte_if_index < MAX_INTERFACES_TO_TRY) { 136 while (nasid_index < MAX_NODES_TO_TRY) {
130 bte = btes_to_try[bte_if_index++]; 137 bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index);
131 138
132 if (bte == NULL) { 139 if (bte == NULL) {
133 continue; 140 continue;
@@ -143,6 +150,15 @@ retry_bteop:
143 break; 150 break;
144 } 151 }
145 } 152 }
153
154 bte_if_index = (bte_if_index + 1) % btes_per_node; /* Next interface */
155 if (bte_if_index == bte_first) {
156 /*
157 * We've tried all interfaces on this node
158 */
159 nasid_index++;
160 }
161
146 bte = NULL; 162 bte = NULL;
147 } 163 }
148 164
@@ -169,7 +185,13 @@ retry_bteop:
169 185
170 /* Initialize the notification to a known value. */ 186 /* Initialize the notification to a known value. */
171 *bte->most_rcnt_na = BTE_WORD_BUSY; 187 *bte->most_rcnt_na = BTE_WORD_BUSY;
188 notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na));
172 189
190 if (is_shub2()) {
191 src = SH2_TIO_PHYS_TO_DMA(src);
192 dest = SH2_TIO_PHYS_TO_DMA(dest);
193 notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr);
194 }
173 /* Set the source and destination registers */ 195 /* Set the source and destination registers */
174 BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); 196 BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src))));
175 BTE_SRC_STORE(bte, TO_PHYS(src)); 197 BTE_SRC_STORE(bte, TO_PHYS(src));
@@ -177,14 +199,12 @@ retry_bteop:
177 BTE_DEST_STORE(bte, TO_PHYS(dest)); 199 BTE_DEST_STORE(bte, TO_PHYS(dest));
178 200
179 /* Set the notification register */ 201 /* Set the notification register */
180 BTE_PRINTKV(("IBNA = 0x%lx)\n", 202 BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr));
181 TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)))); 203 BTE_NOTIF_STORE(bte, notif_phys_addr);
182 BTE_NOTIF_STORE(bte,
183 TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)));
184 204
185 /* Initiate the transfer */ 205 /* Initiate the transfer */
186 BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode))); 206 BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode)));
187 BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode)); 207 bte_start_transfer(bte, transfer_size, BTE_VALID_MODE(mode));
188 208
189 itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec); 209 itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec);
190 210
@@ -195,6 +215,7 @@ retry_bteop:
195 } 215 }
196 216
197 while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) { 217 while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) {
218 cpu_relax();
198 if (ia64_get_itc() > itc_end) { 219 if (ia64_get_itc() > itc_end) {
199 BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n", 220 BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n",
200 NASID_GET(bte->bte_base_addr), bte->bte_num, 221 NASID_GET(bte->bte_base_addr), bte->bte_num,
diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c
index 5c39b43ba3c0..5c5eb01c50f0 100644
--- a/arch/ia64/sn/kernel/huberror.c
+++ b/arch/ia64/sn/kernel/huberror.c
@@ -76,7 +76,7 @@ void hubiio_crb_free(struct hubdev_info *hubdev_info, int crbnum)
76 */ 76 */
77 REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum)); 77 REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum));
78 while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND) 78 while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND)
79 udelay(1); 79 cpu_relax();
80 80
81} 81}
82 82
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 414cdf2e3c96..4564ed0b5ff3 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -18,6 +18,7 @@
18#include <asm/sn/simulator.h> 18#include <asm/sn/simulator.h>
19#include <asm/sn/sn_sal.h> 19#include <asm/sn/sn_sal.h>
20#include <asm/sn/tioca_provider.h> 20#include <asm/sn/tioca_provider.h>
21#include <asm/sn/tioce_provider.h>
21#include "xtalk/hubdev.h" 22#include "xtalk/hubdev.h"
22#include "xtalk/xwidgetdev.h" 23#include "xtalk/xwidgetdev.h"
23 24
@@ -44,6 +45,9 @@ int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */
44 45
45struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ 46struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
46 47
48static int max_segment_number = 0; /* Default highest segment number */
49static int max_pcibus_number = 255; /* Default highest pci bus number */
50
47/* 51/*
48 * Hooks and struct for unsupported pci providers 52 * Hooks and struct for unsupported pci providers
49 */ 53 */
@@ -157,13 +161,28 @@ static void sn_fixup_ionodes(void)
157 uint64_t nasid; 161 uint64_t nasid;
158 int i, widget; 162 int i, widget;
159 163
164 /*
165 * Get SGI Specific HUB chipset information.
166 * Inform Prom that this kernel can support domain bus numbering.
167 */
160 for (i = 0; i < numionodes; i++) { 168 for (i = 0; i < numionodes; i++) {
161 hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo); 169 hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
162 nasid = cnodeid_to_nasid(i); 170 nasid = cnodeid_to_nasid(i);
171 hubdev->max_segment_number = 0xffffffff;
172 hubdev->max_pcibus_number = 0xff;
163 status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); 173 status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev));
164 if (status) 174 if (status)
165 continue; 175 continue;
166 176
177 /* Save the largest Domain and pcibus numbers found. */
178 if (hubdev->max_segment_number) {
179 /*
180 * Dealing with a Prom that supports segments.
181 */
182 max_segment_number = hubdev->max_segment_number;
183 max_pcibus_number = hubdev->max_pcibus_number;
184 }
185
167 /* Attach the error interrupt handlers */ 186 /* Attach the error interrupt handlers */
168 if (nasid & 1) 187 if (nasid & 1)
169 ice_error_init(hubdev); 188 ice_error_init(hubdev);
@@ -230,7 +249,7 @@ void sn_pci_unfixup_slot(struct pci_dev *dev)
230void sn_pci_fixup_slot(struct pci_dev *dev) 249void sn_pci_fixup_slot(struct pci_dev *dev)
231{ 250{
232 int idx; 251 int idx;
233 int segment = 0; 252 int segment = pci_domain_nr(dev->bus);
234 int status = 0; 253 int status = 0;
235 struct pcibus_bussoft *bs; 254 struct pcibus_bussoft *bs;
236 struct pci_bus *host_pci_bus; 255 struct pci_bus *host_pci_bus;
@@ -283,9 +302,9 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
283 * PCI host_pci_dev struct and set up host bus linkages 302 * PCI host_pci_dev struct and set up host bus linkages
284 */ 303 */
285 304
286 bus_no = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32; 305 bus_no = (SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32) & 0xff;
287 devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff; 306 devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff;
288 host_pci_bus = pci_find_bus(pci_domain_nr(dev->bus), bus_no); 307 host_pci_bus = pci_find_bus(segment, bus_no);
289 host_pci_dev = pci_get_slot(host_pci_bus, devfn); 308 host_pci_dev = pci_get_slot(host_pci_bus, devfn);
290 309
291 SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev; 310 SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev;
@@ -333,6 +352,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
333 prom_bussoft_ptr = __va(prom_bussoft_ptr); 352 prom_bussoft_ptr = __va(prom_bussoft_ptr);
334 353
335 controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL); 354 controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL);
355 controller->segment = segment;
336 if (!controller) 356 if (!controller)
337 BUG(); 357 BUG();
338 358
@@ -390,7 +410,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
390 if (controller->node >= num_online_nodes()) { 410 if (controller->node >= num_online_nodes()) {
391 struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); 411 struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
392 412
393 printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu" 413 printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
394 "L_IO=%lx L_MEM=%lx BASE=%lx\n", 414 "L_IO=%lx L_MEM=%lx BASE=%lx\n",
395 b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, 415 b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
396 b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); 416 b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
@@ -445,6 +465,7 @@ sn_sysdata_free_start:
445static int __init sn_pci_init(void) 465static int __init sn_pci_init(void)
446{ 466{
447 int i = 0; 467 int i = 0;
468 int j = 0;
448 struct pci_dev *pci_dev = NULL; 469 struct pci_dev *pci_dev = NULL;
449 extern void sn_init_cpei_timer(void); 470 extern void sn_init_cpei_timer(void);
450#ifdef CONFIG_PROC_FS 471#ifdef CONFIG_PROC_FS
@@ -464,6 +485,7 @@ static int __init sn_pci_init(void)
464 485
465 pcibr_init_provider(); 486 pcibr_init_provider();
466 tioca_init_provider(); 487 tioca_init_provider();
488 tioce_init_provider();
467 489
468 /* 490 /*
469 * This is needed to avoid bounce limit checks in the blk layer 491 * This is needed to avoid bounce limit checks in the blk layer
@@ -479,8 +501,9 @@ static int __init sn_pci_init(void)
479#endif 501#endif
480 502
481 /* busses are not known yet ... */ 503 /* busses are not known yet ... */
482 for (i = 0; i < PCI_BUSES_TO_SCAN; i++) 504 for (i = 0; i <= max_segment_number; i++)
483 sn_pci_controller_fixup(0, i, NULL); 505 for (j = 0; j <= max_pcibus_number; j++)
506 sn_pci_controller_fixup(i, j, NULL);
484 507
485 /* 508 /*
486 * Generic Linux PCI Layer has created the pci_bus and pci_dev 509 * Generic Linux PCI Layer has created the pci_bus and pci_dev
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 392bf8a072b6..01d18b7b5bb3 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 8 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
9 */ 9 */
10 10
11#include <linux/irq.h> 11#include <linux/irq.h>
@@ -76,16 +76,14 @@ static void sn_enable_irq(unsigned int irq)
76 76
77static void sn_ack_irq(unsigned int irq) 77static void sn_ack_irq(unsigned int irq)
78{ 78{
79 uint64_t event_occurred, mask = 0; 79 u64 event_occurred, mask = 0;
80 int nasid;
81 80
82 irq = irq & 0xff; 81 irq = irq & 0xff;
83 nasid = get_nasid();
84 event_occurred = 82 event_occurred =
85 HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED)); 83 HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
86 mask = event_occurred & SH_ALL_INT_MASK; 84 mask = event_occurred & SH_ALL_INT_MASK;
87 HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), 85 HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS),
88 mask); 86 mask);
89 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); 87 __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
90 88
91 move_irq(irq); 89 move_irq(irq);
@@ -93,15 +91,12 @@ static void sn_ack_irq(unsigned int irq)
93 91
94static void sn_end_irq(unsigned int irq) 92static void sn_end_irq(unsigned int irq)
95{ 93{
96 int nasid;
97 int ivec; 94 int ivec;
98 uint64_t event_occurred; 95 u64 event_occurred;
99 96
100 ivec = irq & 0xff; 97 ivec = irq & 0xff;
101 if (ivec == SGI_UART_VECTOR) { 98 if (ivec == SGI_UART_VECTOR) {
102 nasid = get_nasid(); 99 event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
103 event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR
104 (nasid, SH_EVENT_OCCURRED));
105 /* If the UART bit is set here, we may have received an 100 /* If the UART bit is set here, we may have received an
106 * interrupt from the UART that the driver missed. To 101 * interrupt from the UART that the driver missed. To
107 * make sure, we IPI ourselves to force us to look again. 102 * make sure, we IPI ourselves to force us to look again.
@@ -132,6 +127,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
132 int local_widget, status; 127 int local_widget, status;
133 nasid_t local_nasid; 128 nasid_t local_nasid;
134 struct sn_irq_info *new_irq_info; 129 struct sn_irq_info *new_irq_info;
130 struct sn_pcibus_provider *pci_provider;
135 131
136 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); 132 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
137 if (new_irq_info == NULL) 133 if (new_irq_info == NULL)
@@ -171,8 +167,9 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
171 new_irq_info->irq_cpuid = cpuid; 167 new_irq_info->irq_cpuid = cpuid;
172 register_intr_pda(new_irq_info); 168 register_intr_pda(new_irq_info);
173 169
174 if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type)) 170 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
175 pcibr_change_devices_irq(new_irq_info); 171 if (pci_provider && pci_provider->target_interrupt)
172 (pci_provider->target_interrupt)(new_irq_info);
176 173
177 spin_lock(&sn_irq_info_lock); 174 spin_lock(&sn_irq_info_lock);
178 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); 175 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
@@ -317,6 +314,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
317 pci_dev_put(pci_dev); 314 pci_dev_put(pci_dev);
318} 315}
319 316
317static inline void
318sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info)
319{
320 struct sn_pcibus_provider *pci_provider;
321
322 pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
323 if (pci_provider && pci_provider->force_interrupt)
324 (*pci_provider->force_interrupt)(sn_irq_info);
325}
326
320static void force_interrupt(int irq) 327static void force_interrupt(int irq)
321{ 328{
322 struct sn_irq_info *sn_irq_info; 329 struct sn_irq_info *sn_irq_info;
@@ -325,11 +332,9 @@ static void force_interrupt(int irq)
325 return; 332 return;
326 333
327 rcu_read_lock(); 334 rcu_read_lock();
328 list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) { 335 list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
329 if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && 336 sn_call_force_intr_provider(sn_irq_info);
330 (sn_irq_info->irq_bridge != NULL)) 337
331 pcibr_force_interrupt(sn_irq_info);
332 }
333 rcu_read_unlock(); 338 rcu_read_unlock();
334} 339}
335 340
@@ -351,6 +356,14 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
351 struct pcidev_info *pcidev_info; 356 struct pcidev_info *pcidev_info;
352 struct pcibus_info *pcibus_info; 357 struct pcibus_info *pcibus_info;
353 358
359 /*
360 * Bridge types attached to TIO (anything but PIC) do not need this WAR
361 * since they do not target Shub II interrupt registers. If that
362 * ever changes, this check needs to accomodate.
363 */
364 if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
365 return;
366
354 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; 367 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
355 if (!pcidev_info) 368 if (!pcidev_info)
356 return; 369 return;
@@ -377,16 +390,12 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info)
377 break; 390 break;
378 } 391 }
379 if (!test_bit(irr_bit, &irr_reg)) { 392 if (!test_bit(irr_bit, &irr_reg)) {
380 if (!test_bit(irq, pda->sn_soft_irr)) { 393 if (!test_bit(irq, pda->sn_in_service_ivecs)) {
381 if (!test_bit(irq, pda->sn_in_service_ivecs)) { 394 regval &= 0xff;
382 regval &= 0xff; 395 if (sn_irq_info->irq_int_bit & regval &
383 if (sn_irq_info->irq_int_bit & regval & 396 sn_irq_info->irq_last_intr) {
384 sn_irq_info->irq_last_intr) { 397 regval &= ~(sn_irq_info->irq_int_bit & regval);
385 regval &= 398 sn_call_force_intr_provider(sn_irq_info);
386 ~(sn_irq_info->
387 irq_int_bit & regval);
388 pcibr_force_interrupt(sn_irq_info);
389 }
390 } 399 }
391 } 400 }
392 } 401 }
@@ -404,13 +413,7 @@ void sn_lb_int_war_check(void)
404 rcu_read_lock(); 413 rcu_read_lock();
405 for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { 414 for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) {
406 list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) { 415 list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) {
407 /* 416 sn_check_intr(i, sn_irq_info);
408 * Only call for PCI bridges that are fully
409 * initialized.
410 */
411 if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) &&
412 (sn_irq_info->irq_bridge != NULL))
413 sn_check_intr(i, sn_irq_info);
414 } 417 }
415 } 418 }
416 rcu_read_unlock(); 419 rcu_read_unlock();
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 7c7fe441d623..a594aca959e6 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -80,8 +80,6 @@ EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid);
80DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); 80DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda);
81EXPORT_PER_CPU_SYMBOL(__sn_nodepda); 81EXPORT_PER_CPU_SYMBOL(__sn_nodepda);
82 82
83partid_t sn_partid = -1;
84EXPORT_SYMBOL(sn_partid);
85char sn_system_serial_number_string[128]; 83char sn_system_serial_number_string[128];
86EXPORT_SYMBOL(sn_system_serial_number_string); 84EXPORT_SYMBOL(sn_system_serial_number_string);
87u64 sn_partition_serial_number; 85u64 sn_partition_serial_number;
@@ -403,6 +401,7 @@ static void __init sn_init_pdas(char **cmdline_p)
403 memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); 401 memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
404 memset(nodepdaindr[cnode]->phys_cpuid, -1, 402 memset(nodepdaindr[cnode]->phys_cpuid, -1,
405 sizeof(nodepdaindr[cnode]->phys_cpuid)); 403 sizeof(nodepdaindr[cnode]->phys_cpuid));
404 spin_lock_init(&nodepdaindr[cnode]->ptc_lock);
406 } 405 }
407 406
408 /* 407 /*
@@ -532,8 +531,8 @@ void __init sn_cpu_init(void)
532 */ 531 */
533 { 532 {
534 u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0}; 533 u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0};
535 u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_1, 534 u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2,
536 SH2_PIO_WRITE_STATUS_2, SH2_PIO_WRITE_STATUS_3}; 535 SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3};
537 u64 *pio; 536 u64 *pio;
538 pio = is_shub1() ? pio1 : pio2; 537 pio = is_shub1() ? pio1 : pio2;
539 pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); 538 pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]);
diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
index 96cb71d15682..3fa95065a446 100644
--- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
+++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8 8
9#include <asm/types.h> 9#include <asm/types.h>
@@ -11,7 +11,7 @@
11 11
12#define DEADLOCKBIT SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT 12#define DEADLOCKBIT SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT
13#define WRITECOUNTMASK SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK 13#define WRITECOUNTMASK SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK
14#define ALIAS_OFFSET (SH1_PIO_WRITE_STATUS_0_ALIAS-SH1_PIO_WRITE_STATUS_0) 14#define ALIAS_OFFSET 8
15 15
16 16
17 .global sn2_ptc_deadlock_recovery_core 17 .global sn2_ptc_deadlock_recovery_core
@@ -36,13 +36,15 @@ sn2_ptc_deadlock_recovery_core:
36 extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address 36 extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address
37 dep piowcphy=-1,piowcphy,63,1 37 dep piowcphy=-1,piowcphy,63,1
38 movl mask=WRITECOUNTMASK 38 movl mask=WRITECOUNTMASK
39 mov r8=r0
39 40
401: 411:
41 add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register 42 add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register
42 mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR 43 ;;
43 st8.rel [scr2]=scr1;; 44 ld8.acq scr1=[scr2];;
44 45
455: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. 465: ld8.acq scr1=[piowc];; // Wait for PIOs to complete.
47 hint @pause
46 and scr2=scr1,mask;; // mask of writecount bits 48 and scr2=scr1,mask;; // mask of writecount bits
47 cmp.ne p6,p0=zeroval,scr2 49 cmp.ne p6,p0=zeroval,scr2
48(p6) br.cond.sptk 5b 50(p6) br.cond.sptk 5b
@@ -57,6 +59,7 @@ sn2_ptc_deadlock_recovery_core:
57 st8.rel [ptc0]=data0 // Write PTC0 & wait for completion. 59 st8.rel [ptc0]=data0 // Write PTC0 & wait for completion.
58 60
595: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. 615: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
62 hint @pause
60 and scr2=scr1,mask;; // mask of writecount bits 63 and scr2=scr1,mask;; // mask of writecount bits
61 cmp.ne p6,p0=zeroval,scr2 64 cmp.ne p6,p0=zeroval,scr2
62(p6) br.cond.sptk 5b;; 65(p6) br.cond.sptk 5b;;
@@ -67,6 +70,7 @@ sn2_ptc_deadlock_recovery_core:
67(p7) st8.rel [ptc1]=data1;; // Now write PTC1. 70(p7) st8.rel [ptc1]=data1;; // Now write PTC1.
68 71
695: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. 725: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete.
73 hint @pause
70 and scr2=scr1,mask;; // mask of writecount bits 74 and scr2=scr1,mask;; // mask of writecount bits
71 cmp.ne p6,p0=zeroval,scr2 75 cmp.ne p6,p0=zeroval,scr2
72(p6) br.cond.sptk 5b 76(p6) br.cond.sptk 5b
@@ -77,6 +81,7 @@ sn2_ptc_deadlock_recovery_core:
77 srlz.i;; 81 srlz.i;;
78 ////////////// END PHYSICAL MODE //////////////////// 82 ////////////// END PHYSICAL MODE ////////////////////
79 83
84(p8) add r8=1,r8
80(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. 85(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred.
81 86
82 br.ret.sptk rp 87 br.ret.sptk rp
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 7af05a7ac743..0a4ee50c302f 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. 8 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
9 */ 9 */
10 10
11#include <linux/init.h> 11#include <linux/init.h>
@@ -20,6 +20,8 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/bitops.h> 21#include <linux/bitops.h>
22#include <linux/nodemask.h> 22#include <linux/nodemask.h>
23#include <linux/proc_fs.h>
24#include <linux/seq_file.h>
23 25
24#include <asm/processor.h> 26#include <asm/processor.h>
25#include <asm/irq.h> 27#include <asm/irq.h>
@@ -39,12 +41,120 @@
39#include <asm/sn/nodepda.h> 41#include <asm/sn/nodepda.h>
40#include <asm/sn/rw_mmr.h> 42#include <asm/sn/rw_mmr.h>
41 43
42void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0, 44DEFINE_PER_CPU(struct ptc_stats, ptcstats);
43 volatile unsigned long *, unsigned long data1); 45DECLARE_PER_CPU(struct ptc_stats, ptcstats);
44 46
45static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); 47static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
46 48
47static unsigned long sn2_ptc_deadlock_count; 49void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0,
50 volatile unsigned long *, unsigned long data1);
51
52#ifdef DEBUG_PTC
53/*
54 * ptctest:
55 *
56 * xyz - 3 digit hex number:
57 * x - Force PTC purges to use shub:
58 * 0 - no force
59 * 1 - force
60 * y - interupt enable
61 * 0 - disable interrupts
62 * 1 - leave interuupts enabled
63 * z - type of lock:
64 * 0 - global lock
65 * 1 - node local lock
66 * 2 - no lock
67 *
68 * Note: on shub1, only ptctest == 0 is supported. Don't try other values!
69 */
70
71static unsigned int sn2_ptctest = 0;
72
73static int __init ptc_test(char *str)
74{
75 get_option(&str, &sn2_ptctest);
76 return 1;
77}
78__setup("ptctest=", ptc_test);
79
80static inline int ptc_lock(unsigned long *flagp)
81{
82 unsigned long opt = sn2_ptctest & 255;
83
84 switch (opt) {
85 case 0x00:
86 spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
87 break;
88 case 0x01:
89 spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp);
90 break;
91 case 0x02:
92 local_irq_save(*flagp);
93 break;
94 case 0x10:
95 spin_lock(&sn2_global_ptc_lock);
96 break;
97 case 0x11:
98 spin_lock(&sn_nodepda->ptc_lock);
99 break;
100 case 0x12:
101 break;
102 default:
103 BUG();
104 }
105 return opt;
106}
107
108static inline void ptc_unlock(unsigned long flags, int opt)
109{
110 switch (opt) {
111 case 0x00:
112 spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
113 break;
114 case 0x01:
115 spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags);
116 break;
117 case 0x02:
118 local_irq_restore(flags);
119 break;
120 case 0x10:
121 spin_unlock(&sn2_global_ptc_lock);
122 break;
123 case 0x11:
124 spin_unlock(&sn_nodepda->ptc_lock);
125 break;
126 case 0x12:
127 break;
128 default:
129 BUG();
130 }
131}
132#else
133
134#define sn2_ptctest 0
135
136static inline int ptc_lock(unsigned long *flagp)
137{
138 spin_lock_irqsave(&sn2_global_ptc_lock, *flagp);
139 return 0;
140}
141
142static inline void ptc_unlock(unsigned long flags, int opt)
143{
144 spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
145}
146#endif
147
148struct ptc_stats {
149 unsigned long ptc_l;
150 unsigned long change_rid;
151 unsigned long shub_ptc_flushes;
152 unsigned long nodes_flushed;
153 unsigned long deadlocks;
154 unsigned long lock_itc_clocks;
155 unsigned long shub_itc_clocks;
156 unsigned long shub_itc_clocks_max;
157};
48 158
49static inline unsigned long wait_piowc(void) 159static inline unsigned long wait_piowc(void)
50{ 160{
@@ -89,9 +199,9 @@ void
89sn2_global_tlb_purge(unsigned long start, unsigned long end, 199sn2_global_tlb_purge(unsigned long start, unsigned long end,
90 unsigned long nbits) 200 unsigned long nbits)
91{ 201{
92 int i, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; 202 int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0;
93 volatile unsigned long *ptc0, *ptc1; 203 volatile unsigned long *ptc0, *ptc1;
94 unsigned long flags = 0, data0 = 0, data1 = 0; 204 unsigned long itc, itc2, flags, data0 = 0, data1 = 0;
95 struct mm_struct *mm = current->active_mm; 205 struct mm_struct *mm = current->active_mm;
96 short nasids[MAX_NUMNODES], nix; 206 short nasids[MAX_NUMNODES], nix;
97 nodemask_t nodes_flushed; 207 nodemask_t nodes_flushed;
@@ -114,16 +224,19 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
114 start += (1UL << nbits); 224 start += (1UL << nbits);
115 } while (start < end); 225 } while (start < end);
116 ia64_srlz_i(); 226 ia64_srlz_i();
227 __get_cpu_var(ptcstats).ptc_l++;
117 preempt_enable(); 228 preempt_enable();
118 return; 229 return;
119 } 230 }
120 231
121 if (atomic_read(&mm->mm_users) == 1) { 232 if (atomic_read(&mm->mm_users) == 1) {
122 flush_tlb_mm(mm); 233 flush_tlb_mm(mm);
234 __get_cpu_var(ptcstats).change_rid++;
123 preempt_enable(); 235 preempt_enable();
124 return; 236 return;
125 } 237 }
126 238
239 itc = ia64_get_itc();
127 nix = 0; 240 nix = 0;
128 for_each_node_mask(cnode, nodes_flushed) 241 for_each_node_mask(cnode, nodes_flushed)
129 nasids[nix++] = cnodeid_to_nasid(cnode); 242 nasids[nix++] = cnodeid_to_nasid(cnode);
@@ -148,7 +261,12 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
148 261
149 mynasid = get_nasid(); 262 mynasid = get_nasid();
150 263
151 spin_lock_irqsave(&sn2_global_ptc_lock, flags); 264 itc = ia64_get_itc();
265 opt = ptc_lock(&flags);
266 itc2 = ia64_get_itc();
267 __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc;
268 __get_cpu_var(ptcstats).shub_ptc_flushes++;
269 __get_cpu_var(ptcstats).nodes_flushed += nix;
152 270
153 do { 271 do {
154 if (shub1) 272 if (shub1)
@@ -157,7 +275,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
157 data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); 275 data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK);
158 for (i = 0; i < nix; i++) { 276 for (i = 0; i < nix; i++) {
159 nasid = nasids[i]; 277 nasid = nasids[i];
160 if (unlikely(nasid == mynasid)) { 278 if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid)) {
161 ia64_ptcga(start, nbits << 2); 279 ia64_ptcga(start, nbits << 2);
162 ia64_srlz_i(); 280 ia64_srlz_i();
163 } else { 281 } else {
@@ -169,18 +287,22 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
169 flushed = 1; 287 flushed = 1;
170 } 288 }
171 } 289 }
172
173 if (flushed 290 if (flushed
174 && (wait_piowc() & 291 && (wait_piowc() &
175 SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK)) { 292 (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) {
176 sn2_ptc_deadlock_recovery(ptc0, data0, ptc1, data1); 293 sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1);
177 } 294 }
178 295
179 start += (1UL << nbits); 296 start += (1UL << nbits);
180 297
181 } while (start < end); 298 } while (start < end);
182 299
183 spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); 300 itc2 = ia64_get_itc() - itc2;
301 __get_cpu_var(ptcstats).shub_itc_clocks += itc2;
302 if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
303 __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2;
304
305 ptc_unlock(flags, opt);
184 306
185 preempt_enable(); 307 preempt_enable();
186} 308}
@@ -192,31 +314,29 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end,
192 * TLB flush transaction. The recovery sequence is somewhat tricky & is 314 * TLB flush transaction. The recovery sequence is somewhat tricky & is
193 * coded in assembly language. 315 * coded in assembly language.
194 */ 316 */
195void sn2_ptc_deadlock_recovery(volatile unsigned long *ptc0, unsigned long data0, 317void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0,
196 volatile unsigned long *ptc1, unsigned long data1) 318 volatile unsigned long *ptc1, unsigned long data1)
197{ 319{
198 extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, 320 extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
199 volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); 321 volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long);
200 int cnode, mycnode, nasid; 322 short nasid, i;
201 volatile unsigned long *piows; 323 unsigned long *piows, zeroval;
202 volatile unsigned long zeroval;
203 324
204 sn2_ptc_deadlock_count++; 325 __get_cpu_var(ptcstats).deadlocks++;
205 326
206 piows = pda->pio_write_status_addr; 327 piows = (unsigned long *) pda->pio_write_status_addr;
207 zeroval = pda->pio_write_status_val; 328 zeroval = pda->pio_write_status_val;
208 329
209 mycnode = numa_node_id(); 330 for (i=0; i < nix; i++) {
210 331 nasid = nasids[i];
211 for_each_online_node(cnode) { 332 if (!(sn2_ptctest & 3) && nasid == mynasid)
212 if (is_headless_node(cnode) || cnode == mycnode)
213 continue; 333 continue;
214 nasid = cnodeid_to_nasid(cnode);
215 ptc0 = CHANGE_NASID(nasid, ptc0); 334 ptc0 = CHANGE_NASID(nasid, ptc0);
216 if (ptc1) 335 if (ptc1)
217 ptc1 = CHANGE_NASID(nasid, ptc1); 336 ptc1 = CHANGE_NASID(nasid, ptc1);
218 sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); 337 sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval);
219 } 338 }
339
220} 340}
221 341
222/** 342/**
@@ -293,3 +413,93 @@ void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
293 413
294 sn_send_IPI_phys(nasid, physid, vector, delivery_mode); 414 sn_send_IPI_phys(nasid, physid, vector, delivery_mode);
295} 415}
416
417#ifdef CONFIG_PROC_FS
418
419#define PTC_BASENAME "sgi_sn/ptc_statistics"
420
421static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset)
422{
423 if (*offset < NR_CPUS)
424 return offset;
425 return NULL;
426}
427
428static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset)
429{
430 (*offset)++;
431 if (*offset < NR_CPUS)
432 return offset;
433 return NULL;
434}
435
436static void sn2_ptc_seq_stop(struct seq_file *file, void *data)
437{
438}
439
440static int sn2_ptc_seq_show(struct seq_file *file, void *data)
441{
442 struct ptc_stats *stat;
443 int cpu;
444
445 cpu = *(loff_t *) data;
446
447 if (!cpu) {
448 seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n");
449 seq_printf(file, "# ptctest %d\n", sn2_ptctest);
450 }
451
452 if (cpu < NR_CPUS && cpu_online(cpu)) {
453 stat = &per_cpu(ptcstats, cpu);
454 seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
455 stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
456 stat->deadlocks,
457 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
458 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
459 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec);
460 }
461
462 return 0;
463}
464
465static struct seq_operations sn2_ptc_seq_ops = {
466 .start = sn2_ptc_seq_start,
467 .next = sn2_ptc_seq_next,
468 .stop = sn2_ptc_seq_stop,
469 .show = sn2_ptc_seq_show
470};
471
472int sn2_ptc_proc_open(struct inode *inode, struct file *file)
473{
474 return seq_open(file, &sn2_ptc_seq_ops);
475}
476
477static struct file_operations proc_sn2_ptc_operations = {
478 .open = sn2_ptc_proc_open,
479 .read = seq_read,
480 .llseek = seq_lseek,
481 .release = seq_release,
482};
483
484static struct proc_dir_entry *proc_sn2_ptc;
485
486static int __init sn2_ptc_init(void)
487{
488 if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) {
489 printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME);
490 return -EINVAL;
491 }
492 proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations;
493 spin_lock_init(&sn2_global_ptc_lock);
494 return 0;
495}
496
497static void __exit sn2_ptc_exit(void)
498{
499 remove_proc_entry(PTC_BASENAME, NULL);
500}
501
502module_init(sn2_ptc_init);
503module_exit(sn2_ptc_exit);
504#endif /* CONFIG_PROC_FS */
505
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 833e700fdac9..0513aacac8c1 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -36,7 +36,6 @@
36#include <asm/topology.h> 36#include <asm/topology.h>
37#include <asm/smp.h> 37#include <asm/smp.h>
38#include <asm/semaphore.h> 38#include <asm/semaphore.h>
39#include <asm/segment.h>
40#include <asm/uaccess.h> 39#include <asm/uaccess.h>
41#include <asm/sal.h> 40#include <asm/sal.h>
42#include <asm/sn/io.h> 41#include <asm/sn/io.h>
@@ -59,7 +58,7 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
59 struct sn_hwperf_object_info *objbuf = NULL; 58 struct sn_hwperf_object_info *objbuf = NULL;
60 59
61 if ((e = sn_hwperf_init()) < 0) { 60 if ((e = sn_hwperf_init()) < 0) {
62 printk("sn_hwperf_init failed: err %d\n", e); 61 printk(KERN_ERR "sn_hwperf_init failed: err %d\n", e);
63 goto out; 62 goto out;
64 } 63 }
65 64
@@ -111,7 +110,7 @@ static int sn_hwperf_geoid_to_cnode(char *location)
111 if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) 110 if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab))
112 return -1; 111 return -1;
113 112
114 for (cnode = 0; cnode < numionodes; cnode++) { 113 for_each_node(cnode) {
115 geoid = cnodeid_get_geoid(cnode); 114 geoid = cnodeid_get_geoid(cnode);
116 module_id = geo_module(geoid); 115 module_id = geo_module(geoid);
117 this_rack = MODULE_GET_RACK(module_id); 116 this_rack = MODULE_GET_RACK(module_id);
@@ -124,11 +123,13 @@ static int sn_hwperf_geoid_to_cnode(char *location)
124 } 123 }
125 } 124 }
126 125
127 return cnode < numionodes ? cnode : -1; 126 return node_possible(cnode) ? cnode : -1;
128} 127}
129 128
130static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) 129static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
131{ 130{
131 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
132 BUG();
132 if (!obj->sn_hwp_this_part) 133 if (!obj->sn_hwp_this_part)
133 return -1; 134 return -1;
134 return sn_hwperf_geoid_to_cnode(obj->location); 135 return sn_hwperf_geoid_to_cnode(obj->location);
@@ -174,31 +175,199 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj,
174 return slabname; 175 return slabname;
175} 176}
176 177
177static void print_pci_topology(struct seq_file *s, 178static void print_pci_topology(struct seq_file *s)
178 struct sn_hwperf_object_info *obj, int *ordinal, 179{
179 u64 rack, u64 bay, u64 slot, u64 slab) 180 char *p;
181 size_t sz;
182 int e;
183
184 for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) {
185 if (!(p = (char *)kmalloc(sz, GFP_KERNEL)))
186 break;
187 e = ia64_sn_ioif_get_pci_topology(__pa(p), sz);
188 if (e == SALRET_OK)
189 seq_puts(s, p);
190 kfree(p);
191 if (e == SALRET_OK || e == SALRET_NOT_IMPLEMENTED)
192 break;
193 }
194}
195
196static inline int sn_hwperf_has_cpus(cnodeid_t node)
197{
198 return node_online(node) && nr_cpus_node(node);
199}
200
201static inline int sn_hwperf_has_mem(cnodeid_t node)
202{
203 return node_online(node) && NODE_DATA(node)->node_present_pages;
204}
205
206static struct sn_hwperf_object_info *
207sn_hwperf_findobj_id(struct sn_hwperf_object_info *objbuf,
208 int nobj, int id)
180{ 209{
181 char *p1; 210 int i;
182 char *p2; 211 struct sn_hwperf_object_info *p = objbuf;
183 char *pg; 212
184 213 for (i=0; i < nobj; i++, p++) {
185 if (!(pg = (char *)get_zeroed_page(GFP_KERNEL))) 214 if (p->id == id)
186 return; /* ignore */ 215 return p;
187 if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab, 216 }
188 __pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) { 217
189 for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) { 218 return NULL;
190 if (!(p2 = strchr(p1, '\n'))) 219
220}
221
222static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objbuf,
223 int nobj, cnodeid_t node, cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
224{
225 int e;
226 struct sn_hwperf_object_info *nodeobj = NULL;
227 struct sn_hwperf_object_info *op;
228 struct sn_hwperf_object_info *dest;
229 struct sn_hwperf_object_info *router;
230 struct sn_hwperf_port_info ptdata[16];
231 int sz, i, j;
232 cnodeid_t c;
233 int found_mem = 0;
234 int found_cpu = 0;
235
236 if (!node_possible(node))
237 return -EINVAL;
238
239 if (sn_hwperf_has_cpus(node)) {
240 if (near_cpu_node)
241 *near_cpu_node = node;
242 found_cpu++;
243 }
244
245 if (sn_hwperf_has_mem(node)) {
246 if (near_mem_node)
247 *near_mem_node = node;
248 found_mem++;
249 }
250
251 if (found_cpu && found_mem)
252 return 0; /* trivially successful */
253
254 /* find the argument node object */
255 for (i=0, op=objbuf; i < nobj; i++, op++) {
256 if (!SN_HWPERF_IS_NODE(op) && !SN_HWPERF_IS_IONODE(op))
257 continue;
258 if (node == sn_hwperf_obj_to_cnode(op)) {
259 nodeobj = op;
260 break;
261 }
262 }
263 if (!nodeobj) {
264 e = -ENOENT;
265 goto err;
266 }
267
268 /* get it's interconnect topology */
269 sz = op->ports * sizeof(struct sn_hwperf_port_info);
270 if (sz > sizeof(ptdata))
271 BUG();
272 e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
273 SN_HWPERF_ENUM_PORTS, nodeobj->id, sz,
274 (u64)&ptdata, 0, 0, NULL);
275 if (e != SN_HWPERF_OP_OK) {
276 e = -EINVAL;
277 goto err;
278 }
279
280 /* find nearest node with cpus and nearest memory */
281 for (router=NULL, j=0; j < op->ports; j++) {
282 dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id);
283 if (!dest || SN_HWPERF_FOREIGN(dest) ||
284 !SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) {
285 continue;
286 }
287 c = sn_hwperf_obj_to_cnode(dest);
288 if (!found_cpu && sn_hwperf_has_cpus(c)) {
289 if (near_cpu_node)
290 *near_cpu_node = c;
291 found_cpu++;
292 }
293 if (!found_mem && sn_hwperf_has_mem(c)) {
294 if (near_mem_node)
295 *near_mem_node = c;
296 found_mem++;
297 }
298 if (SN_HWPERF_IS_ROUTER(dest))
299 router = dest;
300 }
301
302 if (router && (!found_cpu || !found_mem)) {
303 /* search for a node connected to the same router */
304 sz = router->ports * sizeof(struct sn_hwperf_port_info);
305 if (sz > sizeof(ptdata))
306 BUG();
307 e = ia64_sn_hwperf_op(sn_hwperf_master_nasid,
308 SN_HWPERF_ENUM_PORTS, router->id, sz,
309 (u64)&ptdata, 0, 0, NULL);
310 if (e != SN_HWPERF_OP_OK) {
311 e = -EINVAL;
312 goto err;
313 }
314 for (j=0; j < router->ports; j++) {
315 dest = sn_hwperf_findobj_id(objbuf, nobj,
316 ptdata[j].conn_id);
317 if (!dest || dest->id == node ||
318 SN_HWPERF_FOREIGN(dest) ||
319 !SN_HWPERF_IS_NODE(dest) ||
320 SN_HWPERF_IS_IONODE(dest)) {
321 continue;
322 }
323 c = sn_hwperf_obj_to_cnode(dest);
324 if (!found_cpu && sn_hwperf_has_cpus(c)) {
325 if (near_cpu_node)
326 *near_cpu_node = c;
327 found_cpu++;
328 }
329 if (!found_mem && sn_hwperf_has_mem(c)) {
330 if (near_mem_node)
331 *near_mem_node = c;
332 found_mem++;
333 }
334 if (found_cpu && found_mem)
335 break;
336 }
337 }
338
339 if (!found_cpu || !found_mem) {
340 /* resort to _any_ node with CPUs and memory */
341 for (i=0, op=objbuf; i < nobj; i++, op++) {
342 if (SN_HWPERF_FOREIGN(op) ||
343 SN_HWPERF_IS_IONODE(op) ||
344 !SN_HWPERF_IS_NODE(op)) {
345 continue;
346 }
347 c = sn_hwperf_obj_to_cnode(op);
348 if (!found_cpu && sn_hwperf_has_cpus(c)) {
349 if (near_cpu_node)
350 *near_cpu_node = c;
351 found_cpu++;
352 }
353 if (!found_mem && sn_hwperf_has_mem(c)) {
354 if (near_mem_node)
355 *near_mem_node = c;
356 found_mem++;
357 }
358 if (found_cpu && found_mem)
191 break; 359 break;
192 *p2 = '\0';
193 seq_printf(s, "pcibus %d %s-%s\n",
194 *ordinal, obj->location, p1);
195 (*ordinal)++;
196 p1 = p2 + 1;
197 } 360 }
198 } 361 }
199 free_page((unsigned long)pg); 362
363 if (!found_cpu || !found_mem)
364 e = -ENODATA;
365
366err:
367 return e;
200} 368}
201 369
370
202static int sn_topology_show(struct seq_file *s, void *d) 371static int sn_topology_show(struct seq_file *s, void *d)
203{ 372{
204 int sz; 373 int sz;
@@ -215,7 +384,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
215 struct sn_hwperf_object_info *p; 384 struct sn_hwperf_object_info *p;
216 struct sn_hwperf_object_info *obj = d; /* this object */ 385 struct sn_hwperf_object_info *obj = d; /* this object */
217 struct sn_hwperf_object_info *objs = s->private; /* all objects */ 386 struct sn_hwperf_object_info *objs = s->private; /* all objects */
218 int rack, bay, slot, slab;
219 u8 shubtype; 387 u8 shubtype;
220 u8 system_size; 388 u8 system_size;
221 u8 sharing_size; 389 u8 sharing_size;
@@ -225,7 +393,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
225 u8 region_size; 393 u8 region_size;
226 u16 nasid_mask; 394 u16 nasid_mask;
227 int nasid_msb; 395 int nasid_msb;
228 int pci_bus_ordinal = 0;
229 396
230 if (obj == objs) { 397 if (obj == objs) {
231 seq_printf(s, "# sn_topology version 2\n"); 398 seq_printf(s, "# sn_topology version 2\n");
@@ -253,6 +420,8 @@ static int sn_topology_show(struct seq_file *s, void *d)
253 shubtype ? "shub2" : "shub1", 420 shubtype ? "shub2" : "shub1",
254 (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift, 421 (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift,
255 system_size, sharing_size, coher, region_size); 422 system_size, sharing_size, coher, region_size);
423
424 print_pci_topology(s);
256 } 425 }
257 426
258 if (SN_HWPERF_FOREIGN(obj)) { 427 if (SN_HWPERF_FOREIGN(obj)) {
@@ -272,11 +441,24 @@ static int sn_topology_show(struct seq_file *s, void *d)
272 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) 441 if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
273 seq_putc(s, '\n'); 442 seq_putc(s, '\n');
274 else { 443 else {
444 cnodeid_t near_mem = -1;
445 cnodeid_t near_cpu = -1;
446
275 seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal)); 447 seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal));
276 for (i=0; i < numionodes; i++) { 448
277 seq_printf(s, i ? ":%d" : ", dist %d", 449 if (sn_hwperf_get_nearest_node_objdata(objs, sn_hwperf_obj_cnt,
278 node_distance(ordinal, i)); 450 ordinal, &near_mem, &near_cpu) == 0) {
451 seq_printf(s, ", near_mem_nodeid %d, near_cpu_nodeid %d",
452 near_mem, near_cpu);
453 }
454
455 if (!SN_HWPERF_IS_IONODE(obj)) {
456 for_each_online_node(i) {
457 seq_printf(s, i ? ":%d" : ", dist %d",
458 node_distance(ordinal, i));
459 }
279 } 460 }
461
280 seq_putc(s, '\n'); 462 seq_putc(s, '\n');
281 463
282 /* 464 /*
@@ -300,17 +482,6 @@ static int sn_topology_show(struct seq_file *s, void *d)
300 seq_putc(s, '\n'); 482 seq_putc(s, '\n');
301 } 483 }
302 } 484 }
303
304 /*
305 * PCI busses attached to this node, if any
306 */
307 if (sn_hwperf_location_to_bpos(obj->location,
308 &rack, &bay, &slot, &slab)) {
309 /* export pci bus info */
310 print_pci_topology(s, obj, &pci_bus_ordinal,
311 rack, bay, slot, slab);
312
313 }
314 } 485 }
315 486
316 if (obj->ports) { 487 if (obj->ports) {
@@ -572,6 +743,8 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
572 if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { 743 if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) {
573 memset(p, 0, a.sz); 744 memset(p, 0, a.sz);
574 for (i = 0; i < nobj; i++) { 745 for (i = 0; i < nobj; i++) {
746 if (!SN_HWPERF_IS_NODE(objs + i))
747 continue;
575 node = sn_hwperf_obj_to_cnode(objs + i); 748 node = sn_hwperf_obj_to_cnode(objs + i);
576 for_each_online_cpu(j) { 749 for_each_online_cpu(j) {
577 if (node != cpu_to_node(j)) 750 if (node != cpu_to_node(j))
@@ -598,7 +771,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
598 771
599 case SN_HWPERF_GET_NODE_NASID: 772 case SN_HWPERF_GET_NODE_NASID:
600 if (a.sz != sizeof(u64) || 773 if (a.sz != sizeof(u64) ||
601 (node = a.arg) < 0 || node >= numionodes) { 774 (node = a.arg) < 0 || !node_possible(node)) {
602 r = -EINVAL; 775 r = -EINVAL;
603 goto error; 776 goto error;
604 } 777 }
@@ -627,6 +800,14 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg)
627 vfree(objs); 800 vfree(objs);
628 goto error; 801 goto error;
629 } 802 }
803
804 if (!SN_HWPERF_IS_NODE(objs + i) &&
805 !SN_HWPERF_IS_IONODE(objs + i)) {
806 r = -ENOENT;
807 vfree(objs);
808 goto error;
809 }
810
630 *(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i); 811 *(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i);
631 vfree(objs); 812 vfree(objs);
632 } 813 }
@@ -692,6 +873,7 @@ static int sn_hwperf_init(void)
692 873
693 /* single threaded, once-only initialization */ 874 /* single threaded, once-only initialization */
694 down(&sn_hwperf_init_mutex); 875 down(&sn_hwperf_init_mutex);
876
695 if (sn_hwperf_salheap) { 877 if (sn_hwperf_salheap) {
696 up(&sn_hwperf_init_mutex); 878 up(&sn_hwperf_init_mutex);
697 return e; 879 return e;
@@ -742,19 +924,6 @@ out:
742 sn_hwperf_salheap = NULL; 924 sn_hwperf_salheap = NULL;
743 sn_hwperf_obj_cnt = 0; 925 sn_hwperf_obj_cnt = 0;
744 } 926 }
745
746 if (!e) {
747 /*
748 * Register a dynamic misc device for ioctl. Platforms
749 * supporting hotplug will create /dev/sn_hwperf, else
750 * user can to look up the minor number in /proc/misc.
751 */
752 if ((e = misc_register(&sn_hwperf_dev)) != 0) {
753 printk(KERN_ERR "sn_hwperf_init: misc register "
754 "for \"sn_hwperf\" failed, err %d\n", e);
755 }
756 }
757
758 up(&sn_hwperf_init_mutex); 927 up(&sn_hwperf_init_mutex);
759 return e; 928 return e;
760} 929}
@@ -782,3 +951,41 @@ int sn_topology_release(struct inode *inode, struct file *file)
782 vfree(seq->private); 951 vfree(seq->private);
783 return seq_release(inode, file); 952 return seq_release(inode, file);
784} 953}
954
955int sn_hwperf_get_nearest_node(cnodeid_t node,
956 cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node)
957{
958 int e;
959 int nobj;
960 struct sn_hwperf_object_info *objbuf;
961
962 if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) {
963 e = sn_hwperf_get_nearest_node_objdata(objbuf, nobj,
964 node, near_mem_node, near_cpu_node);
965 vfree(objbuf);
966 }
967
968 return e;
969}
970
971static int __devinit sn_hwperf_misc_register_init(void)
972{
973 int e;
974
975 sn_hwperf_init();
976
977 /*
978 * Register a dynamic misc device for hwperf ioctls. Platforms
979 * supporting hotplug will create /dev/sn_hwperf, else user
980 * can to look up the minor number in /proc/misc.
981 */
982 if ((e = misc_register(&sn_hwperf_dev)) != 0) {
983 printk(KERN_ERR "sn_hwperf_misc_register_init: failed to "
984 "register misc device for \"%s\"\n", sn_hwperf_dev.name);
985 }
986
987 return e;
988}
989
990device_initcall(sn_hwperf_misc_register_init); /* after misc_init() */
991EXPORT_SYMBOL(sn_hwperf_get_nearest_node);
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
index 266a3a84c01d..a06719d752a0 100644
--- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
+++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8#include <linux/config.h> 8#include <linux/config.h>
9#include <asm/uaccess.h> 9#include <asm/uaccess.h>
@@ -15,7 +15,7 @@
15 15
16static int partition_id_show(struct seq_file *s, void *p) 16static int partition_id_show(struct seq_file *s, void *p)
17{ 17{
18 seq_printf(s, "%d\n", sn_local_partid()); 18 seq_printf(s, "%d\n", sn_partition_id);
19 return 0; 19 return 0;
20} 20}
21 21
diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
index cde7375390b0..adf5db2e2afe 100644
--- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c
+++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * 2 *
3 * 3 *
4 * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. 4 * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License 7 * under the terms of version 2 of the GNU General Public License
@@ -50,14 +50,16 @@ void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
50 LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT); 50 LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT);
51 } 51 }
52 52
53 if (enable_shub_wars_1_1()) { 53 if (is_shub1()) {
54 /* Bugfix code for SHUB 1.1 */ 54 if (enable_shub_wars_1_1()) {
55 if (pda->pio_shub_war_cam_addr) 55 /* Bugfix code for SHUB 1.1 */
56 *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; 56 if (pda->pio_shub_war_cam_addr)
57 *pda->pio_shub_war_cam_addr = 0x8000000000000010UL;
58 }
59 if (pda->sn_lb_int_war_ticks == 0)
60 sn_lb_int_war_check();
61 pda->sn_lb_int_war_ticks++;
62 if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
63 pda->sn_lb_int_war_ticks = 0;
57 } 64 }
58 if (pda->sn_lb_int_war_ticks == 0)
59 sn_lb_int_war_check();
60 pda->sn_lb_int_war_ticks++;
61 if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
62 pda->sn_lb_int_war_ticks = 0;
63} 65}
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index 2f915bce25f9..321576b1b425 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,4 +7,4 @@
7# 7#
8# Makefile for the sn pci general routines. 8# Makefile for the sn pci general routines.
9 9
10obj-y := pci_dma.o tioca_provider.o pcibr/ 10obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index b058dc2a0b9d..34093476e965 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -3,7 +3,7 @@
3 * License. See the file "COPYING" in the main directory of this archive 3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved. 6 * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved.
7 */ 7 */
8 8
9#include <linux/types.h> 9#include <linux/types.h>
@@ -215,8 +215,8 @@ void sn_dma_flush(uint64_t addr)
215 int is_tio; 215 int is_tio;
216 int wid_num; 216 int wid_num;
217 int i, j; 217 int i, j;
218 int bwin;
219 uint64_t flags; 218 uint64_t flags;
219 uint64_t itte;
220 struct hubdev_info *hubinfo; 220 struct hubdev_info *hubinfo;
221 volatile struct sn_flush_device_list *p; 221 volatile struct sn_flush_device_list *p;
222 struct sn_flush_nasid_entry *flush_nasid_list; 222 struct sn_flush_nasid_entry *flush_nasid_list;
@@ -233,31 +233,36 @@ void sn_dma_flush(uint64_t addr)
233 if (!hubinfo) { 233 if (!hubinfo) {
234 BUG(); 234 BUG();
235 } 235 }
236 is_tio = (nasid & 1);
237 if (is_tio) {
238 wid_num = TIO_SWIN_WIDGETNUM(addr);
239 bwin = TIO_BWIN_WINDOWNUM(addr);
240 } else {
241 wid_num = SWIN_WIDGETNUM(addr);
242 bwin = BWIN_WINDOWNUM(addr);
243 }
244 236
245 flush_nasid_list = &hubinfo->hdi_flush_nasid_list; 237 flush_nasid_list = &hubinfo->hdi_flush_nasid_list;
246 if (flush_nasid_list->widget_p == NULL) 238 if (flush_nasid_list->widget_p == NULL)
247 return; 239 return;
248 if (bwin > 0) {
249 uint64_t itte = flush_nasid_list->iio_itte[bwin];
250 240
251 if (is_tio) { 241 is_tio = (nasid & 1);
252 wid_num = (itte >> TIO_ITTE_WIDGET_SHIFT) & 242 if (is_tio) {
253 TIO_ITTE_WIDGET_MASK; 243 int itte_index;
254 } else { 244
255 wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & 245 if (TIO_HWIN(addr))
256 IIO_ITTE_WIDGET_MASK; 246 itte_index = 0;
257 } 247 else if (TIO_BWIN_WINDOWNUM(addr))
248 itte_index = TIO_BWIN_WINDOWNUM(addr);
249 else
250 itte_index = -1;
251
252 if (itte_index >= 0) {
253 itte = flush_nasid_list->iio_itte[itte_index];
254 if (! TIO_ITTE_VALID(itte))
255 return;
256 wid_num = TIO_ITTE_WIDGET(itte);
257 } else
258 wid_num = TIO_SWIN_WIDGETNUM(addr);
259 } else {
260 if (BWIN_WINDOWNUM(addr)) {
261 itte = flush_nasid_list->iio_itte[BWIN_WINDOWNUM(addr)];
262 wid_num = IIO_ITTE_WIDGET(itte);
263 } else
264 wid_num = SWIN_WIDGETNUM(addr);
258 } 265 }
259 if (flush_nasid_list->widget_p == NULL)
260 return;
261 if (flush_nasid_list->widget_p[wid_num] == NULL) 266 if (flush_nasid_list->widget_p[wid_num] == NULL)
262 return; 267 return;
263 p = &flush_nasid_list->widget_p[wid_num][0]; 268 p = &flush_nasid_list->widget_p[wid_num][0];
@@ -283,10 +288,16 @@ void sn_dma_flush(uint64_t addr)
283 /* 288 /*
284 * For TIOCP use the Device(x) Write Request Buffer Flush Bridge 289 * For TIOCP use the Device(x) Write Request Buffer Flush Bridge
285 * register since it ensures the data has entered the coherence 290 * register since it ensures the data has entered the coherence
286 * domain, unlike PIC 291 * domain, unlike PIC.
287 */ 292 */
288 if (is_tio) { 293 if (is_tio) {
289 uint32_t tio_id = REMOTE_HUB_L(nasid, TIO_NODE_ID); 294 /*
295 * Note: devices behind TIOCE should never be matched in the
296 * above code, and so the following code is PIC/CP centric.
297 * If CE ever needs the sn_dma_flush mechanism, we will have
298 * to account for that here and in tioce_bus_fixup().
299 */
300 uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID));
290 uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); 301 uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id);
291 302
292 /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ 303 /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */
@@ -306,7 +317,8 @@ void sn_dma_flush(uint64_t addr)
306 *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; 317 *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1;
307 318
308 /* wait for the interrupt to come back. */ 319 /* wait for the interrupt to come back. */
309 while (*(p->sfdl_flush_addr) != 0x10f) ; 320 while (*(p->sfdl_flush_addr) != 0x10f)
321 cpu_relax();
310 322
311 /* okay, everything is synched up. */ 323 /* okay, everything is synched up. */
312 spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); 324 spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index b95e928636a1..7b03b8084ffc 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -15,6 +15,7 @@
15#include <asm/sn/pcibus_provider_defs.h> 15#include <asm/sn/pcibus_provider_defs.h>
16#include <asm/sn/pcidev.h> 16#include <asm/sn/pcidev.h>
17#include <asm/sn/sn_sal.h> 17#include <asm/sn/sn_sal.h>
18#include <asm/sn/sn2/sn_hwperf.h>
18#include "xtalk/xwidgetdev.h" 19#include "xtalk/xwidgetdev.h"
19#include "xtalk/hubdev.h" 20#include "xtalk/hubdev.h"
20 21
@@ -60,7 +61,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
60 ret_stuff.status = 0; 61 ret_stuff.status = 0;
61 ret_stuff.v0 = 0; 62 ret_stuff.v0 = 0;
62 63
63 segment = 0; 64 segment = soft->pbi_buscommon.bs_persist_segment;
64 busnum = soft->pbi_buscommon.bs_persist_busnum; 65 busnum = soft->pbi_buscommon.bs_persist_busnum;
65 SAL_CALL_NOLOCK(ret_stuff, 66 SAL_CALL_NOLOCK(ret_stuff,
66 (u64) SN_SAL_IOIF_ERROR_INTERRUPT, 67 (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
@@ -88,6 +89,7 @@ void *
88pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) 89pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
89{ 90{
90 int nasid, cnode, j; 91 int nasid, cnode, j;
92 cnodeid_t near_cnode;
91 struct hubdev_info *hubdev_info; 93 struct hubdev_info *hubdev_info;
92 struct pcibus_info *soft; 94 struct pcibus_info *soft;
93 struct sn_flush_device_list *sn_flush_device_list; 95 struct sn_flush_device_list *sn_flush_device_list;
@@ -115,7 +117,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
115 /* 117 /*
116 * register the bridge's error interrupt handler 118 * register the bridge's error interrupt handler
117 */ 119 */
118 if (request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, 120 if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler,
119 SA_SHIRQ, "PCIBR error", (void *)(soft))) { 121 SA_SHIRQ, "PCIBR error", (void *)(soft))) {
120 printk(KERN_WARNING 122 printk(KERN_WARNING
121 "pcibr cannot allocate interrupt for error handler\n"); 123 "pcibr cannot allocate interrupt for error handler\n");
@@ -142,9 +144,12 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
142 j++, sn_flush_device_list++) { 144 j++, sn_flush_device_list++) {
143 if (sn_flush_device_list->sfdl_slot == -1) 145 if (sn_flush_device_list->sfdl_slot == -1)
144 continue; 146 continue;
145 if (sn_flush_device_list-> 147 if ((sn_flush_device_list->
146 sfdl_persistent_busnum == 148 sfdl_persistent_segment ==
147 soft->pbi_buscommon.bs_persist_busnum) 149 soft->pbi_buscommon.bs_persist_segment) &&
150 (sn_flush_device_list->
151 sfdl_persistent_busnum ==
152 soft->pbi_buscommon.bs_persist_busnum))
148 sn_flush_device_list->sfdl_pcibus_info = 153 sn_flush_device_list->sfdl_pcibus_info =
149 soft; 154 soft;
150 } 155 }
@@ -158,12 +163,18 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
158 memset(soft->pbi_int_ate_resource.ate, 0, 163 memset(soft->pbi_int_ate_resource.ate, 0,
159 (soft->pbi_int_ate_size * sizeof(uint64_t))); 164 (soft->pbi_int_ate_size * sizeof(uint64_t)));
160 165
161 if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) 166 if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
162 /* 167 /* TIO PCI Bridge: find nearest node with CPUs */
163 * TIO PCI Bridge with no closest node information. 168 int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode);
164 * FIXME: Find another way to determine the closest node 169
165 */ 170 if (e < 0) {
166 controller->node = -1; 171 near_cnode = (cnodeid_t)-1; /* use any node */
172 printk(KERN_WARNING "pcibr_bus_fixup: failed to find "
173 "near node with CPUs to TIO node %d, err=%d\n",
174 cnode, e);
175 }
176 controller->node = near_cnode;
177 }
167 else 178 else
168 controller->node = cnode; 179 controller->node = cnode;
169 return soft; 180 return soft;
@@ -175,6 +186,9 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
175 struct pcibus_info *pcibus_info; 186 struct pcibus_info *pcibus_info;
176 int bit = sn_irq_info->irq_int_bit; 187 int bit = sn_irq_info->irq_int_bit;
177 188
189 if (! sn_irq_info->irq_bridge)
190 return;
191
178 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; 192 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
179 if (pcidev_info) { 193 if (pcidev_info) {
180 pcibus_info = 194 pcibus_info =
@@ -184,7 +198,7 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
184 } 198 }
185} 199}
186 200
187void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info) 201void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
188{ 202{
189 struct pcidev_info *pcidev_info; 203 struct pcidev_info *pcidev_info;
190 struct pcibus_info *pcibus_info; 204 struct pcibus_info *pcibus_info;
@@ -219,6 +233,8 @@ struct sn_pcibus_provider pcibr_provider = {
219 .dma_map_consistent = pcibr_dma_map_consistent, 233 .dma_map_consistent = pcibr_dma_map_consistent,
220 .dma_unmap = pcibr_dma_unmap, 234 .dma_unmap = pcibr_dma_unmap,
221 .bus_fixup = pcibr_bus_fixup, 235 .bus_fixup = pcibr_bus_fixup,
236 .force_interrupt = pcibr_force_interrupt,
237 .target_interrupt = pcibr_target_interrupt
222}; 238};
223 239
224int 240int
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 5d76a7581465..ea09c12f0258 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -559,7 +559,7 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
559 ret_stuff.status = 0; 559 ret_stuff.status = 0;
560 ret_stuff.v0 = 0; 560 ret_stuff.v0 = 0;
561 561
562 segment = 0; 562 segment = soft->ca_common.bs_persist_segment;
563 busnum = soft->ca_common.bs_persist_busnum; 563 busnum = soft->ca_common.bs_persist_busnum;
564 564
565 SAL_CALL_NOLOCK(ret_stuff, 565 SAL_CALL_NOLOCK(ret_stuff,
@@ -622,7 +622,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
622 nasid_to_cnodeid(tioca_common->ca_closest_nasid); 622 nasid_to_cnodeid(tioca_common->ca_closest_nasid);
623 tioca_common->ca_kernel_private = (uint64_t) tioca_kern; 623 tioca_common->ca_kernel_private = (uint64_t) tioca_kern;
624 624
625 bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum); 625 bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment,
626 tioca_common->ca_common.bs_persist_busnum);
626 BUG_ON(!bus); 627 BUG_ON(!bus);
627 tioca_kern->ca_devices = &bus->devices; 628 tioca_kern->ca_devices = &bus->devices;
628 629
@@ -656,6 +657,8 @@ static struct sn_pcibus_provider tioca_pci_interfaces = {
656 .dma_map_consistent = tioca_dma_map, 657 .dma_map_consistent = tioca_dma_map,
657 .dma_unmap = tioca_dma_unmap, 658 .dma_unmap = tioca_dma_unmap,
658 .bus_fixup = tioca_bus_fixup, 659 .bus_fixup = tioca_bus_fixup,
660 .force_interrupt = NULL,
661 .target_interrupt = NULL
659}; 662};
660 663
661/** 664/**
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
new file mode 100644
index 000000000000..8e75db2b825d
--- /dev/null
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -0,0 +1,771 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9#include <linux/types.h>
10#include <linux/interrupt.h>
11#include <linux/pci.h>
12#include <asm/sn/sn_sal.h>
13#include <asm/sn/addrs.h>
14#include <asm/sn/pcidev.h>
15#include <asm/sn/pcibus_provider_defs.h>
16#include <asm/sn/tioce_provider.h>
17
18/**
19 * Bus address ranges for the 5 flavors of TIOCE DMA
20 */
21
22#define TIOCE_D64_MIN 0x8000000000000000UL
23#define TIOCE_D64_MAX 0xffffffffffffffffUL
24#define TIOCE_D64_ADDR(a) ((a) >= TIOCE_D64_MIN)
25
26#define TIOCE_D32_MIN 0x0000000080000000UL
27#define TIOCE_D32_MAX 0x00000000ffffffffUL
28#define TIOCE_D32_ADDR(a) ((a) >= TIOCE_D32_MIN && (a) <= TIOCE_D32_MAX)
29
30#define TIOCE_M32_MIN 0x0000000000000000UL
31#define TIOCE_M32_MAX 0x000000007fffffffUL
32#define TIOCE_M32_ADDR(a) ((a) >= TIOCE_M32_MIN && (a) <= TIOCE_M32_MAX)
33
34#define TIOCE_M40_MIN 0x0000004000000000UL
35#define TIOCE_M40_MAX 0x0000007fffffffffUL
36#define TIOCE_M40_ADDR(a) ((a) >= TIOCE_M40_MIN && (a) <= TIOCE_M40_MAX)
37
38#define TIOCE_M40S_MIN 0x0000008000000000UL
39#define TIOCE_M40S_MAX 0x000000ffffffffffUL
40#define TIOCE_M40S_ADDR(a) ((a) >= TIOCE_M40S_MIN && (a) <= TIOCE_M40S_MAX)
41
42/*
43 * ATE manipulation macros.
44 */
45
46#define ATE_PAGESHIFT(ps) (__ffs(ps))
47#define ATE_PAGEMASK(ps) ((ps)-1)
48
49#define ATE_PAGE(x, ps) ((x) >> ATE_PAGESHIFT(ps))
50#define ATE_NPAGES(start, len, pagesize) \
51 (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
52
53#define ATE_VALID(ate) ((ate) & (1UL << 63))
54#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
55
56/*
57 * Flavors of ate-based mapping supported by tioce_alloc_map()
58 */
59
60#define TIOCE_ATE_M32 1
61#define TIOCE_ATE_M40 2
62#define TIOCE_ATE_M40S 3
63
64#define KB(x) ((x) << 10)
65#define MB(x) ((x) << 20)
66#define GB(x) ((x) << 30)
67
68/**
69 * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode
70 * @ct_addr: system coretalk address
71 *
72 * Map @ct_addr into 64-bit CE bus space. No device context is necessary
73 * and no CE mapping are consumed.
74 *
75 * Bits 53:0 come from the coretalk address. The remaining bits are set as
76 * follows:
77 *
78 * 63 - must be 1 to indicate d64 mode to CE hardware
79 * 62 - barrier bit ... controlled with tioce_dma_barrier()
80 * 61 - 0 since this is not an MSI transaction
81 * 60:54 - reserved, MBZ
82 */
83static uint64_t
84tioce_dma_d64(unsigned long ct_addr)
85{
86 uint64_t bus_addr;
87
88 bus_addr = ct_addr | (1UL << 63);
89
90 return bus_addr;
91}
92
93/**
94 * pcidev_to_tioce - return misc ce related pointers given a pci_dev
95 * @pci_dev: pci device context
96 * @base: ptr to store struct tioce_mmr * for the CE holding this device
97 * @kernel: ptr to store struct tioce_kernel * for the CE holding this device
98 * @port: ptr to store the CE port number that this device is on
99 *
100 * Return pointers to various CE-related structures for the CE upstream of
101 * @pci_dev.
102 */
103static inline void
104pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base,
105 struct tioce_kernel **kernel, int *port)
106{
107 struct pcidev_info *pcidev_info;
108 struct tioce_common *ce_common;
109 struct tioce_kernel *ce_kernel;
110
111 pcidev_info = SN_PCIDEV_INFO(pdev);
112 ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
113 ce_kernel = (struct tioce_kernel *)ce_common->ce_kernel_private;
114
115 if (base)
116 *base = (struct tioce *)ce_common->ce_pcibus.bs_base;
117 if (kernel)
118 *kernel = ce_kernel;
119
120 /*
121 * we use port as a zero-based value internally, even though the
122 * documentation is 1-based.
123 */
124 if (port)
125 *port =
126 (pdev->bus->number < ce_kernel->ce_port1_secondary) ? 0 : 1;
127}
128
129/**
130 * tioce_alloc_map - Given a coretalk address, map it to pcie bus address
131 * space using one of the various ATE-based address modes.
132 * @ce_kern: tioce context
133 * @type: map mode to use
134 * @port: 0-based port that the requesting device is downstream of
135 * @ct_addr: the coretalk address to map
136 * @len: number of bytes to map
137 *
138 * Given the addressing type, set up various paramaters that define the
139 * ATE pool to use. Search for a contiguous block of entries to cover the
140 * length, and if enough resources exist, fill in the ATE's and construct a
141 * tioce_dmamap struct to track the mapping.
142 */
143static uint64_t
144tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
145 uint64_t ct_addr, int len)
146{
147 int i;
148 int j;
149 int first;
150 int last;
151 int entries;
152 int nates;
153 int pagesize;
154 uint64_t *ate_shadow;
155 uint64_t *ate_reg;
156 uint64_t addr;
157 struct tioce *ce_mmr;
158 uint64_t bus_base;
159 struct tioce_dmamap *map;
160
161 ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base;
162
163 switch (type) {
164 case TIOCE_ATE_M32:
165 /*
166 * The first 64 entries of the ate3240 pool are dedicated to
167 * super-page (TIOCE_ATE_M40S) mode.
168 */
169 first = 64;
170 entries = TIOCE_NUM_M3240_ATES - 64;
171 ate_shadow = ce_kern->ce_ate3240_shadow;
172 ate_reg = ce_mmr->ce_ure_ate3240;
173 pagesize = ce_kern->ce_ate3240_pagesize;
174 bus_base = TIOCE_M32_MIN;
175 break;
176 case TIOCE_ATE_M40:
177 first = 0;
178 entries = TIOCE_NUM_M40_ATES;
179 ate_shadow = ce_kern->ce_ate40_shadow;
180 ate_reg = ce_mmr->ce_ure_ate40;
181 pagesize = MB(64);
182 bus_base = TIOCE_M40_MIN;
183 break;
184 case TIOCE_ATE_M40S:
185 /*
186 * ate3240 entries 0-31 are dedicated to port1 super-page
187 * mappings. ate3240 entries 32-63 are dedicated to port2.
188 */
189 first = port * 32;
190 entries = 32;
191 ate_shadow = ce_kern->ce_ate3240_shadow;
192 ate_reg = ce_mmr->ce_ure_ate3240;
193 pagesize = GB(16);
194 bus_base = TIOCE_M40S_MIN;
195 break;
196 default:
197 return 0;
198 }
199
200 nates = ATE_NPAGES(ct_addr, len, pagesize);
201 if (nates > entries)
202 return 0;
203
204 last = first + entries - nates;
205 for (i = first; i <= last; i++) {
206 if (ATE_VALID(ate_shadow[i]))
207 continue;
208
209 for (j = i; j < i + nates; j++)
210 if (ATE_VALID(ate_shadow[j]))
211 break;
212
213 if (j >= i + nates)
214 break;
215 }
216
217 if (i > last)
218 return 0;
219
220 map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC);
221 if (!map)
222 return 0;
223
224 addr = ct_addr;
225 for (j = 0; j < nates; j++) {
226 uint64_t ate;
227
228 ate = ATE_MAKE(addr, pagesize);
229 ate_shadow[i + j] = ate;
230 ate_reg[i + j] = ate;
231 addr += pagesize;
232 }
233
234 map->refcnt = 1;
235 map->nbytes = nates * pagesize;
236 map->ct_start = ct_addr & ~ATE_PAGEMASK(pagesize);
237 map->pci_start = bus_base + (i * pagesize);
238 map->ate_hw = &ate_reg[i];
239 map->ate_shadow = &ate_shadow[i];
240 map->ate_count = nates;
241
242 list_add(&map->ce_dmamap_list, &ce_kern->ce_dmamap_list);
243
244 return (map->pci_start + (ct_addr - map->ct_start));
245}
246
247/**
248 * tioce_dma_d32 - create a DMA mapping using 32-bit direct mode
249 * @pdev: linux pci_dev representing the function
250 * @paddr: system physical address
251 *
252 * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
253 */
254static uint64_t
255tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr)
256{
257 int dma_ok;
258 int port;
259 struct tioce *ce_mmr;
260 struct tioce_kernel *ce_kern;
261 uint64_t ct_upper;
262 uint64_t ct_lower;
263 dma_addr_t bus_addr;
264
265 ct_upper = ct_addr & ~0x3fffffffUL;
266 ct_lower = ct_addr & 0x3fffffffUL;
267
268 pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
269
270 if (ce_kern->ce_port[port].dirmap_refcnt == 0) {
271 volatile uint64_t tmp;
272
273 ce_kern->ce_port[port].dirmap_shadow = ct_upper;
274 ce_mmr->ce_ure_dir_map[port] = ct_upper;
275 tmp = ce_mmr->ce_ure_dir_map[port];
276 dma_ok = 1;
277 } else
278 dma_ok = (ce_kern->ce_port[port].dirmap_shadow == ct_upper);
279
280 if (dma_ok) {
281 ce_kern->ce_port[port].dirmap_refcnt++;
282 bus_addr = TIOCE_D32_MIN + ct_lower;
283 } else
284 bus_addr = 0;
285
286 return bus_addr;
287}
288
289/**
290 * tioce_dma_barrier - swizzle a TIOCE bus address to include or exclude
291 * the barrier bit.
292 * @bus_addr: bus address to swizzle
293 *
294 * Given a TIOCE bus address, set the appropriate bit to indicate barrier
295 * attributes.
296 */
297static uint64_t
298tioce_dma_barrier(uint64_t bus_addr, int on)
299{
300 uint64_t barrier_bit;
301
302 /* barrier not supported in M40/M40S mode */
303 if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr))
304 return bus_addr;
305
306 if (TIOCE_D64_ADDR(bus_addr))
307 barrier_bit = (1UL << 62);
308 else /* must be m32 or d32 */
309 barrier_bit = (1UL << 30);
310
311 return (on) ? (bus_addr | barrier_bit) : (bus_addr & ~barrier_bit);
312}
313
314/**
315 * tioce_dma_unmap - release CE mapping resources
316 * @pdev: linux pci_dev representing the function
317 * @bus_addr: bus address returned by an earlier tioce_dma_map
318 * @dir: mapping direction (unused)
319 *
320 * Locate mapping resources associated with @bus_addr and release them.
321 * For mappings created using the direct modes there are no resources
322 * to release.
323 */
324void
325tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
326{
327 int i;
328 int port;
329 struct tioce_kernel *ce_kern;
330 struct tioce *ce_mmr;
331 unsigned long flags;
332
333 bus_addr = tioce_dma_barrier(bus_addr, 0);
334 pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port);
335
336 /* nothing to do for D64 */
337
338 if (TIOCE_D64_ADDR(bus_addr))
339 return;
340
341 spin_lock_irqsave(&ce_kern->ce_lock, flags);
342
343 if (TIOCE_D32_ADDR(bus_addr)) {
344 if (--ce_kern->ce_port[port].dirmap_refcnt == 0) {
345 ce_kern->ce_port[port].dirmap_shadow = 0;
346 ce_mmr->ce_ure_dir_map[port] = 0;
347 }
348 } else {
349 struct tioce_dmamap *map;
350
351 list_for_each_entry(map, &ce_kern->ce_dmamap_list,
352 ce_dmamap_list) {
353 uint64_t last;
354
355 last = map->pci_start + map->nbytes - 1;
356 if (bus_addr >= map->pci_start && bus_addr <= last)
357 break;
358 }
359
360 if (&map->ce_dmamap_list == &ce_kern->ce_dmamap_list) {
361 printk(KERN_WARNING
362 "%s: %s - no map found for bus_addr 0x%lx\n",
363 __FUNCTION__, pci_name(pdev), bus_addr);
364 } else if (--map->refcnt == 0) {
365 for (i = 0; i < map->ate_count; i++) {
366 map->ate_shadow[i] = 0;
367 map->ate_hw[i] = 0;
368 }
369
370 list_del(&map->ce_dmamap_list);
371 kfree(map);
372 }
373 }
374
375 spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
376}
377
378/**
379 * tioce_do_dma_map - map pages for PCI DMA
380 * @pdev: linux pci_dev representing the function
381 * @paddr: host physical address to map
382 * @byte_count: bytes to map
383 *
384 * This is the main wrapper for mapping host physical pages to CE PCI space.
385 * The mapping mode used is based on the device's dma_mask.
386 */
387static uint64_t
388tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count,
389 int barrier)
390{
391 unsigned long flags;
392 uint64_t ct_addr;
393 uint64_t mapaddr = 0;
394 struct tioce_kernel *ce_kern;
395 struct tioce_dmamap *map;
396 int port;
397 uint64_t dma_mask;
398
399 dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask;
400
401 /* cards must be able to address at least 31 bits */
402 if (dma_mask < 0x7fffffffUL)
403 return 0;
404
405 ct_addr = PHYS_TO_TIODMA(paddr);
406
407 /*
408 * If the device can generate 64 bit addresses, create a D64 map.
409 * Since this should never fail, bypass the rest of the checks.
410 */
411 if (dma_mask == ~0UL) {
412 mapaddr = tioce_dma_d64(ct_addr);
413 goto dma_map_done;
414 }
415
416 pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
417
418 spin_lock_irqsave(&ce_kern->ce_lock, flags);
419
420 /*
421 * D64 didn't work ... See if we have an existing map that covers
422 * this address range. Must account for devices dma_mask here since
423 * an existing map might have been done in a mode using more pci
424 * address bits than this device can support.
425 */
426 list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) {
427 uint64_t last;
428
429 last = map->ct_start + map->nbytes - 1;
430 if (ct_addr >= map->ct_start &&
431 ct_addr + byte_count - 1 <= last &&
432 map->pci_start <= dma_mask) {
433 map->refcnt++;
434 mapaddr = map->pci_start + (ct_addr - map->ct_start);
435 break;
436 }
437 }
438
439 /*
440 * If we don't have a map yet, and the card can generate 40
441 * bit addresses, try the M40/M40S modes. Note these modes do not
442 * support a barrier bit, so if we need a consistent map these
443 * won't work.
444 */
445 if (!mapaddr && !barrier && dma_mask >= 0xffffffffffUL) {
446 /*
447 * We have two options for 40-bit mappings: 16GB "super" ATE's
448 * and 64MB "regular" ATE's. We'll try both if needed for a
449 * given mapping but which one we try first depends on the
450 * size. For requests >64MB, prefer to use a super page with
451 * regular as the fallback. Otherwise, try in the reverse order.
452 */
453
454 if (byte_count > MB(64)) {
455 mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
456 port, ct_addr, byte_count);
457 if (!mapaddr)
458 mapaddr =
459 tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
460 ct_addr, byte_count);
461 } else {
462 mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
463 ct_addr, byte_count);
464 if (!mapaddr)
465 mapaddr =
466 tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
467 port, ct_addr, byte_count);
468 }
469 }
470
471 /*
472 * 32-bit direct is the next mode to try
473 */
474 if (!mapaddr && dma_mask >= 0xffffffffUL)
475 mapaddr = tioce_dma_d32(pdev, ct_addr);
476
477 /*
478 * Last resort, try 32-bit ATE-based map.
479 */
480 if (!mapaddr)
481 mapaddr =
482 tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
483 byte_count);
484
485 spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
486
487dma_map_done:
488 if (mapaddr & barrier)
489 mapaddr = tioce_dma_barrier(mapaddr, 1);
490
491 return mapaddr;
492}
493
494/**
495 * tioce_dma - standard pci dma map interface
496 * @pdev: pci device requesting the map
497 * @paddr: system physical address to map into pci space
498 * @byte_count: # bytes to map
499 *
500 * Simply call tioce_do_dma_map() to create a map with the barrier bit clear
501 * in the address.
502 */
503static uint64_t
504tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
505{
506 return tioce_do_dma_map(pdev, paddr, byte_count, 0);
507}
508
509/**
510 * tioce_dma_consistent - consistent pci dma map interface
511 * @pdev: pci device requesting the map
512 * @paddr: system physical address to map into pci space
513 * @byte_count: # bytes to map
514 *
515 * Simply call tioce_do_dma_map() to create a map with the barrier bit set
516 * in the address.
517 */ static uint64_t
518tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count)
519{
520 return tioce_do_dma_map(pdev, paddr, byte_count, 1);
521}
522
523/**
524 * tioce_error_intr_handler - SGI TIO CE error interrupt handler
525 * @irq: unused
526 * @arg: pointer to tioce_common struct for the given CE
527 * @pt: unused
528 *
529 * Handle a CE error interrupt. Simply a wrapper around a SAL call which
530 * defers processing to the SGI prom.
531 */ static irqreturn_t
532tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt)
533{
534 struct tioce_common *soft = arg;
535 struct ia64_sal_retval ret_stuff;
536 ret_stuff.status = 0;
537 ret_stuff.v0 = 0;
538
539 SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_ERROR_INTERRUPT,
540 soft->ce_pcibus.bs_persist_segment,
541 soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0);
542
543 return IRQ_HANDLED;
544}
545
546/**
547 * tioce_kern_init - init kernel structures related to a given TIOCE
548 * @tioce_common: ptr to a cached tioce_common struct that originated in prom
549 */ static struct tioce_kernel *
550tioce_kern_init(struct tioce_common *tioce_common)
551{
552 int i;
553 uint32_t tmp;
554 struct tioce *tioce_mmr;
555 struct tioce_kernel *tioce_kern;
556
557 tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL);
558 if (!tioce_kern) {
559 return NULL;
560 }
561
562 tioce_kern->ce_common = tioce_common;
563 spin_lock_init(&tioce_kern->ce_lock);
564 INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list);
565 tioce_common->ce_kernel_private = (uint64_t) tioce_kern;
566
567 /*
568 * Determine the secondary bus number of the port2 logical PPB.
569 * This is used to decide whether a given pci device resides on
570 * port1 or port2. Note: We don't have enough plumbing set up
571 * here to use pci_read_config_xxx() so use the raw_pci_ops vector.
572 */
573
574 raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment,
575 tioce_common->ce_pcibus.bs_persist_busnum,
576 PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp);
577 tioce_kern->ce_port1_secondary = (uint8_t) tmp;
578
579 /*
580 * Set PMU pagesize to the largest size available, and zero out
581 * the ate's.
582 */
583
584 tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base;
585 tioce_mmr->ce_ure_page_map &= ~CE_URE_PAGESIZE_MASK;
586 tioce_mmr->ce_ure_page_map |= CE_URE_256K_PAGESIZE;
587 tioce_kern->ce_ate3240_pagesize = KB(256);
588
589 for (i = 0; i < TIOCE_NUM_M40_ATES; i++) {
590 tioce_kern->ce_ate40_shadow[i] = 0;
591 tioce_mmr->ce_ure_ate40[i] = 0;
592 }
593
594 for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) {
595 tioce_kern->ce_ate3240_shadow[i] = 0;
596 tioce_mmr->ce_ure_ate3240[i] = 0;
597 }
598
599 return tioce_kern;
600}
601
602/**
603 * tioce_force_interrupt - implement altix force_interrupt() backend for CE
604 * @sn_irq_info: sn asic irq that we need an interrupt generated for
605 *
606 * Given an sn_irq_info struct, set the proper bit in ce_adm_force_int to
607 * force a secondary interrupt to be generated. This is to work around an
608 * asic issue where there is a small window of opportunity for a legacy device
609 * interrupt to be lost.
610 */
611static void
612tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
613{
614 struct pcidev_info *pcidev_info;
615 struct tioce_common *ce_common;
616 struct tioce *ce_mmr;
617 uint64_t force_int_val;
618
619 if (!sn_irq_info->irq_bridge)
620 return;
621
622 if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_TIOCE)
623 return;
624
625 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
626 if (!pcidev_info)
627 return;
628
629 ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
630 ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
631
632 /*
633 * irq_int_bit is originally set up by prom, and holds the interrupt
634 * bit shift (not mask) as defined by the bit definitions in the
635 * ce_adm_int mmr. These shifts are not the same for the
636 * ce_adm_force_int register, so do an explicit mapping here to make
637 * things clearer.
638 */
639
640 switch (sn_irq_info->irq_int_bit) {
641 case CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT:
642 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT;
643 break;
644 case CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT:
645 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT;
646 break;
647 case CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT:
648 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT;
649 break;
650 case CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT:
651 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT;
652 break;
653 case CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT:
654 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT;
655 break;
656 case CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT:
657 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT;
658 break;
659 case CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT:
660 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT;
661 break;
662 case CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT:
663 force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT;
664 break;
665 default:
666 return;
667 }
668 ce_mmr->ce_adm_force_int = force_int_val;
669}
670
671/**
672 * tioce_target_interrupt - implement set_irq_affinity for tioce resident
673 * functions. Note: only applies to line interrupts, not MSI's.
674 *
675 * @sn_irq_info: SN IRQ context
676 *
677 * Given an sn_irq_info, set the associated CE device's interrupt destination
678 * register. Since the interrupt destination registers are on a per-ce-slot
679 * basis, this will retarget line interrupts for all functions downstream of
680 * the slot.
681 */
682static void
683tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
684{
685 struct pcidev_info *pcidev_info;
686 struct tioce_common *ce_common;
687 struct tioce *ce_mmr;
688 int bit;
689
690 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
691 if (!pcidev_info)
692 return;
693
694 ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
695 ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
696
697 bit = sn_irq_info->irq_int_bit;
698
699 ce_mmr->ce_adm_int_mask |= (1UL << bit);
700 ce_mmr->ce_adm_int_dest[bit] =
701 ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
702 sn_irq_info->irq_xtalkaddr;
703 ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
704
705 tioce_force_interrupt(sn_irq_info);
706}
707
708/**
709 * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
710 * @prom_bussoft: Common prom/kernel struct representing the bus
711 *
712 * Replicates the tioce_common pointed to by @prom_bussoft in kernel
713 * space. Allocates and initializes a kernel-only area for a given CE,
714 * and sets up an irq for handling CE error interrupts.
715 *
716 * On successful setup, returns the kernel version of tioce_common back to
717 * the caller.
718 */
719static void *
720tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
721{
722 struct tioce_common *tioce_common;
723
724 /*
725 * Allocate kernel bus soft and copy from prom.
726 */
727
728 tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL);
729 if (!tioce_common)
730 return NULL;
731
732 memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common));
733 tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET;
734
735 if (tioce_kern_init(tioce_common) == NULL) {
736 kfree(tioce_common);
737 return NULL;
738 }
739
740 if (request_irq(SGI_PCIASIC_ERROR,
741 tioce_error_intr_handler,
742 SA_SHIRQ, "TIOCE error", (void *)tioce_common))
743 printk(KERN_WARNING
744 "%s: Unable to get irq %d. "
745 "Error interrupts won't be routed for "
746 "TIOCE bus %04x:%02x\n",
747 __FUNCTION__, SGI_PCIASIC_ERROR,
748 tioce_common->ce_pcibus.bs_persist_segment,
749 tioce_common->ce_pcibus.bs_persist_busnum);
750
751 return tioce_common;
752}
753
754static struct sn_pcibus_provider tioce_pci_interfaces = {
755 .dma_map = tioce_dma,
756 .dma_map_consistent = tioce_dma_consistent,
757 .dma_unmap = tioce_dma_unmap,
758 .bus_fixup = tioce_bus_fixup,
759 .force_interrupt = tioce_force_interrupt,
760 .target_interrupt = tioce_target_interrupt
761};
762
763/**
764 * tioce_init_provider - init SN PCI provider ops for TIO CE
765 */
766int
767tioce_init_provider(void)
768{
769 sn_pci_provider[PCIIO_ASIC_TYPE_TIOCE] = &tioce_pci_interfaces;
770 return 0;
771}
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 117f183f0b43..8520df9cee6d 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -71,21 +71,31 @@ config M5206e
71 help 71 help
72 Motorola ColdFire 5206e processor support. 72 Motorola ColdFire 5206e processor support.
73 73
74config M523x
75 bool "MCF523x"
76 help
77 Freescale Coldfire 5230/1/2/4/5 processor support
78
74config M5249 79config M5249
75 bool "MCF5249" 80 bool "MCF5249"
76 help 81 help
77 Motorola ColdFire 5249 processor support. 82 Motorola ColdFire 5249 processor support.
78 83
79config M527x 84config M5271
80 bool "MCF527x" 85 bool "MCF5271"
81 help 86 help
82 Freescale (Motorola) ColdFire 5270/5271/5274/5275 processor support. 87 Freescale (Motorola) ColdFire 5270/5271 processor support.
83 88
84config M5272 89config M5272
85 bool "MCF5272" 90 bool "MCF5272"
86 help 91 help
87 Motorola ColdFire 5272 processor support. 92 Motorola ColdFire 5272 processor support.
88 93
94config M5275
95 bool "MCF5275"
96 help
97 Freescale (Motorola) ColdFire 5274/5275 processor support.
98
89config M528x 99config M528x
90 bool "MCF528x" 100 bool "MCF528x"
91 help 101 help
@@ -103,9 +113,14 @@ config M5407
103 113
104endchoice 114endchoice
105 115
116config M527x
117 bool
118 depends on (M5271 || M5275)
119 default y
120
106config COLDFIRE 121config COLDFIRE
107 bool 122 bool
108 depends on (M5206 || M5206e || M5249 || M527x || M5272 || M528x || M5307 || M5407) 123 depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
109 default y 124 default y
110 125
111choice 126choice
@@ -183,6 +198,11 @@ config CLOCK_60MHz
183 help 198 help
184 Select a 60MHz CPU clock frequency. 199 Select a 60MHz CPU clock frequency.
185 200
201config CLOCK_62_5MHz
202 bool "62.5MHz"
203 help
204 Select a 62.5MHz CPU clock frequency.
205
186config CLOCK_64MHz 206config CLOCK_64MHz
187 bool "64MHz" 207 bool "64MHz"
188 help 208 help
@@ -302,6 +322,12 @@ config ELITE
302 help 322 help
303 Support for the Motorola M5206eLITE board. 323 Support for the Motorola M5206eLITE board.
304 324
325config M5235EVB
326 bool "Freescale M5235EVB support"
327 depends on M523x
328 help
329 Support for the Freescale M5235EVB board.
330
305config M5249C3 331config M5249C3
306 bool "Motorola M5249C3 board support" 332 bool "Motorola M5249C3 board support"
307 depends on M5249 333 depends on M5249
@@ -310,13 +336,13 @@ config M5249C3
310 336
311config M5271EVB 337config M5271EVB
312 bool "Freescale (Motorola) M5271EVB board support" 338 bool "Freescale (Motorola) M5271EVB board support"
313 depends on M527x 339 depends on M5271
314 help 340 help
315 Support for the Freescale (Motorola) M5271EVB board. 341 Support for the Freescale (Motorola) M5271EVB board.
316 342
317config M5275EVB 343config M5275EVB
318 bool "Freescale (Motorola) M5275EVB board support" 344 bool "Freescale (Motorola) M5275EVB board support"
319 depends on M527x 345 depends on M5275
320 help 346 help
321 Support for the Freescale (Motorola) M5275EVB board. 347 Support for the Freescale (Motorola) M5275EVB board.
322 348
@@ -343,6 +369,12 @@ config COBRA5282
343 depends on M528x 369 depends on M528x
344 help 370 help
345 Support for the senTec COBRA5282 board. 371 Support for the senTec COBRA5282 board.
372
373config SOM5282EM
374 bool "EMAC.Inc SOM5282EM board support"
375 depends on M528x
376 help
377 Support for the EMAC.Inc SOM5282EM module.
346 378
347config ARN5307 379config ARN5307
348 bool "Arnewsh 5307 board support" 380 bool "Arnewsh 5307 board support"
@@ -410,6 +442,12 @@ config CPU16B
410 help 442 help
411 Support for the SNEHA CPU16B board. 443 Support for the SNEHA CPU16B board.
412 444
445config MOD5272
446 bool "Netburner MOD-5272 board support"
447 depends on M5272
448 help
449 Support for the Netburner MOD-5272 board.
450
413config ROMFS_FROM_ROM 451config ROMFS_FROM_ROM
414 bool " ROMFS image not RAM resident" 452 bool " ROMFS image not RAM resident"
415 depends on (NETtel || SNAPGEAR) 453 depends on (NETtel || SNAPGEAR)
@@ -430,7 +468,7 @@ config ARNEWSH
430config MOTOROLA 468config MOTOROLA
431 bool 469 bool
432 default y 470 default y
433 depends on (M5206eC3 || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) 471 depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
434 472
435config HW_FEITH 473config HW_FEITH
436 bool 474 bool
@@ -441,6 +479,11 @@ config senTec
441 bool 479 bool
442 default y 480 default y
443 depends on (COBRA5272 || COBRA5282) 481 depends on (COBRA5272 || COBRA5282)
482
483config EMAC_INC
484 bool
485 default y
486 depends on (SOM5282EM)
444 487
445config SNEHA 488config SNEHA
446 bool 489 bool
@@ -455,6 +498,15 @@ config LARGE_ALLOCS
455 a lot of RAM, and you need to able to allocate very large 498 a lot of RAM, and you need to able to allocate very large
456 contiguous chunks. If unsure, say N. 499 contiguous chunks. If unsure, say N.
457 500
501config 4KSTACKS
502 bool "Use 4Kb for kernel stacks instead of 8Kb"
503 default y
504 help
505 If you say Y here the kernel will use a 4Kb stacksize for the
506 kernel stack attached to each process/thread. This facilitates
507 running more threads on a system and also reduces the pressure
508 on the VM subsystem for higher order allocations.
509
458choice 510choice
459 prompt "RAM size" 511 prompt "RAM size"
460 default AUTO 512 default AUTO
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index a254aa9d4998..97022ed0da38 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328) := 68VZ328
14platform-$(CONFIG_M68360) := 68360 14platform-$(CONFIG_M68360) := 68360
15platform-$(CONFIG_M5206) := 5206 15platform-$(CONFIG_M5206) := 5206
16platform-$(CONFIG_M5206e) := 5206e 16platform-$(CONFIG_M5206e) := 5206e
17platform-$(CONFIG_M523x) := 523x
17platform-$(CONFIG_M5249) := 5249 18platform-$(CONFIG_M5249) := 5249
18platform-$(CONFIG_M527x) := 527x 19platform-$(CONFIG_M527x) := 527x
19platform-$(CONFIG_M5272) := 5272 20platform-$(CONFIG_M5272) := 5272
@@ -29,6 +30,7 @@ board-$(CONFIG_UCQUICC) := uCquicc
29board-$(CONFIG_DRAGEN2) := de2 30board-$(CONFIG_DRAGEN2) := de2
30board-$(CONFIG_ARNEWSH) := ARNEWSH 31board-$(CONFIG_ARNEWSH) := ARNEWSH
31board-$(CONFIG_MOTOROLA) := MOTOROLA 32board-$(CONFIG_MOTOROLA) := MOTOROLA
33board-$(CONFIG_M5235EVB) := M5235EVB
32board-$(CONFIG_M5271EVB) := M5271EVB 34board-$(CONFIG_M5271EVB) := M5271EVB
33board-$(CONFIG_M5275EVB) := M5275EVB 35board-$(CONFIG_M5275EVB) := M5275EVB
34board-$(CONFIG_M5282EVB) := M5282EVB 36board-$(CONFIG_M5282EVB) := M5282EVB
@@ -39,6 +41,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3
39board-$(CONFIG_CLEOPATRA) := CLEOPATRA 41board-$(CONFIG_CLEOPATRA) := CLEOPATRA
40board-$(CONFIG_senTec) := senTec 42board-$(CONFIG_senTec) := senTec
41board-$(CONFIG_SNEHA) := SNEHA 43board-$(CONFIG_SNEHA) := SNEHA
44board-$(CONFIG_MOD5272) := MOD5272
42BOARD := $(board-y) 45BOARD := $(board-y)
43 46
44model-$(CONFIG_RAMKERNEL) := ram 47model-$(CONFIG_RAMKERNEL) := ram
@@ -53,6 +56,7 @@ MODEL := $(model-y)
53# 56#
54cpuclass-$(CONFIG_M5206) := 5307 57cpuclass-$(CONFIG_M5206) := 5307
55cpuclass-$(CONFIG_M5206e) := 5307 58cpuclass-$(CONFIG_M5206e) := 5307
59cpuclass-$(CONFIG_M523x) := 5307
56cpuclass-$(CONFIG_M5249) := 5307 60cpuclass-$(CONFIG_M5249) := 5307
57cpuclass-$(CONFIG_M527x) := 5307 61cpuclass-$(CONFIG_M527x) := 5307
58cpuclass-$(CONFIG_M5272) := 5307 62cpuclass-$(CONFIG_M5272) := 5307
@@ -76,6 +80,7 @@ export PLATFORM BOARD MODEL CPUCLASS
76# 80#
77cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 81cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200
78cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 82cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200
83cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307
79cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 84cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200
80cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 85cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307
81cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307 86cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index e4bd31be966a..87f2d6587c56 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -1,24 +1,48 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.13-uc0
4# Wed Aug 31 15:03:26 2005
3# 5#
6CONFIG_M68KNOMMU=y
4# CONFIG_MMU is not set 7# CONFIG_MMU is not set
5# CONFIG_FPU is not set 8# CONFIG_FPU is not set
6CONFIG_UID16=y 9CONFIG_UID16=y
7CONFIG_RWSEM_GENERIC_SPINLOCK=y 10CONFIG_RWSEM_GENERIC_SPINLOCK=y
8# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set 11# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
12CONFIG_GENERIC_CALIBRATE_DELAY=y
9 13
10# 14#
11# Code maturity level options 15# Code maturity level options
12# 16#
13CONFIG_EXPERIMENTAL=y 17CONFIG_EXPERIMENTAL=y
18CONFIG_CLEAN_COMPILE=y
19CONFIG_BROKEN_ON_SMP=y
20CONFIG_INIT_ENV_ARG_LIMIT=32
14 21
15# 22#
16# General setup 23# General setup
17# 24#
18# CONFIG_SYSVIPC is not set 25CONFIG_LOCALVERSION=""
26# CONFIG_POSIX_MQUEUE is not set
19# CONFIG_BSD_PROCESS_ACCT is not set 27# CONFIG_BSD_PROCESS_ACCT is not set
20# CONFIG_SYSCTL is not set 28# CONFIG_SYSCTL is not set
21CONFIG_LOG_BUF_SHIFT=14 29# CONFIG_AUDIT is not set
30# CONFIG_HOTPLUG is not set
31# CONFIG_KOBJECT_UEVENT is not set
32# CONFIG_IKCONFIG is not set
33CONFIG_EMBEDDED=y
34# CONFIG_KALLSYMS is not set
35CONFIG_PRINTK=y
36CONFIG_BUG=y
37CONFIG_BASE_FULL=y
38# CONFIG_FUTEX is not set
39# CONFIG_EPOLL is not set
40# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
41CONFIG_CC_ALIGN_FUNCTIONS=0
42CONFIG_CC_ALIGN_LABELS=0
43CONFIG_CC_ALIGN_LOOPS=0
44CONFIG_CC_ALIGN_JUMPS=0
45CONFIG_BASE_SMALL=0
22 46
23# 47#
24# Loadable module support 48# Loadable module support
@@ -34,9 +58,11 @@ CONFIG_LOG_BUF_SHIFT=14
34# CONFIG_M68360 is not set 58# CONFIG_M68360 is not set
35# CONFIG_M5206 is not set 59# CONFIG_M5206 is not set
36# CONFIG_M5206e is not set 60# CONFIG_M5206e is not set
61# CONFIG_M523x is not set
37# CONFIG_M5249 is not set 62# CONFIG_M5249 is not set
38# CONFIG_M527x is not set 63# CONFIG_M5271 is not set
39CONFIG_M5272=y 64CONFIG_M5272=y
65# CONFIG_M5275 is not set
40# CONFIG_M528x is not set 66# CONFIG_M528x is not set
41# CONFIG_M5307 is not set 67# CONFIG_M5307 is not set
42# CONFIG_M5407 is not set 68# CONFIG_M5407 is not set
@@ -54,6 +80,8 @@ CONFIG_COLDFIRE=y
54# CONFIG_CLOCK_50MHz is not set 80# CONFIG_CLOCK_50MHz is not set
55# CONFIG_CLOCK_54MHz is not set 81# CONFIG_CLOCK_54MHz is not set
56# CONFIG_CLOCK_60MHz is not set 82# CONFIG_CLOCK_60MHz is not set
83# CONFIG_CLOCK_62_5MHz is not set
84# CONFIG_CLOCK_64MHz is not set
57CONFIG_CLOCK_66MHz=y 85CONFIG_CLOCK_66MHz=y
58# CONFIG_CLOCK_70MHz is not set 86# CONFIG_CLOCK_70MHz is not set
59# CONFIG_CLOCK_100MHz is not set 87# CONFIG_CLOCK_100MHz is not set
@@ -65,13 +93,19 @@ CONFIG_CLOCK_66MHz=y
65# Platform 93# Platform
66# 94#
67CONFIG_M5272C3=y 95CONFIG_M5272C3=y
96# CONFIG_COBRA5272 is not set
97# CONFIG_CANCam is not set
98# CONFIG_SCALES is not set
68# CONFIG_NETtel is not set 99# CONFIG_NETtel is not set
100# CONFIG_CPU16B is not set
101# CONFIG_MOD5272 is not set
69CONFIG_MOTOROLA=y 102CONFIG_MOTOROLA=y
70# CONFIG_LARGE_ALLOCS is not set 103# CONFIG_LARGE_ALLOCS is not set
71# CONFIG_RAMAUTO is not set 104CONFIG_4KSTACKS=y
105CONFIG_RAMAUTO=y
72# CONFIG_RAM4MB is not set 106# CONFIG_RAM4MB is not set
73# CONFIG_RAM8MB is not set 107# CONFIG_RAM8MB is not set
74CONFIG_RAM16MB=y 108# CONFIG_RAM16MB is not set
75# CONFIG_RAM32MB is not set 109# CONFIG_RAM32MB is not set
76CONFIG_RAMAUTOBIT=y 110CONFIG_RAMAUTOBIT=y
77# CONFIG_RAM8BIT is not set 111# CONFIG_RAM8BIT is not set
@@ -79,20 +113,34 @@ CONFIG_RAMAUTOBIT=y
79# CONFIG_RAM32BIT is not set 113# CONFIG_RAM32BIT is not set
80CONFIG_RAMKERNEL=y 114CONFIG_RAMKERNEL=y
81# CONFIG_ROMKERNEL is not set 115# CONFIG_ROMKERNEL is not set
82# CONFIG_HIMEMKERNEL is not set 116CONFIG_SELECT_MEMORY_MODEL=y
117CONFIG_FLATMEM_MANUAL=y
118# CONFIG_DISCONTIGMEM_MANUAL is not set
119# CONFIG_SPARSEMEM_MANUAL is not set
120CONFIG_FLATMEM=y
121CONFIG_FLAT_NODE_MEM_MAP=y
83 122
84# 123#
85# Bus options (PCI, PCMCIA, EISA, MCA, ISA) 124# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
86# 125#
87# CONFIG_PCI is not set 126# CONFIG_PCI is not set
88# CONFIG_HOTPLUG is not set 127
128#
129# PCCARD (PCMCIA/CardBus) support
130#
131# CONFIG_PCCARD is not set
132
133#
134# PCI Hotplug Support
135#
89 136
90# 137#
91# Executable file formats 138# Executable file formats
92# 139#
93CONFIG_KCORE_AOUT=y
94CONFIG_BINFMT_FLAT=y 140CONFIG_BINFMT_FLAT=y
95# CONFIG_BINFMT_ZFLAT is not set 141# CONFIG_BINFMT_ZFLAT is not set
142# CONFIG_BINFMT_SHARED_FLAT is not set
143# CONFIG_BINFMT_MISC is not set
96 144
97# 145#
98# Power management options 146# Power management options
@@ -100,12 +148,82 @@ CONFIG_BINFMT_FLAT=y
100# CONFIG_PM is not set 148# CONFIG_PM is not set
101 149
102# 150#
151# Networking
152#
153CONFIG_NET=y
154
155#
156# Networking options
157#
158CONFIG_PACKET=y
159# CONFIG_PACKET_MMAP is not set
160CONFIG_UNIX=y
161# CONFIG_NET_KEY is not set
162CONFIG_INET=y
163# CONFIG_IP_MULTICAST is not set
164# CONFIG_IP_ADVANCED_ROUTER is not set
165CONFIG_IP_FIB_HASH=y
166# CONFIG_IP_PNP is not set
167# CONFIG_NET_IPIP is not set
168# CONFIG_NET_IPGRE is not set
169# CONFIG_ARPD is not set
170# CONFIG_SYN_COOKIES is not set
171# CONFIG_INET_AH is not set
172# CONFIG_INET_ESP is not set
173# CONFIG_INET_IPCOMP is not set
174# CONFIG_INET_TUNNEL is not set
175# CONFIG_IP_TCPDIAG is not set
176# CONFIG_IP_TCPDIAG_IPV6 is not set
177# CONFIG_TCP_CONG_ADVANCED is not set
178CONFIG_TCP_CONG_BIC=y
179# CONFIG_IPV6 is not set
180# CONFIG_NETFILTER is not set
181
182#
183# SCTP Configuration (EXPERIMENTAL)
184#
185# CONFIG_IP_SCTP is not set
186# CONFIG_ATM is not set
187# CONFIG_BRIDGE is not set
188# CONFIG_VLAN_8021Q is not set
189# CONFIG_DECNET is not set
190# CONFIG_LLC2 is not set
191# CONFIG_IPX is not set
192# CONFIG_ATALK is not set
193# CONFIG_X25 is not set
194# CONFIG_LAPB is not set
195# CONFIG_NET_DIVERT is not set
196# CONFIG_ECONET is not set
197# CONFIG_WAN_ROUTER is not set
198# CONFIG_NET_SCHED is not set
199# CONFIG_NET_CLS_ROUTE is not set
200
201#
202# Network testing
203#
204# CONFIG_NET_PKTGEN is not set
205# CONFIG_HAMRADIO is not set
206# CONFIG_IRDA is not set
207# CONFIG_BT is not set
208
209#
210# Device Drivers
211#
212
213#
214# Generic Driver Options
215#
216CONFIG_STANDALONE=y
217CONFIG_PREVENT_FIRMWARE_BUILD=y
218# CONFIG_FW_LOADER is not set
219
220#
103# Memory Technology Devices (MTD) 221# Memory Technology Devices (MTD)
104# 222#
105CONFIG_MTD=y 223CONFIG_MTD=y
106# CONFIG_MTD_DEBUG is not set 224# CONFIG_MTD_DEBUG is not set
107CONFIG_MTD_PARTITIONS=y
108# CONFIG_MTD_CONCAT is not set 225# CONFIG_MTD_CONCAT is not set
226CONFIG_MTD_PARTITIONS=y
109# CONFIG_MTD_REDBOOT_PARTS is not set 227# CONFIG_MTD_REDBOOT_PARTS is not set
110# CONFIG_MTD_CMDLINE_PARTS is not set 228# CONFIG_MTD_CMDLINE_PARTS is not set
111 229
@@ -116,35 +234,50 @@ CONFIG_MTD_CHAR=y
116CONFIG_MTD_BLOCK=y 234CONFIG_MTD_BLOCK=y
117# CONFIG_FTL is not set 235# CONFIG_FTL is not set
118# CONFIG_NFTL is not set 236# CONFIG_NFTL is not set
237# CONFIG_INFTL is not set
119 238
120# 239#
121# RAM/ROM/Flash chip drivers 240# RAM/ROM/Flash chip drivers
122# 241#
123# CONFIG_MTD_CFI is not set 242# CONFIG_MTD_CFI is not set
124# CONFIG_MTD_JEDECPROBE is not set 243# CONFIG_MTD_JEDECPROBE is not set
244CONFIG_MTD_MAP_BANK_WIDTH_1=y
245CONFIG_MTD_MAP_BANK_WIDTH_2=y
246CONFIG_MTD_MAP_BANK_WIDTH_4=y
247# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
248# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
249# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
250CONFIG_MTD_CFI_I1=y
251CONFIG_MTD_CFI_I2=y
252# CONFIG_MTD_CFI_I4 is not set
253# CONFIG_MTD_CFI_I8 is not set
125CONFIG_MTD_RAM=y 254CONFIG_MTD_RAM=y
126# CONFIG_MTD_ROM is not set 255# CONFIG_MTD_ROM is not set
127# CONFIG_MTD_ABSENT is not set 256# CONFIG_MTD_ABSENT is not set
128# CONFIG_MTD_OBSOLETE_CHIPS is not set
129 257
130# 258#
131# Mapping drivers for chip access 259# Mapping drivers for chip access
132# 260#
261# CONFIG_MTD_COMPLEX_MAPPINGS is not set
133CONFIG_MTD_UCLINUX=y 262CONFIG_MTD_UCLINUX=y
263# CONFIG_MTD_SNAPGEARuC is not set
264# CONFIG_MTD_PLATRAM is not set
134 265
135# 266#
136# Self-contained MTD device drivers 267# Self-contained MTD device drivers
137# 268#
138# CONFIG_MTD_SLRAM is not set 269# CONFIG_MTD_SLRAM is not set
270# CONFIG_MTD_PHRAM is not set
139# CONFIG_MTD_MTDRAM is not set 271# CONFIG_MTD_MTDRAM is not set
140# CONFIG_MTD_BLKMTD is not set 272# CONFIG_MTD_BLKMTD is not set
273# CONFIG_MTD_BLOCK2MTD is not set
141 274
142# 275#
143# Disk-On-Chip Device Drivers 276# Disk-On-Chip Device Drivers
144# 277#
145# CONFIG_MTD_DOC1000 is not set
146# CONFIG_MTD_DOC2000 is not set 278# CONFIG_MTD_DOC2000 is not set
147# CONFIG_MTD_DOC2001 is not set 279# CONFIG_MTD_DOC2001 is not set
280# CONFIG_MTD_DOC2001PLUS is not set
148 281
149# 282#
150# NAND Flash Device Drivers 283# NAND Flash Device Drivers
@@ -159,21 +292,32 @@ CONFIG_MTD_UCLINUX=y
159# 292#
160# Plug and Play support 293# Plug and Play support
161# 294#
162# CONFIG_PNP is not set
163 295
164# 296#
165# Block devices 297# Block devices
166# 298#
167# CONFIG_BLK_DEV_FD is not set 299# CONFIG_BLK_DEV_FD is not set
300# CONFIG_BLK_DEV_COW_COMMON is not set
168# CONFIG_BLK_DEV_LOOP is not set 301# CONFIG_BLK_DEV_LOOP is not set
169# CONFIG_BLK_DEV_NBD is not set 302# CONFIG_BLK_DEV_NBD is not set
170CONFIG_BLK_DEV_RAM=y 303CONFIG_BLK_DEV_RAM=y
304CONFIG_BLK_DEV_RAM_COUNT=16
171CONFIG_BLK_DEV_RAM_SIZE=4096 305CONFIG_BLK_DEV_RAM_SIZE=4096
172# CONFIG_BLK_DEV_INITRD is not set 306# CONFIG_BLK_DEV_INITRD is not set
173# CONFIG_BLK_DEV_BLKMEM is not set 307CONFIG_INITRAMFS_SOURCE=""
308# CONFIG_CDROM_PKTCDVD is not set
174 309
175# 310#
176# ATA/IDE/MFM/RLL support 311# IO Schedulers
312#
313CONFIG_IOSCHED_NOOP=y
314# CONFIG_IOSCHED_AS is not set
315# CONFIG_IOSCHED_DEADLINE is not set
316# CONFIG_IOSCHED_CFQ is not set
317# CONFIG_ATA_OVER_ETH is not set
318
319#
320# ATA/ATAPI/MFM/RLL support
177# 321#
178# CONFIG_IDE is not set 322# CONFIG_IDE is not set
179 323
@@ -190,249 +334,230 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
190# 334#
191# Fusion MPT device support 335# Fusion MPT device support
192# 336#
337# CONFIG_FUSION is not set
193 338
194# 339#
195# I2O device support 340# IEEE 1394 (FireWire) support
196#
197
198#
199# Networking support
200#
201CONFIG_NET=y
202
203#
204# Networking options
205#
206CONFIG_PACKET=y
207# CONFIG_PACKET_MMAP is not set
208# CONFIG_NETLINK_DEV is not set
209# CONFIG_NETFILTER is not set
210# CONFIG_FILTER is not set
211CONFIG_UNIX=y
212# CONFIG_NET_KEY is not set
213CONFIG_INET=y
214# CONFIG_IP_MULTICAST is not set
215# CONFIG_IP_ADVANCED_ROUTER is not set
216# CONFIG_IP_PNP is not set
217# CONFIG_NET_IPIP is not set
218# CONFIG_NET_IPGRE is not set
219# CONFIG_ARPD is not set
220# CONFIG_INET_ECN is not set
221# CONFIG_SYN_COOKIES is not set
222# CONFIG_INET_AH is not set
223# CONFIG_INET_ESP is not set
224# CONFIG_XFRM_USER is not set
225# CONFIG_IPV6 is not set
226
227#
228# SCTP Configuration (EXPERIMENTAL)
229# 341#
230CONFIG_IPV6_SCTP__=y
231# CONFIG_IP_SCTP is not set
232# CONFIG_ATM is not set
233# CONFIG_VLAN_8021Q is not set
234# CONFIG_LLC is not set
235# CONFIG_DECNET is not set
236# CONFIG_BRIDGE is not set
237# CONFIG_X25 is not set
238# CONFIG_LAPB is not set
239# CONFIG_NET_DIVERT is not set
240# CONFIG_ECONET is not set
241# CONFIG_WAN_ROUTER is not set
242# CONFIG_NET_HW_FLOWCONTROL is not set
243 342
244# 343#
245# QoS and/or fair queueing 344# I2O device support
246# 345#
247# CONFIG_NET_SCHED is not set
248 346
249# 347#
250# Network testing 348# Network device support
251# 349#
252# CONFIG_NET_PKTGEN is not set
253CONFIG_NETDEVICES=y 350CONFIG_NETDEVICES=y
254# CONFIG_DUMMY is not set 351# CONFIG_DUMMY is not set
255# CONFIG_BONDING is not set 352# CONFIG_BONDING is not set
256# CONFIG_EQUALIZER is not set 353# CONFIG_EQUALIZER is not set
257# CONFIG_TUN is not set 354# CONFIG_TUN is not set
258# CONFIG_ETHERTAP is not set
259 355
260# 356#
261# Ethernet (10 or 100Mbit) 357# Ethernet (10 or 100Mbit)
262# 358#
263CONFIG_NET_ETHERNET=y 359CONFIG_NET_ETHERNET=y
264# CONFIG_MII is not set 360# CONFIG_MII is not set
361# CONFIG_NET_VENDOR_SMC is not set
362# CONFIG_NE2000 is not set
363# CONFIG_NET_PCI is not set
265CONFIG_FEC=y 364CONFIG_FEC=y
365# CONFIG_FEC2 is not set
266 366
267# 367#
268# Ethernet (1000 Mbit) 368# Ethernet (1000 Mbit)
269# 369#
370
371#
372# Ethernet (10000 Mbit)
373#
374
375#
376# Token Ring devices
377#
378
379#
380# Wireless LAN (non-hamradio)
381#
382# CONFIG_NET_RADIO is not set
383
384#
385# Wan interfaces
386#
387# CONFIG_WAN is not set
270CONFIG_PPP=y 388CONFIG_PPP=y
271# CONFIG_PPP_MULTILINK is not set 389# CONFIG_PPP_MULTILINK is not set
390# CONFIG_PPP_FILTER is not set
272# CONFIG_PPP_ASYNC is not set 391# CONFIG_PPP_ASYNC is not set
273# CONFIG_PPP_SYNC_TTY is not set 392# CONFIG_PPP_SYNC_TTY is not set
274# CONFIG_PPP_DEFLATE is not set 393# CONFIG_PPP_DEFLATE is not set
275# CONFIG_PPP_BSDCOMP is not set 394# CONFIG_PPP_BSDCOMP is not set
276# CONFIG_PPPOE is not set 395# CONFIG_PPPOE is not set
277# CONFIG_SLIP is not set 396# CONFIG_SLIP is not set
397# CONFIG_SHAPER is not set
398# CONFIG_NETCONSOLE is not set
399# CONFIG_NETPOLL is not set
400# CONFIG_NET_POLL_CONTROLLER is not set
278 401
279# 402#
280# Wireless LAN (non-hamradio) 403# ISDN subsystem
281# 404#
282# CONFIG_NET_RADIO is not set 405# CONFIG_ISDN is not set
283 406
284# 407#
285# Token Ring devices (depends on LLC=y) 408# Telephony Support
286# 409#
287# CONFIG_SHAPER is not set 410# CONFIG_PHONE is not set
288 411
289# 412#
290# Wan interfaces 413# Input device support
291# 414#
292# CONFIG_WAN is not set 415# CONFIG_INPUT is not set
293 416
294# 417#
295# Amateur Radio support 418# Hardware I/O ports
296# 419#
297# CONFIG_HAMRADIO is not set 420# CONFIG_SERIO is not set
421# CONFIG_GAMEPORT is not set
298 422
299# 423#
300# IrDA (infrared) support 424# Character devices
301# 425#
302# CONFIG_IRDA is not set 426# CONFIG_VT is not set
427# CONFIG_SERIAL_NONSTANDARD is not set
428# CONFIG_LEDMAN is not set
429# CONFIG_RESETSWITCH is not set
303 430
304# 431#
305# ISDN subsystem 432# Serial drivers
306# 433#
307# CONFIG_ISDN_BOOL is not set 434# CONFIG_SERIAL_8250 is not set
308 435
309# 436#
310# Telephony Support 437# Non-8250 serial port support
311# 438#
312# CONFIG_PHONE is not set 439CONFIG_SERIAL_COLDFIRE=y
440# CONFIG_UNIX98_PTYS is not set
441CONFIG_LEGACY_PTYS=y
442CONFIG_LEGACY_PTY_COUNT=256
313 443
314# 444#
315# Input device support 445# IPMI
316# 446#
317CONFIG_INPUT=y 447# CONFIG_IPMI_HANDLER is not set
318 448
319# 449#
320# Userland interfaces 450# Watchdog Cards
321# 451#
322CONFIG_INPUT_MOUSEDEV=y 452# CONFIG_WATCHDOG is not set
323CONFIG_INPUT_MOUSEDEV_PSAUX=y 453# CONFIG_MCFWATCHDOG is not set
324CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 454# CONFIG_RTC is not set
325CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 455# CONFIG_GEN_RTC is not set
326# CONFIG_INPUT_JOYDEV is not set 456# CONFIG_DTLK is not set
327# CONFIG_INPUT_TSDEV is not set 457# CONFIG_R3964 is not set
328# CONFIG_INPUT_EVDEV is not set
329# CONFIG_INPUT_EVBUG is not set
330 458
331# 459#
332# Input I/O drivers 460# Ftape, the floppy tape device driver
333# 461#
334# CONFIG_GAMEPORT is not set 462# CONFIG_RAW_DRIVER is not set
335CONFIG_SOUND_GAMEPORT=y
336CONFIG_SERIO=y
337CONFIG_SERIO_I8042=y
338CONFIG_SERIO_SERPORT=y
339# CONFIG_SERIO_CT82C710 is not set
340 463
341# 464#
342# Input Device Drivers 465# TPM devices
343# 466#
344CONFIG_INPUT_KEYBOARD=y 467# CONFIG_MCF_QSPI is not set
345CONFIG_KEYBOARD_ATKBD=y 468# CONFIG_M41T11M6 is not set
346# CONFIG_KEYBOARD_SUNKBD is not set
347# CONFIG_KEYBOARD_XTKBD is not set
348# CONFIG_KEYBOARD_NEWTON is not set
349CONFIG_INPUT_MOUSE=y
350CONFIG_MOUSE_PS2=y
351# CONFIG_MOUSE_SERIAL is not set
352# CONFIG_INPUT_JOYSTICK is not set
353# CONFIG_INPUT_TOUCHSCREEN is not set
354# CONFIG_INPUT_MISC is not set
355 469
356# 470#
357# Character devices 471# I2C support
358# 472#
359# CONFIG_VT is not set 473# CONFIG_I2C is not set
360# CONFIG_SERIAL_NONSTANDARD is not set 474# CONFIG_I2C_SENSOR is not set
361# CONFIG_RESETSWITCH is not set
362 475
363# 476#
364# Serial drivers 477# Dallas's 1-wire bus
365# 478#
366# CONFIG_SERIAL_8250 is not set 479# CONFIG_W1 is not set
367 480
368# 481#
369# Non-8250 serial port support 482# Hardware Monitoring support
370# 483#
371CONFIG_SERIAL_COLDFIRE=y 484# CONFIG_HWMON is not set
372# CONFIG_UNIX98_PTYS is not set
373 485
374# 486#
375# I2C support 487# Misc devices
376# 488#
377# CONFIG_I2C is not set
378 489
379# 490#
380# I2C Hardware Sensors Mainboard support 491# Multimedia devices
381# 492#
493# CONFIG_VIDEO_DEV is not set
382 494
383# 495#
384# I2C Hardware Sensors Chip support 496# Digital Video Broadcasting Devices
385# 497#
498# CONFIG_DVB is not set
386 499
387# 500#
388# Mice 501# Graphics support
389# 502#
390# CONFIG_BUSMOUSE is not set 503# CONFIG_FB is not set
391# CONFIG_QIC02_TAPE is not set
392 504
393# 505#
394# IPMI 506# SPI support
395# 507#
396# CONFIG_IPMI_HANDLER is not set 508# CONFIG_SPI is not set
397 509
398# 510#
399# Watchdog Cards 511# Sound
400# 512#
401# CONFIG_WATCHDOG is not set 513# CONFIG_SOUND is not set
402# CONFIG_NVRAM is not set
403# CONFIG_RTC is not set
404# CONFIG_GEN_RTC is not set
405# CONFIG_DTLK is not set
406# CONFIG_R3964 is not set
407# CONFIG_APPLICOM is not set
408 514
409# 515#
410# Ftape, the floppy tape device driver 516# USB support
411# 517#
412# CONFIG_FTAPE is not set 518# CONFIG_USB_ARCH_HAS_HCD is not set
413# CONFIG_AGP is not set 519# CONFIG_USB_ARCH_HAS_OHCI is not set
414# CONFIG_DRM is not set
415# CONFIG_RAW_DRIVER is not set
416# CONFIG_HANGCHECK_TIMER is not set
417 520
418# 521#
419# Multimedia devices 522# USB Gadget Support
523#
524# CONFIG_USB_GADGET is not set
525
526#
527# MMC/SD Card support
528#
529# CONFIG_MMC is not set
530
531#
532# InfiniBand support
533#
534
535#
536# SN Devices
420# 537#
421# CONFIG_VIDEO_DEV is not set
422 538
423# 539#
424# File systems 540# File systems
425# 541#
426CONFIG_EXT2_FS=y 542CONFIG_EXT2_FS=y
427# CONFIG_EXT2_FS_XATTR is not set 543# CONFIG_EXT2_FS_XATTR is not set
544# CONFIG_EXT2_FS_XIP is not set
428# CONFIG_EXT3_FS is not set 545# CONFIG_EXT3_FS is not set
429# CONFIG_JBD is not set 546# CONFIG_JBD is not set
430# CONFIG_REISERFS_FS is not set 547# CONFIG_REISERFS_FS is not set
431# CONFIG_JFS_FS is not set 548# CONFIG_JFS_FS is not set
549# CONFIG_FS_POSIX_ACL is not set
550
551#
552# XFS support
553#
432# CONFIG_XFS_FS is not set 554# CONFIG_XFS_FS is not set
433# CONFIG_MINIX_FS is not set 555# CONFIG_MINIX_FS is not set
434CONFIG_ROMFS_FS=y 556CONFIG_ROMFS_FS=y
557CONFIG_MAGIC_ROM_PTR=y
558# CONFIG_INOTIFY is not set
435# CONFIG_QUOTA is not set 559# CONFIG_QUOTA is not set
560# CONFIG_DNOTIFY is not set
436# CONFIG_AUTOFS_FS is not set 561# CONFIG_AUTOFS_FS is not set
437# CONFIG_AUTOFS4_FS is not set 562# CONFIG_AUTOFS4_FS is not set
438 563
@@ -445,15 +570,17 @@ CONFIG_ROMFS_FS=y
445# 570#
446# DOS/FAT/NT Filesystems 571# DOS/FAT/NT Filesystems
447# 572#
448# CONFIG_FAT_FS is not set 573# CONFIG_MSDOS_FS is not set
574# CONFIG_VFAT_FS is not set
449# CONFIG_NTFS_FS is not set 575# CONFIG_NTFS_FS is not set
450 576
451# 577#
452# Pseudo filesystems 578# Pseudo filesystems
453# 579#
454CONFIG_PROC_FS=y 580CONFIG_PROC_FS=y
455# CONFIG_DEVFS_FS is not set 581CONFIG_SYSFS=y
456# CONFIG_TMPFS is not set 582# CONFIG_TMPFS is not set
583# CONFIG_HUGETLB_PAGE is not set
457CONFIG_RAMFS=y 584CONFIG_RAMFS=y
458 585
459# 586#
@@ -462,6 +589,7 @@ CONFIG_RAMFS=y
462# CONFIG_ADFS_FS is not set 589# CONFIG_ADFS_FS is not set
463# CONFIG_AFFS_FS is not set 590# CONFIG_AFFS_FS is not set
464# CONFIG_HFS_FS is not set 591# CONFIG_HFS_FS is not set
592# CONFIG_HFSPLUS_FS is not set
465# CONFIG_BEFS_FS is not set 593# CONFIG_BEFS_FS is not set
466# CONFIG_BFS_FS is not set 594# CONFIG_BFS_FS is not set
467# CONFIG_EFS_FS is not set 595# CONFIG_EFS_FS is not set
@@ -479,12 +607,10 @@ CONFIG_RAMFS=y
479# 607#
480# CONFIG_NFS_FS is not set 608# CONFIG_NFS_FS is not set
481# CONFIG_NFSD is not set 609# CONFIG_NFSD is not set
482# CONFIG_EXPORTFS is not set
483# CONFIG_SMB_FS is not set 610# CONFIG_SMB_FS is not set
484# CONFIG_CIFS is not set 611# CONFIG_CIFS is not set
485# CONFIG_NCP_FS is not set 612# CONFIG_NCP_FS is not set
486# CONFIG_CODA_FS is not set 613# CONFIG_CODA_FS is not set
487# CONFIG_INTERMEZZO_FS is not set
488# CONFIG_AFS_FS is not set 614# CONFIG_AFS_FS is not set
489 615
490# 616#
@@ -494,30 +620,19 @@ CONFIG_RAMFS=y
494CONFIG_MSDOS_PARTITION=y 620CONFIG_MSDOS_PARTITION=y
495 621
496# 622#
497# Graphics support 623# Native Language Support
498#
499# CONFIG_FB is not set
500
501#
502# Sound
503#
504# CONFIG_SOUND is not set
505
506#
507# USB support
508#
509
510#
511# Bluetooth support
512# 624#
513# CONFIG_BT is not set 625# CONFIG_NLS is not set
514 626
515# 627#
516# Kernel hacking 628# Kernel hacking
517# 629#
630# CONFIG_PRINTK_TIME is not set
631# CONFIG_DEBUG_KERNEL is not set
632CONFIG_LOG_BUF_SHIFT=14
518# CONFIG_FULLDEBUG is not set 633# CONFIG_FULLDEBUG is not set
519# CONFIG_MAGIC_SYSRQ is not set
520# CONFIG_HIGHPROFILE is not set 634# CONFIG_HIGHPROFILE is not set
635# CONFIG_BOOTPARAM is not set
521# CONFIG_DUMPTOFLASH is not set 636# CONFIG_DUMPTOFLASH is not set
522# CONFIG_NO_KERNEL_MSG is not set 637# CONFIG_NO_KERNEL_MSG is not set
523# CONFIG_BDM_DISABLE is not set 638# CONFIG_BDM_DISABLE is not set
@@ -525,6 +640,7 @@ CONFIG_MSDOS_PARTITION=y
525# 640#
526# Security options 641# Security options
527# 642#
643# CONFIG_KEYS is not set
528# CONFIG_SECURITY is not set 644# CONFIG_SECURITY is not set
529 645
530# 646#
@@ -533,6 +649,12 @@ CONFIG_MSDOS_PARTITION=y
533# CONFIG_CRYPTO is not set 649# CONFIG_CRYPTO is not set
534 650
535# 651#
652# Hardware crypto devices
653#
654
655#
536# Library routines 656# Library routines
537# 657#
658# CONFIG_CRC_CCITT is not set
538# CONFIG_CRC32 is not set 659# CONFIG_CRC32 is not set
660# CONFIG_LIBCRC32C is not set
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 557238596dcb..a220345e9746 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -6,7 +6,7 @@
6 * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} 6 * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com}
7 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> 7 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
8 * Copyright (C) 1995 Hamish Macdonald 8 * Copyright (C) 1995 Hamish Macdonald
9 * Copyright (C) 2000 Lineo Inc. (www.lineo.com) 9 * Copyright (C) 2000 Lineo Inc. (www.lineo.com)
10 * Copyright (C) 2001 Lineo, Inc. <www.lineo.com> 10 * Copyright (C) 2001 Lineo, Inc. <www.lineo.com>
11 * 11 *
12 * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca> 12 * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca>
@@ -23,6 +23,7 @@
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/fb.h> 25#include <linux/fb.h>
26#include <linux/module.h>
26#include <linux/console.h> 27#include <linux/console.h>
27#include <linux/genhd.h> 28#include <linux/genhd.h>
28#include <linux/errno.h> 29#include <linux/errno.h>
@@ -45,6 +46,9 @@ unsigned long rom_length;
45unsigned long memory_start; 46unsigned long memory_start;
46unsigned long memory_end; 47unsigned long memory_end;
47 48
49EXPORT_SYMBOL(memory_start);
50EXPORT_SYMBOL(memory_end);
51
48char command_line[COMMAND_LINE_SIZE]; 52char command_line[COMMAND_LINE_SIZE];
49 53
50/* setup some dummy routines */ 54/* setup some dummy routines */
@@ -103,15 +107,21 @@ void (*mach_power_off)( void ) = NULL;
103#if defined(CONFIG_M5206e) 107#if defined(CONFIG_M5206e)
104 #define CPU "COLDFIRE(m5206e)" 108 #define CPU "COLDFIRE(m5206e)"
105#endif 109#endif
110#if defined(CONFIG_M523x)
111 #define CPU "COLDFIRE(m523x)"
112#endif
106#if defined(CONFIG_M5249) 113#if defined(CONFIG_M5249)
107 #define CPU "COLDFIRE(m5249)" 114 #define CPU "COLDFIRE(m5249)"
108#endif 115#endif
109#if defined(CONFIG_M527x) 116#if defined(CONFIG_M5271)
110 #define CPU "COLDFIRE(m5270/5271/5274/5275)" 117 #define CPU "COLDFIRE(m5270/5271)"
111#endif 118#endif
112#if defined(CONFIG_M5272) 119#if defined(CONFIG_M5272)
113 #define CPU "COLDFIRE(m5272)" 120 #define CPU "COLDFIRE(m5272)"
114#endif 121#endif
122#if defined(CONFIG_M5275)
123 #define CPU "COLDFIRE(m5274/5275)"
124#endif
115#if defined(CONFIG_M528x) 125#if defined(CONFIG_M528x)
116 #define CPU "COLDFIRE(m5280/5282)" 126 #define CPU "COLDFIRE(m5280/5282)"
117#endif 127#endif
@@ -152,7 +162,7 @@ void setup_arch(char **cmdline_p)
152 init_mm.start_code = (unsigned long) &_stext; 162 init_mm.start_code = (unsigned long) &_stext;
153 init_mm.end_code = (unsigned long) &_etext; 163 init_mm.end_code = (unsigned long) &_etext;
154 init_mm.end_data = (unsigned long) &_edata; 164 init_mm.end_data = (unsigned long) &_edata;
155 init_mm.brk = (unsigned long) 0; 165 init_mm.brk = (unsigned long) 0;
156 166
157 config_BSP(&command_line[0], sizeof(command_line)); 167 config_BSP(&command_line[0], sizeof(command_line));
158 168
@@ -171,7 +181,7 @@ void setup_arch(char **cmdline_p)
171#endif 181#endif
172#ifdef CONFIG_ELITE 182#ifdef CONFIG_ELITE
173 printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n"); 183 printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
174#endif 184#endif
175#ifdef CONFIG_TELOS 185#ifdef CONFIG_TELOS
176 printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n"); 186 printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n");
177#endif 187#endif
@@ -200,6 +210,9 @@ void setup_arch(char **cmdline_p)
200#ifdef CONFIG_DRAGEN2 210#ifdef CONFIG_DRAGEN2
201 printk(KERN_INFO "DragonEngine II board support by Georges Menie\n"); 211 printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
202#endif 212#endif
213#ifdef CONFIG_M5235EVB
214 printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)");
215#endif
203 216
204#ifdef DEBUG 217#ifdef DEBUG
205 printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " 218 printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
@@ -223,7 +236,7 @@ void setup_arch(char **cmdline_p)
223 saved_command_line[COMMAND_LINE_SIZE-1] = 0; 236 saved_command_line[COMMAND_LINE_SIZE-1] = 0;
224 237
225#ifdef DEBUG 238#ifdef DEBUG
226 if (strlen(*cmdline_p)) 239 if (strlen(*cmdline_p))
227 printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p); 240 printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
228#endif 241#endif
229 242
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index ad7dc6347f19..5bc068462864 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -21,6 +21,7 @@
21#include <linux/signal.h> 21#include <linux/signal.h>
22#include <linux/kernel.h> 22#include <linux/kernel.h>
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/module.h>
24#include <linux/types.h> 25#include <linux/types.h>
25#include <linux/a.out.h> 26#include <linux/a.out.h>
26#include <linux/user.h> 27#include <linux/user.h>
@@ -38,7 +39,7 @@
38#include <asm/machdep.h> 39#include <asm/machdep.h>
39#include <asm/siginfo.h> 40#include <asm/siginfo.h>
40 41
41static char *vec_names[] = { 42static char const * const vec_names[] = {
42 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", 43 "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
43 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", 44 "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
44 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", 45 "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
@@ -106,17 +107,20 @@ asmlinkage void buserr_c(struct frame *fp)
106 107
107int kstack_depth_to_print = 48; 108int kstack_depth_to_print = 48;
108 109
109void show_stack(struct task_struct *task, unsigned long *esp) 110void show_stack(struct task_struct *task, unsigned long *stack)
110{ 111{
111 unsigned long *stack, *endstack, addr; 112 unsigned long *endstack, addr;
112 extern char _start, _etext; 113 extern char _start, _etext;
113 int i; 114 int i;
114 115
115 if (esp == NULL) 116 if (!stack) {
116 esp = (unsigned long *) &esp; 117 if (task)
118 stack = (unsigned long *)task->thread.ksp;
119 else
120 stack = (unsigned long *)&stack;
121 }
117 122
118 stack = esp; 123 addr = (unsigned long) stack;
119 addr = (unsigned long) esp;
120 endstack = (unsigned long *) PAGE_ALIGN(addr); 124 endstack = (unsigned long *) PAGE_ALIGN(addr);
121 125
122 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); 126 printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
@@ -306,6 +310,8 @@ void dump_stack(void)
306 show_stack(current, &stack); 310 show_stack(current, &stack);
307} 311}
308 312
313EXPORT_SYMBOL(dump_stack);
314
309#ifdef CONFIG_M68KFPU_EMU 315#ifdef CONFIG_M68KFPU_EMU
310asmlinkage void fpemu_signal(int signal, int code, void *addr) 316asmlinkage void fpemu_signal(int signal, int code, void *addr)
311{ 317{
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index 31cb12892da5..47f06787190d 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -107,7 +107,7 @@
107 */ 107 */
108#if defined(CONFIG_ELITE) 108#if defined(CONFIG_ELITE)
109#define RAM_START 0x30020000 109#define RAM_START 0x30020000
110#define RAM_END 0xe0000 110#define RAM_LENGTH 0xe0000
111#endif 111#endif
112 112
113/* 113/*
@@ -118,7 +118,8 @@
118#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \ 118#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
119 defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \ 119 defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
120 defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \ 120 defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \
121 defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) 121 defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) || \
122 defined(CONFIG_M5235EVB)
122#define RAM_START 0x20000 123#define RAM_START 0x20000
123#define RAM_LENGTH 0x3e0000 124#define RAM_LENGTH 0x3e0000
124#endif 125#endif
@@ -145,6 +146,16 @@
145#define RAM_LENGTH 0x3f0000 146#define RAM_LENGTH 0x3f0000
146#endif 147#endif
147 148
149
150/*
151 * The EMAC SoM-5282EM module.
152 */
153#if defined(CONFIG_SOM5282EM)
154#define RAM_START 0x10000
155#define RAM_LENGTH 0xff0000
156#endif
157
158
148/* 159/*
149 * These flash boot boards use all of ram for operation. Again the 160 * These flash boot boards use all of ram for operation. Again the
150 * actual memory size is not important here, assume at least 4MiB. 161 * actual memory size is not important here, assume at least 4MiB.
@@ -158,7 +169,7 @@
158#endif 169#endif
159 170
160/* 171/*
161 * Sneha Boards mimimun memmory 172 * Sneha Boards mimimun memory
162 * The end of RAM will vary depending on how much ram is fitted, 173 * The end of RAM will vary depending on how much ram is fitted,
163 * but this isn't important here, we assume at least 4MiB. 174 * but this isn't important here, we assume at least 4MiB.
164 */ 175 */
@@ -167,6 +178,12 @@
167#define RAM_LENGTH 0x3e0000 178#define RAM_LENGTH 0x3e0000
168#endif 179#endif
169 180
181#if defined(CONFIG_MOD5272)
182#define RAM_START 0x02000000
183#define RAM_LENGTH 0x00800000
184#define RAMVEC_START 0x20000000
185#define RAMVEC_LENGTH 0x00000400
186#endif
170 187
171#if defined(CONFIG_RAMKERNEL) 188#if defined(CONFIG_RAMKERNEL)
172#define TEXT ram 189#define TEXT ram
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
new file mode 100644
index 000000000000..22767ce506e0
--- /dev/null
+++ b/arch/m68knommu/platform/523x/config.c
@@ -0,0 +1,82 @@
1/***************************************************************************/
2
3/*
4 * linux/arch/m68knommu/platform/523x/config.c
5 *
6 * Sub-architcture dependant initialization code for the Freescale
7 * 523x CPUs.
8 *
9 * Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com)
10 * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
11 */
12
13/***************************************************************************/
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/param.h>
19#include <linux/init.h>
20#include <linux/interrupt.h>
21#include <asm/dma.h>
22#include <asm/traps.h>
23#include <asm/machdep.h>
24#include <asm/coldfire.h>
25#include <asm/mcfsim.h>
26#include <asm/mcfdma.h>
27
28/***************************************************************************/
29
30void coldfire_pit_tick(void);
31void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
32unsigned long coldfire_pit_offset(void);
33void coldfire_trap_init(void);
34void coldfire_reset(void);
35
36/***************************************************************************/
37
38/*
39 * DMA channel base address table.
40 */
41unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
42 MCF_MBAR + MCFDMA_BASE0,
43};
44
45unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
46
47/***************************************************************************/
48
49void mcf_disableall(void)
50{
51 *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff;
52 *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff;
53}
54
55/***************************************************************************/
56
57void mcf_autovector(unsigned int vec)
58{
59 /* Everything is auto-vectored on the 5272 */
60}
61
62/***************************************************************************/
63
64void config_BSP(char *commandp, int size)
65{
66 mcf_disableall();
67
68#ifdef CONFIG_BOOTPARAM
69 strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
70 commandp[size-1] = 0;
71#else
72 memset(commandp, 0, size);
73#endif
74
75 mach_sched_init = coldfire_pit_init;
76 mach_tick = coldfire_pit_tick;
77 mach_gettimeoffset = coldfire_pit_offset;
78 mach_trap_init = coldfire_trap_init;
79 mach_reset = coldfire_reset;
80}
81
82/***************************************************************************/
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index c7d7a395c4cc..7f4ba837901f 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -39,14 +39,18 @@
39 * Memory size exceptions for special cases. Some boards may be set 39 * Memory size exceptions for special cases. Some boards may be set
40 * for auto memory sizing, but we can't do it that way for some reason. 40 * for auto memory sizing, but we can't do it that way for some reason.
41 * For example the 5206eLITE board has static RAM, and auto-detecting 41 * For example the 5206eLITE board has static RAM, and auto-detecting
42 * the SDRAM will do you no good at all. 42 * the SDRAM will do you no good at all. Same goes for the MOD5272.
43 */ 43 */
44#ifdef CONFIG_RAMAUTO 44#ifdef CONFIG_RAMAUTO
45#if defined(CONFIG_M5206eLITE) 45#if defined(CONFIG_M5206eLITE)
46#define MEM_SIZE 0x00100000 /* 1MiB default memory */ 46#define MEM_SIZE 0x00100000 /* 1MiB default memory */
47#endif
48#if defined(CONFIG_MOD5272)
49#define MEM_SIZE 0x00800000 /* 8MiB default memory */
47#endif 50#endif
48#endif /* CONFIG_RAMAUTO */ 51#endif /* CONFIG_RAMAUTO */
49 52
53
50/* 54/*
51 * If we don't have a fixed memory size now, then lets build in code 55 * If we don't have a fixed memory size now, then lets build in code
52 * to auto detect the DRAM size. Obviously this is the prefered 56 * to auto detect the DRAM size. Obviously this is the prefered
@@ -100,11 +104,15 @@
100 104
101/* 105/*
102 * Most ColdFire boards have their DRAM starting at address 0. 106 * Most ColdFire boards have their DRAM starting at address 0.
103 * Notable exception is the 5206eLITE board. 107 * Notable exception is the 5206eLITE board, another is the MOD5272.
104 */ 108 */
105#if defined(CONFIG_M5206eLITE) 109#if defined(CONFIG_M5206eLITE)
106#define MEM_BASE 0x30000000 110#define MEM_BASE 0x30000000
107#endif 111#endif
112#if defined(CONFIG_MOD5272)
113#define MEM_BASE 0x02000000
114#define VBR_BASE 0x20000000 /* vectors in SRAM */
115#endif
108 116
109#ifndef MEM_BASE 117#ifndef MEM_BASE
110#define MEM_BASE 0x00000000 /* memory base at address 0 */ 118#define MEM_BASE 0x00000000 /* memory base at address 0 */
@@ -188,6 +196,7 @@ _start:
188 movel %a7,_rambase 196 movel %a7,_rambase
189 197
190 GET_MEM_SIZE /* macro code determines size */ 198 GET_MEM_SIZE /* macro code determines size */
199 addl %a7,%d0
191 movel %d0,_ramend /* set end ram addr */ 200 movel %d0,_ramend /* set end ram addr */
192 201
193 /* 202 /*
diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S
index 0f5d1fe8eb5f..7d8990d784a2 100644
--- a/arch/m68knommu/platform/68328/entry.S
+++ b/arch/m68knommu/platform/68328/entry.S
@@ -79,7 +79,7 @@ ENTRY(system_call)
79 movel %sp@(PT_ORIG_D0),%d0 79 movel %sp@(PT_ORIG_D0),%d0
80 80
81 movel %sp,%d1 /* get thread_info pointer */ 81 movel %sp,%d1 /* get thread_info pointer */
82 andl #0xffffe000,%d1 82 andl #-THREAD_SIZE,%d1
83 movel %d1,%a2 83 movel %d1,%a2
84 btst #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS) 84 btst #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS)
85 jne do_trace 85 jne do_trace
@@ -105,7 +105,7 @@ Luser_return:
105 andw #ALLOWINT,%sr 105 andw #ALLOWINT,%sr
106 106
107 movel %sp,%d1 /* get thread_info pointer */ 107 movel %sp,%d1 /* get thread_info pointer */
108 andl #0xffffe000,%d1 108 andl #-THREAD_SIZE,%d1
109 movel %d1,%a2 109 movel %d1,%a2
110 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ 110 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
111 andl #_TIF_WORK_MASK,%d1 111 andl #_TIF_WORK_MASK,%d1
diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S
index f7bc80a60e0f..8ff48adf24ab 100644
--- a/arch/m68knommu/platform/68360/entry.S
+++ b/arch/m68knommu/platform/68360/entry.S
@@ -96,7 +96,7 @@ Luser_return:
96 andw #ALLOWINT,%sr 96 andw #ALLOWINT,%sr
97 97
98 movel %sp,%d1 /* get thread_info pointer */ 98 movel %sp,%d1 /* get thread_info pointer */
99 andl #0xffffe000,%d1 99 andl #-THREAD_SIZE,%d1
100 movel %d1,%a2 100 movel %d1,%a2
101 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ 101 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */
102 andl #_TIF_WORK_MASK,%d1 102 andl #_TIF_WORK_MASK,%d1
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index f9b0d778dd82..d1b6e6dcb504 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -21,11 +21,13 @@ CC := $(CC) -m32
21endif 21endif
22 22
23LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic 23LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic
24CPPFLAGS += -Iarch/$(ARCH) 24CPPFLAGS += -Iarch/$(ARCH) -Iinclude3
25AFLAGS += -Iarch/$(ARCH) 25AFLAGS += -Iarch/$(ARCH)
26CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ 26CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \
27 -ffixed-r2 -mmultiple 27 -ffixed-r2 -mmultiple
28CPP = $(CC) -E $(CFLAGS) 28CPP = $(CC) -E $(CFLAGS)
29# Temporary hack until we have migrated to asm-powerpc
30LINUXINCLUDE += -Iinclude3
29 31
30CHECKFLAGS += -D__powerpc__ 32CHECKFLAGS += -D__powerpc__
31 33
@@ -101,6 +103,7 @@ endef
101 103
102archclean: 104archclean:
103 $(Q)$(MAKE) $(clean)=arch/ppc/boot 105 $(Q)$(MAKE) $(clean)=arch/ppc/boot
106 $(Q)rm -rf include3
104 107
105prepare: include/asm-$(ARCH)/offsets.h checkbin 108prepare: include/asm-$(ARCH)/offsets.h checkbin
106 109
@@ -110,6 +113,12 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
110include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s 113include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
111 $(call filechk,gen-asm-offsets) 114 $(call filechk,gen-asm-offsets)
112 115
116# Temporary hack until we have migrated to asm-powerpc
117include/asm: include3/asm
118include3/asm:
119 $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi
120 $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm
121
113# Use the file '.tmp_gas_check' for binutils tests, as gas won't output 122# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
114# to stdout and these checks are run even on install targets. 123# to stdout and these checks are run even on install targets.
115TOUT := .tmp_gas_check 124TOUT := .tmp_gas_check
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c
deleted file mode 100644
index 93400dfcce7f..000000000000
--- a/arch/ppc/boot/utils/addRamDisk.c
+++ /dev/null
@@ -1,203 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <netinet/in.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <string.h>
8
9#define ElfHeaderSize (64 * 1024)
10#define ElfPages (ElfHeaderSize / 4096)
11#define KERNELBASE (0xc0000000)
12
13void get4k(FILE *file, char *buf )
14{
15 unsigned j;
16 unsigned num = fread(buf, 1, 4096, file);
17 for ( j=num; j<4096; ++j )
18 buf[j] = 0;
19}
20
21void put4k(FILE *file, char *buf )
22{
23 fwrite(buf, 1, 4096, file);
24}
25
26void death(const char *msg, FILE *fdesc, const char *fname)
27{
28 printf(msg);
29 fclose(fdesc);
30 unlink(fname);
31 exit(1);
32}
33
34int main(int argc, char **argv)
35{
36 char inbuf[4096];
37 FILE *ramDisk = NULL;
38 FILE *inputVmlinux = NULL;
39 FILE *outputVmlinux = NULL;
40 unsigned i = 0;
41 u_int32_t ramFileLen = 0;
42 u_int32_t ramLen = 0;
43 u_int32_t roundR = 0;
44 u_int32_t kernelLen = 0;
45 u_int32_t actualKernelLen = 0;
46 u_int32_t round = 0;
47 u_int32_t roundedKernelLen = 0;
48 u_int32_t ramStartOffs = 0;
49 u_int32_t ramPages = 0;
50 u_int32_t roundedKernelPages = 0;
51 u_int32_t hvReleaseData = 0;
52 u_int32_t eyeCatcher = 0xc8a5d9c4;
53 u_int32_t naca = 0;
54 u_int32_t xRamDisk = 0;
55 u_int32_t xRamDiskSize = 0;
56 if ( argc < 2 ) {
57 printf("Name of RAM disk file missing.\n");
58 exit(1);
59 }
60
61 if ( argc < 3 ) {
62 printf("Name of vmlinux file missing.\n");
63 exit(1);
64 }
65
66 if ( argc < 4 ) {
67 printf("Name of vmlinux output file missing.\n");
68 exit(1);
69 }
70
71 ramDisk = fopen(argv[1], "r");
72 if ( ! ramDisk ) {
73 printf("RAM disk file \"%s\" failed to open.\n", argv[1]);
74 exit(1);
75 }
76 inputVmlinux = fopen(argv[2], "r");
77 if ( ! inputVmlinux ) {
78 printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
79 exit(1);
80 }
81 outputVmlinux = fopen(argv[3], "w+");
82 if ( ! outputVmlinux ) {
83 printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
84 exit(1);
85 }
86 fseek(ramDisk, 0, SEEK_END);
87 ramFileLen = ftell(ramDisk);
88 fseek(ramDisk, 0, SEEK_SET);
89 printf("%s file size = %d\n", argv[1], ramFileLen);
90
91 ramLen = ramFileLen;
92
93 roundR = 4096 - (ramLen % 4096);
94 if ( roundR ) {
95 printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR);
96 ramLen += roundR;
97 }
98
99 printf("Rounded RAM disk size is %d\n", ramLen);
100 fseek(inputVmlinux, 0, SEEK_END);
101 kernelLen = ftell(inputVmlinux);
102 fseek(inputVmlinux, 0, SEEK_SET);
103 printf("kernel file size = %d\n", kernelLen);
104 if ( kernelLen == 0 ) {
105 printf("You must have a linux kernel specified as argv[2]\n");
106 exit(1);
107 }
108
109 actualKernelLen = kernelLen - ElfHeaderSize;
110
111 printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen);
112
113 round = actualKernelLen % 4096;
114 roundedKernelLen = actualKernelLen;
115 if ( round )
116 roundedKernelLen += (4096 - round);
117
118 printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen);
119
120 ramStartOffs = roundedKernelLen;
121 ramPages = ramLen / 4096;
122
123 printf("RAM disk pages to copy = %d\n", ramPages);
124
125 // Copy 64K ELF header
126 for (i=0; i<(ElfPages); ++i) {
127 get4k( inputVmlinux, inbuf );
128 put4k( outputVmlinux, inbuf );
129 }
130
131 roundedKernelPages = roundedKernelLen / 4096;
132
133 fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
134
135 for ( i=0; i<roundedKernelPages; ++i ) {
136 get4k( inputVmlinux, inbuf );
137 put4k( outputVmlinux, inbuf );
138 }
139
140 for ( i=0; i<ramPages; ++i ) {
141 get4k( ramDisk, inbuf );
142 put4k( outputVmlinux, inbuf );
143 }
144
145 /* Close the input files */
146 fclose(ramDisk);
147 fclose(inputVmlinux);
148 /* And flush the written output file */
149 fflush(outputVmlinux);
150
151 /* fseek to the hvReleaseData pointer */
152 fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
153 if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
154 death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]);
155 }
156 hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
157 printf("hvReleaseData is at %08x\n", hvReleaseData);
158
159 /* fseek to the hvReleaseData */
160 fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
161 if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
162 death("Could not read hvReleaseData\n", outputVmlinux, argv[3]);
163 }
164 /* Check hvReleaseData sanity */
165 if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
166 death("hvReleaseData is invalid\n", outputVmlinux, argv[3]);
167 }
168 /* Get the naca pointer */
169 naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE;
170 printf("naca is at %08x\n", naca);
171
172 /* fseek to the naca */
173 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
174 if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
175 death("Could not read naca\n", outputVmlinux, argv[3]);
176 }
177 xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
178 xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
179 /* Make sure a RAM disk isn't already present */
180 if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
181 death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]);
182 }
183 /* Fill in the values */
184 *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
185 *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages);
186
187 /* Write out the new naca */
188 fflush(outputVmlinux);
189 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
190 if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
191 death("Could not write naca\n", outputVmlinux, argv[3]);
192 }
193 printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n",
194 ramPages, ramStartOffs);
195
196 /* Done */
197 fclose(outputVmlinux);
198 /* Set permission to executable */
199 chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
200
201 return 0;
202}
203
diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S
index 468721d9ebd2..3fb1fb619d2c 100644
--- a/arch/ppc/kernel/cpu_setup_6xx.S
+++ b/arch/ppc/kernel/cpu_setup_6xx.S
@@ -249,8 +249,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM)
249 sync 249 sync
250 isync 250 isync
251 251
252 /* Enable L2 HW prefetch 252 /* Enable L2 HW prefetch, if L2 is enabled
253 */ 253 */
254 mfspr r3,SPRN_L2CR
255 andis. r3,r3,L2CR_L2E@h
256 beqlr
254 mfspr r3,SPRN_MSSCR0 257 mfspr r3,SPRN_MSSCR0
255 ori r3,r3,3 258 ori r3,r3,3
256 sync 259 sync
diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S
index c39441048266..861115249b35 100644
--- a/arch/ppc/kernel/l2cr.S
+++ b/arch/ppc/kernel/l2cr.S
@@ -156,6 +156,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
156 The bit moved on the 7450..... 156 The bit moved on the 7450.....
157 ****/ 157 ****/
158 158
159BEGIN_FTR_SECTION
160 /* Disable L2 prefetch on some 745x and try to ensure
161 * L2 prefetch engines are idle. As explained by errata
162 * text, we can't be sure they are, we just hope very hard
163 * that well be enough (sic !). At least I noticed Apple
164 * doesn't even bother doing the dcbf's here...
165 */
166 mfspr r4,SPRN_MSSCR0
167 rlwinm r4,r4,0,0,29
168 sync
169 mtspr SPRN_MSSCR0,r4
170 sync
171 isync
172 lis r4,KERNELBASE@h
173 dcbf 0,r4
174 dcbf 0,r4
175 dcbf 0,r4
176 dcbf 0,r4
177END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
178
159 /* TODO: use HW flush assist when available */ 179 /* TODO: use HW flush assist when available */
160 180
161 lis r4,0x0002 181 lis r4,0x0002
@@ -230,7 +250,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
230 oris r3,r3,0x8000 250 oris r3,r3,0x8000
231 mtspr SPRN_L2CR,r3 251 mtspr SPRN_L2CR,r3
232 sync 252 sync
233 253
254 /* Enable L2 HW prefetch on 744x/745x */
255BEGIN_FTR_SECTION
256 mfspr r3,SPRN_MSSCR0
257 ori r3,r3,3
258 sync
259 mtspr SPRN_MSSCR0,r3
260 sync
261 isync
262END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450)
2344: 2634:
235 264
236 /* Restore HID0[DPM] to whatever it was before */ 265 /* Restore HID0[DPM] to whatever it was before */
diff --git a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c
index a3702cfe8f7c..4c888da89b3c 100644
--- a/arch/ppc/syslib/m8xx_setup.c
+++ b/arch/ppc/syslib/m8xx_setup.c
@@ -57,7 +57,7 @@ unsigned char __res[sizeof(bd_t)];
57extern void m8xx_ide_init(void); 57extern void m8xx_ide_init(void);
58 58
59extern unsigned long find_available_memory(void); 59extern unsigned long find_available_memory(void);
60extern void m8xx_cpm_reset(); 60extern void m8xx_cpm_reset(void);
61extern void m8xx_wdt_handler_install(bd_t *bp); 61extern void m8xx_wdt_handler_install(bd_t *bp);
62extern void rpxfb_alloc_pages(void); 62extern void rpxfb_alloc_pages(void);
63extern void cpm_interrupt_init(void); 63extern void cpm_interrupt_init(void);
@@ -266,8 +266,8 @@ m8xx_show_percpuinfo(struct seq_file *m, int i)
266 266
267 bp = (bd_t *)__res; 267 bp = (bd_t *)__res;
268 268
269 seq_printf(m, "clock\t\t: %ldMHz\n" 269 seq_printf(m, "clock\t\t: %uMHz\n"
270 "bus clock\t: %ldMHz\n", 270 "bus clock\t: %uMHz\n",
271 bp->bi_intfreq / 1000000, 271 bp->bi_intfreq / 1000000,
272 bp->bi_busfreq / 1000000); 272 bp->bi_busfreq / 1000000);
273 273
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 2ce87836c671..13b262f10216 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -302,12 +302,6 @@ config GENERIC_HARDIRQS
302 bool 302 bool
303 default y 303 default y
304 304
305config MSCHUNKS
306 bool
307 depends on PPC_ISERIES
308 default y
309
310
311config PPC_RTAS 305config PPC_RTAS
312 bool 306 bool
313 depends on PPC_PSERIES || PPC_BPA 307 depends on PPC_PSERIES || PPC_BPA
@@ -350,13 +344,46 @@ config SECCOMP
350 344
351 If unsure, say Y. Only embedded should say N here. 345 If unsure, say Y. Only embedded should say N here.
352 346
347source "fs/Kconfig.binfmt"
348
349config HOTPLUG_CPU
350 bool "Support for hot-pluggable CPUs"
351 depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
352 select HOTPLUG
353 ---help---
354 Say Y here to be able to turn CPUs off and on.
355
356 Say N if you are unsure.
357
358config PROC_DEVICETREE
359 bool "Support for Open Firmware device tree in /proc"
360 depends on !PPC_ISERIES
361 help
362 This option adds a device-tree directory under /proc which contains
363 an image of the device tree that the kernel copies from Open
364 Firmware. If unsure, say Y here.
365
366config CMDLINE_BOOL
367 bool "Default bootloader kernel arguments"
368 depends on !PPC_ISERIES
369
370config CMDLINE
371 string "Initial kernel command string"
372 depends on CMDLINE_BOOL
373 default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
374 help
375 On some platforms, there is currently no way for the boot loader to
376 pass arguments to the kernel. For these platforms, you can supply
377 some command-line options at build time by entering them here. In
378 most cases you will need to specify the root device here.
379
353endmenu 380endmenu
354 381
355config ISA_DMA_API 382config ISA_DMA_API
356 bool 383 bool
357 default y 384 default y
358 385
359menu "General setup" 386menu "Bus Options"
360 387
361config ISA 388config ISA
362 bool 389 bool
@@ -389,45 +416,12 @@ config PCI_DOMAINS
389 bool 416 bool
390 default PCI 417 default PCI
391 418
392source "fs/Kconfig.binfmt"
393
394source "drivers/pci/Kconfig" 419source "drivers/pci/Kconfig"
395 420
396config HOTPLUG_CPU
397 bool "Support for hot-pluggable CPUs"
398 depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
399 select HOTPLUG
400 ---help---
401 Say Y here to be able to turn CPUs off and on.
402
403 Say N if you are unsure.
404
405source "drivers/pcmcia/Kconfig" 421source "drivers/pcmcia/Kconfig"
406 422
407source "drivers/pci/hotplug/Kconfig" 423source "drivers/pci/hotplug/Kconfig"
408 424
409config PROC_DEVICETREE
410 bool "Support for Open Firmware device tree in /proc"
411 depends on !PPC_ISERIES
412 help
413 This option adds a device-tree directory under /proc which contains
414 an image of the device tree that the kernel copies from Open
415 Firmware. If unsure, say Y here.
416
417config CMDLINE_BOOL
418 bool "Default bootloader kernel arguments"
419 depends on !PPC_ISERIES
420
421config CMDLINE
422 string "Initial kernel command string"
423 depends on CMDLINE_BOOL
424 default "console=ttyS0,9600 console=tty0 root=/dev/sda2"
425 help
426 On some platforms, there is currently no way for the boot loader to
427 pass arguments to the kernel. For these platforms, you can supply
428 some command-line options at build time by entering them here. In
429 most cases you will need to specify the root device here.
430
431endmenu 425endmenu
432 426
433source "net/Kconfig" 427source "net/Kconfig"
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 731b84758331..6350cce82efb 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -55,6 +55,8 @@ LDFLAGS := -m elf64ppc
55LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) 55LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
56CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \ 56CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \
57 -mcall-aixdesc 57 -mcall-aixdesc
58# Temporary hack until we have migrated to asm-powerpc
59CPPFLAGS += -Iinclude3
58 60
59GCC_VERSION := $(call cc-version) 61GCC_VERSION := $(call cc-version)
60GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;) 62GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;)
@@ -112,6 +114,7 @@ all: $(KBUILD_IMAGE)
112 114
113archclean: 115archclean:
114 $(Q)$(MAKE) $(clean)=$(boot) 116 $(Q)$(MAKE) $(clean)=$(boot)
117 $(Q)rm -rf include3
115 118
116prepare: include/asm-ppc64/offsets.h 119prepare: include/asm-ppc64/offsets.h
117 120
@@ -121,6 +124,12 @@ arch/ppc64/kernel/asm-offsets.s: include/asm include/linux/version.h \
121include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s 124include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s
122 $(call filechk,gen-asm-offsets) 125 $(call filechk,gen-asm-offsets)
123 126
127# Temporary hack until we have migrated to asm-powerpc
128include/asm: include3/asm
129include3/asm:
130 $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi;
131 $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm
132
124define archhelp 133define archhelp
125 echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)' 134 echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
126 echo ' zImage.initrd- Compressed kernel image with initrd attached,' 135 echo ' zImage.initrd- Compressed kernel image with initrd attached,'
diff --git a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
index 683b2d43c15f..2c5f5e73d00c 100644
--- a/arch/ppc64/boot/Makefile
+++ b/arch/ppc64/boot/Makefile
@@ -22,8 +22,8 @@
22 22
23 23
24HOSTCC := gcc 24HOSTCC := gcc
25BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 25BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include)
26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional 26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
27BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds 27BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
28OBJCOPYFLAGS := contents,alloc,load,readonly,data 28OBJCOPYFLAGS := contents,alloc,load,readonly,data
29 29
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c
index 719663a694bb..8041a9845ab7 100644
--- a/arch/ppc64/boot/addnote.c
+++ b/arch/ppc64/boot/addnote.c
@@ -157,7 +157,7 @@ main(int ac, char **av)
157 PUT_32BE(ns, strlen(arch) + 1); 157 PUT_32BE(ns, strlen(arch) + 1);
158 PUT_32BE(ns + 4, N_DESCR * 4); 158 PUT_32BE(ns + 4, N_DESCR * 4);
159 PUT_32BE(ns + 8, 0x1275); 159 PUT_32BE(ns + 8, 0x1275);
160 strcpy(&buf[ns + 12], arch); 160 strcpy((char *) &buf[ns + 12], arch);
161 ns += 12 + strlen(arch) + 1; 161 ns += 12 + strlen(arch) + 1;
162 for (i = 0; i < N_DESCR; ++i, ns += 4) 162 for (i = 0; i < N_DESCR; ++i, ns += 4)
163 PUT_32BE(ns, descr[i]); 163 PUT_32BE(ns, descr[i]);
@@ -172,7 +172,7 @@ main(int ac, char **av)
172 PUT_32BE(ns, strlen(rpaname) + 1); 172 PUT_32BE(ns, strlen(rpaname) + 1);
173 PUT_32BE(ns + 4, sizeof(rpanote)); 173 PUT_32BE(ns + 4, sizeof(rpanote));
174 PUT_32BE(ns + 8, 0x12759999); 174 PUT_32BE(ns + 8, 0x12759999);
175 strcpy(&buf[ns + 12], rpaname); 175 strcpy((char *) &buf[ns + 12], rpaname);
176 ns += 12 + ROUNDUP(strlen(rpaname) + 1); 176 ns += 12 + ROUNDUP(strlen(rpaname) + 1);
177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) 177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
178 PUT_32BE(ns, rpanote[i]); 178 PUT_32BE(ns, rpanote[i]);
diff --git a/arch/ppc64/boot/crt0.S b/arch/ppc64/boot/crt0.S
index 04d3e74cd72f..3861e7f9cf19 100644
--- a/arch/ppc64/boot/crt0.S
+++ b/arch/ppc64/boot/crt0.S
@@ -9,7 +9,7 @@
9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32. 9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
10 */ 10 */
11 11
12#include <asm/ppc_asm.h> 12#include "ppc_asm.h"
13 13
14 .text 14 .text
15 .globl _start 15 .globl _start
diff --git a/arch/ppc64/boot/div64.S b/arch/ppc64/boot/div64.S
index 38f7e466d7d6..722f360a32a9 100644
--- a/arch/ppc64/boot/div64.S
+++ b/arch/ppc64/boot/div64.S
@@ -13,7 +13,7 @@
13 * as published by the Free Software Foundation; either version 13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version. 14 * 2 of the License, or (at your option) any later version.
15 */ 15 */
16#include <asm/ppc_asm.h> 16#include "ppc_asm.h"
17 17
18 .globl __div64_32 18 .globl __div64_32
19__div64_32: 19__div64_32:
diff --git a/arch/ppc64/boot/elf.h b/arch/ppc64/boot/elf.h
new file mode 100644
index 000000000000..d4828fcf1cb9
--- /dev/null
+++ b/arch/ppc64/boot/elf.h
@@ -0,0 +1,149 @@
1#ifndef _PPC_BOOT_ELF_H_
2#define _PPC_BOOT_ELF_H_
3
4/* 32-bit ELF base types. */
5typedef unsigned int Elf32_Addr;
6typedef unsigned short Elf32_Half;
7typedef unsigned int Elf32_Off;
8typedef signed int Elf32_Sword;
9typedef unsigned int Elf32_Word;
10
11/* 64-bit ELF base types. */
12typedef unsigned long long Elf64_Addr;
13typedef unsigned short Elf64_Half;
14typedef signed short Elf64_SHalf;
15typedef unsigned long long Elf64_Off;
16typedef signed int Elf64_Sword;
17typedef unsigned int Elf64_Word;
18typedef unsigned long long Elf64_Xword;
19typedef signed long long Elf64_Sxword;
20
21/* These constants are for the segment types stored in the image headers */
22#define PT_NULL 0
23#define PT_LOAD 1
24#define PT_DYNAMIC 2
25#define PT_INTERP 3
26#define PT_NOTE 4
27#define PT_SHLIB 5
28#define PT_PHDR 6
29#define PT_TLS 7 /* Thread local storage segment */
30#define PT_LOOS 0x60000000 /* OS-specific */
31#define PT_HIOS 0x6fffffff /* OS-specific */
32#define PT_LOPROC 0x70000000
33#define PT_HIPROC 0x7fffffff
34#define PT_GNU_EH_FRAME 0x6474e550
35
36#define PT_GNU_STACK (PT_LOOS + 0x474e551)
37
38/* These constants define the different elf file types */
39#define ET_NONE 0
40#define ET_REL 1
41#define ET_EXEC 2
42#define ET_DYN 3
43#define ET_CORE 4
44#define ET_LOPROC 0xff00
45#define ET_HIPROC 0xffff
46
47/* These constants define the various ELF target machines */
48#define EM_NONE 0
49#define EM_PPC 20 /* PowerPC */
50#define EM_PPC64 21 /* PowerPC64 */
51
52#define EI_NIDENT 16
53
54typedef struct elf32_hdr {
55 unsigned char e_ident[EI_NIDENT];
56 Elf32_Half e_type;
57 Elf32_Half e_machine;
58 Elf32_Word e_version;
59 Elf32_Addr e_entry; /* Entry point */
60 Elf32_Off e_phoff;
61 Elf32_Off e_shoff;
62 Elf32_Word e_flags;
63 Elf32_Half e_ehsize;
64 Elf32_Half e_phentsize;
65 Elf32_Half e_phnum;
66 Elf32_Half e_shentsize;
67 Elf32_Half e_shnum;
68 Elf32_Half e_shstrndx;
69} Elf32_Ehdr;
70
71typedef struct elf64_hdr {
72 unsigned char e_ident[16]; /* ELF "magic number" */
73 Elf64_Half e_type;
74 Elf64_Half e_machine;
75 Elf64_Word e_version;
76 Elf64_Addr e_entry; /* Entry point virtual address */
77 Elf64_Off e_phoff; /* Program header table file offset */
78 Elf64_Off e_shoff; /* Section header table file offset */
79 Elf64_Word e_flags;
80 Elf64_Half e_ehsize;
81 Elf64_Half e_phentsize;
82 Elf64_Half e_phnum;
83 Elf64_Half e_shentsize;
84 Elf64_Half e_shnum;
85 Elf64_Half e_shstrndx;
86} Elf64_Ehdr;
87
88/* These constants define the permissions on sections in the program
89 header, p_flags. */
90#define PF_R 0x4
91#define PF_W 0x2
92#define PF_X 0x1
93
94typedef struct elf32_phdr {
95 Elf32_Word p_type;
96 Elf32_Off p_offset;
97 Elf32_Addr p_vaddr;
98 Elf32_Addr p_paddr;
99 Elf32_Word p_filesz;
100 Elf32_Word p_memsz;
101 Elf32_Word p_flags;
102 Elf32_Word p_align;
103} Elf32_Phdr;
104
105typedef struct elf64_phdr {
106 Elf64_Word p_type;
107 Elf64_Word p_flags;
108 Elf64_Off p_offset; /* Segment file offset */
109 Elf64_Addr p_vaddr; /* Segment virtual address */
110 Elf64_Addr p_paddr; /* Segment physical address */
111 Elf64_Xword p_filesz; /* Segment size in file */
112 Elf64_Xword p_memsz; /* Segment size in memory */
113 Elf64_Xword p_align; /* Segment alignment, file & memory */
114} Elf64_Phdr;
115
116#define EI_MAG0 0 /* e_ident[] indexes */
117#define EI_MAG1 1
118#define EI_MAG2 2
119#define EI_MAG3 3
120#define EI_CLASS 4
121#define EI_DATA 5
122#define EI_VERSION 6
123#define EI_OSABI 7
124#define EI_PAD 8
125
126#define ELFMAG0 0x7f /* EI_MAG */
127#define ELFMAG1 'E'
128#define ELFMAG2 'L'
129#define ELFMAG3 'F'
130#define ELFMAG "\177ELF"
131#define SELFMAG 4
132
133#define ELFCLASSNONE 0 /* EI_CLASS */
134#define ELFCLASS32 1
135#define ELFCLASS64 2
136#define ELFCLASSNUM 3
137
138#define ELFDATANONE 0 /* e_ident[EI_DATA] */
139#define ELFDATA2LSB 1
140#define ELFDATA2MSB 2
141
142#define EV_NONE 0 /* e_version, EI_VERSION */
143#define EV_CURRENT 1
144#define EV_NUM 2
145
146#define ELFOSABI_NONE 0
147#define ELFOSABI_LINUX 3
148
149#endif /* _PPC_BOOT_ELF_H_ */
diff --git a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
index 199d9804f61c..99e68cfbe688 100644
--- a/arch/ppc64/boot/main.c
+++ b/arch/ppc64/boot/main.c
@@ -8,36 +8,28 @@
8 * as published by the Free Software Foundation; either version 8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11#include "ppc32-types.h" 11#include <stdarg.h>
12#include <stddef.h>
13#include "elf.h"
14#include "page.h"
15#include "string.h"
16#include "stdio.h"
17#include "prom.h"
12#include "zlib.h" 18#include "zlib.h"
13#include <linux/elf.h> 19
14#include <linux/string.h> 20static void gunzip(void *, int, unsigned char *, int *);
15#include <asm/processor.h> 21extern void flush_cache(void *, unsigned long);
16#include <asm/page.h> 22
17
18extern void *finddevice(const char *);
19extern int getprop(void *, const char *, void *, int);
20extern void printf(const char *fmt, ...);
21extern int sprintf(char *buf, const char *fmt, ...);
22void gunzip(void *, int, unsigned char *, int *);
23void *claim(unsigned int, unsigned int, unsigned int);
24void flush_cache(void *, unsigned long);
25void pause(void);
26extern void exit(void);
27
28unsigned long strlen(const char *s);
29void *memmove(void *dest, const void *src, unsigned long n);
30void *memcpy(void *dest, const void *src, unsigned long n);
31 23
32/* Value picked to match that used by yaboot */ 24/* Value picked to match that used by yaboot */
33#define PROG_START 0x01400000 25#define PROG_START 0x01400000
34#define RAM_END (256<<20) // Fixme: use OF */ 26#define RAM_END (256<<20) // Fixme: use OF */
35 27
36char *avail_ram; 28static char *avail_ram;
37char *begin_avail, *end_avail; 29static char *begin_avail, *end_avail;
38char *avail_high; 30static char *avail_high;
39unsigned int heap_use; 31static unsigned int heap_use;
40unsigned int heap_max; 32static unsigned int heap_max;
41 33
42extern char _start[]; 34extern char _start[];
43extern char _vmlinux_start[]; 35extern char _vmlinux_start[];
@@ -52,9 +44,9 @@ struct addr_range {
52 unsigned long size; 44 unsigned long size;
53 unsigned long memsize; 45 unsigned long memsize;
54}; 46};
55struct addr_range vmlinux = {0, 0, 0}; 47static struct addr_range vmlinux = {0, 0, 0};
56struct addr_range vmlinuz = {0, 0, 0}; 48static struct addr_range vmlinuz = {0, 0, 0};
57struct addr_range initrd = {0, 0, 0}; 49static struct addr_range initrd = {0, 0, 0};
58 50
59static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ 51static char scratch[128<<10]; /* 128kB of scratch space for gunzip */
60 52
@@ -64,13 +56,6 @@ typedef void (*kernel_entry_t)( unsigned long,
64 void *); 56 void *);
65 57
66 58
67int (*prom)(void *);
68
69void *chosen_handle;
70void *stdin;
71void *stdout;
72void *stderr;
73
74#undef DEBUG 59#undef DEBUG
75 60
76static unsigned long claim_base = PROG_START; 61static unsigned long claim_base = PROG_START;
@@ -277,7 +262,7 @@ void zfree(void *x, void *addr, unsigned nb)
277 262
278#define DEFLATED 8 263#define DEFLATED 8
279 264
280void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) 265static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
281{ 266{
282 z_stream s; 267 z_stream s;
283 int r, i, flags; 268 int r, i, flags;
diff --git a/arch/ppc64/boot/page.h b/arch/ppc64/boot/page.h
new file mode 100644
index 000000000000..14eca30fef64
--- /dev/null
+++ b/arch/ppc64/boot/page.h
@@ -0,0 +1,34 @@
1#ifndef _PPC_BOOT_PAGE_H
2#define _PPC_BOOT_PAGE_H
3/*
4 * Copyright (C) 2001 PPC64 Team, IBM Corp
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#ifdef __ASSEMBLY__
13#define ASM_CONST(x) x
14#else
15#define __ASM_CONST(x) x##UL
16#define ASM_CONST(x) __ASM_CONST(x)
17#endif
18
19/* PAGE_SHIFT determines the page size */
20#define PAGE_SHIFT 12
21#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
22#define PAGE_MASK (~(PAGE_SIZE-1))
23
24/* align addr on a size boundary - adjust address up/down if needed */
25#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
26#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1)))
27
28/* align addr on a size boundary - adjust address up if needed */
29#define _ALIGN(addr,size) _ALIGN_UP(addr,size)
30
31/* to align the pointer to the (next) page boundary */
32#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE)
33
34#endif /* _PPC_BOOT_PAGE_H */
diff --git a/arch/ppc64/boot/ppc32-types.h b/arch/ppc64/boot/ppc32-types.h
deleted file mode 100644
index f7b8884f8f70..000000000000
--- a/arch/ppc64/boot/ppc32-types.h
+++ /dev/null
@@ -1,36 +0,0 @@
1#ifndef _PPC64_TYPES_H
2#define _PPC64_TYPES_H
3
4typedef __signed__ char __s8;
5typedef unsigned char __u8;
6
7typedef __signed__ short __s16;
8typedef unsigned short __u16;
9
10typedef __signed__ int __s32;
11typedef unsigned int __u32;
12
13typedef __signed__ long long __s64;
14typedef unsigned long long __u64;
15
16typedef signed char s8;
17typedef unsigned char u8;
18
19typedef signed short s16;
20typedef unsigned short u16;
21
22typedef signed int s32;
23typedef unsigned int u32;
24
25typedef signed long long s64;
26typedef unsigned long long u64;
27
28typedef struct {
29 __u32 u[4];
30} __attribute((aligned(16))) __vector128;
31
32#define BITS_PER_LONG 32
33
34typedef __vector128 vector128;
35
36#endif /* _PPC64_TYPES_H */
diff --git a/arch/ppc64/boot/ppc_asm.h b/arch/ppc64/boot/ppc_asm.h
new file mode 100644
index 000000000000..1c2c2817f9b7
--- /dev/null
+++ b/arch/ppc64/boot/ppc_asm.h
@@ -0,0 +1,62 @@
1#ifndef _PPC64_PPC_ASM_H
2#define _PPC64_PPC_ASM_H
3/*
4 *
5 * Definitions used by various bits of low-level assembly code on PowerPC.
6 *
7 * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15/* Condition Register Bit Fields */
16
17#define cr0 0
18#define cr1 1
19#define cr2 2
20#define cr3 3
21#define cr4 4
22#define cr5 5
23#define cr6 6
24#define cr7 7
25
26
27/* General Purpose Registers (GPRs) */
28
29#define r0 0
30#define r1 1
31#define r2 2
32#define r3 3
33#define r4 4
34#define r5 5
35#define r6 6
36#define r7 7
37#define r8 8
38#define r9 9
39#define r10 10
40#define r11 11
41#define r12 12
42#define r13 13
43#define r14 14
44#define r15 15
45#define r16 16
46#define r17 17
47#define r18 18
48#define r19 19
49#define r20 20
50#define r21 21
51#define r22 22
52#define r23 23
53#define r24 24
54#define r25 25
55#define r26 26
56#define r27 27
57#define r28 28
58#define r29 29
59#define r30 30
60#define r31 31
61
62#endif /* _PPC64_PPC_ASM_H */
diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c
index 5e48b80ff5a0..4bea2f4dcb06 100644
--- a/arch/ppc64/boot/prom.c
+++ b/arch/ppc64/boot/prom.c
@@ -7,43 +7,19 @@
7 * 2 of the License, or (at your option) any later version. 7 * 2 of the License, or (at your option) any later version.
8 */ 8 */
9#include <stdarg.h> 9#include <stdarg.h>
10#include <linux/types.h> 10#include <stddef.h>
11#include <linux/string.h> 11#include "string.h"
12#include <linux/ctype.h> 12#include "stdio.h"
13 13#include "prom.h"
14extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);
15
16/* The unnecessary pointer compare is there
17 * to check for type safety (n must be 64bit)
18 */
19# define do_div(n,base) ({ \
20 __u32 __base = (base); \
21 __u32 __rem; \
22 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
23 if (((n) >> 32) == 0) { \
24 __rem = (__u32)(n) % __base; \
25 (n) = (__u32)(n) / __base; \
26 } else \
27 __rem = __div64_32(&(n), __base); \
28 __rem; \
29 })
30 14
31int (*prom)(void *); 15int (*prom)(void *);
32 16
33void *chosen_handle; 17void *chosen_handle;
18
34void *stdin; 19void *stdin;
35void *stdout; 20void *stdout;
36void *stderr; 21void *stderr;
37 22
38void exit(void);
39void *finddevice(const char *name);
40int getprop(void *phandle, const char *name, void *buf, int buflen);
41void chrpboot(int a1, int a2, void *prom); /* in main.c */
42
43int printf(char *fmt, ...);
44
45/* there is no convenient header to get this from... -- paulus */
46extern unsigned long strlen(const char *);
47 23
48int 24int
49write(void *handle, void *ptr, int nb) 25write(void *handle, void *ptr, int nb)
@@ -210,107 +186,6 @@ fputs(char *str, void *f)
210 return write(f, str, n) == n? 0: -1; 186 return write(f, str, n) == n? 0: -1;
211} 187}
212 188
213int
214readchar(void)
215{
216 char ch;
217
218 for (;;) {
219 switch (read(stdin, &ch, 1)) {
220 case 1:
221 return ch;
222 case -1:
223 printf("read(stdin) returned -1\r\n");
224 return -1;
225 }
226 }
227}
228
229static char line[256];
230static char *lineptr;
231static int lineleft;
232
233int
234getchar(void)
235{
236 int c;
237
238 if (lineleft == 0) {
239 lineptr = line;
240 for (;;) {
241 c = readchar();
242 if (c == -1 || c == 4)
243 break;
244 if (c == '\r' || c == '\n') {
245 *lineptr++ = '\n';
246 putchar('\n');
247 break;
248 }
249 switch (c) {
250 case 0177:
251 case '\b':
252 if (lineptr > line) {
253 putchar('\b');
254 putchar(' ');
255 putchar('\b');
256 --lineptr;
257 }
258 break;
259 case 'U' & 0x1F:
260 while (lineptr > line) {
261 putchar('\b');
262 putchar(' ');
263 putchar('\b');
264 --lineptr;
265 }
266 break;
267 default:
268 if (lineptr >= &line[sizeof(line) - 1])
269 putchar('\a');
270 else {
271 putchar(c);
272 *lineptr++ = c;
273 }
274 }
275 }
276 lineleft = lineptr - line;
277 lineptr = line;
278 }
279 if (lineleft == 0)
280 return -1;
281 --lineleft;
282 return *lineptr++;
283}
284
285
286
287/* String functions lifted from lib/vsprintf.c and lib/ctype.c */
288unsigned char _ctype[] = {
289_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
290_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
291_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
292_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
293_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
294_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
295_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
296_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
297_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
298_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
299_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
300_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
301_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
302_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
303_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
304_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
3050,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
3060,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
307_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
308_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
309_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
310_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
311_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
312_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
313
314size_t strnlen(const char * s, size_t count) 189size_t strnlen(const char * s, size_t count)
315{ 190{
316 const char *sc; 191 const char *sc;
@@ -320,44 +195,30 @@ size_t strnlen(const char * s, size_t count)
320 return sc - s; 195 return sc - s;
321} 196}
322 197
323unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) 198extern unsigned int __div64_32(unsigned long long *dividend,
324{ 199 unsigned int divisor);
325 unsigned long result = 0,value;
326 200
327 if (!base) { 201/* The unnecessary pointer compare is there
328 base = 10; 202 * to check for type safety (n must be 64bit)
329 if (*cp == '0') { 203 */
330 base = 8; 204# define do_div(n,base) ({ \
331 cp++; 205 unsigned int __base = (base); \
332 if ((*cp == 'x') && isxdigit(cp[1])) { 206 unsigned int __rem; \
333 cp++; 207 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
334 base = 16; 208 if (((n) >> 32) == 0) { \
335 } 209 __rem = (unsigned int)(n) % __base; \
336 } 210 (n) = (unsigned int)(n) / __base; \
337 } 211 } else \
338 while (isxdigit(*cp) && 212 __rem = __div64_32(&(n), __base); \
339 (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) { 213 __rem; \
340 result = result*base + value; 214 })
341 cp++;
342 }
343 if (endp)
344 *endp = (char *)cp;
345 return result;
346}
347
348long simple_strtol(const char *cp,char **endp,unsigned int base)
349{
350 if(*cp=='-')
351 return -simple_strtoul(cp+1,endp,base);
352 return simple_strtoul(cp,endp,base);
353}
354 215
355static int skip_atoi(const char **s) 216static int skip_atoi(const char **s)
356{ 217{
357 int i=0; 218 int i, c;
358 219
359 while (isdigit(**s)) 220 for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
360 i = i*10 + *((*s)++) - '0'; 221 i = i*10 + c - '0';
361 return i; 222 return i;
362} 223}
363 224
@@ -436,9 +297,6 @@ static char * number(char * str, unsigned long long num, int base, int size, int
436 return str; 297 return str;
437} 298}
438 299
439/* Forward decl. needed for IP address printing stuff... */
440int sprintf(char * buf, const char *fmt, ...);
441
442int vsprintf(char *buf, const char *fmt, va_list args) 300int vsprintf(char *buf, const char *fmt, va_list args)
443{ 301{
444 int len; 302 int len;
@@ -477,7 +335,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
477 335
478 /* get field width */ 336 /* get field width */
479 field_width = -1; 337 field_width = -1;
480 if (isdigit(*fmt)) 338 if ('0' <= *fmt && *fmt <= '9')
481 field_width = skip_atoi(&fmt); 339 field_width = skip_atoi(&fmt);
482 else if (*fmt == '*') { 340 else if (*fmt == '*') {
483 ++fmt; 341 ++fmt;
@@ -493,7 +351,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
493 precision = -1; 351 precision = -1;
494 if (*fmt == '.') { 352 if (*fmt == '.') {
495 ++fmt; 353 ++fmt;
496 if (isdigit(*fmt)) 354 if ('0' <= *fmt && *fmt <= '9')
497 precision = skip_atoi(&fmt); 355 precision = skip_atoi(&fmt);
498 else if (*fmt == '*') { 356 else if (*fmt == '*') {
499 ++fmt; 357 ++fmt;
@@ -628,7 +486,7 @@ int sprintf(char * buf, const char *fmt, ...)
628static char sprint_buf[1024]; 486static char sprint_buf[1024];
629 487
630int 488int
631printf(char *fmt, ...) 489printf(const char *fmt, ...)
632{ 490{
633 va_list args; 491 va_list args;
634 int n; 492 int n;
diff --git a/arch/ppc64/boot/prom.h b/arch/ppc64/boot/prom.h
new file mode 100644
index 000000000000..96ab5aec740c
--- /dev/null
+++ b/arch/ppc64/boot/prom.h
@@ -0,0 +1,18 @@
1#ifndef _PPC_BOOT_PROM_H_
2#define _PPC_BOOT_PROM_H_
3
4extern int (*prom) (void *);
5extern void *chosen_handle;
6
7extern void *stdin;
8extern void *stdout;
9extern void *stderr;
10
11extern int write(void *handle, void *ptr, int nb);
12extern int read(void *handle, void *ptr, int nb);
13extern void exit(void);
14extern void pause(void);
15extern void *finddevice(const char *);
16extern void *claim(unsigned long virt, unsigned long size, unsigned long align);
17extern int getprop(void *phandle, const char *name, void *buf, int buflen);
18#endif /* _PPC_BOOT_PROM_H_ */
diff --git a/arch/ppc64/boot/stdio.h b/arch/ppc64/boot/stdio.h
new file mode 100644
index 000000000000..24bd3a8dee94
--- /dev/null
+++ b/arch/ppc64/boot/stdio.h
@@ -0,0 +1,16 @@
1#ifndef _PPC_BOOT_STDIO_H_
2#define _PPC_BOOT_STDIO_H_
3
4extern int printf(const char *fmt, ...);
5
6extern int sprintf(char *buf, const char *fmt, ...);
7
8extern int vsprintf(char *buf, const char *fmt, va_list args);
9
10extern int putc(int c, void *f);
11extern int putchar(int c);
12extern int getchar(void);
13
14extern int fputs(char *str, void *f);
15
16#endif /* _PPC_BOOT_STDIO_H_ */
diff --git a/arch/ppc64/boot/string.S b/arch/ppc64/boot/string.S
index ba5f2d21c9ea..7ade87ae7718 100644
--- a/arch/ppc64/boot/string.S
+++ b/arch/ppc64/boot/string.S
@@ -9,7 +9,7 @@
9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32. 9 * NOTE: this code runs in 32 bit mode and is packaged as ELF32.
10 */ 10 */
11 11
12#include <asm/ppc_asm.h> 12#include "ppc_asm.h"
13 13
14 .text 14 .text
15 .globl strcpy 15 .globl strcpy
diff --git a/arch/ppc64/boot/string.h b/arch/ppc64/boot/string.h
new file mode 100644
index 000000000000..9289258bcbd6
--- /dev/null
+++ b/arch/ppc64/boot/string.h
@@ -0,0 +1,16 @@
1#ifndef _PPC_BOOT_STRING_H_
2#define _PPC_BOOT_STRING_H_
3
4extern char *strcpy(char *dest, const char *src);
5extern char *strncpy(char *dest, const char *src, size_t n);
6extern char *strcat(char *dest, const char *src);
7extern int strcmp(const char *s1, const char *s2);
8extern size_t strlen(const char *s);
9extern size_t strnlen(const char *s, size_t count);
10
11extern void *memset(void *s, int c, size_t n);
12extern void *memmove(void *dest, const void *src, unsigned long n);
13extern void *memcpy(void *dest, const void *src, unsigned long n);
14extern int memcmp(const void *s1, const void *s2, size_t n);
15
16#endif /* _PPC_BOOT_STRING_H_ */
diff --git a/arch/ppc64/boot/zlib.c b/arch/ppc64/boot/zlib.c
index 78837e884b8b..0d910cd2079d 100644
--- a/arch/ppc64/boot/zlib.c
+++ b/arch/ppc64/boot/zlib.c
@@ -107,7 +107,7 @@ extern void *memcpy(void *, const void *, unsigned long);
107 107
108/* Diagnostic functions */ 108/* Diagnostic functions */
109#ifdef DEBUG_ZLIB 109#ifdef DEBUG_ZLIB
110# include <stdio.h> 110# include "stdio.h"
111# ifndef verbose 111# ifndef verbose
112# define verbose 0 112# define verbose 0
113# endif 113# endif
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index ab567741e80e..fc83d9330282 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -103,10 +103,10 @@ CONFIG_PREEMPT_NONE=y
103# CONFIG_PREEMPT_VOLUNTARY is not set 103# CONFIG_PREEMPT_VOLUNTARY is not set
104# CONFIG_PREEMPT is not set 104# CONFIG_PREEMPT is not set
105# CONFIG_PREEMPT_BKL is not set 105# CONFIG_PREEMPT_BKL is not set
106CONFIG_HZ_100=y 106# CONFIG_HZ_100 is not set
107# CONFIG_HZ_250 is not set 107CONFIG_HZ_250=y
108# CONFIG_HZ_1000 is not set 108# CONFIG_HZ_1000 is not set
109CONFIG_HZ=100 109CONFIG_HZ=250
110CONFIG_GENERIC_HARDIRQS=y 110CONFIG_GENERIC_HARDIRQS=y
111CONFIG_SECCOMP=y 111CONFIG_SECCOMP=y
112CONFIG_ISA_DMA_API=y 112CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index 394ba18b58c7..013d4e0e4003 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -94,12 +94,11 @@ CONFIG_PREEMPT_NONE=y
94# CONFIG_PREEMPT_VOLUNTARY is not set 94# CONFIG_PREEMPT_VOLUNTARY is not set
95# CONFIG_PREEMPT is not set 95# CONFIG_PREEMPT is not set
96# CONFIG_PREEMPT_BKL is not set 96# CONFIG_PREEMPT_BKL is not set
97CONFIG_HZ_100=y 97# CONFIG_HZ_100 is not set
98# CONFIG_HZ_250 is not set 98CONFIG_HZ_250=y
99# CONFIG_HZ_1000 is not set 99# CONFIG_HZ_1000 is not set
100CONFIG_HZ=100 100CONFIG_HZ=250
101CONFIG_GENERIC_HARDIRQS=y 101CONFIG_GENERIC_HARDIRQS=y
102CONFIG_MSCHUNKS=y
103CONFIG_LPARCFG=y 102CONFIG_LPARCFG=y
104CONFIG_SECCOMP=y 103CONFIG_SECCOMP=y
105CONFIG_ISA_DMA_API=y 104CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
index 2033fe663dbe..dd42892cd873 100644
--- a/arch/ppc64/configs/maple_defconfig
+++ b/arch/ppc64/configs/maple_defconfig
@@ -103,10 +103,10 @@ CONFIG_PREEMPT_NONE=y
103# CONFIG_PREEMPT_VOLUNTARY is not set 103# CONFIG_PREEMPT_VOLUNTARY is not set
104# CONFIG_PREEMPT is not set 104# CONFIG_PREEMPT is not set
105# CONFIG_PREEMPT_BKL is not set 105# CONFIG_PREEMPT_BKL is not set
106CONFIG_HZ_100=y 106# CONFIG_HZ_100 is not set
107# CONFIG_HZ_250 is not set 107CONFIG_HZ_250=y
108# CONFIG_HZ_1000 is not set 108# CONFIG_HZ_1000 is not set
109CONFIG_HZ=100 109CONFIG_HZ=250
110CONFIG_GENERIC_HARDIRQS=y 110CONFIG_GENERIC_HARDIRQS=y
111CONFIG_SECCOMP=y 111CONFIG_SECCOMP=y
112CONFIG_ISA_DMA_API=y 112CONFIG_ISA_DMA_API=y
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index 297fd5229487..29f7b80b0efc 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -112,10 +112,10 @@ CONFIG_PREEMPT_NONE=y
112# CONFIG_PREEMPT_VOLUNTARY is not set 112# CONFIG_PREEMPT_VOLUNTARY is not set
113# CONFIG_PREEMPT is not set 113# CONFIG_PREEMPT is not set
114# CONFIG_PREEMPT_BKL is not set 114# CONFIG_PREEMPT_BKL is not set
115CONFIG_HZ_100=y 115# CONFIG_HZ_100 is not set
116# CONFIG_HZ_250 is not set 116CONFIG_HZ_250=y
117# CONFIG_HZ_1000 is not set 117# CONFIG_HZ_1000 is not set
118CONFIG_HZ=100 118CONFIG_HZ=250
119CONFIG_EEH=y 119CONFIG_EEH=y
120CONFIG_GENERIC_HARDIRQS=y 120CONFIG_GENERIC_HARDIRQS=y
121CONFIG_PPC_RTAS=y 121CONFIG_PPC_RTAS=y
diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
index c361e7727b7a..7cb4750bb7a9 100644
--- a/arch/ppc64/defconfig
+++ b/arch/ppc64/defconfig
@@ -114,10 +114,10 @@ CONFIG_PREEMPT_NONE=y
114# CONFIG_PREEMPT_VOLUNTARY is not set 114# CONFIG_PREEMPT_VOLUNTARY is not set
115# CONFIG_PREEMPT is not set 115# CONFIG_PREEMPT is not set
116# CONFIG_PREEMPT_BKL is not set 116# CONFIG_PREEMPT_BKL is not set
117CONFIG_HZ_100=y 117# CONFIG_HZ_100 is not set
118# CONFIG_HZ_250 is not set 118CONFIG_HZ_250=y
119# CONFIG_HZ_1000 is not set 119# CONFIG_HZ_1000 is not set
120CONFIG_HZ=100 120CONFIG_HZ=250
121CONFIG_EEH=y 121CONFIG_EEH=y
122CONFIG_GENERIC_HARDIRQS=y 122CONFIG_GENERIC_HARDIRQS=y
123CONFIG_PPC_RTAS=y 123CONFIG_PPC_RTAS=y
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
index 1c11031c838e..0a9c23ca2f0c 100644
--- a/arch/ppc64/kernel/LparData.c
+++ b/arch/ppc64/kernel/LparData.c
@@ -51,6 +51,17 @@ struct HvReleaseData hvReleaseData = {
51 0xf4, 0x4b, 0xf6, 0xf4 }, 51 0xf4, 0x4b, 0xf6, 0xf4 },
52}; 52};
53 53
54/*
55 * The NACA. The first dword of the naca is required by the iSeries
56 * hypervisor to point to itVpdAreas. The hypervisor finds the NACA
57 * through the pointer in hvReleaseData.
58 */
59struct naca_struct naca = {
60 .xItVpdAreas = &itVpdAreas,
61 .xRamDisk = 0,
62 .xRamDiskSize = 0,
63};
64
54extern void system_reset_iSeries(void); 65extern void system_reset_iSeries(void);
55extern void machine_check_iSeries(void); 66extern void machine_check_iSeries(void);
56extern void data_access_iSeries(void); 67extern void data_access_iSeries(void);
@@ -214,29 +225,3 @@ struct ItVpdAreas itVpdAreas = {
214 0,0 225 0,0
215 } 226 }
216}; 227};
217
218struct msChunks msChunks;
219EXPORT_SYMBOL(msChunks);
220
221/* Depending on whether this is called from iSeries or pSeries setup
222 * code, the location of the msChunks struct may or may not have
223 * to be reloc'd, so we force the caller to do that for us by passing
224 * in a pointer to the structure.
225 */
226unsigned long
227msChunks_alloc(unsigned long mem, unsigned long num_chunks, unsigned long chunk_size)
228{
229 unsigned long offset = reloc_offset();
230 struct msChunks *_msChunks = PTRRELOC(&msChunks);
231
232 _msChunks->num_chunks = num_chunks;
233 _msChunks->chunk_size = chunk_size;
234 _msChunks->chunk_shift = __ilog2(chunk_size);
235 _msChunks->chunk_mask = (1UL<<_msChunks->chunk_shift)-1;
236
237 mem = _ALIGN(mem, sizeof(msChunks_entry));
238 _msChunks->abs = (msChunks_entry *)(mem + offset);
239 mem += num_chunks * sizeof(msChunks_entry);
240
241 return mem;
242}
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 2ecccb6b4f8c..f4b3bfcc109d 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ 11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
12 ptrace32.o signal32.o rtc.o init_task.o \ 12 ptrace32.o signal32.o rtc.o init_task.o \
13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ 13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
14 iommu.o sysfs.o vdso.o pmc.o 14 iommu.o sysfs.o vdso.o pmc.o firmware.o
15obj-y += vdso32/ vdso64/ 15obj-y += vdso32/ vdso64/
16 16
17obj-$(CONFIG_PPC_OF) += of_device.o 17obj-$(CONFIG_PPC_OF) += of_device.o
@@ -50,7 +50,10 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o
50obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o 50obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
51obj-$(CONFIG_BOOTX_TEXT) += btext.o 51obj-$(CONFIG_BOOTX_TEXT) += btext.o
52obj-$(CONFIG_HVCS) += hvcserver.o 52obj-$(CONFIG_HVCS) += hvcserver.o
53obj-$(CONFIG_IBMVIO) += vio.o 53
54vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o
55vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o
56obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y)
54obj-$(CONFIG_XICS) += xics.o 57obj-$(CONFIG_XICS) += xics.o
55obj-$(CONFIG_MPIC) += mpic.o 58obj-$(CONFIG_MPIC) += mpic.o
56 59
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index abb9e5b5da03..17e35d0fed09 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -94,7 +94,8 @@ int main(void)
94 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); 94 DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
95 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); 95 DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
96#ifdef CONFIG_HUGETLB_PAGE 96#ifdef CONFIG_HUGETLB_PAGE
97 DEFINE(PACAHTLBSEGS, offsetof(struct paca_struct, context.htlb_segs)); 97 DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
98 DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
98#endif /* CONFIG_HUGETLB_PAGE */ 99#endif /* CONFIG_HUGETLB_PAGE */
99 DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); 100 DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr));
100 DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); 101 DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen));
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 77cec42f9525..4847f2ac8c9f 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -5,7 +5,7 @@
5 * 5 *
6 * Modifications for ppc64: 6 * Modifications for ppc64:
7 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com> 7 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 11 * as published by the Free Software Foundation; either version
@@ -60,7 +60,6 @@ struct cpu_spec cpu_specs[] = {
60 .icache_bsize = 128, 60 .icache_bsize = 128,
61 .dcache_bsize = 128, 61 .dcache_bsize = 128,
62 .cpu_setup = __setup_cpu_power3, 62 .cpu_setup = __setup_cpu_power3,
63 .firmware_features = COMMON_PPC64_FW,
64 }, 63 },
65 { /* Power3+ */ 64 { /* Power3+ */
66 .pvr_mask = 0xffff0000, 65 .pvr_mask = 0xffff0000,
@@ -73,7 +72,6 @@ struct cpu_spec cpu_specs[] = {
73 .icache_bsize = 128, 72 .icache_bsize = 128,
74 .dcache_bsize = 128, 73 .dcache_bsize = 128,
75 .cpu_setup = __setup_cpu_power3, 74 .cpu_setup = __setup_cpu_power3,
76 .firmware_features = COMMON_PPC64_FW,
77 }, 75 },
78 { /* Northstar */ 76 { /* Northstar */
79 .pvr_mask = 0xffff0000, 77 .pvr_mask = 0xffff0000,
@@ -86,7 +84,6 @@ struct cpu_spec cpu_specs[] = {
86 .icache_bsize = 128, 84 .icache_bsize = 128,
87 .dcache_bsize = 128, 85 .dcache_bsize = 128,
88 .cpu_setup = __setup_cpu_power3, 86 .cpu_setup = __setup_cpu_power3,
89 .firmware_features = COMMON_PPC64_FW,
90 }, 87 },
91 { /* Pulsar */ 88 { /* Pulsar */
92 .pvr_mask = 0xffff0000, 89 .pvr_mask = 0xffff0000,
@@ -99,7 +96,6 @@ struct cpu_spec cpu_specs[] = {
99 .icache_bsize = 128, 96 .icache_bsize = 128,
100 .dcache_bsize = 128, 97 .dcache_bsize = 128,
101 .cpu_setup = __setup_cpu_power3, 98 .cpu_setup = __setup_cpu_power3,
102 .firmware_features = COMMON_PPC64_FW,
103 }, 99 },
104 { /* I-star */ 100 { /* I-star */
105 .pvr_mask = 0xffff0000, 101 .pvr_mask = 0xffff0000,
@@ -112,7 +108,6 @@ struct cpu_spec cpu_specs[] = {
112 .icache_bsize = 128, 108 .icache_bsize = 128,
113 .dcache_bsize = 128, 109 .dcache_bsize = 128,
114 .cpu_setup = __setup_cpu_power3, 110 .cpu_setup = __setup_cpu_power3,
115 .firmware_features = COMMON_PPC64_FW,
116 }, 111 },
117 { /* S-star */ 112 { /* S-star */
118 .pvr_mask = 0xffff0000, 113 .pvr_mask = 0xffff0000,
@@ -125,7 +120,6 @@ struct cpu_spec cpu_specs[] = {
125 .icache_bsize = 128, 120 .icache_bsize = 128,
126 .dcache_bsize = 128, 121 .dcache_bsize = 128,
127 .cpu_setup = __setup_cpu_power3, 122 .cpu_setup = __setup_cpu_power3,
128 .firmware_features = COMMON_PPC64_FW,
129 }, 123 },
130 { /* Power4 */ 124 { /* Power4 */
131 .pvr_mask = 0xffff0000, 125 .pvr_mask = 0xffff0000,
@@ -138,7 +132,6 @@ struct cpu_spec cpu_specs[] = {
138 .icache_bsize = 128, 132 .icache_bsize = 128,
139 .dcache_bsize = 128, 133 .dcache_bsize = 128,
140 .cpu_setup = __setup_cpu_power4, 134 .cpu_setup = __setup_cpu_power4,
141 .firmware_features = COMMON_PPC64_FW,
142 }, 135 },
143 { /* Power4+ */ 136 { /* Power4+ */
144 .pvr_mask = 0xffff0000, 137 .pvr_mask = 0xffff0000,
@@ -151,7 +144,6 @@ struct cpu_spec cpu_specs[] = {
151 .icache_bsize = 128, 144 .icache_bsize = 128,
152 .dcache_bsize = 128, 145 .dcache_bsize = 128,
153 .cpu_setup = __setup_cpu_power4, 146 .cpu_setup = __setup_cpu_power4,
154 .firmware_features = COMMON_PPC64_FW,
155 }, 147 },
156 { /* PPC970 */ 148 { /* PPC970 */
157 .pvr_mask = 0xffff0000, 149 .pvr_mask = 0xffff0000,
@@ -166,7 +158,6 @@ struct cpu_spec cpu_specs[] = {
166 .icache_bsize = 128, 158 .icache_bsize = 128,
167 .dcache_bsize = 128, 159 .dcache_bsize = 128,
168 .cpu_setup = __setup_cpu_ppc970, 160 .cpu_setup = __setup_cpu_ppc970,
169 .firmware_features = COMMON_PPC64_FW,
170 }, 161 },
171 { /* PPC970FX */ 162 { /* PPC970FX */
172 .pvr_mask = 0xffff0000, 163 .pvr_mask = 0xffff0000,
@@ -181,7 +172,6 @@ struct cpu_spec cpu_specs[] = {
181 .icache_bsize = 128, 172 .icache_bsize = 128,
182 .dcache_bsize = 128, 173 .dcache_bsize = 128,
183 .cpu_setup = __setup_cpu_ppc970, 174 .cpu_setup = __setup_cpu_ppc970,
184 .firmware_features = COMMON_PPC64_FW,
185 }, 175 },
186 { /* PPC970MP */ 176 { /* PPC970MP */
187 .pvr_mask = 0xffff0000, 177 .pvr_mask = 0xffff0000,
@@ -196,7 +186,6 @@ struct cpu_spec cpu_specs[] = {
196 .icache_bsize = 128, 186 .icache_bsize = 128,
197 .dcache_bsize = 128, 187 .dcache_bsize = 128,
198 .cpu_setup = __setup_cpu_ppc970, 188 .cpu_setup = __setup_cpu_ppc970,
199 .firmware_features = COMMON_PPC64_FW,
200 }, 189 },
201 { /* Power5 */ 190 { /* Power5 */
202 .pvr_mask = 0xffff0000, 191 .pvr_mask = 0xffff0000,
@@ -211,7 +200,6 @@ struct cpu_spec cpu_specs[] = {
211 .icache_bsize = 128, 200 .icache_bsize = 128,
212 .dcache_bsize = 128, 201 .dcache_bsize = 128,
213 .cpu_setup = __setup_cpu_power4, 202 .cpu_setup = __setup_cpu_power4,
214 .firmware_features = COMMON_PPC64_FW,
215 }, 203 },
216 { /* Power5 */ 204 { /* Power5 */
217 .pvr_mask = 0xffff0000, 205 .pvr_mask = 0xffff0000,
@@ -226,7 +214,6 @@ struct cpu_spec cpu_specs[] = {
226 .icache_bsize = 128, 214 .icache_bsize = 128,
227 .dcache_bsize = 128, 215 .dcache_bsize = 128,
228 .cpu_setup = __setup_cpu_power4, 216 .cpu_setup = __setup_cpu_power4,
229 .firmware_features = COMMON_PPC64_FW,
230 }, 217 },
231 { /* BE DD1.x */ 218 { /* BE DD1.x */
232 .pvr_mask = 0xffff0000, 219 .pvr_mask = 0xffff0000,
@@ -241,7 +228,6 @@ struct cpu_spec cpu_specs[] = {
241 .icache_bsize = 128, 228 .icache_bsize = 128,
242 .dcache_bsize = 128, 229 .dcache_bsize = 128,
243 .cpu_setup = __setup_cpu_be, 230 .cpu_setup = __setup_cpu_be,
244 .firmware_features = COMMON_PPC64_FW,
245 }, 231 },
246 { /* default match */ 232 { /* default match */
247 .pvr_mask = 0x00000000, 233 .pvr_mask = 0x00000000,
@@ -254,29 +240,5 @@ struct cpu_spec cpu_specs[] = {
254 .icache_bsize = 128, 240 .icache_bsize = 128,
255 .dcache_bsize = 128, 241 .dcache_bsize = 128,
256 .cpu_setup = __setup_cpu_power4, 242 .cpu_setup = __setup_cpu_power4,
257 .firmware_features = COMMON_PPC64_FW,
258 } 243 }
259}; 244};
260
261firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
262 {FW_FEATURE_PFT, "hcall-pft"},
263 {FW_FEATURE_TCE, "hcall-tce"},
264 {FW_FEATURE_SPRG0, "hcall-sprg0"},
265 {FW_FEATURE_DABR, "hcall-dabr"},
266 {FW_FEATURE_COPY, "hcall-copy"},
267 {FW_FEATURE_ASR, "hcall-asr"},
268 {FW_FEATURE_DEBUG, "hcall-debug"},
269 {FW_FEATURE_PERF, "hcall-perf"},
270 {FW_FEATURE_DUMP, "hcall-dump"},
271 {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
272 {FW_FEATURE_MIGRATE, "hcall-migrate"},
273 {FW_FEATURE_PERFMON, "hcall-perfmon"},
274 {FW_FEATURE_CRQ, "hcall-crq"},
275 {FW_FEATURE_VIO, "hcall-vio"},
276 {FW_FEATURE_RDMA, "hcall-rdma"},
277 {FW_FEATURE_LLAN, "hcall-lLAN"},
278 {FW_FEATURE_BULK, "hcall-bulk"},
279 {FW_FEATURE_XDABR, "hcall-xdabr"},
280 {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
281 {FW_FEATURE_SPLPAR, "hcall-splpar"},
282};
diff --git a/arch/ppc64/kernel/firmware.c b/arch/ppc64/kernel/firmware.c
new file mode 100644
index 000000000000..d8432c0fb27d
--- /dev/null
+++ b/arch/ppc64/kernel/firmware.c
@@ -0,0 +1,47 @@
1/*
2 * arch/ppc64/kernel/firmware.c
3 *
4 * Extracted from cputable.c
5 *
6 * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
7 *
8 * Modifications for ppc64:
9 * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com>
10 * Copyright (C) 2005 Stephen Rothwell, IBM Corporation
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#include <linux/config.h>
19
20#include <asm/firmware.h>
21
22unsigned long ppc64_firmware_features;
23
24#ifdef CONFIG_PPC_PSERIES
25firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = {
26 {FW_FEATURE_PFT, "hcall-pft"},
27 {FW_FEATURE_TCE, "hcall-tce"},
28 {FW_FEATURE_SPRG0, "hcall-sprg0"},
29 {FW_FEATURE_DABR, "hcall-dabr"},
30 {FW_FEATURE_COPY, "hcall-copy"},
31 {FW_FEATURE_ASR, "hcall-asr"},
32 {FW_FEATURE_DEBUG, "hcall-debug"},
33 {FW_FEATURE_PERF, "hcall-perf"},
34 {FW_FEATURE_DUMP, "hcall-dump"},
35 {FW_FEATURE_INTERRUPT, "hcall-interrupt"},
36 {FW_FEATURE_MIGRATE, "hcall-migrate"},
37 {FW_FEATURE_PERFMON, "hcall-perfmon"},
38 {FW_FEATURE_CRQ, "hcall-crq"},
39 {FW_FEATURE_VIO, "hcall-vio"},
40 {FW_FEATURE_RDMA, "hcall-rdma"},
41 {FW_FEATURE_LLAN, "hcall-lLAN"},
42 {FW_FEATURE_BULK, "hcall-bulk"},
43 {FW_FEATURE_XDABR, "hcall-xdabr"},
44 {FW_FEATURE_MULTITCE, "hcall-multi-tce"},
45 {FW_FEATURE_SPLPAR, "hcall-splpar"},
46};
47#endif
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index accaa052d31f..036959775623 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -23,14 +23,11 @@
23 * 2 of the License, or (at your option) any later version. 23 * 2 of the License, or (at your option) any later version.
24 */ 24 */
25 25
26#define SECONDARY_PROCESSORS
27
28#include <linux/config.h> 26#include <linux/config.h>
29#include <linux/threads.h> 27#include <linux/threads.h>
30#include <asm/processor.h> 28#include <asm/processor.h>
31#include <asm/page.h> 29#include <asm/page.h>
32#include <asm/mmu.h> 30#include <asm/mmu.h>
33#include <asm/naca.h>
34#include <asm/systemcfg.h> 31#include <asm/systemcfg.h>
35#include <asm/ppc_asm.h> 32#include <asm/ppc_asm.h>
36#include <asm/offsets.h> 33#include <asm/offsets.h>
@@ -45,18 +42,13 @@
45#endif 42#endif
46 43
47/* 44/*
48 * hcall interface to pSeries LPAR
49 */
50#define H_SET_ASR 0x30
51
52/*
53 * We layout physical memory as follows: 45 * We layout physical memory as follows:
54 * 0x0000 - 0x00ff : Secondary processor spin code 46 * 0x0000 - 0x00ff : Secondary processor spin code
55 * 0x0100 - 0x2fff : pSeries Interrupt prologs 47 * 0x0100 - 0x2fff : pSeries Interrupt prologs
56 * 0x3000 - 0x3fff : Interrupt support 48 * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs
57 * 0x4000 - 0x4fff : NACA 49 * 0x6000 - 0x6fff : Initial (CPU0) segment table
58 * 0x6000 : iSeries and common interrupt prologs 50 * 0x7000 - 0x7fff : FWNMI data area
59 * 0x9000 - 0x9fff : Initial segment table 51 * 0x8000 - : Early init and support code
60 */ 52 */
61 53
62/* 54/*
@@ -94,6 +86,7 @@ END_FTR_SECTION(0, 1)
94 86
95 /* Catch branch to 0 in real mode */ 87 /* Catch branch to 0 in real mode */
96 trap 88 trap
89
97#ifdef CONFIG_PPC_ISERIES 90#ifdef CONFIG_PPC_ISERIES
98 /* 91 /*
99 * At offset 0x20, there is a pointer to iSeries LPAR data. 92 * At offset 0x20, there is a pointer to iSeries LPAR data.
@@ -103,12 +96,12 @@ END_FTR_SECTION(0, 1)
103 .llong hvReleaseData-KERNELBASE 96 .llong hvReleaseData-KERNELBASE
104 97
105 /* 98 /*
106 * At offset 0x28 and 0x30 are offsets to the msChunks 99 * At offset 0x28 and 0x30 are offsets to the mschunks_map
107 * array (used by the iSeries LPAR debugger to do translation 100 * array (used by the iSeries LPAR debugger to do translation
108 * between physical addresses and absolute addresses) and 101 * between physical addresses and absolute addresses) and
109 * to the pidhash table (also used by the debugger) 102 * to the pidhash table (also used by the debugger)
110 */ 103 */
111 .llong msChunks-KERNELBASE 104 .llong mschunks_map-KERNELBASE
112 .llong 0 /* pidhash-KERNELBASE SFRXXX */ 105 .llong 0 /* pidhash-KERNELBASE SFRXXX */
113 106
114 /* Offset 0x38 - Pointer to start of embedded System.map */ 107 /* Offset 0x38 - Pointer to start of embedded System.map */
@@ -120,7 +113,7 @@ embedded_sysmap_start:
120embedded_sysmap_end: 113embedded_sysmap_end:
121 .llong 0 114 .llong 0
122 115
123#else /* CONFIG_PPC_ISERIES */ 116#endif /* CONFIG_PPC_ISERIES */
124 117
125 /* Secondary processors spin on this value until it goes to 1. */ 118 /* Secondary processors spin on this value until it goes to 1. */
126 .globl __secondary_hold_spinloop 119 .globl __secondary_hold_spinloop
@@ -155,7 +148,7 @@ _GLOBAL(__secondary_hold)
155 std r24,__secondary_hold_acknowledge@l(0) 148 std r24,__secondary_hold_acknowledge@l(0)
156 sync 149 sync
157 150
158 /* All secondary cpu's wait here until told to start. */ 151 /* All secondary cpus wait here until told to start. */
159100: ld r4,__secondary_hold_spinloop@l(0) 152100: ld r4,__secondary_hold_spinloop@l(0)
160 cmpdi 0,r4,1 153 cmpdi 0,r4,1
161 bne 100b 154 bne 100b
@@ -170,7 +163,6 @@ _GLOBAL(__secondary_hold)
170 BUG_OPCODE 163 BUG_OPCODE
171#endif 164#endif
172#endif 165#endif
173#endif
174 166
175/* This value is used to mark exception frames on the stack. */ 167/* This value is used to mark exception frames on the stack. */
176 .section ".toc","aw" 168 .section ".toc","aw"
@@ -502,33 +494,37 @@ system_call_pSeries:
502 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) 494 STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
503 STD_EXCEPTION_PSERIES(0x1700, altivec_assist) 495 STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
504 496
497 . = 0x3000
498
499/*** pSeries interrupt support ***/
500
505 /* moved from 0xf00 */ 501 /* moved from 0xf00 */
506 STD_EXCEPTION_PSERIES(0x3000, performance_monitor) 502 STD_EXCEPTION_PSERIES(., performance_monitor)
507 503
508 . = 0x3100 504 .align 7
509_GLOBAL(do_stab_bolted_pSeries) 505_GLOBAL(do_stab_bolted_pSeries)
510 mtcrf 0x80,r12 506 mtcrf 0x80,r12
511 mfspr r12,SPRG2 507 mfspr r12,SPRG2
512 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) 508 EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
513 509
514 510/*
515 /* Space for the naca. Architected to be located at real address 511 * Vectors for the FWNMI option. Share common code.
516 * NACA_PHYS_ADDR. Various tools rely on this location being fixed. 512 */
517 * The first dword of the naca is required by iSeries LPAR to 513 .globl system_reset_fwnmi
518 * point to itVpdAreas. On pSeries native, this value is not used. 514system_reset_fwnmi:
519 */ 515 HMT_MEDIUM
520 . = NACA_PHYS_ADDR 516 mtspr SPRG1,r13 /* save r13 */
521 .globl __end_interrupts 517 RUNLATCH_ON(r13)
522__end_interrupts: 518 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
523#ifdef CONFIG_PPC_ISERIES
524 .globl naca
525naca:
526 .llong itVpdAreas
527 .llong 0 /* xRamDisk */
528 .llong 0 /* xRamDiskSize */
529 519
530 . = 0x6100 520 .globl machine_check_fwnmi
521machine_check_fwnmi:
522 HMT_MEDIUM
523 mtspr SPRG1,r13 /* save r13 */
524 RUNLATCH_ON(r13)
525 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
531 526
527#ifdef CONFIG_PPC_ISERIES
532/*** ISeries-LPAR interrupt handlers ***/ 528/*** ISeries-LPAR interrupt handlers ***/
533 529
534 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) 530 STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC)
@@ -626,9 +622,7 @@ system_reset_iSeries:
626 622
627 cmpwi 0,r23,0 623 cmpwi 0,r23,0
628 beq iSeries_secondary_smp_loop /* Loop until told to go */ 624 beq iSeries_secondary_smp_loop /* Loop until told to go */
629#ifdef SECONDARY_PROCESSORS
630 bne .__secondary_start /* Loop until told to go */ 625 bne .__secondary_start /* Loop until told to go */
631#endif
632iSeries_secondary_smp_loop: 626iSeries_secondary_smp_loop:
633 /* Let the Hypervisor know we are alive */ 627 /* Let the Hypervisor know we are alive */
634 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ 628 /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */
@@ -671,51 +665,8 @@ hardware_interrupt_iSeries_masked:
671 ld r13,PACA_EXGEN+EX_R13(r13) 665 ld r13,PACA_EXGEN+EX_R13(r13)
672 rfid 666 rfid
673 b . /* prevent speculative execution */ 667 b . /* prevent speculative execution */
674#endif
675
676/*
677 * Data area reserved for FWNMI option.
678 */
679 .= 0x7000
680 .globl fwnmi_data_area
681fwnmi_data_area:
682
683#ifdef CONFIG_PPC_ISERIES
684 . = LPARMAP_PHYS
685#include "lparmap.s"
686#endif /* CONFIG_PPC_ISERIES */ 668#endif /* CONFIG_PPC_ISERIES */
687 669
688/*
689 * Vectors for the FWNMI option. Share common code.
690 */
691 . = 0x8000
692 .globl system_reset_fwnmi
693system_reset_fwnmi:
694 HMT_MEDIUM
695 mtspr SPRG1,r13 /* save r13 */
696 RUNLATCH_ON(r13)
697 EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
698 .globl machine_check_fwnmi
699machine_check_fwnmi:
700 HMT_MEDIUM
701 mtspr SPRG1,r13 /* save r13 */
702 RUNLATCH_ON(r13)
703 EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
704
705 /*
706 * Space for the initial segment table
707 * For LPAR, the hypervisor must fill in at least one entry
708 * before we get control (with relocate on)
709 */
710 . = STAB0_PHYS_ADDR
711 .globl __start_stab
712__start_stab:
713
714 . = (STAB0_PHYS_ADDR + PAGE_SIZE)
715 .globl __end_stab
716__end_stab:
717
718
719/*** Common interrupt handlers ***/ 670/*** Common interrupt handlers ***/
720 671
721 STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) 672 STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
@@ -752,8 +703,8 @@ machine_check_common:
752 * R9 contains the saved CR, r13 points to the paca, 703 * R9 contains the saved CR, r13 points to the paca,
753 * r10 contains the (bad) kernel stack pointer, 704 * r10 contains the (bad) kernel stack pointer,
754 * r11 and r12 contain the saved SRR0 and SRR1. 705 * r11 and r12 contain the saved SRR0 and SRR1.
755 * We switch to using the paca guard page as an emergency stack, 706 * We switch to using an emergency stack, save the registers there,
756 * save the registers there, and call kernel_bad_stack(), which panics. 707 * and call kernel_bad_stack(), which panics.
757 */ 708 */
758bad_stack: 709bad_stack:
759 ld r1,PACAEMERGSP(r13) 710 ld r1,PACAEMERGSP(r13)
@@ -906,6 +857,62 @@ fp_unavailable_common:
906 bl .kernel_fp_unavailable_exception 857 bl .kernel_fp_unavailable_exception
907 BUG_OPCODE 858 BUG_OPCODE
908 859
860/*
861 * load_up_fpu(unused, unused, tsk)
862 * Disable FP for the task which had the FPU previously,
863 * and save its floating-point registers in its thread_struct.
864 * Enables the FPU for use in the kernel on return.
865 * On SMP we know the fpu is free, since we give it up every
866 * switch (ie, no lazy save of the FP registers).
867 * On entry: r13 == 'current' && last_task_used_math != 'current'
868 */
869_STATIC(load_up_fpu)
870 mfmsr r5 /* grab the current MSR */
871 ori r5,r5,MSR_FP
872 mtmsrd r5 /* enable use of fpu now */
873 isync
874/*
875 * For SMP, we don't do lazy FPU switching because it just gets too
876 * horrendously complex, especially when a task switches from one CPU
877 * to another. Instead we call giveup_fpu in switch_to.
878 *
879 */
880#ifndef CONFIG_SMP
881 ld r3,last_task_used_math@got(r2)
882 ld r4,0(r3)
883 cmpdi 0,r4,0
884 beq 1f
885 /* Save FP state to last_task_used_math's THREAD struct */
886 addi r4,r4,THREAD
887 SAVE_32FPRS(0, r4)
888 mffs fr0
889 stfd fr0,THREAD_FPSCR(r4)
890 /* Disable FP for last_task_used_math */
891 ld r5,PT_REGS(r4)
892 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
893 li r6,MSR_FP|MSR_FE0|MSR_FE1
894 andc r4,r4,r6
895 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
8961:
897#endif /* CONFIG_SMP */
898 /* enable use of FP after return */
899 ld r4,PACACURRENT(r13)
900 addi r5,r4,THREAD /* Get THREAD */
901 ld r4,THREAD_FPEXC_MODE(r5)
902 ori r12,r12,MSR_FP
903 or r12,r12,r4
904 std r12,_MSR(r1)
905 lfd fr0,THREAD_FPSCR(r5)
906 mtfsf 0xff,fr0
907 REST_32FPRS(0, r5)
908#ifndef CONFIG_SMP
909 /* Update last_task_used_math to 'current' */
910 subi r4,r5,THREAD /* Back to 'current' */
911 std r4,0(r3)
912#endif /* CONFIG_SMP */
913 /* restore registers and return */
914 b fast_exception_return
915
909 .align 7 916 .align 7
910 .globl altivec_unavailable_common 917 .globl altivec_unavailable_common
911altivec_unavailable_common: 918altivec_unavailable_common:
@@ -921,6 +928,80 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
921 bl .altivec_unavailable_exception 928 bl .altivec_unavailable_exception
922 b .ret_from_except 929 b .ret_from_except
923 930
931#ifdef CONFIG_ALTIVEC
932/*
933 * load_up_altivec(unused, unused, tsk)
934 * Disable VMX for the task which had it previously,
935 * and save its vector registers in its thread_struct.
936 * Enables the VMX for use in the kernel on return.
937 * On SMP we know the VMX is free, since we give it up every
938 * switch (ie, no lazy save of the vector registers).
939 * On entry: r13 == 'current' && last_task_used_altivec != 'current'
940 */
941_STATIC(load_up_altivec)
942 mfmsr r5 /* grab the current MSR */
943 oris r5,r5,MSR_VEC@h
944 mtmsrd r5 /* enable use of VMX now */
945 isync
946
947/*
948 * For SMP, we don't do lazy VMX switching because it just gets too
949 * horrendously complex, especially when a task switches from one CPU
950 * to another. Instead we call giveup_altvec in switch_to.
951 * VRSAVE isn't dealt with here, that is done in the normal context
952 * switch code. Note that we could rely on vrsave value to eventually
953 * avoid saving all of the VREGs here...
954 */
955#ifndef CONFIG_SMP
956 ld r3,last_task_used_altivec@got(r2)
957 ld r4,0(r3)
958 cmpdi 0,r4,0
959 beq 1f
960 /* Save VMX state to last_task_used_altivec's THREAD struct */
961 addi r4,r4,THREAD
962 SAVE_32VRS(0,r5,r4)
963 mfvscr vr0
964 li r10,THREAD_VSCR
965 stvx vr0,r10,r4
966 /* Disable VMX for last_task_used_altivec */
967 ld r5,PT_REGS(r4)
968 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
969 lis r6,MSR_VEC@h
970 andc r4,r4,r6
971 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
9721:
973#endif /* CONFIG_SMP */
974 /* Hack: if we get an altivec unavailable trap with VRSAVE
975 * set to all zeros, we assume this is a broken application
976 * that fails to set it properly, and thus we switch it to
977 * all 1's
978 */
979 mfspr r4,SPRN_VRSAVE
980 cmpdi 0,r4,0
981 bne+ 1f
982 li r4,-1
983 mtspr SPRN_VRSAVE,r4
9841:
985 /* enable use of VMX after return */
986 ld r4,PACACURRENT(r13)
987 addi r5,r4,THREAD /* Get THREAD */
988 oris r12,r12,MSR_VEC@h
989 std r12,_MSR(r1)
990 li r4,1
991 li r10,THREAD_VSCR
992 stw r4,THREAD_USED_VR(r5)
993 lvx vr0,r10,r5
994 mtvscr vr0
995 REST_32VRS(0,r4,r5)
996#ifndef CONFIG_SMP
997 /* Update last_task_used_math to 'current' */
998 subi r4,r5,THREAD /* Back to 'current' */
999 std r4,0(r3)
1000#endif /* CONFIG_SMP */
1001 /* restore registers and return */
1002 b fast_exception_return
1003#endif /* CONFIG_ALTIVEC */
1004
924/* 1005/*
925 * Hash table stuff 1006 * Hash table stuff
926 */ 1007 */
@@ -1167,6 +1248,42 @@ unrecov_slb:
1167 bl .unrecoverable_exception 1248 bl .unrecoverable_exception
1168 b 1b 1249 b 1b
1169 1250
1251/*
1252 * Space for CPU0's segment table.
1253 *
1254 * On iSeries, the hypervisor must fill in at least one entry before
1255 * we get control (with relocate on). The address is give to the hv
1256 * as a page number (see xLparMap in LparData.c), so this must be at a
1257 * fixed address (the linker can't compute (u64)&initial_stab >>
1258 * PAGE_SHIFT).
1259 */
1260 . = STAB0_PHYS_ADDR /* 0x6000 */
1261 .globl initial_stab
1262initial_stab:
1263 .space 4096
1264
1265/*
1266 * Data area reserved for FWNMI option.
1267 * This address (0x7000) is fixed by the RPA.
1268 */
1269 .= 0x7000
1270 .globl fwnmi_data_area
1271fwnmi_data_area:
1272
1273 /* iSeries does not use the FWNMI stuff, so it is safe to put
1274 * this here, even if we later allow kernels that will boot on
1275 * both pSeries and iSeries */
1276#ifdef CONFIG_PPC_ISERIES
1277 . = LPARMAP_PHYS
1278#include "lparmap.s"
1279/*
1280 * This ".text" is here for old compilers that generate a trailing
1281 * .note section when compiling .c files to .s
1282 */
1283 .text
1284#endif /* CONFIG_PPC_ISERIES */
1285
1286 . = 0x8000
1170 1287
1171/* 1288/*
1172 * On pSeries, secondary processors spin in the following code. 1289 * On pSeries, secondary processors spin in the following code.
@@ -1200,7 +1317,7 @@ _GLOBAL(pSeries_secondary_smp_init)
1200 b .kexec_wait /* next kernel might do better */ 1317 b .kexec_wait /* next kernel might do better */
1201 1318
12022: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ 13192: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
1203 /* From now on, r24 is expected to be logica cpuid */ 1320 /* From now on, r24 is expected to be logical cpuid */
1204 mr r24,r5 1321 mr r24,r5
12053: HMT_LOW 13223: HMT_LOW
1206 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ 1323 lbz r23,PACAPROCSTART(r13) /* Test if this processor should */
@@ -1213,10 +1330,8 @@ _GLOBAL(pSeries_secondary_smp_init)
1213 1330
1214 cmpwi 0,r23,0 1331 cmpwi 0,r23,0
1215#ifdef CONFIG_SMP 1332#ifdef CONFIG_SMP
1216#ifdef SECONDARY_PROCESSORS
1217 bne .__secondary_start 1333 bne .__secondary_start
1218#endif 1334#endif
1219#endif
1220 b 3b /* Loop until told to go */ 1335 b 3b /* Loop until told to go */
1221 1336
1222#ifdef CONFIG_PPC_ISERIES 1337#ifdef CONFIG_PPC_ISERIES
@@ -1430,228 +1545,6 @@ _GLOBAL(copy_and_flush)
1430.align 8 1545.align 8
1431copy_to_here: 1546copy_to_here:
1432 1547
1433/*
1434 * load_up_fpu(unused, unused, tsk)
1435 * Disable FP for the task which had the FPU previously,
1436 * and save its floating-point registers in its thread_struct.
1437 * Enables the FPU for use in the kernel on return.
1438 * On SMP we know the fpu is free, since we give it up every
1439 * switch (ie, no lazy save of the FP registers).
1440 * On entry: r13 == 'current' && last_task_used_math != 'current'
1441 */
1442_STATIC(load_up_fpu)
1443 mfmsr r5 /* grab the current MSR */
1444 ori r5,r5,MSR_FP
1445 mtmsrd r5 /* enable use of fpu now */
1446 isync
1447/*
1448 * For SMP, we don't do lazy FPU switching because it just gets too
1449 * horrendously complex, especially when a task switches from one CPU
1450 * to another. Instead we call giveup_fpu in switch_to.
1451 *
1452 */
1453#ifndef CONFIG_SMP
1454 ld r3,last_task_used_math@got(r2)
1455 ld r4,0(r3)
1456 cmpdi 0,r4,0
1457 beq 1f
1458 /* Save FP state to last_task_used_math's THREAD struct */
1459 addi r4,r4,THREAD
1460 SAVE_32FPRS(0, r4)
1461 mffs fr0
1462 stfd fr0,THREAD_FPSCR(r4)
1463 /* Disable FP for last_task_used_math */
1464 ld r5,PT_REGS(r4)
1465 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1466 li r6,MSR_FP|MSR_FE0|MSR_FE1
1467 andc r4,r4,r6
1468 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
14691:
1470#endif /* CONFIG_SMP */
1471 /* enable use of FP after return */
1472 ld r4,PACACURRENT(r13)
1473 addi r5,r4,THREAD /* Get THREAD */
1474 ld r4,THREAD_FPEXC_MODE(r5)
1475 ori r12,r12,MSR_FP
1476 or r12,r12,r4
1477 std r12,_MSR(r1)
1478 lfd fr0,THREAD_FPSCR(r5)
1479 mtfsf 0xff,fr0
1480 REST_32FPRS(0, r5)
1481#ifndef CONFIG_SMP
1482 /* Update last_task_used_math to 'current' */
1483 subi r4,r5,THREAD /* Back to 'current' */
1484 std r4,0(r3)
1485#endif /* CONFIG_SMP */
1486 /* restore registers and return */
1487 b fast_exception_return
1488
1489/*
1490 * disable_kernel_fp()
1491 * Disable the FPU.
1492 */
1493_GLOBAL(disable_kernel_fp)
1494 mfmsr r3
1495 rldicl r0,r3,(63-MSR_FP_LG),1
1496 rldicl r3,r0,(MSR_FP_LG+1),0
1497 mtmsrd r3 /* disable use of fpu now */
1498 isync
1499 blr
1500
1501/*
1502 * giveup_fpu(tsk)
1503 * Disable FP for the task given as the argument,
1504 * and save the floating-point registers in its thread_struct.
1505 * Enables the FPU for use in the kernel on return.
1506 */
1507_GLOBAL(giveup_fpu)
1508 mfmsr r5
1509 ori r5,r5,MSR_FP
1510 mtmsrd r5 /* enable use of fpu now */
1511 isync
1512 cmpdi 0,r3,0
1513 beqlr- /* if no previous owner, done */
1514 addi r3,r3,THREAD /* want THREAD of task */
1515 ld r5,PT_REGS(r3)
1516 cmpdi 0,r5,0
1517 SAVE_32FPRS(0, r3)
1518 mffs fr0
1519 stfd fr0,THREAD_FPSCR(r3)
1520 beq 1f
1521 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1522 li r3,MSR_FP|MSR_FE0|MSR_FE1
1523 andc r4,r4,r3 /* disable FP for previous task */
1524 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
15251:
1526#ifndef CONFIG_SMP
1527 li r5,0
1528 ld r4,last_task_used_math@got(r2)
1529 std r5,0(r4)
1530#endif /* CONFIG_SMP */
1531 blr
1532
1533
1534#ifdef CONFIG_ALTIVEC
1535
1536/*
1537 * load_up_altivec(unused, unused, tsk)
1538 * Disable VMX for the task which had it previously,
1539 * and save its vector registers in its thread_struct.
1540 * Enables the VMX for use in the kernel on return.
1541 * On SMP we know the VMX is free, since we give it up every
1542 * switch (ie, no lazy save of the vector registers).
1543 * On entry: r13 == 'current' && last_task_used_altivec != 'current'
1544 */
1545_STATIC(load_up_altivec)
1546 mfmsr r5 /* grab the current MSR */
1547 oris r5,r5,MSR_VEC@h
1548 mtmsrd r5 /* enable use of VMX now */
1549 isync
1550
1551/*
1552 * For SMP, we don't do lazy VMX switching because it just gets too
1553 * horrendously complex, especially when a task switches from one CPU
1554 * to another. Instead we call giveup_altvec in switch_to.
1555 * VRSAVE isn't dealt with here, that is done in the normal context
1556 * switch code. Note that we could rely on vrsave value to eventually
1557 * avoid saving all of the VREGs here...
1558 */
1559#ifndef CONFIG_SMP
1560 ld r3,last_task_used_altivec@got(r2)
1561 ld r4,0(r3)
1562 cmpdi 0,r4,0
1563 beq 1f
1564 /* Save VMX state to last_task_used_altivec's THREAD struct */
1565 addi r4,r4,THREAD
1566 SAVE_32VRS(0,r5,r4)
1567 mfvscr vr0
1568 li r10,THREAD_VSCR
1569 stvx vr0,r10,r4
1570 /* Disable VMX for last_task_used_altivec */
1571 ld r5,PT_REGS(r4)
1572 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1573 lis r6,MSR_VEC@h
1574 andc r4,r4,r6
1575 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
15761:
1577#endif /* CONFIG_SMP */
1578 /* Hack: if we get an altivec unavailable trap with VRSAVE
1579 * set to all zeros, we assume this is a broken application
1580 * that fails to set it properly, and thus we switch it to
1581 * all 1's
1582 */
1583 mfspr r4,SPRN_VRSAVE
1584 cmpdi 0,r4,0
1585 bne+ 1f
1586 li r4,-1
1587 mtspr SPRN_VRSAVE,r4
15881:
1589 /* enable use of VMX after return */
1590 ld r4,PACACURRENT(r13)
1591 addi r5,r4,THREAD /* Get THREAD */
1592 oris r12,r12,MSR_VEC@h
1593 std r12,_MSR(r1)
1594 li r4,1
1595 li r10,THREAD_VSCR
1596 stw r4,THREAD_USED_VR(r5)
1597 lvx vr0,r10,r5
1598 mtvscr vr0
1599 REST_32VRS(0,r4,r5)
1600#ifndef CONFIG_SMP
1601 /* Update last_task_used_math to 'current' */
1602 subi r4,r5,THREAD /* Back to 'current' */
1603 std r4,0(r3)
1604#endif /* CONFIG_SMP */
1605 /* restore registers and return */
1606 b fast_exception_return
1607
1608/*
1609 * disable_kernel_altivec()
1610 * Disable the VMX.
1611 */
1612_GLOBAL(disable_kernel_altivec)
1613 mfmsr r3
1614 rldicl r0,r3,(63-MSR_VEC_LG),1
1615 rldicl r3,r0,(MSR_VEC_LG+1),0
1616 mtmsrd r3 /* disable use of VMX now */
1617 isync
1618 blr
1619
1620/*
1621 * giveup_altivec(tsk)
1622 * Disable VMX for the task given as the argument,
1623 * and save the vector registers in its thread_struct.
1624 * Enables the VMX for use in the kernel on return.
1625 */
1626_GLOBAL(giveup_altivec)
1627 mfmsr r5
1628 oris r5,r5,MSR_VEC@h
1629 mtmsrd r5 /* enable use of VMX now */
1630 isync
1631 cmpdi 0,r3,0
1632 beqlr- /* if no previous owner, done */
1633 addi r3,r3,THREAD /* want THREAD of task */
1634 ld r5,PT_REGS(r3)
1635 cmpdi 0,r5,0
1636 SAVE_32VRS(0,r4,r3)
1637 mfvscr vr0
1638 li r4,THREAD_VSCR
1639 stvx vr0,r4,r3
1640 beq 1f
1641 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
1642 lis r3,MSR_VEC@h
1643 andc r4,r4,r3 /* disable FP for previous task */
1644 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
16451:
1646#ifndef CONFIG_SMP
1647 li r5,0
1648 ld r4,last_task_used_altivec@got(r2)
1649 std r5,0(r4)
1650#endif /* CONFIG_SMP */
1651 blr
1652
1653#endif /* CONFIG_ALTIVEC */
1654
1655#ifdef CONFIG_SMP 1548#ifdef CONFIG_SMP
1656#ifdef CONFIG_PPC_PMAC 1549#ifdef CONFIG_PPC_PMAC
1657/* 1550/*
@@ -2002,9 +1895,6 @@ _STATIC(start_here_common)
2002 1895
2003 bl .start_kernel 1896 bl .start_kernel
2004 1897
2005_GLOBAL(__setup_cpu_power3)
2006 blr
2007
2008_GLOBAL(hmt_init) 1898_GLOBAL(hmt_init)
2009#ifdef CONFIG_HMT 1899#ifdef CONFIG_HMT
2010 LOADADDR(r5, hmt_thread_data) 1900 LOADADDR(r5, hmt_thread_data)
@@ -2095,20 +1985,19 @@ _GLOBAL(smp_release_cpus)
2095 1985
2096/* 1986/*
2097 * We put a few things here that have to be page-aligned. 1987 * We put a few things here that have to be page-aligned.
2098 * This stuff goes at the beginning of the data segment, 1988 * This stuff goes at the beginning of the bss, which is page-aligned.
2099 * which is page-aligned.
2100 */ 1989 */
2101 .data 1990 .section ".bss"
1991
2102 .align 12 1992 .align 12
2103 .globl sdata 1993
2104sdata:
2105 .globl empty_zero_page 1994 .globl empty_zero_page
2106empty_zero_page: 1995empty_zero_page:
2107 .space 4096 1996 .space PAGE_SIZE
2108 1997
2109 .globl swapper_pg_dir 1998 .globl swapper_pg_dir
2110swapper_pg_dir: 1999swapper_pg_dir:
2111 .space 4096 2000 .space PAGE_SIZE
2112 2001
2113/* 2002/*
2114 * This space gets a copy of optional info passed to us by the bootstrap 2003 * This space gets a copy of optional info passed to us by the bootstrap
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index b0250ae4a72a..2192055a90a0 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -41,6 +41,7 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
41 unsigned long prpn, unsigned long vflags, 41 unsigned long prpn, unsigned long vflags,
42 unsigned long rflags) 42 unsigned long rflags)
43{ 43{
44 unsigned long arpn;
44 long slot; 45 long slot;
45 hpte_t lhpte; 46 hpte_t lhpte;
46 int secondary = 0; 47 int secondary = 0;
@@ -70,8 +71,10 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
70 slot &= 0x7fffffffffffffff; 71 slot &= 0x7fffffffffffffff;
71 } 72 }
72 73
74 arpn = phys_to_abs(prpn << PAGE_SHIFT) >> PAGE_SHIFT;
75
73 lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; 76 lhpte.v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
74 lhpte.r = (physRpn_to_absRpn(prpn) << HPTE_R_RPN_SHIFT) | rflags; 77 lhpte.r = (arpn << HPTE_R_RPN_SHIFT) | rflags;
75 78
76 /* Now fill in the actual HPTE */ 79 /* Now fill in the actual HPTE */
77 HvCallHpt_addValidate(slot, secondary, &lhpte); 80 HvCallHpt_addValidate(slot, secondary, &lhpte);
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index a649edbb23b6..3ffefbbc6623 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -39,6 +39,7 @@
39#include <asm/cputable.h> 39#include <asm/cputable.h>
40#include <asm/sections.h> 40#include <asm/sections.h>
41#include <asm/iommu.h> 41#include <asm/iommu.h>
42#include <asm/firmware.h>
42 43
43#include <asm/time.h> 44#include <asm/time.h>
44#include "iSeries_setup.h" 45#include "iSeries_setup.h"
@@ -314,6 +315,8 @@ static void __init iSeries_init_early(void)
314 315
315 DBG(" -> iSeries_init_early()\n"); 316 DBG(" -> iSeries_init_early()\n");
316 317
318 ppc64_firmware_features = FW_FEATURE_ISERIES;
319
317 ppcdbg_initialize(); 320 ppcdbg_initialize();
318 321
319#if defined(CONFIG_BLK_DEV_INITRD) 322#if defined(CONFIG_BLK_DEV_INITRD)
@@ -412,6 +415,22 @@ static void __init iSeries_init_early(void)
412 DBG(" <- iSeries_init_early()\n"); 415 DBG(" <- iSeries_init_early()\n");
413} 416}
414 417
418struct mschunks_map mschunks_map = {
419 /* XXX We don't use these, but Piranha might need them. */
420 .chunk_size = MSCHUNKS_CHUNK_SIZE,
421 .chunk_shift = MSCHUNKS_CHUNK_SHIFT,
422 .chunk_mask = MSCHUNKS_OFFSET_MASK,
423};
424EXPORT_SYMBOL(mschunks_map);
425
426void mschunks_alloc(unsigned long num_chunks)
427{
428 klimit = _ALIGN(klimit, sizeof(u32));
429 mschunks_map.mapping = (u32 *)klimit;
430 klimit += num_chunks * sizeof(u32);
431 mschunks_map.num_chunks = num_chunks;
432}
433
415/* 434/*
416 * The iSeries may have very large memories ( > 128 GB ) and a partition 435 * The iSeries may have very large memories ( > 128 GB ) and a partition
417 * may get memory in "chunks" that may be anywhere in the 2**52 real 436 * may get memory in "chunks" that may be anywhere in the 2**52 real
@@ -449,7 +468,7 @@ static void __init build_iSeries_Memory_Map(void)
449 468
450 /* Chunk size on iSeries is 256K bytes */ 469 /* Chunk size on iSeries is 256K bytes */
451 totalChunks = (u32)HvLpConfig_getMsChunks(); 470 totalChunks = (u32)HvLpConfig_getMsChunks();
452 klimit = msChunks_alloc(klimit, totalChunks, 1UL << 18); 471 mschunks_alloc(totalChunks);
453 472
454 /* 473 /*
455 * Get absolute address of our load area 474 * Get absolute address of our load area
@@ -486,7 +505,7 @@ static void __init build_iSeries_Memory_Map(void)
486 printk("Load area size %dK\n", loadAreaSize * 256); 505 printk("Load area size %dK\n", loadAreaSize * 256);
487 506
488 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk) 507 for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk)
489 msChunks.abs[nextPhysChunk] = 508 mschunks_map.mapping[nextPhysChunk] =
490 loadAreaFirstChunk + nextPhysChunk; 509 loadAreaFirstChunk + nextPhysChunk;
491 510
492 /* 511 /*
@@ -495,7 +514,7 @@ static void __init build_iSeries_Memory_Map(void)
495 */ 514 */
496 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress()); 515 hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress());
497 hptSizePages = (u32)HvCallHpt_getHptPages(); 516 hptSizePages = (u32)HvCallHpt_getHptPages();
498 hptSizeChunks = hptSizePages >> (msChunks.chunk_shift - PAGE_SHIFT); 517 hptSizeChunks = hptSizePages >> (MSCHUNKS_CHUNK_SHIFT - PAGE_SHIFT);
499 hptLastChunk = hptFirstChunk + hptSizeChunks - 1; 518 hptLastChunk = hptFirstChunk + hptSizeChunks - 1;
500 519
501 printk("HPT absolute addr = %016lx, size = %dK\n", 520 printk("HPT absolute addr = %016lx, size = %dK\n",
@@ -552,7 +571,8 @@ static void __init build_iSeries_Memory_Map(void)
552 (absChunk > hptLastChunk)) && 571 (absChunk > hptLastChunk)) &&
553 ((absChunk < loadAreaFirstChunk) || 572 ((absChunk < loadAreaFirstChunk) ||
554 (absChunk > loadAreaLastChunk))) { 573 (absChunk > loadAreaLastChunk))) {
555 msChunks.abs[nextPhysChunk] = absChunk; 574 mschunks_map.mapping[nextPhysChunk] =
575 absChunk;
556 ++nextPhysChunk; 576 ++nextPhysChunk;
557 } 577 }
558 } 578 }
@@ -944,6 +964,8 @@ void __init iSeries_early_setup(void)
944 ppc_md.calibrate_decr = iSeries_calibrate_decr; 964 ppc_md.calibrate_decr = iSeries_calibrate_decr;
945 ppc_md.progress = iSeries_progress; 965 ppc_md.progress = iSeries_progress;
946 966
967 /* XXX Implement enable_pmcs for iSeries */
968
947 if (get_paca()->lppaca.shared_proc) { 969 if (get_paca()->lppaca.shared_proc) {
948 ppc_md.idle_loop = iseries_shared_idle; 970 ppc_md.idle_loop = iseries_shared_idle;
949 printk(KERN_INFO "Using shared processor idle loop\n"); 971 printk(KERN_INFO "Using shared processor idle loop\n");
diff --git a/arch/ppc64/kernel/iSeries_vio.c b/arch/ppc64/kernel/iSeries_vio.c
new file mode 100644
index 000000000000..6b754b0c8344
--- /dev/null
+++ b/arch/ppc64/kernel/iSeries_vio.c
@@ -0,0 +1,155 @@
1/*
2 * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2005 Stephen Rothwell, IBM Corp.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <linux/types.h>
12#include <linux/device.h>
13#include <linux/init.h>
14
15#include <asm/vio.h>
16#include <asm/iommu.h>
17#include <asm/abs_addr.h>
18#include <asm/page.h>
19#include <asm/iSeries/vio.h>
20#include <asm/iSeries/HvTypes.h>
21#include <asm/iSeries/HvLpConfig.h>
22#include <asm/iSeries/HvCallXm.h>
23
24struct device *iSeries_vio_dev = &vio_bus_device.dev;
25EXPORT_SYMBOL(iSeries_vio_dev);
26
27static struct iommu_table veth_iommu_table;
28static struct iommu_table vio_iommu_table;
29
30static void __init iommu_vio_init(void)
31{
32 struct iommu_table *t;
33 struct iommu_table_cb cb;
34 unsigned long cbp;
35 unsigned long itc_entries;
36
37 cb.itc_busno = 255; /* Bus 255 is the virtual bus */
38 cb.itc_virtbus = 0xff; /* Ask for virtual bus */
39
40 cbp = virt_to_abs(&cb);
41 HvCallXm_getTceTableParms(cbp);
42
43 itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
44 veth_iommu_table.it_size = itc_entries / 2;
45 veth_iommu_table.it_busno = cb.itc_busno;
46 veth_iommu_table.it_offset = cb.itc_offset;
47 veth_iommu_table.it_index = cb.itc_index;
48 veth_iommu_table.it_type = TCE_VB;
49 veth_iommu_table.it_blocksize = 1;
50
51 t = iommu_init_table(&veth_iommu_table);
52
53 if (!t)
54 printk("Virtual Bus VETH TCE table failed.\n");
55
56 vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
57 vio_iommu_table.it_busno = cb.itc_busno;
58 vio_iommu_table.it_offset = cb.itc_offset +
59 veth_iommu_table.it_size;
60 vio_iommu_table.it_index = cb.itc_index;
61 vio_iommu_table.it_type = TCE_VB;
62 vio_iommu_table.it_blocksize = 1;
63
64 t = iommu_init_table(&vio_iommu_table);
65
66 if (!t)
67 printk("Virtual Bus VIO TCE table failed.\n");
68}
69
70/**
71 * vio_register_device_iseries: - Register a new iSeries vio device.
72 * @voidev: The device to register.
73 */
74static struct vio_dev *__init vio_register_device_iseries(char *type,
75 uint32_t unit_num)
76{
77 struct vio_dev *viodev;
78
79 /* allocate a vio_dev for this device */
80 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
81 if (!viodev)
82 return NULL;
83 memset(viodev, 0, sizeof(struct vio_dev));
84
85 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
86
87 viodev->name = viodev->dev.bus_id;
88 viodev->type = type;
89 viodev->unit_address = unit_num;
90 viodev->iommu_table = &vio_iommu_table;
91 if (vio_register_device(viodev) == NULL) {
92 kfree(viodev);
93 return NULL;
94 }
95 return viodev;
96}
97
98void __init probe_bus_iseries(void)
99{
100 HvLpIndexMap vlan_map;
101 struct vio_dev *viodev;
102 int i;
103
104 /* there is only one of each of these */
105 vio_register_device_iseries("viocons", 0);
106 vio_register_device_iseries("vscsi", 0);
107
108 vlan_map = HvLpConfig_getVirtualLanIndexMap();
109 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
110 if ((vlan_map & (0x8000 >> i)) == 0)
111 continue;
112 viodev = vio_register_device_iseries("vlan", i);
113 /* veth is special and has it own iommu_table */
114 viodev->iommu_table = &veth_iommu_table;
115 }
116 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
117 vio_register_device_iseries("viodasd", i);
118 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
119 vio_register_device_iseries("viocd", i);
120 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
121 vio_register_device_iseries("viotape", i);
122}
123
124/**
125 * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
126 * vio_device_id
127 */
128static int vio_match_device_iseries(const struct vio_device_id *id,
129 const struct vio_dev *dev)
130{
131 return strncmp(dev->type, id->type, strlen(id->type)) == 0;
132}
133
134static struct vio_bus_ops vio_bus_ops_iseries = {
135 .match = vio_match_device_iseries,
136};
137
138/**
139 * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
140 */
141static int __init vio_bus_init_iseries(void)
142{
143 int err;
144
145 err = vio_bus_init(&vio_bus_ops_iseries);
146 if (err == 0) {
147 iommu_vio_init();
148 vio_bus_device.iommu_table = &vio_iommu_table;
149 iSeries_vio_dev = &vio_bus_device.dev;
150 probe_bus_iseries();
151 }
152 return err;
153}
154
155__initcall(vio_bus_init_iseries);
diff --git a/arch/ppc64/kernel/lmb.c b/arch/ppc64/kernel/lmb.c
index d6c6bd03d2a4..5adaca2ddc9d 100644
--- a/arch/ppc64/kernel/lmb.c
+++ b/arch/ppc64/kernel/lmb.c
@@ -28,33 +28,28 @@ void lmb_dump_all(void)
28{ 28{
29#ifdef DEBUG 29#ifdef DEBUG
30 unsigned long i; 30 unsigned long i;
31 struct lmb *_lmb = &lmb;
32 31
33 udbg_printf("lmb_dump_all:\n"); 32 udbg_printf("lmb_dump_all:\n");
34 udbg_printf(" memory.cnt = 0x%lx\n", 33 udbg_printf(" memory.cnt = 0x%lx\n",
35 _lmb->memory.cnt); 34 lmb.memory.cnt);
36 udbg_printf(" memory.size = 0x%lx\n", 35 udbg_printf(" memory.size = 0x%lx\n",
37 _lmb->memory.size); 36 lmb.memory.size);
38 for (i=0; i < _lmb->memory.cnt ;i++) { 37 for (i=0; i < lmb.memory.cnt ;i++) {
39 udbg_printf(" memory.region[0x%x].base = 0x%lx\n", 38 udbg_printf(" memory.region[0x%x].base = 0x%lx\n",
40 i, _lmb->memory.region[i].base); 39 i, lmb.memory.region[i].base);
41 udbg_printf(" .physbase = 0x%lx\n",
42 _lmb->memory.region[i].physbase);
43 udbg_printf(" .size = 0x%lx\n", 40 udbg_printf(" .size = 0x%lx\n",
44 _lmb->memory.region[i].size); 41 lmb.memory.region[i].size);
45 } 42 }
46 43
47 udbg_printf("\n reserved.cnt = 0x%lx\n", 44 udbg_printf("\n reserved.cnt = 0x%lx\n",
48 _lmb->reserved.cnt); 45 lmb.reserved.cnt);
49 udbg_printf(" reserved.size = 0x%lx\n", 46 udbg_printf(" reserved.size = 0x%lx\n",
50 _lmb->reserved.size); 47 lmb.reserved.size);
51 for (i=0; i < _lmb->reserved.cnt ;i++) { 48 for (i=0; i < lmb.reserved.cnt ;i++) {
52 udbg_printf(" reserved.region[0x%x].base = 0x%lx\n", 49 udbg_printf(" reserved.region[0x%x].base = 0x%lx\n",
53 i, _lmb->reserved.region[i].base); 50 i, lmb.reserved.region[i].base);
54 udbg_printf(" .physbase = 0x%lx\n",
55 _lmb->reserved.region[i].physbase);
56 udbg_printf(" .size = 0x%lx\n", 51 udbg_printf(" .size = 0x%lx\n",
57 _lmb->reserved.region[i].size); 52 lmb.reserved.region[i].size);
58 } 53 }
59#endif /* DEBUG */ 54#endif /* DEBUG */
60} 55}
@@ -98,7 +93,6 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
98 rgn->region[r1].size += rgn->region[r2].size; 93 rgn->region[r1].size += rgn->region[r2].size;
99 for (i=r2; i < rgn->cnt-1; i++) { 94 for (i=r2; i < rgn->cnt-1; i++) {
100 rgn->region[i].base = rgn->region[i+1].base; 95 rgn->region[i].base = rgn->region[i+1].base;
101 rgn->region[i].physbase = rgn->region[i+1].physbase;
102 rgn->region[i].size = rgn->region[i+1].size; 96 rgn->region[i].size = rgn->region[i+1].size;
103 } 97 }
104 rgn->cnt--; 98 rgn->cnt--;
@@ -108,49 +102,29 @@ lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, unsigned long r2)
108void __init 102void __init
109lmb_init(void) 103lmb_init(void)
110{ 104{
111 struct lmb *_lmb = &lmb;
112
113 /* Create a dummy zero size LMB which will get coalesced away later. 105 /* Create a dummy zero size LMB which will get coalesced away later.
114 * This simplifies the lmb_add() code below... 106 * This simplifies the lmb_add() code below...
115 */ 107 */
116 _lmb->memory.region[0].base = 0; 108 lmb.memory.region[0].base = 0;
117 _lmb->memory.region[0].size = 0; 109 lmb.memory.region[0].size = 0;
118 _lmb->memory.cnt = 1; 110 lmb.memory.cnt = 1;
119 111
120 /* Ditto. */ 112 /* Ditto. */
121 _lmb->reserved.region[0].base = 0; 113 lmb.reserved.region[0].base = 0;
122 _lmb->reserved.region[0].size = 0; 114 lmb.reserved.region[0].size = 0;
123 _lmb->reserved.cnt = 1; 115 lmb.reserved.cnt = 1;
124} 116}
125 117
126/* This routine called with relocation disabled. */ 118/* This routine called with relocation disabled. */
127void __init 119void __init
128lmb_analyze(void) 120lmb_analyze(void)
129{ 121{
130 unsigned long i; 122 int i;
131 unsigned long mem_size = 0; 123
132 unsigned long size_mask = 0; 124 lmb.memory.size = 0;
133 struct lmb *_lmb = &lmb;
134#ifdef CONFIG_MSCHUNKS
135 unsigned long physbase = 0;
136#endif
137
138 for (i=0; i < _lmb->memory.cnt; i++) {
139 unsigned long lmb_size;
140
141 lmb_size = _lmb->memory.region[i].size;
142
143#ifdef CONFIG_MSCHUNKS
144 _lmb->memory.region[i].physbase = physbase;
145 physbase += lmb_size;
146#else
147 _lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
148#endif
149 mem_size += lmb_size;
150 size_mask |= lmb_size;
151 }
152 125
153 _lmb->memory.size = mem_size; 126 for (i = 0; i < lmb.memory.cnt; i++)
127 lmb.memory.size += lmb.memory.region[i].size;
154} 128}
155 129
156/* This routine called with relocation disabled. */ 130/* This routine called with relocation disabled. */
@@ -168,7 +142,6 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
168 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize); 142 adjacent = lmb_addrs_adjacent(base,size,rgnbase,rgnsize);
169 if ( adjacent > 0 ) { 143 if ( adjacent > 0 ) {
170 rgn->region[i].base -= size; 144 rgn->region[i].base -= size;
171 rgn->region[i].physbase -= size;
172 rgn->region[i].size += size; 145 rgn->region[i].size += size;
173 coalesced++; 146 coalesced++;
174 break; 147 break;
@@ -195,11 +168,9 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
195 for (i=rgn->cnt-1; i >= 0; i--) { 168 for (i=rgn->cnt-1; i >= 0; i--) {
196 if (base < rgn->region[i].base) { 169 if (base < rgn->region[i].base) {
197 rgn->region[i+1].base = rgn->region[i].base; 170 rgn->region[i+1].base = rgn->region[i].base;
198 rgn->region[i+1].physbase = rgn->region[i].physbase;
199 rgn->region[i+1].size = rgn->region[i].size; 171 rgn->region[i+1].size = rgn->region[i].size;
200 } else { 172 } else {
201 rgn->region[i+1].base = base; 173 rgn->region[i+1].base = base;
202 rgn->region[i+1].physbase = lmb_abs_to_phys(base);
203 rgn->region[i+1].size = size; 174 rgn->region[i+1].size = size;
204 break; 175 break;
205 } 176 }
@@ -213,12 +184,11 @@ lmb_add_region(struct lmb_region *rgn, unsigned long base, unsigned long size)
213long __init 184long __init
214lmb_add(unsigned long base, unsigned long size) 185lmb_add(unsigned long base, unsigned long size)
215{ 186{
216 struct lmb *_lmb = &lmb; 187 struct lmb_region *_rgn = &(lmb.memory);
217 struct lmb_region *_rgn = &(_lmb->memory);
218 188
219 /* On pSeries LPAR systems, the first LMB is our RMO region. */ 189 /* On pSeries LPAR systems, the first LMB is our RMO region. */
220 if ( base == 0 ) 190 if ( base == 0 )
221 _lmb->rmo_size = size; 191 lmb.rmo_size = size;
222 192
223 return lmb_add_region(_rgn, base, size); 193 return lmb_add_region(_rgn, base, size);
224 194
@@ -227,8 +197,7 @@ lmb_add(unsigned long base, unsigned long size)
227long __init 197long __init
228lmb_reserve(unsigned long base, unsigned long size) 198lmb_reserve(unsigned long base, unsigned long size)
229{ 199{
230 struct lmb *_lmb = &lmb; 200 struct lmb_region *_rgn = &(lmb.reserved);
231 struct lmb_region *_rgn = &(_lmb->reserved);
232 201
233 return lmb_add_region(_rgn, base, size); 202 return lmb_add_region(_rgn, base, size);
234} 203}
@@ -260,13 +229,10 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
260{ 229{
261 long i, j; 230 long i, j;
262 unsigned long base = 0; 231 unsigned long base = 0;
263 struct lmb *_lmb = &lmb;
264 struct lmb_region *_mem = &(_lmb->memory);
265 struct lmb_region *_rsv = &(_lmb->reserved);
266 232
267 for (i=_mem->cnt-1; i >= 0; i--) { 233 for (i=lmb.memory.cnt-1; i >= 0; i--) {
268 unsigned long lmbbase = _mem->region[i].base; 234 unsigned long lmbbase = lmb.memory.region[i].base;
269 unsigned long lmbsize = _mem->region[i].size; 235 unsigned long lmbsize = lmb.memory.region[i].size;
270 236
271 if ( max_addr == LMB_ALLOC_ANYWHERE ) 237 if ( max_addr == LMB_ALLOC_ANYWHERE )
272 base = _ALIGN_DOWN(lmbbase+lmbsize-size, align); 238 base = _ALIGN_DOWN(lmbbase+lmbsize-size, align);
@@ -276,8 +242,8 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
276 continue; 242 continue;
277 243
278 while ( (lmbbase <= base) && 244 while ( (lmbbase <= base) &&
279 ((j = lmb_overlaps_region(_rsv,base,size)) >= 0) ) { 245 ((j = lmb_overlaps_region(&lmb.reserved,base,size)) >= 0) ) {
280 base = _ALIGN_DOWN(_rsv->region[j].base-size, align); 246 base = _ALIGN_DOWN(lmb.reserved.region[j].base-size, align);
281 } 247 }
282 248
283 if ( (base != 0) && (lmbbase <= base) ) 249 if ( (base != 0) && (lmbbase <= base) )
@@ -287,62 +253,24 @@ lmb_alloc_base(unsigned long size, unsigned long align, unsigned long max_addr)
287 if ( i < 0 ) 253 if ( i < 0 )
288 return 0; 254 return 0;
289 255
290 lmb_add_region(_rsv, base, size); 256 lmb_add_region(&lmb.reserved, base, size);
291 257
292 return base; 258 return base;
293} 259}
294 260
261/* You must call lmb_analyze() before this. */
295unsigned long __init 262unsigned long __init
296lmb_phys_mem_size(void) 263lmb_phys_mem_size(void)
297{ 264{
298 struct lmb *_lmb = &lmb; 265 return lmb.memory.size;
299#ifdef CONFIG_MSCHUNKS
300 return _lmb->memory.size;
301#else
302 struct lmb_region *_mem = &(_lmb->memory);
303 unsigned long total = 0;
304 int i;
305
306 /* add all physical memory to the bootmem map */
307 for (i=0; i < _mem->cnt; i++)
308 total += _mem->region[i].size;
309 return total;
310#endif /* CONFIG_MSCHUNKS */
311} 266}
312 267
313unsigned long __init 268unsigned long __init
314lmb_end_of_DRAM(void) 269lmb_end_of_DRAM(void)
315{ 270{
316 struct lmb *_lmb = &lmb; 271 int idx = lmb.memory.cnt - 1;
317 struct lmb_region *_mem = &(_lmb->memory);
318 int idx = _mem->cnt - 1;
319
320#ifdef CONFIG_MSCHUNKS
321 return (_mem->region[idx].physbase + _mem->region[idx].size);
322#else
323 return (_mem->region[idx].base + _mem->region[idx].size);
324#endif /* CONFIG_MSCHUNKS */
325
326 return 0;
327}
328
329unsigned long __init
330lmb_abs_to_phys(unsigned long aa)
331{
332 unsigned long i, pa = aa;
333 struct lmb *_lmb = &lmb;
334 struct lmb_region *_mem = &(_lmb->memory);
335
336 for (i=0; i < _mem->cnt; i++) {
337 unsigned long lmbbase = _mem->region[i].base;
338 unsigned long lmbsize = _mem->region[i].size;
339 if ( lmb_addrs_overlap(aa,1,lmbbase,lmbsize) ) {
340 pa = _mem->region[i].physbase + (aa - lmbbase);
341 break;
342 }
343 }
344 272
345 return pa; 273 return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
346} 274}
347 275
348/* 276/*
@@ -353,20 +281,19 @@ void __init lmb_enforce_memory_limit(void)
353{ 281{
354 extern unsigned long memory_limit; 282 extern unsigned long memory_limit;
355 unsigned long i, limit; 283 unsigned long i, limit;
356 struct lmb_region *mem = &(lmb.memory);
357 284
358 if (! memory_limit) 285 if (! memory_limit)
359 return; 286 return;
360 287
361 limit = memory_limit; 288 limit = memory_limit;
362 for (i = 0; i < mem->cnt; i++) { 289 for (i = 0; i < lmb.memory.cnt; i++) {
363 if (limit > mem->region[i].size) { 290 if (limit > lmb.memory.region[i].size) {
364 limit -= mem->region[i].size; 291 limit -= lmb.memory.region[i].size;
365 continue; 292 continue;
366 } 293 }
367 294
368 mem->region[i].size = limit; 295 lmb.memory.region[i].size = limit;
369 mem->cnt = i + 1; 296 lmb.memory.cnt = i + 1;
370 break; 297 break;
371 } 298 }
372} 299}
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index 02e96627fa66..edad361a8db0 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -29,7 +29,7 @@
29#include <asm/iSeries/HvLpConfig.h> 29#include <asm/iSeries/HvLpConfig.h>
30#include <asm/lppaca.h> 30#include <asm/lppaca.h>
31#include <asm/hvcall.h> 31#include <asm/hvcall.h>
32#include <asm/cputable.h> 32#include <asm/firmware.h>
33#include <asm/rtas.h> 33#include <asm/rtas.h>
34#include <asm/system.h> 34#include <asm/system.h>
35#include <asm/time.h> 35#include <asm/time.h>
@@ -273,6 +273,7 @@ static void parse_system_parameter_string(struct seq_file *m)
273 if (!workbuffer) { 273 if (!workbuffer) {
274 printk(KERN_ERR "%s %s kmalloc failure at line %d \n", 274 printk(KERN_ERR "%s %s kmalloc failure at line %d \n",
275 __FILE__, __FUNCTION__, __LINE__); 275 __FILE__, __FUNCTION__, __LINE__);
276 kfree(local_buffer);
276 return; 277 return;
277 } 278 }
278#ifdef LPARCFG_DEBUG 279#ifdef LPARCFG_DEBUG
@@ -377,7 +378,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
377 378
378 partition_active_processors = lparcfg_count_active_processors(); 379 partition_active_processors = lparcfg_count_active_processors();
379 380
380 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 381 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
381 unsigned long h_entitled, h_unallocated; 382 unsigned long h_entitled, h_unallocated;
382 unsigned long h_aggregation, h_resource; 383 unsigned long h_aggregation, h_resource;
383 unsigned long pool_idle_time, pool_procs; 384 unsigned long pool_idle_time, pool_procs;
@@ -571,7 +572,7 @@ int __init lparcfg_init(void)
571 mode_t mode = S_IRUSR; 572 mode_t mode = S_IRUSR;
572 573
573 /* Allow writing if we have FW_FEATURE_SPLPAR */ 574 /* Allow writing if we have FW_FEATURE_SPLPAR */
574 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 575 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
575 lparcfg_fops.write = lparcfg_write; 576 lparcfg_fops.write = lparcfg_write;
576 mode |= S_IWUSR; 577 mode |= S_IWUSR;
577 } 578 }
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index a05b50b738e9..474df0a862bf 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -680,6 +680,104 @@ _GLOBAL(kernel_thread)
680 ld r30,-16(r1) 680 ld r30,-16(r1)
681 blr 681 blr
682 682
683/*
684 * disable_kernel_fp()
685 * Disable the FPU.
686 */
687_GLOBAL(disable_kernel_fp)
688 mfmsr r3
689 rldicl r0,r3,(63-MSR_FP_LG),1
690 rldicl r3,r0,(MSR_FP_LG+1),0
691 mtmsrd r3 /* disable use of fpu now */
692 isync
693 blr
694
695/*
696 * giveup_fpu(tsk)
697 * Disable FP for the task given as the argument,
698 * and save the floating-point registers in its thread_struct.
699 * Enables the FPU for use in the kernel on return.
700 */
701_GLOBAL(giveup_fpu)
702 mfmsr r5
703 ori r5,r5,MSR_FP
704 mtmsrd r5 /* enable use of fpu now */
705 isync
706 cmpdi 0,r3,0
707 beqlr- /* if no previous owner, done */
708 addi r3,r3,THREAD /* want THREAD of task */
709 ld r5,PT_REGS(r3)
710 cmpdi 0,r5,0
711 SAVE_32FPRS(0, r3)
712 mffs fr0
713 stfd fr0,THREAD_FPSCR(r3)
714 beq 1f
715 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
716 li r3,MSR_FP|MSR_FE0|MSR_FE1
717 andc r4,r4,r3 /* disable FP for previous task */
718 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
7191:
720#ifndef CONFIG_SMP
721 li r5,0
722 ld r4,last_task_used_math@got(r2)
723 std r5,0(r4)
724#endif /* CONFIG_SMP */
725 blr
726
727#ifdef CONFIG_ALTIVEC
728
729#if 0 /* this has no callers for now */
730/*
731 * disable_kernel_altivec()
732 * Disable the VMX.
733 */
734_GLOBAL(disable_kernel_altivec)
735 mfmsr r3
736 rldicl r0,r3,(63-MSR_VEC_LG),1
737 rldicl r3,r0,(MSR_VEC_LG+1),0
738 mtmsrd r3 /* disable use of VMX now */
739 isync
740 blr
741#endif /* 0 */
742
743/*
744 * giveup_altivec(tsk)
745 * Disable VMX for the task given as the argument,
746 * and save the vector registers in its thread_struct.
747 * Enables the VMX for use in the kernel on return.
748 */
749_GLOBAL(giveup_altivec)
750 mfmsr r5
751 oris r5,r5,MSR_VEC@h
752 mtmsrd r5 /* enable use of VMX now */
753 isync
754 cmpdi 0,r3,0
755 beqlr- /* if no previous owner, done */
756 addi r3,r3,THREAD /* want THREAD of task */
757 ld r5,PT_REGS(r3)
758 cmpdi 0,r5,0
759 SAVE_32VRS(0,r4,r3)
760 mfvscr vr0
761 li r4,THREAD_VSCR
762 stvx vr0,r4,r3
763 beq 1f
764 ld r4,_MSR-STACK_FRAME_OVERHEAD(r5)
765 lis r3,MSR_VEC@h
766 andc r4,r4,r3 /* disable FP for previous task */
767 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)
7681:
769#ifndef CONFIG_SMP
770 li r5,0
771 ld r4,last_task_used_altivec@got(r2)
772 std r5,0(r4)
773#endif /* CONFIG_SMP */
774 blr
775
776#endif /* CONFIG_ALTIVEC */
777
778_GLOBAL(__setup_cpu_power3)
779 blr
780
683/* kexec_wait(phys_cpu) 781/* kexec_wait(phys_cpu)
684 * 782 *
685 * wait for the flag to change, indicating this kernel is going away but 783 * wait for the flag to change, indicating this kernel is going away but
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index b80e81984ba8..da580812ddfe 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -236,7 +236,6 @@ void of_device_unregister(struct of_device *ofdev)
236struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) 236struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
237{ 237{
238 struct of_device *dev; 238 struct of_device *dev;
239 u32 *reg;
240 239
241 dev = kmalloc(sizeof(*dev), GFP_KERNEL); 240 dev = kmalloc(sizeof(*dev), GFP_KERNEL);
242 if (!dev) 241 if (!dev)
@@ -250,7 +249,6 @@ struct of_device* of_platform_device_create(struct device_node *np, const char *
250 dev->dev.bus = &of_platform_bus_type; 249 dev->dev.bus = &of_platform_bus_type;
251 dev->dev.release = of_release_dev; 250 dev->dev.release = of_release_dev;
252 251
253 reg = (u32 *)get_property(np, "reg", NULL);
254 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); 252 strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
255 253
256 if (of_device_register(dev) != 0) { 254 if (of_device_register(dev) != 0) {
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c
index 69130522a87e..9d5e1e7fc389 100644
--- a/arch/ppc64/kernel/pSeries_iommu.c
+++ b/arch/ppc64/kernel/pSeries_iommu.c
@@ -45,6 +45,7 @@
45#include <asm/plpar_wrappers.h> 45#include <asm/plpar_wrappers.h>
46#include <asm/pSeries_reconfig.h> 46#include <asm/pSeries_reconfig.h>
47#include <asm/systemcfg.h> 47#include <asm/systemcfg.h>
48#include <asm/firmware.h>
48#include "pci.h" 49#include "pci.h"
49 50
50#define DBG(fmt...) 51#define DBG(fmt...)
@@ -546,7 +547,7 @@ void iommu_init_early_pSeries(void)
546 } 547 }
547 548
548 if (systemcfg->platform & PLATFORM_LPAR) { 549 if (systemcfg->platform & PLATFORM_LPAR) {
549 if (cur_cpu_spec->firmware_features & FW_FEATURE_MULTITCE) { 550 if (firmware_has_feature(FW_FEATURE_MULTITCE)) {
550 ppc_md.tce_build = tce_buildmulti_pSeriesLP; 551 ppc_md.tce_build = tce_buildmulti_pSeriesLP;
551 ppc_md.tce_free = tce_freemulti_pSeriesLP; 552 ppc_md.tce_free = tce_freemulti_pSeriesLP;
552 } else { 553 } else {
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index 74dd144dcce8..0a3ddc9227c5 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -52,7 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_4out);
52EXPORT_SYMBOL(plpar_hcall_norets); 52EXPORT_SYMBOL(plpar_hcall_norets);
53EXPORT_SYMBOL(plpar_hcall_8arg_2ret); 53EXPORT_SYMBOL(plpar_hcall_8arg_2ret);
54 54
55extern void fw_feature_init(void);
56extern void pSeries_find_serial_port(void); 55extern void pSeries_find_serial_port(void);
57 56
58 57
@@ -279,7 +278,6 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
279 unsigned long va, unsigned long prpn, 278 unsigned long va, unsigned long prpn,
280 unsigned long vflags, unsigned long rflags) 279 unsigned long vflags, unsigned long rflags)
281{ 280{
282 unsigned long arpn = physRpn_to_absRpn(prpn);
283 unsigned long lpar_rc; 281 unsigned long lpar_rc;
284 unsigned long flags; 282 unsigned long flags;
285 unsigned long slot; 283 unsigned long slot;
@@ -290,7 +288,7 @@ long pSeries_lpar_hpte_insert(unsigned long hpte_group,
290 if (vflags & HPTE_V_LARGE) 288 if (vflags & HPTE_V_LARGE)
291 hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT); 289 hpte_v &= ~(1UL << HPTE_V_AVPN_SHIFT);
292 290
293 hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags; 291 hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
294 292
295 /* Now fill in the actual HPTE */ 293 /* Now fill in the actual HPTE */
296 /* Set CEC cookie to 0 */ 294 /* Set CEC cookie to 0 */
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 5bec956e44a0..f0f0630cf07c 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -60,7 +60,8 @@
60#include <asm/nvram.h> 60#include <asm/nvram.h>
61#include <asm/plpar_wrappers.h> 61#include <asm/plpar_wrappers.h>
62#include <asm/xics.h> 62#include <asm/xics.h>
63#include <asm/cputable.h> 63#include <asm/firmware.h>
64#include <asm/pmc.h>
64 65
65#include "i8259.h" 66#include "i8259.h"
66#include "mpic.h" 67#include "mpic.h"
@@ -187,6 +188,21 @@ static void __init pSeries_setup_mpic(void)
187 " MPIC "); 188 " MPIC ");
188} 189}
189 190
191static void pseries_lpar_enable_pmcs(void)
192{
193 unsigned long set, reset;
194
195 power4_enable_pmcs();
196
197 set = 1UL << 63;
198 reset = 0;
199 plpar_hcall_norets(H_PERFMON, set, reset);
200
201 /* instruct hypervisor to maintain PMCs */
202 if (firmware_has_feature(FW_FEATURE_SPLPAR))
203 get_paca()->lppaca.pmcregs_in_use = 1;
204}
205
190static void __init pSeries_setup_arch(void) 206static void __init pSeries_setup_arch(void)
191{ 207{
192 /* Fixup ppc_md depending on the type of interrupt controller */ 208 /* Fixup ppc_md depending on the type of interrupt controller */
@@ -231,11 +247,9 @@ static void __init pSeries_setup_arch(void)
231 247
232 pSeries_nvram_init(); 248 pSeries_nvram_init();
233 249
234 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
235 vpa_init(boot_cpuid);
236
237 /* Choose an idle loop */ 250 /* Choose an idle loop */
238 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { 251 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
252 vpa_init(boot_cpuid);
239 if (get_paca()->lppaca.shared_proc) { 253 if (get_paca()->lppaca.shared_proc) {
240 printk(KERN_INFO "Using shared processor idle loop\n"); 254 printk(KERN_INFO "Using shared processor idle loop\n");
241 ppc_md.idle_loop = pseries_shared_idle; 255 ppc_md.idle_loop = pseries_shared_idle;
@@ -247,6 +261,11 @@ static void __init pSeries_setup_arch(void)
247 printk(KERN_INFO "Using default idle loop\n"); 261 printk(KERN_INFO "Using default idle loop\n");
248 ppc_md.idle_loop = default_idle; 262 ppc_md.idle_loop = default_idle;
249 } 263 }
264
265 if (systemcfg->platform & PLATFORM_LPAR)
266 ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
267 else
268 ppc_md.enable_pmcs = power4_enable_pmcs;
250} 269}
251 270
252static int __init pSeries_init_panel(void) 271static int __init pSeries_init_panel(void)
@@ -260,11 +279,11 @@ static int __init pSeries_init_panel(void)
260arch_initcall(pSeries_init_panel); 279arch_initcall(pSeries_init_panel);
261 280
262 281
263/* Build up the firmware_features bitmask field 282/* Build up the ppc64_firmware_features bitmask field
264 * using contents of device-tree/ibm,hypertas-functions. 283 * using contents of device-tree/ibm,hypertas-functions.
265 * Ultimately this functionality may be moved into prom.c prom_init(). 284 * Ultimately this functionality may be moved into prom.c prom_init().
266 */ 285 */
267void __init fw_feature_init(void) 286static void __init fw_feature_init(void)
268{ 287{
269 struct device_node * dn; 288 struct device_node * dn;
270 char * hypertas; 289 char * hypertas;
@@ -272,7 +291,7 @@ void __init fw_feature_init(void)
272 291
273 DBG(" -> fw_feature_init()\n"); 292 DBG(" -> fw_feature_init()\n");
274 293
275 cur_cpu_spec->firmware_features = 0; 294 ppc64_firmware_features = 0;
276 dn = of_find_node_by_path("/rtas"); 295 dn = of_find_node_by_path("/rtas");
277 if (dn == NULL) { 296 if (dn == NULL) {
278 printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n"); 297 printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n");
@@ -288,7 +307,7 @@ void __init fw_feature_init(void)
288 if ((firmware_features_table[i].name) && 307 if ((firmware_features_table[i].name) &&
289 (strcmp(firmware_features_table[i].name,hypertas))==0) { 308 (strcmp(firmware_features_table[i].name,hypertas))==0) {
290 /* we have a match */ 309 /* we have a match */
291 cur_cpu_spec->firmware_features |= 310 ppc64_firmware_features |=
292 (firmware_features_table[i].val); 311 (firmware_features_table[i].val);
293 break; 312 break;
294 } 313 }
@@ -302,7 +321,7 @@ void __init fw_feature_init(void)
302 of_node_put(dn); 321 of_node_put(dn);
303 no_rtas: 322 no_rtas:
304 printk(KERN_INFO "firmware_features = 0x%lx\n", 323 printk(KERN_INFO "firmware_features = 0x%lx\n",
305 cur_cpu_spec->firmware_features); 324 ppc64_firmware_features);
306 325
307 DBG(" <- fw_feature_init()\n"); 326 DBG(" <- fw_feature_init()\n");
308} 327}
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index 62c55a123560..79c7f3223665 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -41,6 +41,7 @@
41#include <asm/machdep.h> 41#include <asm/machdep.h>
42#include <asm/xics.h> 42#include <asm/xics.h>
43#include <asm/cputable.h> 43#include <asm/cputable.h>
44#include <asm/firmware.h>
44#include <asm/system.h> 45#include <asm/system.h>
45#include <asm/rtas.h> 46#include <asm/rtas.h>
46#include <asm/plpar_wrappers.h> 47#include <asm/plpar_wrappers.h>
@@ -326,7 +327,7 @@ static void __devinit smp_xics_setup_cpu(int cpu)
326 if (cpu != boot_cpuid) 327 if (cpu != boot_cpuid)
327 xics_setup_cpu(); 328 xics_setup_cpu();
328 329
329 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) 330 if (firmware_has_feature(FW_FEATURE_SPLPAR))
330 vpa_init(cpu); 331 vpa_init(cpu);
331 332
332 cpu_clear(cpu, of_spin_map); 333 cpu_clear(cpu, of_spin_map);
diff --git a/arch/ppc64/kernel/pSeries_vio.c b/arch/ppc64/kernel/pSeries_vio.c
new file mode 100644
index 000000000000..e0ae06f58f86
--- /dev/null
+++ b/arch/ppc64/kernel/pSeries_vio.c
@@ -0,0 +1,273 @@
1/*
2 * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
3 *
4 * Copyright (c) 2003-2005 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com>
8 * Stephen Rothwell
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/init.h>
17#include <linux/module.h>
18#include <linux/mm.h>
19#include <linux/kobject.h>
20#include <asm/iommu.h>
21#include <asm/dma.h>
22#include <asm/prom.h>
23#include <asm/vio.h>
24#include <asm/hvcall.h>
25
26extern struct subsystem devices_subsys; /* needed for vio_find_name() */
27
28static void probe_bus_pseries(void)
29{
30 struct device_node *node_vroot, *of_node;
31
32 node_vroot = find_devices("vdevice");
33 if ((node_vroot == NULL) || (node_vroot->child == NULL))
34 /* this machine doesn't do virtual IO, and that's ok */
35 return;
36
37 /*
38 * Create struct vio_devices for each virtual device in the device tree.
39 * Drivers will associate with them later.
40 */
41 for (of_node = node_vroot->child; of_node != NULL;
42 of_node = of_node->sibling) {
43 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
44 vio_register_device_node(of_node);
45 }
46}
47
48/**
49 * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
50 * vio_device_id
51 */
52static int vio_match_device_pseries(const struct vio_device_id *id,
53 const struct vio_dev *dev)
54{
55 return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
56 device_is_compatible(dev->dev.platform_data, id->compat);
57}
58
59static void vio_release_device_pseries(struct device *dev)
60{
61 /* XXX free TCE table */
62 of_node_put(dev->platform_data);
63}
64
65static ssize_t viodev_show_devspec(struct device *dev,
66 struct device_attribute *attr, char *buf)
67{
68 struct device_node *of_node = dev->platform_data;
69
70 return sprintf(buf, "%s\n", of_node->full_name);
71}
72DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
73
74static void vio_unregister_device_pseries(struct vio_dev *viodev)
75{
76 device_remove_file(&viodev->dev, &dev_attr_devspec);
77}
78
79static struct vio_bus_ops vio_bus_ops_pseries = {
80 .match = vio_match_device_pseries,
81 .unregister_device = vio_unregister_device_pseries,
82 .release_device = vio_release_device_pseries,
83};
84
85/**
86 * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
87 */
88static int __init vio_bus_init_pseries(void)
89{
90 int err;
91
92 err = vio_bus_init(&vio_bus_ops_pseries);
93 if (err == 0)
94 probe_bus_pseries();
95 return err;
96}
97
98__initcall(vio_bus_init_pseries);
99
100/**
101 * vio_build_iommu_table: - gets the dma information from OF and
102 * builds the TCE tree.
103 * @dev: the virtual device.
104 *
105 * Returns a pointer to the built tce tree, or NULL if it can't
106 * find property.
107*/
108static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
109{
110 unsigned int *dma_window;
111 struct iommu_table *newTceTable;
112 unsigned long offset;
113 int dma_window_property_size;
114
115 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
116 if(!dma_window) {
117 return NULL;
118 }
119
120 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
121
122 /* There should be some code to extract the phys-encoded offset
123 using prom_n_addr_cells(). However, according to a comment
124 on earlier versions, it's always zero, so we don't bother */
125 offset = dma_window[1] >> PAGE_SHIFT;
126
127 /* TCE table size - measured in tce entries */
128 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
129 /* offset for VIO should always be 0 */
130 newTceTable->it_offset = offset;
131 newTceTable->it_busno = 0;
132 newTceTable->it_index = (unsigned long)dma_window[0];
133 newTceTable->it_type = TCE_VB;
134
135 return iommu_init_table(newTceTable);
136}
137
138/**
139 * vio_register_device_node: - Register a new vio device.
140 * @of_node: The OF node for this device.
141 *
142 * Creates and initializes a vio_dev structure from the data in
143 * of_node (dev.platform_data) and adds it to the list of virtual devices.
144 * Returns a pointer to the created vio_dev or NULL if node has
145 * NULL device_type or compatible fields.
146 */
147struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
148{
149 struct vio_dev *viodev;
150 unsigned int *unit_address;
151 unsigned int *irq_p;
152
153 /* we need the 'device_type' property, in order to match with drivers */
154 if ((NULL == of_node->type)) {
155 printk(KERN_WARNING
156 "%s: node %s missing 'device_type'\n", __FUNCTION__,
157 of_node->name ? of_node->name : "<unknown>");
158 return NULL;
159 }
160
161 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
162 if (!unit_address) {
163 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
164 of_node->name ? of_node->name : "<unknown>");
165 return NULL;
166 }
167
168 /* allocate a vio_dev for this node */
169 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
170 if (!viodev) {
171 return NULL;
172 }
173 memset(viodev, 0, sizeof(struct vio_dev));
174
175 viodev->dev.platform_data = of_node_get(of_node);
176
177 viodev->irq = NO_IRQ;
178 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
179 if (irq_p) {
180 int virq = virt_irq_create_mapping(*irq_p);
181 if (virq == NO_IRQ) {
182 printk(KERN_ERR "Unable to allocate interrupt "
183 "number for %s\n", of_node->full_name);
184 } else
185 viodev->irq = irq_offset_up(virq);
186 }
187
188 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
189 viodev->name = of_node->name;
190 viodev->type = of_node->type;
191 viodev->unit_address = *unit_address;
192 viodev->iommu_table = vio_build_iommu_table(viodev);
193
194 /* register with generic device framework */
195 if (vio_register_device(viodev) == NULL) {
196 /* XXX free TCE table */
197 kfree(viodev);
198 return NULL;
199 }
200 device_create_file(&viodev->dev, &dev_attr_devspec);
201
202 return viodev;
203}
204EXPORT_SYMBOL(vio_register_device_node);
205
206/**
207 * vio_get_attribute: - get attribute for virtual device
208 * @vdev: The vio device to get property.
209 * @which: The property/attribute to be extracted.
210 * @length: Pointer to length of returned data size (unused if NULL).
211 *
212 * Calls prom.c's get_property() to return the value of the
213 * attribute specified by the preprocessor constant @which
214*/
215const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
216{
217 return get_property(vdev->dev.platform_data, (char*)which, length);
218}
219EXPORT_SYMBOL(vio_get_attribute);
220
221/* vio_find_name() - internal because only vio.c knows how we formatted the
222 * kobject name
223 * XXX once vio_bus_type.devices is actually used as a kset in
224 * drivers/base/bus.c, this function should be removed in favor of
225 * "device_find(kobj_name, &vio_bus_type)"
226 */
227static struct vio_dev *vio_find_name(const char *kobj_name)
228{
229 struct kobject *found;
230
231 found = kset_find_obj(&devices_subsys.kset, kobj_name);
232 if (!found)
233 return NULL;
234
235 return to_vio_dev(container_of(found, struct device, kobj));
236}
237
238/**
239 * vio_find_node - find an already-registered vio_dev
240 * @vnode: device_node of the virtual device we're looking for
241 */
242struct vio_dev *vio_find_node(struct device_node *vnode)
243{
244 uint32_t *unit_address;
245 char kobj_name[BUS_ID_SIZE];
246
247 /* construct the kobject name from the device node */
248 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
249 if (!unit_address)
250 return NULL;
251 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
252
253 return vio_find_name(kobj_name);
254}
255EXPORT_SYMBOL(vio_find_node);
256
257int vio_enable_interrupts(struct vio_dev *dev)
258{
259 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
260 if (rc != H_Success)
261 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
262 return rc;
263}
264EXPORT_SYMBOL(vio_enable_interrupts);
265
266int vio_disable_interrupts(struct vio_dev *dev)
267{
268 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
269 if (rc != H_Success)
270 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
271 return rc;
272}
273EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
index 6316188737b6..6182a2cd90a5 100644
--- a/arch/ppc64/kernel/pacaData.c
+++ b/arch/ppc64/kernel/pacaData.c
@@ -78,7 +78,7 @@ extern unsigned long __toc_start;
78 78
79#define BOOTCPU_PACA_INIT(number) \ 79#define BOOTCPU_PACA_INIT(number) \
80{ \ 80{ \
81 PACA_INIT_COMMON(number, 1, 0, STAB0_VIRT_ADDR) \ 81 PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
82 PACA_INIT_ISERIES(number) \ 82 PACA_INIT_ISERIES(number) \
83} 83}
84 84
@@ -90,7 +90,7 @@ extern unsigned long __toc_start;
90 90
91#define BOOTCPU_PACA_INIT(number) \ 91#define BOOTCPU_PACA_INIT(number) \
92{ \ 92{ \
93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR) \ 93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
94} 94}
95#endif 95#endif
96 96
diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
index e40877fa67cd..8ff86a766cdf 100644
--- a/arch/ppc64/kernel/pmac_setup.c
+++ b/arch/ppc64/kernel/pmac_setup.c
@@ -71,6 +71,7 @@
71#include <asm/of_device.h> 71#include <asm/of_device.h>
72#include <asm/lmb.h> 72#include <asm/lmb.h>
73#include <asm/smu.h> 73#include <asm/smu.h>
74#include <asm/pmc.h>
74 75
75#include "pmac.h" 76#include "pmac.h"
76#include "mpic.h" 77#include "mpic.h"
@@ -511,4 +512,5 @@ struct machdep_calls __initdata pmac_md = {
511 .progress = pmac_progress, 512 .progress = pmac_progress,
512 .check_legacy_ioport = pmac_check_legacy_ioport, 513 .check_legacy_ioport = pmac_check_legacy_ioport,
513 .idle_loop = native_idle, 514 .idle_loop = native_idle,
515 .enable_pmcs = power4_enable_pmcs,
514}; 516};
diff --git a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
index 67be773f9c00..cdfec7438d01 100644
--- a/arch/ppc64/kernel/pmc.c
+++ b/arch/ppc64/kernel/pmc.c
@@ -65,3 +65,24 @@ void release_pmc_hardware(void)
65 spin_unlock(&pmc_owner_lock); 65 spin_unlock(&pmc_owner_lock);
66} 66}
67EXPORT_SYMBOL_GPL(release_pmc_hardware); 67EXPORT_SYMBOL_GPL(release_pmc_hardware);
68
69void power4_enable_pmcs(void)
70{
71 unsigned long hid0;
72
73 hid0 = mfspr(HID0);
74 hid0 |= 1UL << (63 - 20);
75
76 /* POWER4 requires the following sequence */
77 asm volatile(
78 "sync\n"
79 "mtspr %1, %0\n"
80 "mfspr %0, %1\n"
81 "mfspr %0, %1\n"
82 "mfspr %0, %1\n"
83 "mfspr %0, %1\n"
84 "mfspr %0, %1\n"
85 "mfspr %0, %1\n"
86 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
87 "memory");
88}
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index f7cae05e40fb..7a7e027653ad 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -50,6 +50,7 @@
50#include <asm/machdep.h> 50#include <asm/machdep.h>
51#include <asm/iSeries/HvCallHpt.h> 51#include <asm/iSeries/HvCallHpt.h>
52#include <asm/cputable.h> 52#include <asm/cputable.h>
53#include <asm/firmware.h>
53#include <asm/sections.h> 54#include <asm/sections.h>
54#include <asm/tlbflush.h> 55#include <asm/tlbflush.h>
55#include <asm/time.h> 56#include <asm/time.h>
@@ -202,11 +203,10 @@ struct task_struct *__switch_to(struct task_struct *prev,
202 new_thread = &new->thread; 203 new_thread = &new->thread;
203 old_thread = &current->thread; 204 old_thread = &current->thread;
204 205
205/* Collect purr utilization data per process and per processor wise */ 206 /* Collect purr utilization data per process and per processor
206/* purr is nothing but processor time base */ 207 * wise purr is nothing but processor time base
207 208 */
208#if defined(CONFIG_PPC_PSERIES) 209 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
209 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
210 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 210 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
211 long unsigned start_tb, current_tb; 211 long unsigned start_tb, current_tb;
212 start_tb = old_thread->start_tb; 212 start_tb = old_thread->start_tb;
@@ -214,8 +214,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
214 old_thread->accum_tb += (current_tb - start_tb); 214 old_thread->accum_tb += (current_tb - start_tb);
215 new_thread->start_tb = current_tb; 215 new_thread->start_tb = current_tb;
216 } 216 }
217#endif
218
219 217
220 local_irq_save(flags); 218 local_irq_save(flags);
221 last = _switch(old_thread, new_thread); 219 last = _switch(old_thread, new_thread);
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 5aca01ddd81f..b21848826791 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -625,8 +625,8 @@ void __init finish_device_tree(void)
625 625
626static inline char *find_flat_dt_string(u32 offset) 626static inline char *find_flat_dt_string(u32 offset)
627{ 627{
628 return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings 628 return ((char *)initial_boot_params) +
629 + offset; 629 initial_boot_params->off_dt_strings + offset;
630} 630}
631 631
632/** 632/**
@@ -635,26 +635,33 @@ static inline char *find_flat_dt_string(u32 offset)
635 * unflatten the tree 635 * unflatten the tree
636 */ 636 */
637static int __init scan_flat_dt(int (*it)(unsigned long node, 637static int __init scan_flat_dt(int (*it)(unsigned long node,
638 const char *full_path, void *data), 638 const char *uname, int depth,
639 void *data),
639 void *data) 640 void *data)
640{ 641{
641 unsigned long p = ((unsigned long)initial_boot_params) + 642 unsigned long p = ((unsigned long)initial_boot_params) +
642 initial_boot_params->off_dt_struct; 643 initial_boot_params->off_dt_struct;
643 int rc = 0; 644 int rc = 0;
645 int depth = -1;
644 646
645 do { 647 do {
646 u32 tag = *((u32 *)p); 648 u32 tag = *((u32 *)p);
647 char *pathp; 649 char *pathp;
648 650
649 p += 4; 651 p += 4;
650 if (tag == OF_DT_END_NODE) 652 if (tag == OF_DT_END_NODE) {
653 depth --;
654 continue;
655 }
656 if (tag == OF_DT_NOP)
651 continue; 657 continue;
652 if (tag == OF_DT_END) 658 if (tag == OF_DT_END)
653 break; 659 break;
654 if (tag == OF_DT_PROP) { 660 if (tag == OF_DT_PROP) {
655 u32 sz = *((u32 *)p); 661 u32 sz = *((u32 *)p);
656 p += 8; 662 p += 8;
657 p = _ALIGN(p, sz >= 8 ? 8 : 4); 663 if (initial_boot_params->version < 0x10)
664 p = _ALIGN(p, sz >= 8 ? 8 : 4);
658 p += sz; 665 p += sz;
659 p = _ALIGN(p, 4); 666 p = _ALIGN(p, 4);
660 continue; 667 continue;
@@ -664,9 +671,18 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
664 " device tree !\n", tag); 671 " device tree !\n", tag);
665 return -EINVAL; 672 return -EINVAL;
666 } 673 }
674 depth++;
667 pathp = (char *)p; 675 pathp = (char *)p;
668 p = _ALIGN(p + strlen(pathp) + 1, 4); 676 p = _ALIGN(p + strlen(pathp) + 1, 4);
669 rc = it(p, pathp, data); 677 if ((*pathp) == '/') {
678 char *lp, *np;
679 for (lp = NULL, np = pathp; *np; np++)
680 if ((*np) == '/')
681 lp = np+1;
682 if (lp != NULL)
683 pathp = lp;
684 }
685 rc = it(p, pathp, depth, data);
670 if (rc != 0) 686 if (rc != 0)
671 break; 687 break;
672 } while(1); 688 } while(1);
@@ -689,17 +705,21 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
689 const char *nstr; 705 const char *nstr;
690 706
691 p += 4; 707 p += 4;
708 if (tag == OF_DT_NOP)
709 continue;
692 if (tag != OF_DT_PROP) 710 if (tag != OF_DT_PROP)
693 return NULL; 711 return NULL;
694 712
695 sz = *((u32 *)p); 713 sz = *((u32 *)p);
696 noff = *((u32 *)(p + 4)); 714 noff = *((u32 *)(p + 4));
697 p += 8; 715 p += 8;
698 p = _ALIGN(p, sz >= 8 ? 8 : 4); 716 if (initial_boot_params->version < 0x10)
717 p = _ALIGN(p, sz >= 8 ? 8 : 4);
699 718
700 nstr = find_flat_dt_string(noff); 719 nstr = find_flat_dt_string(noff);
701 if (nstr == NULL) { 720 if (nstr == NULL) {
702 printk(KERN_WARNING "Can't find property index name !\n"); 721 printk(KERN_WARNING "Can't find property index"
722 " name !\n");
703 return NULL; 723 return NULL;
704 } 724 }
705 if (strcmp(name, nstr) == 0) { 725 if (strcmp(name, nstr) == 0) {
@@ -713,7 +733,7 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
713} 733}
714 734
715static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, 735static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
716 unsigned long align) 736 unsigned long align)
717{ 737{
718 void *res; 738 void *res;
719 739
@@ -727,13 +747,16 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
727static unsigned long __init unflatten_dt_node(unsigned long mem, 747static unsigned long __init unflatten_dt_node(unsigned long mem,
728 unsigned long *p, 748 unsigned long *p,
729 struct device_node *dad, 749 struct device_node *dad,
730 struct device_node ***allnextpp) 750 struct device_node ***allnextpp,
751 unsigned long fpsize)
731{ 752{
732 struct device_node *np; 753 struct device_node *np;
733 struct property *pp, **prev_pp = NULL; 754 struct property *pp, **prev_pp = NULL;
734 char *pathp; 755 char *pathp;
735 u32 tag; 756 u32 tag;
736 unsigned int l; 757 unsigned int l, allocl;
758 int has_name = 0;
759 int new_format = 0;
737 760
738 tag = *((u32 *)(*p)); 761 tag = *((u32 *)(*p));
739 if (tag != OF_DT_BEGIN_NODE) { 762 if (tag != OF_DT_BEGIN_NODE) {
@@ -742,21 +765,62 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
742 } 765 }
743 *p += 4; 766 *p += 4;
744 pathp = (char *)*p; 767 pathp = (char *)*p;
745 l = strlen(pathp) + 1; 768 l = allocl = strlen(pathp) + 1;
746 *p = _ALIGN(*p + l, 4); 769 *p = _ALIGN(*p + l, 4);
747 770
748 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l, 771 /* version 0x10 has a more compact unit name here instead of the full
772 * path. we accumulate the full path size using "fpsize", we'll rebuild
773 * it later. We detect this because the first character of the name is
774 * not '/'.
775 */
776 if ((*pathp) != '/') {
777 new_format = 1;
778 if (fpsize == 0) {
779 /* root node: special case. fpsize accounts for path
780 * plus terminating zero. root node only has '/', so
781 * fpsize should be 2, but we want to avoid the first
782 * level nodes to have two '/' so we use fpsize 1 here
783 */
784 fpsize = 1;
785 allocl = 2;
786 } else {
787 /* account for '/' and path size minus terminal 0
788 * already in 'l'
789 */
790 fpsize += l;
791 allocl = fpsize;
792 }
793 }
794
795
796 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
749 __alignof__(struct device_node)); 797 __alignof__(struct device_node));
750 if (allnextpp) { 798 if (allnextpp) {
751 memset(np, 0, sizeof(*np)); 799 memset(np, 0, sizeof(*np));
752 np->full_name = ((char*)np) + sizeof(struct device_node); 800 np->full_name = ((char*)np) + sizeof(struct device_node);
753 memcpy(np->full_name, pathp, l); 801 if (new_format) {
802 char *p = np->full_name;
803 /* rebuild full path for new format */
804 if (dad && dad->parent) {
805 strcpy(p, dad->full_name);
806#ifdef DEBUG
807 if ((strlen(p) + l + 1) != allocl) {
808 DBG("%s: p: %d, l: %d, a: %d\n",
809 pathp, strlen(p), l, allocl);
810 }
811#endif
812 p += strlen(p);
813 }
814 *(p++) = '/';
815 memcpy(p, pathp, l);
816 } else
817 memcpy(np->full_name, pathp, l);
754 prev_pp = &np->properties; 818 prev_pp = &np->properties;
755 **allnextpp = np; 819 **allnextpp = np;
756 *allnextpp = &np->allnext; 820 *allnextpp = &np->allnext;
757 if (dad != NULL) { 821 if (dad != NULL) {
758 np->parent = dad; 822 np->parent = dad;
759 /* we temporarily use the `next' field as `last_child'. */ 823 /* we temporarily use the next field as `last_child'*/
760 if (dad->next == 0) 824 if (dad->next == 0)
761 dad->child = np; 825 dad->child = np;
762 else 826 else
@@ -770,18 +834,26 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
770 char *pname; 834 char *pname;
771 835
772 tag = *((u32 *)(*p)); 836 tag = *((u32 *)(*p));
837 if (tag == OF_DT_NOP) {
838 *p += 4;
839 continue;
840 }
773 if (tag != OF_DT_PROP) 841 if (tag != OF_DT_PROP)
774 break; 842 break;
775 *p += 4; 843 *p += 4;
776 sz = *((u32 *)(*p)); 844 sz = *((u32 *)(*p));
777 noff = *((u32 *)((*p) + 4)); 845 noff = *((u32 *)((*p) + 4));
778 *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4); 846 *p += 8;
847 if (initial_boot_params->version < 0x10)
848 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
779 849
780 pname = find_flat_dt_string(noff); 850 pname = find_flat_dt_string(noff);
781 if (pname == NULL) { 851 if (pname == NULL) {
782 printk("Can't find property name in list !\n"); 852 printk("Can't find property name in list !\n");
783 break; 853 break;
784 } 854 }
855 if (strcmp(pname, "name") == 0)
856 has_name = 1;
785 l = strlen(pname) + 1; 857 l = strlen(pname) + 1;
786 pp = unflatten_dt_alloc(&mem, sizeof(struct property), 858 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
787 __alignof__(struct property)); 859 __alignof__(struct property));
@@ -801,6 +873,36 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
801 } 873 }
802 *p = _ALIGN((*p) + sz, 4); 874 *p = _ALIGN((*p) + sz, 4);
803 } 875 }
876 /* with version 0x10 we may not have the name property, recreate
877 * it here from the unit name if absent
878 */
879 if (!has_name) {
880 char *p = pathp, *ps = pathp, *pa = NULL;
881 int sz;
882
883 while (*p) {
884 if ((*p) == '@')
885 pa = p;
886 if ((*p) == '/')
887 ps = p + 1;
888 p++;
889 }
890 if (pa < ps)
891 pa = p;
892 sz = (pa - ps) + 1;
893 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
894 __alignof__(struct property));
895 if (allnextpp) {
896 pp->name = "name";
897 pp->length = sz;
898 pp->value = (unsigned char *)(pp + 1);
899 *prev_pp = pp;
900 prev_pp = &pp->next;
901 memcpy(pp->value, ps, sz - 1);
902 ((char *)pp->value)[sz - 1] = 0;
903 DBG("fixed up name for %s -> %s\n", pathp, pp->value);
904 }
905 }
804 if (allnextpp) { 906 if (allnextpp) {
805 *prev_pp = NULL; 907 *prev_pp = NULL;
806 np->name = get_property(np, "name", NULL); 908 np->name = get_property(np, "name", NULL);
@@ -812,11 +914,11 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
812 np->type = "<NULL>"; 914 np->type = "<NULL>";
813 } 915 }
814 while (tag == OF_DT_BEGIN_NODE) { 916 while (tag == OF_DT_BEGIN_NODE) {
815 mem = unflatten_dt_node(mem, p, np, allnextpp); 917 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
816 tag = *((u32 *)(*p)); 918 tag = *((u32 *)(*p));
817 } 919 }
818 if (tag != OF_DT_END_NODE) { 920 if (tag != OF_DT_END_NODE) {
819 printk("Weird tag at start of node: %x\n", tag); 921 printk("Weird tag at end of node: %x\n", tag);
820 return mem; 922 return mem;
821 } 923 }
822 *p += 4; 924 *p += 4;
@@ -842,21 +944,32 @@ void __init unflatten_device_tree(void)
842 /* First pass, scan for size */ 944 /* First pass, scan for size */
843 start = ((unsigned long)initial_boot_params) + 945 start = ((unsigned long)initial_boot_params) +
844 initial_boot_params->off_dt_struct; 946 initial_boot_params->off_dt_struct;
845 size = unflatten_dt_node(0, &start, NULL, NULL); 947 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
948 size = (size | 3) + 1;
846 949
847 DBG(" size is %lx, allocating...\n", size); 950 DBG(" size is %lx, allocating...\n", size);
848 951
849 /* Allocate memory for the expanded device tree */ 952 /* Allocate memory for the expanded device tree */
850 mem = (unsigned long)abs_to_virt(lmb_alloc(size, 953 mem = lmb_alloc(size + 4, __alignof__(struct device_node));
851 __alignof__(struct device_node))); 954 if (!mem) {
955 DBG("Couldn't allocate memory with lmb_alloc()!\n");
956 panic("Couldn't allocate memory with lmb_alloc()!\n");
957 }
958 mem = (unsigned long)abs_to_virt(mem);
959
960 ((u32 *)mem)[size / 4] = 0xdeadbeef;
961
852 DBG(" unflattening...\n", mem); 962 DBG(" unflattening...\n", mem);
853 963
854 /* Second pass, do actual unflattening */ 964 /* Second pass, do actual unflattening */
855 start = ((unsigned long)initial_boot_params) + 965 start = ((unsigned long)initial_boot_params) +
856 initial_boot_params->off_dt_struct; 966 initial_boot_params->off_dt_struct;
857 unflatten_dt_node(mem, &start, NULL, &allnextp); 967 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
858 if (*((u32 *)start) != OF_DT_END) 968 if (*((u32 *)start) != OF_DT_END)
859 printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start)); 969 printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
970 if (((u32 *)mem)[size / 4] != 0xdeadbeef)
971 printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
972 ((u32 *)mem)[size / 4] );
860 *allnextp = NULL; 973 *allnextp = NULL;
861 974
862 /* Get pointer to OF "/chosen" node for use everywhere */ 975 /* Get pointer to OF "/chosen" node for use everywhere */
@@ -880,7 +993,7 @@ void __init unflatten_device_tree(void)
880 993
881 994
882static int __init early_init_dt_scan_cpus(unsigned long node, 995static int __init early_init_dt_scan_cpus(unsigned long node,
883 const char *full_path, void *data) 996 const char *uname, int depth, void *data)
884{ 997{
885 char *type = get_flat_dt_prop(node, "device_type", NULL); 998 char *type = get_flat_dt_prop(node, "device_type", NULL);
886 u32 *prop; 999 u32 *prop;
@@ -947,13 +1060,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
947} 1060}
948 1061
949static int __init early_init_dt_scan_chosen(unsigned long node, 1062static int __init early_init_dt_scan_chosen(unsigned long node,
950 const char *full_path, void *data) 1063 const char *uname, int depth, void *data)
951{ 1064{
952 u32 *prop; 1065 u32 *prop;
953 u64 *prop64; 1066 u64 *prop64;
954 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end; 1067 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
955 1068
956 if (strcmp(full_path, "/chosen") != 0) 1069 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
1070
1071 if (depth != 1 || strcmp(uname, "chosen") != 0)
957 return 0; 1072 return 0;
958 1073
959 /* get platform type */ 1074 /* get platform type */
@@ -1003,18 +1118,20 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1003} 1118}
1004 1119
1005static int __init early_init_dt_scan_root(unsigned long node, 1120static int __init early_init_dt_scan_root(unsigned long node,
1006 const char *full_path, void *data) 1121 const char *uname, int depth, void *data)
1007{ 1122{
1008 u32 *prop; 1123 u32 *prop;
1009 1124
1010 if (strcmp(full_path, "/") != 0) 1125 if (depth != 0)
1011 return 0; 1126 return 0;
1012 1127
1013 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); 1128 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
1014 dt_root_size_cells = (prop == NULL) ? 1 : *prop; 1129 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
1015 1130 DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
1131
1016 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); 1132 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
1017 dt_root_addr_cells = (prop == NULL) ? 2 : *prop; 1133 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
1134 DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
1018 1135
1019 /* break now */ 1136 /* break now */
1020 return 1; 1137 return 1;
@@ -1042,7 +1159,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
1042 1159
1043 1160
1044static int __init early_init_dt_scan_memory(unsigned long node, 1161static int __init early_init_dt_scan_memory(unsigned long node,
1045 const char *full_path, void *data) 1162 const char *uname, int depth, void *data)
1046{ 1163{
1047 char *type = get_flat_dt_prop(node, "device_type", NULL); 1164 char *type = get_flat_dt_prop(node, "device_type", NULL);
1048 cell_t *reg, *endp; 1165 cell_t *reg, *endp;
@@ -1058,7 +1175,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
1058 1175
1059 endp = reg + (l / sizeof(cell_t)); 1176 endp = reg + (l / sizeof(cell_t));
1060 1177
1061 DBG("memory scan node %s ...\n", full_path); 1178 DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
1179 uname, l, reg[0], reg[1], reg[2], reg[3]);
1180
1062 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { 1181 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
1063 unsigned long base, size; 1182 unsigned long base, size;
1064 1183
@@ -1469,10 +1588,11 @@ struct device_node *of_find_node_by_path(const char *path)
1469 struct device_node *np = allnodes; 1588 struct device_node *np = allnodes;
1470 1589
1471 read_lock(&devtree_lock); 1590 read_lock(&devtree_lock);
1472 for (; np != 0; np = np->allnext) 1591 for (; np != 0; np = np->allnext) {
1473 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 1592 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
1474 && of_node_get(np)) 1593 && of_node_get(np))
1475 break; 1594 break;
1595 }
1476 read_unlock(&devtree_lock); 1596 read_unlock(&devtree_lock);
1477 return np; 1597 return np;
1478} 1598}
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index dbbe6c79d8da..122283a1d39a 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -892,7 +892,10 @@ static void __init prom_init_mem(void)
892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) 892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
893 RELOC(alloc_top) = RELOC(rmo_top); 893 RELOC(alloc_top) = RELOC(rmo_top);
894 else 894 else
895 RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top)); 895 /* Some RS64 machines have buggy firmware where claims up at 1GB
896 * fails. Cap at 768MB as a workaround. Still plenty of room.
897 */
898 RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top));
896 899
897 prom_printf("memory layout at init:\n"); 900 prom_printf("memory layout at init:\n");
898 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); 901 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
@@ -1534,7 +1537,8 @@ static unsigned long __init dt_find_string(char *str)
1534 */ 1537 */
1535#define MAX_PROPERTY_NAME 64 1538#define MAX_PROPERTY_NAME 64
1536 1539
1537static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, 1540static void __init scan_dt_build_strings(phandle node,
1541 unsigned long *mem_start,
1538 unsigned long *mem_end) 1542 unsigned long *mem_end)
1539{ 1543{
1540 unsigned long offset = reloc_offset(); 1544 unsigned long offset = reloc_offset();
@@ -1547,16 +1551,21 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1547 /* get and store all property names */ 1551 /* get and store all property names */
1548 prev_name = RELOC(""); 1552 prev_name = RELOC("");
1549 for (;;) { 1553 for (;;) {
1550 int rc;
1551
1552 /* 64 is max len of name including nul. */ 1554 /* 64 is max len of name including nul. */
1553 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); 1555 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
1554 rc = call_prom("nextprop", 3, 1, node, prev_name, namep); 1556 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
1555 if (rc != 1) {
1556 /* No more nodes: unwind alloc */ 1557 /* No more nodes: unwind alloc */
1557 *mem_start = (unsigned long)namep; 1558 *mem_start = (unsigned long)namep;
1558 break; 1559 break;
1559 } 1560 }
1561
1562 /* skip "name" */
1563 if (strcmp(namep, RELOC("name")) == 0) {
1564 *mem_start = (unsigned long)namep;
1565 prev_name = RELOC("name");
1566 continue;
1567 }
1568 /* get/create string entry */
1560 soff = dt_find_string(namep); 1569 soff = dt_find_string(namep);
1561 if (soff != 0) { 1570 if (soff != 0) {
1562 *mem_start = (unsigned long)namep; 1571 *mem_start = (unsigned long)namep;
@@ -1571,7 +1580,7 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1571 1580
1572 /* do all our children */ 1581 /* do all our children */
1573 child = call_prom("child", 1, 1, node); 1582 child = call_prom("child", 1, 1, node);
1574 while (child != (phandle)0) { 1583 while (child != 0) {
1575 scan_dt_build_strings(child, mem_start, mem_end); 1584 scan_dt_build_strings(child, mem_start, mem_end);
1576 child = call_prom("peer", 1, 1, child); 1585 child = call_prom("peer", 1, 1, child);
1577 } 1586 }
@@ -1580,16 +1589,13 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1580static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1589static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1581 unsigned long *mem_end) 1590 unsigned long *mem_end)
1582{ 1591{
1583 int l, align;
1584 phandle child; 1592 phandle child;
1585 char *namep, *prev_name, *sstart, *p, *ep; 1593 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
1586 unsigned long soff; 1594 unsigned long soff;
1587 unsigned char *valp; 1595 unsigned char *valp;
1588 unsigned long offset = reloc_offset(); 1596 unsigned long offset = reloc_offset();
1589 char pname[MAX_PROPERTY_NAME]; 1597 static char pname[MAX_PROPERTY_NAME];
1590 char *path; 1598 int l;
1591
1592 path = RELOC(prom_scratch);
1593 1599
1594 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); 1600 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1595 1601
@@ -1599,23 +1605,33 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1599 namep, *mem_end - *mem_start); 1605 namep, *mem_end - *mem_start);
1600 if (l >= 0) { 1606 if (l >= 0) {
1601 /* Didn't fit? Get more room. */ 1607 /* Didn't fit? Get more room. */
1602 if (l+1 > *mem_end - *mem_start) { 1608 if ((l+1) > (*mem_end - *mem_start)) {
1603 namep = make_room(mem_start, mem_end, l+1, 1); 1609 namep = make_room(mem_start, mem_end, l+1, 1);
1604 call_prom("package-to-path", 3, 1, node, namep, l); 1610 call_prom("package-to-path", 3, 1, node, namep, l);
1605 } 1611 }
1606 namep[l] = '\0'; 1612 namep[l] = '\0';
1613
1607 /* Fixup an Apple bug where they have bogus \0 chars in the 1614 /* Fixup an Apple bug where they have bogus \0 chars in the
1608 * middle of the path in some properties 1615 * middle of the path in some properties
1609 */ 1616 */
1610 for (p = namep, ep = namep + l; p < ep; p++) 1617 for (p = namep, ep = namep + l; p < ep; p++)
1611 if (*p == '\0') { 1618 if (*p == '\0') {
1612 memmove(p, p+1, ep - p); 1619 memmove(p, p+1, ep - p);
1613 ep--; l--; 1620 ep--; l--; p--;
1614 } 1621 }
1615 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); 1622
1623 /* now try to extract the unit name in that mess */
1624 for (p = namep, lp = NULL; *p; p++)
1625 if (*p == '/')
1626 lp = p + 1;
1627 if (lp != NULL)
1628 memmove(namep, lp, strlen(lp) + 1);
1629 *mem_start = _ALIGN(((unsigned long) namep) +
1630 strlen(namep) + 1, 4);
1616 } 1631 }
1617 1632
1618 /* get it again for debugging */ 1633 /* get it again for debugging */
1634 path = RELOC(prom_scratch);
1619 memset(path, 0, PROM_SCRATCH_SIZE); 1635 memset(path, 0, PROM_SCRATCH_SIZE);
1620 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); 1636 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1621 1637
@@ -1623,23 +1639,27 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1623 prev_name = RELOC(""); 1639 prev_name = RELOC("");
1624 sstart = (char *)RELOC(dt_string_start); 1640 sstart = (char *)RELOC(dt_string_start);
1625 for (;;) { 1641 for (;;) {
1626 int rc; 1642 if (call_prom("nextprop", 3, 1, node, prev_name,
1627 1643 RELOC(pname)) != 1)
1628 rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
1629 if (rc != 1)
1630 break; 1644 break;
1631 1645
1646 /* skip "name" */
1647 if (strcmp(RELOC(pname), RELOC("name")) == 0) {
1648 prev_name = RELOC("name");
1649 continue;
1650 }
1651
1632 /* find string offset */ 1652 /* find string offset */
1633 soff = dt_find_string(pname); 1653 soff = dt_find_string(RELOC(pname));
1634 if (soff == 0) { 1654 if (soff == 0) {
1635 prom_printf("WARNING: Can't find string index for <%s>, node %s\n", 1655 prom_printf("WARNING: Can't find string index for"
1636 pname, path); 1656 " <%s>, node %s\n", RELOC(pname), path);
1637 break; 1657 break;
1638 } 1658 }
1639 prev_name = sstart + soff; 1659 prev_name = sstart + soff;
1640 1660
1641 /* get length */ 1661 /* get length */
1642 l = call_prom("getproplen", 2, 1, node, pname); 1662 l = call_prom("getproplen", 2, 1, node, RELOC(pname));
1643 1663
1644 /* sanity checks */ 1664 /* sanity checks */
1645 if (l == PROM_ERROR) 1665 if (l == PROM_ERROR)
@@ -1648,7 +1668,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1648 prom_printf("WARNING: ignoring large property "); 1668 prom_printf("WARNING: ignoring large property ");
1649 /* It seems OF doesn't null-terminate the path :-( */ 1669 /* It seems OF doesn't null-terminate the path :-( */
1650 prom_printf("[%s] ", path); 1670 prom_printf("[%s] ", path);
1651 prom_printf("%s length 0x%x\n", pname, l); 1671 prom_printf("%s length 0x%x\n", RELOC(pname), l);
1652 continue; 1672 continue;
1653 } 1673 }
1654 1674
@@ -1658,17 +1678,16 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1658 dt_push_token(soff, mem_start, mem_end); 1678 dt_push_token(soff, mem_start, mem_end);
1659 1679
1660 /* push property content */ 1680 /* push property content */
1661 align = (l >= 8) ? 8 : 4; 1681 valp = make_room(mem_start, mem_end, l, 4);
1662 valp = make_room(mem_start, mem_end, l, align); 1682 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
1663 call_prom("getprop", 4, 1, node, pname, valp, l);
1664 *mem_start = _ALIGN(*mem_start, 4); 1683 *mem_start = _ALIGN(*mem_start, 4);
1665 } 1684 }
1666 1685
1667 /* Add a "linux,phandle" property. */ 1686 /* Add a "linux,phandle" property. */
1668 soff = dt_find_string(RELOC("linux,phandle")); 1687 soff = dt_find_string(RELOC("linux,phandle"));
1669 if (soff == 0) 1688 if (soff == 0)
1670 prom_printf("WARNING: Can't find string index for <linux-phandle>" 1689 prom_printf("WARNING: Can't find string index for"
1671 " node %s\n", path); 1690 " <linux-phandle> node %s\n", path);
1672 else { 1691 else {
1673 dt_push_token(OF_DT_PROP, mem_start, mem_end); 1692 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1674 dt_push_token(4, mem_start, mem_end); 1693 dt_push_token(4, mem_start, mem_end);
@@ -1679,7 +1698,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1679 1698
1680 /* do all our children */ 1699 /* do all our children */
1681 child = call_prom("child", 1, 1, node); 1700 child = call_prom("child", 1, 1, node);
1682 while (child != (phandle)0) { 1701 while (child != 0) {
1683 scan_dt_build_struct(child, mem_start, mem_end); 1702 scan_dt_build_struct(child, mem_start, mem_end);
1684 child = call_prom("peer", 1, 1, child); 1703 child = call_prom("peer", 1, 1, child);
1685 } 1704 }
@@ -1718,7 +1737,8 @@ static void __init flatten_device_tree(void)
1718 1737
1719 /* Build header and make room for mem rsv map */ 1738 /* Build header and make room for mem rsv map */
1720 mem_start = _ALIGN(mem_start, 4); 1739 mem_start = _ALIGN(mem_start, 4);
1721 hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4); 1740 hdr = make_room(&mem_start, &mem_end,
1741 sizeof(struct boot_param_header), 4);
1722 RELOC(dt_header_start) = (unsigned long)hdr; 1742 RELOC(dt_header_start) = (unsigned long)hdr;
1723 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); 1743 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1724 1744
@@ -1731,11 +1751,11 @@ static void __init flatten_device_tree(void)
1731 namep = make_room(&mem_start, &mem_end, 16, 1); 1751 namep = make_room(&mem_start, &mem_end, 16, 1);
1732 strcpy(namep, RELOC("linux,phandle")); 1752 strcpy(namep, RELOC("linux,phandle"));
1733 mem_start = (unsigned long)namep + strlen(namep) + 1; 1753 mem_start = (unsigned long)namep + strlen(namep) + 1;
1734 RELOC(dt_string_end) = mem_start;
1735 1754
1736 /* Build string array */ 1755 /* Build string array */
1737 prom_printf("Building dt strings...\n"); 1756 prom_printf("Building dt strings...\n");
1738 scan_dt_build_strings(root, &mem_start, &mem_end); 1757 scan_dt_build_strings(root, &mem_start, &mem_end);
1758 RELOC(dt_string_end) = mem_start;
1739 1759
1740 /* Build structure */ 1760 /* Build structure */
1741 mem_start = PAGE_ALIGN(mem_start); 1761 mem_start = PAGE_ALIGN(mem_start);
@@ -1750,9 +1770,11 @@ static void __init flatten_device_tree(void)
1750 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); 1770 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1751 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); 1771 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1752 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); 1772 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
1773 hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
1753 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); 1774 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1754 hdr->version = OF_DT_VERSION; 1775 hdr->version = OF_DT_VERSION;
1755 hdr->last_comp_version = 1; 1776 /* Version 16 is not backward compatible */
1777 hdr->last_comp_version = 0x10;
1756 1778
1757 /* Reserve the whole thing and copy the reserve map in, we 1779 /* Reserve the whole thing and copy the reserve map in, we
1758 * also bump mem_reserve_cnt to cause further reservations to 1780 * also bump mem_reserve_cnt to cause further reservations to
@@ -1808,6 +1830,9 @@ static void __init fixup_device_tree(void)
1808 /* does it need fixup ? */ 1830 /* does it need fixup ? */
1809 if (prom_getproplen(i2c, "interrupts") > 0) 1831 if (prom_getproplen(i2c, "interrupts") > 0)
1810 return; 1832 return;
1833
1834 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
1835
1811 /* interrupt on this revision of u3 is number 0 and level */ 1836 /* interrupt on this revision of u3 is number 0 and level */
1812 interrupts[0] = 0; 1837 interrupts[0] = 0;
1813 interrupts[1] = 1; 1838 interrupts[1] = 1;
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 1048817befb8..1dccadaddd1d 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -58,6 +58,21 @@ static int config_access_valid(struct device_node *dn, int where)
58 return 0; 58 return 0;
59} 59}
60 60
61static int of_device_available(struct device_node * dn)
62{
63 char * status;
64
65 status = get_property(dn, "status", NULL);
66
67 if (!status)
68 return 1;
69
70 if (!strcmp(status, "okay"))
71 return 1;
72
73 return 0;
74}
75
61static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) 76static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
62{ 77{
63 int returnval = -1; 78 int returnval = -1;
@@ -103,7 +118,7 @@ static int rtas_pci_read_config(struct pci_bus *bus,
103 118
104 /* Search only direct children of the bus */ 119 /* Search only direct children of the bus */
105 for (dn = busdn->child; dn; dn = dn->sibling) 120 for (dn = busdn->child; dn; dn = dn->sibling)
106 if (dn->devfn == devfn) 121 if (dn->devfn == devfn && of_device_available(dn))
107 return rtas_read_config(dn, where, size, val); 122 return rtas_read_config(dn, where, size, val);
108 return PCIBIOS_DEVICE_NOT_FOUND; 123 return PCIBIOS_DEVICE_NOT_FOUND;
109} 124}
@@ -146,7 +161,7 @@ static int rtas_pci_write_config(struct pci_bus *bus,
146 161
147 /* Search only direct children of the bus */ 162 /* Search only direct children of the bus */
148 for (dn = busdn->child; dn; dn = dn->sibling) 163 for (dn = busdn->child; dn; dn = dn->sibling)
149 if (dn->devfn == devfn) 164 if (dn->devfn == devfn && of_device_available(dn))
150 return rtas_write_config(dn, where, size, val); 165 return rtas_write_config(dn, where, size, val);
151 return PCIBIOS_DEVICE_NOT_FOUND; 166 return PCIBIOS_DEVICE_NOT_FOUND;
152} 167}
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index e9c24d2dbd91..ee3b20de2e7a 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -536,15 +536,19 @@ static void __init check_for_initrd(void)
536 536
537 DBG(" -> check_for_initrd()\n"); 537 DBG(" -> check_for_initrd()\n");
538 538
539 prop = (u64 *)get_property(of_chosen, "linux,initrd-start", NULL); 539 if (of_chosen) {
540 if (prop != NULL) { 540 prop = (u64 *)get_property(of_chosen,
541 initrd_start = (unsigned long)__va(*prop); 541 "linux,initrd-start", NULL);
542 prop = (u64 *)get_property(of_chosen, "linux,initrd-end", NULL);
543 if (prop != NULL) { 542 if (prop != NULL) {
544 initrd_end = (unsigned long)__va(*prop); 543 initrd_start = (unsigned long)__va(*prop);
545 initrd_below_start_ok = 1; 544 prop = (u64 *)get_property(of_chosen,
546 } else 545 "linux,initrd-end", NULL);
547 initrd_start = 0; 546 if (prop != NULL) {
547 initrd_end = (unsigned long)__va(*prop);
548 initrd_below_start_ok = 1;
549 } else
550 initrd_start = 0;
551 }
548 } 552 }
549 553
550 /* If we were passed an initrd, set the ROOT_DEV properly if the values 554 /* If we were passed an initrd, set the ROOT_DEV properly if the values
@@ -627,7 +631,7 @@ void __init setup_system(void)
627 * Initialize xmon 631 * Initialize xmon
628 */ 632 */
629#ifdef CONFIG_XMON_DEFAULT 633#ifdef CONFIG_XMON_DEFAULT
630 xmon_init(); 634 xmon_init(1);
631#endif 635#endif
632 /* 636 /*
633 * Register early console 637 * Register early console
@@ -1343,11 +1347,13 @@ static int __init early_xmon(char *p)
1343 /* ensure xmon is enabled */ 1347 /* ensure xmon is enabled */
1344 if (p) { 1348 if (p) {
1345 if (strncmp(p, "on", 2) == 0) 1349 if (strncmp(p, "on", 2) == 0)
1346 xmon_init(); 1350 xmon_init(1);
1351 if (strncmp(p, "off", 3) == 0)
1352 xmon_init(0);
1347 if (strncmp(p, "early", 5) != 0) 1353 if (strncmp(p, "early", 5) != 0)
1348 return 0; 1354 return 0;
1349 } 1355 }
1350 xmon_init(); 1356 xmon_init(1);
1351 debugger(NULL); 1357 debugger(NULL);
1352 1358
1353 return 0; 1359 return 0;
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 02b8ac4e0168..f311ee7c0070 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -13,6 +13,7 @@
13#include <asm/current.h> 13#include <asm/current.h>
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/cputable.h> 15#include <asm/cputable.h>
16#include <asm/firmware.h>
16#include <asm/hvcall.h> 17#include <asm/hvcall.h>
17#include <asm/prom.h> 18#include <asm/prom.h>
18#include <asm/systemcfg.h> 19#include <asm/systemcfg.h>
@@ -100,6 +101,8 @@ static int __init setup_smt_snooze_delay(char *str)
100} 101}
101__setup("smt-snooze-delay=", setup_smt_snooze_delay); 102__setup("smt-snooze-delay=", setup_smt_snooze_delay);
102 103
104#endif /* CONFIG_PPC_MULTIPLATFORM */
105
103/* 106/*
104 * Enabling PMCs will slow partition context switch times so we only do 107 * Enabling PMCs will slow partition context switch times so we only do
105 * it the first time we write to the PMCs. 108 * it the first time we write to the PMCs.
@@ -109,65 +112,15 @@ static DEFINE_PER_CPU(char, pmcs_enabled);
109 112
110void ppc64_enable_pmcs(void) 113void ppc64_enable_pmcs(void)
111{ 114{
112 unsigned long hid0;
113#ifdef CONFIG_PPC_PSERIES
114 unsigned long set, reset;
115#endif /* CONFIG_PPC_PSERIES */
116
117 /* Only need to enable them once */ 115 /* Only need to enable them once */
118 if (__get_cpu_var(pmcs_enabled)) 116 if (__get_cpu_var(pmcs_enabled))
119 return; 117 return;
120 118
121 __get_cpu_var(pmcs_enabled) = 1; 119 __get_cpu_var(pmcs_enabled) = 1;
122 120
123 switch (systemcfg->platform) { 121 if (ppc_md.enable_pmcs)
124 case PLATFORM_PSERIES: 122 ppc_md.enable_pmcs();
125 case PLATFORM_POWERMAC:
126 hid0 = mfspr(HID0);
127 hid0 |= 1UL << (63 - 20);
128
129 /* POWER4 requires the following sequence */
130 asm volatile(
131 "sync\n"
132 "mtspr %1, %0\n"
133 "mfspr %0, %1\n"
134 "mfspr %0, %1\n"
135 "mfspr %0, %1\n"
136 "mfspr %0, %1\n"
137 "mfspr %0, %1\n"
138 "mfspr %0, %1\n"
139 "isync" : "=&r" (hid0) : "i" (HID0), "0" (hid0):
140 "memory");
141 break;
142
143#ifdef CONFIG_PPC_PSERIES
144 case PLATFORM_PSERIES_LPAR:
145 set = 1UL << 63;
146 reset = 0;
147 plpar_hcall_norets(H_PERFMON, set, reset);
148 break;
149#endif /* CONFIG_PPC_PSERIES */
150
151 default:
152 break;
153 }
154
155#ifdef CONFIG_PPC_PSERIES
156 /* instruct hypervisor to maintain PMCs */
157 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR)
158 get_paca()->lppaca.pmcregs_in_use = 1;
159#endif /* CONFIG_PPC_PSERIES */
160} 123}
161
162#else
163
164/* PMC stuff */
165void ppc64_enable_pmcs(void)
166{
167 /* XXX Implement for iseries */
168}
169#endif /* CONFIG_PPC_MULTIPLATFORM */
170
171EXPORT_SYMBOL(ppc64_enable_pmcs); 124EXPORT_SYMBOL(ppc64_enable_pmcs);
172 125
173/* XXX convert to rusty's on_one_cpu */ 126/* XXX convert to rusty's on_one_cpu */
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 909462e1adea..1696e1b05bb9 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -67,6 +67,7 @@
67#include <asm/prom.h> 67#include <asm/prom.h>
68#include <asm/sections.h> 68#include <asm/sections.h>
69#include <asm/systemcfg.h> 69#include <asm/systemcfg.h>
70#include <asm/firmware.h>
70 71
71u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; 72u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
72 73
@@ -370,13 +371,11 @@ int timer_interrupt(struct pt_regs * regs)
370 process_hvlpevents(regs); 371 process_hvlpevents(regs);
371#endif 372#endif
372 373
373/* collect purr register values often, for accurate calculations */ 374 /* collect purr register values often, for accurate calculations */
374#if defined(CONFIG_PPC_PSERIES) 375 if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
375 if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
376 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 376 struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
377 cu->current_tb = mfspr(SPRN_PURR); 377 cu->current_tb = mfspr(SPRN_PURR);
378 } 378 }
379#endif
380 379
381 irq_exit(); 380 irq_exit();
382 381
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index 0c0ba71ac0e8..c90e1dd875ce 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -1,10 +1,11 @@
1/* 1/*
2 * IBM PowerPC Virtual I/O Infrastructure Support. 2 * IBM PowerPC Virtual I/O Infrastructure Support.
3 * 3 *
4 * Copyright (c) 2003 IBM Corp. 4 * Copyright (c) 2003-2005 IBM Corp.
5 * Dave Engebretsen engebret@us.ibm.com 5 * Dave Engebretsen engebret@us.ibm.com
6 * Santiago Leon santil@us.ibm.com 6 * Santiago Leon santil@us.ibm.com
7 * Hollis Blanchard <hollisb@us.ibm.com> 7 * Hollis Blanchard <hollisb@us.ibm.com>
8 * Stephen Rothwell
8 * 9 *
9 * This program is free software; you can redistribute it and/or 10 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 11 * modify it under the terms of the GNU General Public License
@@ -14,61 +15,30 @@
14 15
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/console.h> 17#include <linux/console.h>
17#include <linux/version.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/kobject.h>
20#include <linux/mm.h> 19#include <linux/mm.h>
21#include <linux/dma-mapping.h> 20#include <linux/dma-mapping.h>
22#include <asm/rtas.h>
23#include <asm/iommu.h> 21#include <asm/iommu.h>
24#include <asm/dma.h> 22#include <asm/dma.h>
25#include <asm/ppcdebug.h>
26#include <asm/vio.h> 23#include <asm/vio.h>
27#include <asm/hvcall.h>
28#include <asm/iSeries/vio.h>
29#include <asm/iSeries/HvTypes.h>
30#include <asm/iSeries/HvCallXm.h>
31#include <asm/iSeries/HvLpConfig.h>
32
33#define DBGENTER() pr_debug("%s entered\n", __FUNCTION__)
34
35extern struct subsystem devices_subsys; /* needed for vio_find_name() */
36 24
37static const struct vio_device_id *vio_match_device( 25static const struct vio_device_id *vio_match_device(
38 const struct vio_device_id *, const struct vio_dev *); 26 const struct vio_device_id *, const struct vio_dev *);
39 27
40#ifdef CONFIG_PPC_PSERIES 28struct vio_dev vio_bus_device = { /* fake "parent" device */
41static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
42static int vio_num_address_cells;
43#endif
44#ifdef CONFIG_PPC_ISERIES
45static struct iommu_table veth_iommu_table;
46static struct iommu_table vio_iommu_table;
47#endif
48static struct vio_dev vio_bus_device = { /* fake "parent" device */
49 .name = vio_bus_device.dev.bus_id, 29 .name = vio_bus_device.dev.bus_id,
50 .type = "", 30 .type = "",
51#ifdef CONFIG_PPC_ISERIES
52 .iommu_table = &vio_iommu_table,
53#endif
54 .dev.bus_id = "vio", 31 .dev.bus_id = "vio",
55 .dev.bus = &vio_bus_type, 32 .dev.bus = &vio_bus_type,
56}; 33};
57 34
58#ifdef CONFIG_PPC_ISERIES 35static struct vio_bus_ops vio_bus_ops;
59static struct vio_dev *__init vio_register_device_iseries(char *type,
60 uint32_t unit_num);
61
62struct device *iSeries_vio_dev = &vio_bus_device.dev;
63EXPORT_SYMBOL(iSeries_vio_dev);
64
65#define device_is_compatible(a, b) 1
66 36
67#endif 37/*
68 38 * Convert from struct device to struct vio_dev and pass to driver.
69/* convert from struct device to struct vio_dev and pass to driver.
70 * dev->driver has already been set by generic code because vio_bus_match 39 * dev->driver has already been set by generic code because vio_bus_match
71 * succeeded. */ 40 * succeeded.
41 */
72static int vio_bus_probe(struct device *dev) 42static int vio_bus_probe(struct device *dev)
73{ 43{
74 struct vio_dev *viodev = to_vio_dev(dev); 44 struct vio_dev *viodev = to_vio_dev(dev);
@@ -76,15 +46,12 @@ static int vio_bus_probe(struct device *dev)
76 const struct vio_device_id *id; 46 const struct vio_device_id *id;
77 int error = -ENODEV; 47 int error = -ENODEV;
78 48
79 DBGENTER();
80
81 if (!viodrv->probe) 49 if (!viodrv->probe)
82 return error; 50 return error;
83 51
84 id = vio_match_device(viodrv->id_table, viodev); 52 id = vio_match_device(viodrv->id_table, viodev);
85 if (id) { 53 if (id)
86 error = viodrv->probe(viodev, id); 54 error = viodrv->probe(viodev, id);
87 }
88 55
89 return error; 56 return error;
90} 57}
@@ -95,11 +62,8 @@ static int vio_bus_remove(struct device *dev)
95 struct vio_dev *viodev = to_vio_dev(dev); 62 struct vio_dev *viodev = to_vio_dev(dev);
96 struct vio_driver *viodrv = to_vio_driver(dev->driver); 63 struct vio_driver *viodrv = to_vio_driver(dev->driver);
97 64
98 DBGENTER(); 65 if (viodrv->remove)
99
100 if (viodrv->remove) {
101 return viodrv->remove(viodev); 66 return viodrv->remove(viodev);
102 }
103 67
104 /* driver can't remove */ 68 /* driver can't remove */
105 return 1; 69 return 1;
@@ -135,193 +99,72 @@ void vio_unregister_driver(struct vio_driver *viodrv)
135EXPORT_SYMBOL(vio_unregister_driver); 99EXPORT_SYMBOL(vio_unregister_driver);
136 100
137/** 101/**
138 * vio_match_device: - Tell if a VIO device has a matching VIO device id structure. 102 * vio_match_device: - Tell if a VIO device has a matching
139 * @ids: array of VIO device id structures to search in 103 * VIO device id structure.
140 * @dev: the VIO device structure to match against 104 * @ids: array of VIO device id structures to search in
105 * @dev: the VIO device structure to match against
141 * 106 *
142 * Used by a driver to check whether a VIO device present in the 107 * Used by a driver to check whether a VIO device present in the
143 * system is in its list of supported devices. Returns the matching 108 * system is in its list of supported devices. Returns the matching
144 * vio_device_id structure or NULL if there is no match. 109 * vio_device_id structure or NULL if there is no match.
145 */ 110 */
146static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, 111static const struct vio_device_id *vio_match_device(
147 const struct vio_dev *dev) 112 const struct vio_device_id *ids, const struct vio_dev *dev)
148{ 113{
149 DBGENTER(); 114 while (ids->type[0] != '\0') {
150 115 if (vio_bus_ops.match(ids, dev))
151 while (ids->type) {
152 if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
153 device_is_compatible(dev->dev.platform_data, ids->compat))
154 return ids; 116 return ids;
155 ids++; 117 ids++;
156 } 118 }
157 return NULL; 119 return NULL;
158} 120}
159 121
160#ifdef CONFIG_PPC_ISERIES
161void __init iommu_vio_init(void)
162{
163 struct iommu_table *t;
164 struct iommu_table_cb cb;
165 unsigned long cbp;
166 unsigned long itc_entries;
167
168 cb.itc_busno = 255; /* Bus 255 is the virtual bus */
169 cb.itc_virtbus = 0xff; /* Ask for virtual bus */
170
171 cbp = virt_to_abs(&cb);
172 HvCallXm_getTceTableParms(cbp);
173
174 itc_entries = cb.itc_size * PAGE_SIZE / sizeof(union tce_entry);
175 veth_iommu_table.it_size = itc_entries / 2;
176 veth_iommu_table.it_busno = cb.itc_busno;
177 veth_iommu_table.it_offset = cb.itc_offset;
178 veth_iommu_table.it_index = cb.itc_index;
179 veth_iommu_table.it_type = TCE_VB;
180 veth_iommu_table.it_blocksize = 1;
181
182 t = iommu_init_table(&veth_iommu_table);
183
184 if (!t)
185 printk("Virtual Bus VETH TCE table failed.\n");
186
187 vio_iommu_table.it_size = itc_entries - veth_iommu_table.it_size;
188 vio_iommu_table.it_busno = cb.itc_busno;
189 vio_iommu_table.it_offset = cb.itc_offset +
190 veth_iommu_table.it_size;
191 vio_iommu_table.it_index = cb.itc_index;
192 vio_iommu_table.it_type = TCE_VB;
193 vio_iommu_table.it_blocksize = 1;
194
195 t = iommu_init_table(&vio_iommu_table);
196
197 if (!t)
198 printk("Virtual Bus VIO TCE table failed.\n");
199}
200#endif
201
202#ifdef CONFIG_PPC_PSERIES
203static void probe_bus_pseries(void)
204{
205 struct device_node *node_vroot, *of_node;
206
207 node_vroot = find_devices("vdevice");
208 if ((node_vroot == NULL) || (node_vroot->child == NULL))
209 /* this machine doesn't do virtual IO, and that's ok */
210 return;
211
212 vio_num_address_cells = prom_n_addr_cells(node_vroot->child);
213
214 /*
215 * Create struct vio_devices for each virtual device in the device tree.
216 * Drivers will associate with them later.
217 */
218 for (of_node = node_vroot->child; of_node != NULL;
219 of_node = of_node->sibling) {
220 printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
221 vio_register_device_node(of_node);
222 }
223}
224#endif
225
226#ifdef CONFIG_PPC_ISERIES
227static void probe_bus_iseries(void)
228{
229 HvLpIndexMap vlan_map = HvLpConfig_getVirtualLanIndexMap();
230 struct vio_dev *viodev;
231 int i;
232
233 /* there is only one of each of these */
234 vio_register_device_iseries("viocons", 0);
235 vio_register_device_iseries("vscsi", 0);
236
237 vlan_map = HvLpConfig_getVirtualLanIndexMap();
238 for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
239 if ((vlan_map & (0x8000 >> i)) == 0)
240 continue;
241 viodev = vio_register_device_iseries("vlan", i);
242 /* veth is special and has it own iommu_table */
243 viodev->iommu_table = &veth_iommu_table;
244 }
245 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
246 vio_register_device_iseries("viodasd", i);
247 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
248 vio_register_device_iseries("viocd", i);
249 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
250 vio_register_device_iseries("viotape", i);
251}
252#endif
253
254/** 122/**
255 * vio_bus_init: - Initialize the virtual IO bus 123 * vio_bus_init: - Initialize the virtual IO bus
256 */ 124 */
257static int __init vio_bus_init(void) 125int __init vio_bus_init(struct vio_bus_ops *ops)
258{ 126{
259 int err; 127 int err;
260 128
129 vio_bus_ops = *ops;
130
261 err = bus_register(&vio_bus_type); 131 err = bus_register(&vio_bus_type);
262 if (err) { 132 if (err) {
263 printk(KERN_ERR "failed to register VIO bus\n"); 133 printk(KERN_ERR "failed to register VIO bus\n");
264 return err; 134 return err;
265 } 135 }
266 136
267 /* the fake parent of all vio devices, just to give us a nice directory */ 137 /*
138 * The fake parent of all vio devices, just to give us
139 * a nice directory
140 */
268 err = device_register(&vio_bus_device.dev); 141 err = device_register(&vio_bus_device.dev);
269 if (err) { 142 if (err) {
270 printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, 143 printk(KERN_WARNING "%s: device_register returned %i\n",
271 err); 144 __FUNCTION__, err);
272 return err; 145 return err;
273 } 146 }
274 147
275#ifdef CONFIG_PPC_PSERIES
276 probe_bus_pseries();
277#endif
278#ifdef CONFIG_PPC_ISERIES
279 probe_bus_iseries();
280#endif
281
282 return 0; 148 return 0;
283} 149}
284 150
285__initcall(vio_bus_init);
286
287/* vio_dev refcount hit 0 */ 151/* vio_dev refcount hit 0 */
288static void __devinit vio_dev_release(struct device *dev) 152static void __devinit vio_dev_release(struct device *dev)
289{ 153{
290 DBGENTER(); 154 if (vio_bus_ops.release_device)
291 155 vio_bus_ops.release_device(dev);
292#ifdef CONFIG_PPC_PSERIES
293 /* XXX free TCE table */
294 of_node_put(dev->platform_data);
295#endif
296 kfree(to_vio_dev(dev)); 156 kfree(to_vio_dev(dev));
297} 157}
298 158
299#ifdef CONFIG_PPC_PSERIES 159static ssize_t viodev_show_name(struct device *dev,
300static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) 160 struct device_attribute *attr, char *buf)
301{
302 struct device_node *of_node = dev->platform_data;
303
304 return sprintf(buf, "%s\n", of_node->full_name);
305}
306DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
307#endif
308
309static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
310{ 161{
311 return sprintf(buf, "%s\n", to_vio_dev(dev)->name); 162 return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
312} 163}
313DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); 164DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
314 165
315static struct vio_dev * __devinit vio_register_device_common( 166struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
316 struct vio_dev *viodev, char *name, char *type,
317 uint32_t unit_address, struct iommu_table *iommu_table)
318{ 167{
319 DBGENTER();
320
321 viodev->name = name;
322 viodev->type = type;
323 viodev->unit_address = unit_address;
324 viodev->iommu_table = iommu_table;
325 /* init generic 'struct device' fields: */ 168 /* init generic 'struct device' fields: */
326 viodev->dev.parent = &vio_bus_device.dev; 169 viodev->dev.parent = &vio_bus_device.dev;
327 viodev->dev.bus = &vio_bus_type; 170 viodev->dev.bus = &vio_bus_type;
@@ -338,222 +181,15 @@ static struct vio_dev * __devinit vio_register_device_common(
338 return viodev; 181 return viodev;
339} 182}
340 183
341#ifdef CONFIG_PPC_PSERIES
342/**
343 * vio_register_device_node: - Register a new vio device.
344 * @of_node: The OF node for this device.
345 *
346 * Creates and initializes a vio_dev structure from the data in
347 * of_node (dev.platform_data) and adds it to the list of virtual devices.
348 * Returns a pointer to the created vio_dev or NULL if node has
349 * NULL device_type or compatible fields.
350 */
351struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
352{
353 struct vio_dev *viodev;
354 unsigned int *unit_address;
355 unsigned int *irq_p;
356
357 DBGENTER();
358
359 /* we need the 'device_type' property, in order to match with drivers */
360 if ((NULL == of_node->type)) {
361 printk(KERN_WARNING
362 "%s: node %s missing 'device_type'\n", __FUNCTION__,
363 of_node->name ? of_node->name : "<unknown>");
364 return NULL;
365 }
366
367 unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
368 if (!unit_address) {
369 printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
370 of_node->name ? of_node->name : "<unknown>");
371 return NULL;
372 }
373
374 /* allocate a vio_dev for this node */
375 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
376 if (!viodev) {
377 return NULL;
378 }
379 memset(viodev, 0, sizeof(struct vio_dev));
380
381 viodev->dev.platform_data = of_node_get(of_node);
382
383 viodev->irq = NO_IRQ;
384 irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
385 if (irq_p) {
386 int virq = virt_irq_create_mapping(*irq_p);
387 if (virq == NO_IRQ) {
388 printk(KERN_ERR "Unable to allocate interrupt "
389 "number for %s\n", of_node->full_name);
390 } else
391 viodev->irq = irq_offset_up(virq);
392 }
393
394 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
395
396 /* register with generic device framework */
397 if (vio_register_device_common(viodev, of_node->name, of_node->type,
398 *unit_address, vio_build_iommu_table(viodev))
399 == NULL) {
400 /* XXX free TCE table */
401 kfree(viodev);
402 return NULL;
403 }
404 device_create_file(&viodev->dev, &dev_attr_devspec);
405
406 return viodev;
407}
408EXPORT_SYMBOL(vio_register_device_node);
409#endif
410
411#ifdef CONFIG_PPC_ISERIES
412/**
413 * vio_register_device: - Register a new vio device.
414 * @voidev: The device to register.
415 */
416static struct vio_dev *__init vio_register_device_iseries(char *type,
417 uint32_t unit_num)
418{
419 struct vio_dev *viodev;
420
421 DBGENTER();
422
423 /* allocate a vio_dev for this node */
424 viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
425 if (!viodev)
426 return NULL;
427 memset(viodev, 0, sizeof(struct vio_dev));
428
429 snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
430
431 return vio_register_device_common(viodev, viodev->dev.bus_id, type,
432 unit_num, &vio_iommu_table);
433}
434#endif
435
436void __devinit vio_unregister_device(struct vio_dev *viodev) 184void __devinit vio_unregister_device(struct vio_dev *viodev)
437{ 185{
438 DBGENTER(); 186 if (vio_bus_ops.unregister_device)
439#ifdef CONFIG_PPC_PSERIES 187 vio_bus_ops.unregister_device(viodev);
440 device_remove_file(&viodev->dev, &dev_attr_devspec);
441#endif
442 device_remove_file(&viodev->dev, &dev_attr_name); 188 device_remove_file(&viodev->dev, &dev_attr_name);
443 device_unregister(&viodev->dev); 189 device_unregister(&viodev->dev);
444} 190}
445EXPORT_SYMBOL(vio_unregister_device); 191EXPORT_SYMBOL(vio_unregister_device);
446 192
447#ifdef CONFIG_PPC_PSERIES
448/**
449 * vio_get_attribute: - get attribute for virtual device
450 * @vdev: The vio device to get property.
451 * @which: The property/attribute to be extracted.
452 * @length: Pointer to length of returned data size (unused if NULL).
453 *
454 * Calls prom.c's get_property() to return the value of the
455 * attribute specified by the preprocessor constant @which
456*/
457const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
458{
459 return get_property(vdev->dev.platform_data, (char*)which, length);
460}
461EXPORT_SYMBOL(vio_get_attribute);
462
463/* vio_find_name() - internal because only vio.c knows how we formatted the
464 * kobject name
465 * XXX once vio_bus_type.devices is actually used as a kset in
466 * drivers/base/bus.c, this function should be removed in favor of
467 * "device_find(kobj_name, &vio_bus_type)"
468 */
469static struct vio_dev *vio_find_name(const char *kobj_name)
470{
471 struct kobject *found;
472
473 found = kset_find_obj(&devices_subsys.kset, kobj_name);
474 if (!found)
475 return NULL;
476
477 return to_vio_dev(container_of(found, struct device, kobj));
478}
479
480/**
481 * vio_find_node - find an already-registered vio_dev
482 * @vnode: device_node of the virtual device we're looking for
483 */
484struct vio_dev *vio_find_node(struct device_node *vnode)
485{
486 uint32_t *unit_address;
487 char kobj_name[BUS_ID_SIZE];
488
489 /* construct the kobject name from the device node */
490 unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
491 if (!unit_address)
492 return NULL;
493 snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
494
495 return vio_find_name(kobj_name);
496}
497EXPORT_SYMBOL(vio_find_node);
498
499/**
500 * vio_build_iommu_table: - gets the dma information from OF and builds the TCE tree.
501 * @dev: the virtual device.
502 *
503 * Returns a pointer to the built tce tree, or NULL if it can't
504 * find property.
505*/
506static struct iommu_table * vio_build_iommu_table(struct vio_dev *dev)
507{
508 unsigned int *dma_window;
509 struct iommu_table *newTceTable;
510 unsigned long offset;
511 int dma_window_property_size;
512
513 dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
514 if(!dma_window) {
515 return NULL;
516 }
517
518 newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
519
520 /* There should be some code to extract the phys-encoded offset
521 using prom_n_addr_cells(). However, according to a comment
522 on earlier versions, it's always zero, so we don't bother */
523 offset = dma_window[1] >> PAGE_SHIFT;
524
525 /* TCE table size - measured in tce entries */
526 newTceTable->it_size = dma_window[4] >> PAGE_SHIFT;
527 /* offset for VIO should always be 0 */
528 newTceTable->it_offset = offset;
529 newTceTable->it_busno = 0;
530 newTceTable->it_index = (unsigned long)dma_window[0];
531 newTceTable->it_type = TCE_VB;
532
533 return iommu_init_table(newTceTable);
534}
535
536int vio_enable_interrupts(struct vio_dev *dev)
537{
538 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
539 if (rc != H_Success) {
540 printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
541 }
542 return rc;
543}
544EXPORT_SYMBOL(vio_enable_interrupts);
545
546int vio_disable_interrupts(struct vio_dev *dev)
547{
548 int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
549 if (rc != H_Success) {
550 printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
551 }
552 return rc;
553}
554EXPORT_SYMBOL(vio_disable_interrupts);
555#endif
556
557static dma_addr_t vio_map_single(struct device *dev, void *vaddr, 193static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
558 size_t size, enum dma_data_direction direction) 194 size_t size, enum dma_data_direction direction)
559{ 195{
@@ -615,18 +251,8 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv)
615 const struct vio_dev *vio_dev = to_vio_dev(dev); 251 const struct vio_dev *vio_dev = to_vio_dev(dev);
616 struct vio_driver *vio_drv = to_vio_driver(drv); 252 struct vio_driver *vio_drv = to_vio_driver(drv);
617 const struct vio_device_id *ids = vio_drv->id_table; 253 const struct vio_device_id *ids = vio_drv->id_table;
618 const struct vio_device_id *found_id;
619
620 DBGENTER();
621 254
622 if (!ids) 255 return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
623 return 0;
624
625 found_id = vio_match_device(ids, vio_dev);
626 if (found_id)
627 return 1;
628
629 return 0;
630} 256}
631 257
632struct bus_type vio_bus_type = { 258struct bus_type vio_bus_type = {
diff --git a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S
index fbff24827ae7..35eb49e1b890 100644
--- a/arch/ppc64/mm/hash_low.S
+++ b/arch/ppc64/mm/hash_low.S
@@ -129,12 +129,10 @@ _GLOBAL(__hash_page)
129 * code rather than call a C function...) 129 * code rather than call a C function...)
130 */ 130 */
131BEGIN_FTR_SECTION 131BEGIN_FTR_SECTION
132BEGIN_FTR_SECTION
133 mr r4,r30 132 mr r4,r30
134 mr r5,r7 133 mr r5,r7
135 bl .hash_page_do_lazy_icache 134 bl .hash_page_do_lazy_icache
136END_FTR_SECTION_IFSET(CPU_FTR_NOEXECUTE) 135END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
137END_FTR_SECTION_IFCLR(CPU_FTR_COHERENT_ICACHE)
138 136
139 /* At this point, r3 contains new PP bits, save them in 137 /* At this point, r3 contains new PP bits, save them in
140 * place of "access" in the param area (sic) 138 * place of "access" in the param area (sic)
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index a6abd3a979bf..7626bb59954d 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -51,7 +51,6 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
51 unsigned long prpn, unsigned long vflags, 51 unsigned long prpn, unsigned long vflags,
52 unsigned long rflags) 52 unsigned long rflags)
53{ 53{
54 unsigned long arpn = physRpn_to_absRpn(prpn);
55 hpte_t *hptep = htab_address + hpte_group; 54 hpte_t *hptep = htab_address + hpte_group;
56 unsigned long hpte_v, hpte_r; 55 unsigned long hpte_v, hpte_r;
57 int i; 56 int i;
@@ -74,7 +73,7 @@ long native_hpte_insert(unsigned long hpte_group, unsigned long va,
74 hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID; 73 hpte_v = (va >> 23) << HPTE_V_AVPN_SHIFT | vflags | HPTE_V_VALID;
75 if (vflags & HPTE_V_LARGE) 74 if (vflags & HPTE_V_LARGE)
76 va &= ~(1UL << HPTE_V_AVPN_SHIFT); 75 va &= ~(1UL << HPTE_V_AVPN_SHIFT);
77 hpte_r = (arpn << HPTE_R_RPN_SHIFT) | rflags; 76 hpte_r = (prpn << HPTE_R_RPN_SHIFT) | rflags;
78 77
79 hptep->r = hpte_r; 78 hptep->r = hpte_r;
80 /* Guarantee the second dword is visible before the valid bit */ 79 /* Guarantee the second dword is visible before the valid bit */
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 623b5d130c31..09475c8edf7c 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -210,7 +210,7 @@ void __init htab_initialize(void)
210 210
211 /* create bolted the linear mapping in the hash table */ 211 /* create bolted the linear mapping in the hash table */
212 for (i=0; i < lmb.memory.cnt; i++) { 212 for (i=0; i < lmb.memory.cnt; i++) {
213 base = lmb.memory.region[i].physbase + KERNELBASE; 213 base = lmb.memory.region[i].base + KERNELBASE;
214 size = lmb.memory.region[i].size; 214 size = lmb.memory.region[i].size;
215 215
216 DBG("creating mapping for region: %lx : %lx\n", base, size); 216 DBG("creating mapping for region: %lx : %lx\n", base, size);
@@ -302,7 +302,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
302 int local = 0; 302 int local = 0;
303 cpumask_t tmp; 303 cpumask_t tmp;
304 304
305 if ((ea & ~REGION_MASK) > EADDR_MASK) 305 if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
306 return 1; 306 return 1;
307 307
308 switch (REGION_ID(ea)) { 308 switch (REGION_ID(ea)) {
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index f9524602818d..e7833c80eb68 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -27,124 +27,94 @@
27 27
28#include <linux/sysctl.h> 28#include <linux/sysctl.h>
29 29
30#define HUGEPGDIR_SHIFT (HPAGE_SHIFT + PAGE_SHIFT - 3) 30#define NUM_LOW_AREAS (0x100000000UL >> SID_SHIFT)
31#define HUGEPGDIR_SIZE (1UL << HUGEPGDIR_SHIFT) 31#define NUM_HIGH_AREAS (PGTABLE_RANGE >> HTLB_AREA_SHIFT)
32#define HUGEPGDIR_MASK (~(HUGEPGDIR_SIZE-1))
33 32
34#define HUGEPTE_INDEX_SIZE 9 33/* Modelled after find_linux_pte() */
35#define HUGEPGD_INDEX_SIZE 10 34pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
36
37#define PTRS_PER_HUGEPTE (1 << HUGEPTE_INDEX_SIZE)
38#define PTRS_PER_HUGEPGD (1 << HUGEPGD_INDEX_SIZE)
39
40static inline int hugepgd_index(unsigned long addr)
41{
42 return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT;
43}
44
45static pud_t *hugepgd_offset(struct mm_struct *mm, unsigned long addr)
46{ 35{
47 int index; 36 pgd_t *pg;
37 pud_t *pu;
38 pmd_t *pm;
39 pte_t *pt;
48 40
49 if (! mm->context.huge_pgdir) 41 BUG_ON(! in_hugepage_area(mm->context, addr));
50 return NULL;
51 42
43 addr &= HPAGE_MASK;
44
45 pg = pgd_offset(mm, addr);
46 if (!pgd_none(*pg)) {
47 pu = pud_offset(pg, addr);
48 if (!pud_none(*pu)) {
49 pm = pmd_offset(pu, addr);
50 pt = (pte_t *)pm;
51 BUG_ON(!pmd_none(*pm)
52 && !(pte_present(*pt) && pte_huge(*pt)));
53 return pt;
54 }
55 }
52 56
53 index = hugepgd_index(addr); 57 return NULL;
54 BUG_ON(index >= PTRS_PER_HUGEPGD);
55 return (pud_t *)(mm->context.huge_pgdir + index);
56} 58}
57 59
58static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr) 60pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
59{ 61{
60 int index; 62 pgd_t *pg;
61 63 pud_t *pu;
62 if (pud_none(*dir)) 64 pmd_t *pm;
63 return NULL; 65 pte_t *pt;
64 66
65 index = (addr >> HPAGE_SHIFT) % PTRS_PER_HUGEPTE;
66 return (pte_t *)pud_page(*dir) + index;
67}
68
69static pud_t *hugepgd_alloc(struct mm_struct *mm, unsigned long addr)
70{
71 BUG_ON(! in_hugepage_area(mm->context, addr)); 67 BUG_ON(! in_hugepage_area(mm->context, addr));
72 68
73 if (! mm->context.huge_pgdir) { 69 addr &= HPAGE_MASK;
74 pgd_t *new;
75 spin_unlock(&mm->page_table_lock);
76 /* Don't use pgd_alloc(), because we want __GFP_REPEAT */
77 new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT);
78 BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
79 spin_lock(&mm->page_table_lock);
80 70
81 /* 71 pg = pgd_offset(mm, addr);
82 * Because we dropped the lock, we should re-check the 72 pu = pud_alloc(mm, pg, addr);
83 * entry, as somebody else could have populated it..
84 */
85 if (mm->context.huge_pgdir)
86 pgd_free(new);
87 else
88 mm->context.huge_pgdir = new;
89 }
90 return hugepgd_offset(mm, addr);
91}
92 73
93static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr) 74 if (pu) {
94{ 75 pm = pmd_alloc(mm, pu, addr);
95 if (! pud_present(*dir)) { 76 if (pm) {
96 pte_t *new; 77 pt = (pte_t *)pm;
97 78 BUG_ON(!pmd_none(*pm)
98 spin_unlock(&mm->page_table_lock); 79 && !(pte_present(*pt) && pte_huge(*pt)));
99 new = kmem_cache_alloc(zero_cache, GFP_KERNEL | __GFP_REPEAT); 80 return pt;
100 BUG_ON(memcmp(new, empty_zero_page, PAGE_SIZE));
101 spin_lock(&mm->page_table_lock);
102 /*
103 * Because we dropped the lock, we should re-check the
104 * entry, as somebody else could have populated it..
105 */
106 if (pud_present(*dir)) {
107 if (new)
108 kmem_cache_free(zero_cache, new);
109 } else {
110 struct page *ptepage;
111
112 if (! new)
113 return NULL;
114 ptepage = virt_to_page(new);
115 ptepage->mapping = (void *) mm;
116 ptepage->index = addr & HUGEPGDIR_MASK;
117 pud_populate(mm, dir, new);
118 } 81 }
119 } 82 }
120 83
121 return hugepte_offset(dir, addr); 84 return NULL;
122} 85}
123 86
124pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) 87#define HUGEPTE_BATCH_SIZE (HPAGE_SIZE / PMD_SIZE)
125{
126 pud_t *pud;
127 88
128 BUG_ON(! in_hugepage_area(mm->context, addr)); 89void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
90 pte_t *ptep, pte_t pte)
91{
92 int i;
129 93
130 pud = hugepgd_offset(mm, addr); 94 if (pte_present(*ptep)) {
131 if (! pud) 95 pte_clear(mm, addr, ptep);
132 return NULL; 96 flush_tlb_pending();
97 }
133 98
134 return hugepte_offset(pud, addr); 99 for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) {
100 *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
101 ptep++;
102 }
135} 103}
136 104
137pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) 105pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
106 pte_t *ptep)
138{ 107{
139 pud_t *pud; 108 unsigned long old = pte_update(ptep, ~0UL);
109 int i;
140 110
141 BUG_ON(! in_hugepage_area(mm->context, addr)); 111 if (old & _PAGE_HASHPTE)
112 hpte_update(mm, addr, old, 0);
142 113
143 pud = hugepgd_alloc(mm, addr); 114 for (i = 1; i < HUGEPTE_BATCH_SIZE; i++)
144 if (! pud) 115 ptep[i] = __pte(0);
145 return NULL;
146 116
147 return hugepte_alloc(mm, pud, addr); 117 return __pte(old);
148} 118}
149 119
150/* 120/*
@@ -162,15 +132,17 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
162 return 0; 132 return 0;
163} 133}
164 134
165static void flush_segments(void *parm) 135static void flush_low_segments(void *parm)
166{ 136{
167 u16 segs = (unsigned long) parm; 137 u16 areas = (unsigned long) parm;
168 unsigned long i; 138 unsigned long i;
169 139
170 asm volatile("isync" : : : "memory"); 140 asm volatile("isync" : : : "memory");
171 141
172 for (i = 0; i < 16; i++) { 142 BUILD_BUG_ON((sizeof(areas)*8) != NUM_LOW_AREAS);
173 if (! (segs & (1U << i))) 143
144 for (i = 0; i < NUM_LOW_AREAS; i++) {
145 if (! (areas & (1U << i)))
174 continue; 146 continue;
175 asm volatile("slbie %0" : : "r" (i << SID_SHIFT)); 147 asm volatile("slbie %0" : : "r" (i << SID_SHIFT));
176 } 148 }
@@ -178,13 +150,33 @@ static void flush_segments(void *parm)
178 asm volatile("isync" : : : "memory"); 150 asm volatile("isync" : : : "memory");
179} 151}
180 152
181static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg) 153static void flush_high_segments(void *parm)
182{ 154{
183 unsigned long start = seg << SID_SHIFT; 155 u16 areas = (unsigned long) parm;
184 unsigned long end = (seg+1) << SID_SHIFT; 156 unsigned long i, j;
157
158 asm volatile("isync" : : : "memory");
159
160 BUILD_BUG_ON((sizeof(areas)*8) != NUM_HIGH_AREAS);
161
162 for (i = 0; i < NUM_HIGH_AREAS; i++) {
163 if (! (areas & (1U << i)))
164 continue;
165 for (j = 0; j < (1UL << (HTLB_AREA_SHIFT-SID_SHIFT)); j++)
166 asm volatile("slbie %0"
167 :: "r" ((i << HTLB_AREA_SHIFT) + (j << SID_SHIFT)));
168 }
169
170 asm volatile("isync" : : : "memory");
171}
172
173static int prepare_low_area_for_htlb(struct mm_struct *mm, unsigned long area)
174{
175 unsigned long start = area << SID_SHIFT;
176 unsigned long end = (area+1) << SID_SHIFT;
185 struct vm_area_struct *vma; 177 struct vm_area_struct *vma;
186 178
187 BUG_ON(seg >= 16); 179 BUG_ON(area >= NUM_LOW_AREAS);
188 180
189 /* Check no VMAs are in the region */ 181 /* Check no VMAs are in the region */
190 vma = find_vma(mm, start); 182 vma = find_vma(mm, start);
@@ -194,20 +186,39 @@ static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg)
194 return 0; 186 return 0;
195} 187}
196 188
197static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs) 189static int prepare_high_area_for_htlb(struct mm_struct *mm, unsigned long area)
190{
191 unsigned long start = area << HTLB_AREA_SHIFT;
192 unsigned long end = (area+1) << HTLB_AREA_SHIFT;
193 struct vm_area_struct *vma;
194
195 BUG_ON(area >= NUM_HIGH_AREAS);
196
197 /* Check no VMAs are in the region */
198 vma = find_vma(mm, start);
199 if (vma && (vma->vm_start < end))
200 return -EBUSY;
201
202 return 0;
203}
204
205static int open_low_hpage_areas(struct mm_struct *mm, u16 newareas)
198{ 206{
199 unsigned long i; 207 unsigned long i;
200 208
201 newsegs &= ~(mm->context.htlb_segs); 209 BUILD_BUG_ON((sizeof(newareas)*8) != NUM_LOW_AREAS);
202 if (! newsegs) 210 BUILD_BUG_ON((sizeof(mm->context.low_htlb_areas)*8) != NUM_LOW_AREAS);
211
212 newareas &= ~(mm->context.low_htlb_areas);
213 if (! newareas)
203 return 0; /* The segments we want are already open */ 214 return 0; /* The segments we want are already open */
204 215
205 for (i = 0; i < 16; i++) 216 for (i = 0; i < NUM_LOW_AREAS; i++)
206 if ((1 << i) & newsegs) 217 if ((1 << i) & newareas)
207 if (prepare_low_seg_for_htlb(mm, i) != 0) 218 if (prepare_low_area_for_htlb(mm, i) != 0)
208 return -EBUSY; 219 return -EBUSY;
209 220
210 mm->context.htlb_segs |= newsegs; 221 mm->context.low_htlb_areas |= newareas;
211 222
212 /* update the paca copy of the context struct */ 223 /* update the paca copy of the context struct */
213 get_paca()->context = mm->context; 224 get_paca()->context = mm->context;
@@ -215,29 +226,63 @@ static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs)
215 /* the context change must make it to memory before the flush, 226 /* the context change must make it to memory before the flush,
216 * so that further SLB misses do the right thing. */ 227 * so that further SLB misses do the right thing. */
217 mb(); 228 mb();
218 on_each_cpu(flush_segments, (void *)(unsigned long)newsegs, 0, 1); 229 on_each_cpu(flush_low_segments, (void *)(unsigned long)newareas, 0, 1);
230
231 return 0;
232}
233
234static int open_high_hpage_areas(struct mm_struct *mm, u16 newareas)
235{
236 unsigned long i;
237
238 BUILD_BUG_ON((sizeof(newareas)*8) != NUM_HIGH_AREAS);
239 BUILD_BUG_ON((sizeof(mm->context.high_htlb_areas)*8)
240 != NUM_HIGH_AREAS);
241
242 newareas &= ~(mm->context.high_htlb_areas);
243 if (! newareas)
244 return 0; /* The areas we want are already open */
245
246 for (i = 0; i < NUM_HIGH_AREAS; i++)
247 if ((1 << i) & newareas)
248 if (prepare_high_area_for_htlb(mm, i) != 0)
249 return -EBUSY;
250
251 mm->context.high_htlb_areas |= newareas;
252
253 /* update the paca copy of the context struct */
254 get_paca()->context = mm->context;
255
256 /* the context change must make it to memory before the flush,
257 * so that further SLB misses do the right thing. */
258 mb();
259 on_each_cpu(flush_high_segments, (void *)(unsigned long)newareas, 0, 1);
219 260
220 return 0; 261 return 0;
221} 262}
222 263
223int prepare_hugepage_range(unsigned long addr, unsigned long len) 264int prepare_hugepage_range(unsigned long addr, unsigned long len)
224{ 265{
225 if (within_hugepage_high_range(addr, len)) 266 int err;
226 return 0; 267
227 else if ((addr < 0x100000000UL) && ((addr+len) < 0x100000000UL)) { 268 if ( (addr+len) < addr )
228 int err; 269 return -EINVAL;
229 /* Yes, we need both tests, in case addr+len overflows 270
230 * 64-bit arithmetic */ 271 if ((addr + len) < 0x100000000UL)
231 err = open_low_hpage_segs(current->mm, 272 err = open_low_hpage_areas(current->mm,
232 LOW_ESID_MASK(addr, len)); 273 LOW_ESID_MASK(addr, len));
233 if (err) 274 else
234 printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)" 275 err = open_high_hpage_areas(current->mm,
235 " failed (segs: 0x%04hx)\n", addr, len, 276 HTLB_AREA_MASK(addr, len));
236 LOW_ESID_MASK(addr, len)); 277 if (err) {
278 printk(KERN_DEBUG "prepare_hugepage_range(%lx, %lx)"
279 " failed (lowmask: 0x%04hx, highmask: 0x%04hx)\n",
280 addr, len,
281 LOW_ESID_MASK(addr, len), HTLB_AREA_MASK(addr, len));
237 return err; 282 return err;
238 } 283 }
239 284
240 return -EINVAL; 285 return 0;
241} 286}
242 287
243struct page * 288struct page *
@@ -309,8 +354,8 @@ full_search:
309 vma = find_vma(mm, addr); 354 vma = find_vma(mm, addr);
310 continue; 355 continue;
311 } 356 }
312 if (touches_hugepage_high_range(addr, len)) { 357 if (touches_hugepage_high_range(mm, addr, len)) {
313 addr = TASK_HPAGE_END; 358 addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
314 vma = find_vma(mm, addr); 359 vma = find_vma(mm, addr);
315 continue; 360 continue;
316 } 361 }
@@ -389,8 +434,9 @@ hugepage_recheck:
389 if (touches_hugepage_low_range(mm, addr, len)) { 434 if (touches_hugepage_low_range(mm, addr, len)) {
390 addr = (addr & ((~0) << SID_SHIFT)) - len; 435 addr = (addr & ((~0) << SID_SHIFT)) - len;
391 goto hugepage_recheck; 436 goto hugepage_recheck;
392 } else if (touches_hugepage_high_range(addr, len)) { 437 } else if (touches_hugepage_high_range(mm, addr, len)) {
393 addr = TASK_HPAGE_BASE - len; 438 addr = (addr & ((~0UL) << HTLB_AREA_SHIFT)) - len;
439 goto hugepage_recheck;
394 } 440 }
395 441
396 /* 442 /*
@@ -481,23 +527,28 @@ static unsigned long htlb_get_low_area(unsigned long len, u16 segmask)
481 return -ENOMEM; 527 return -ENOMEM;
482} 528}
483 529
484static unsigned long htlb_get_high_area(unsigned long len) 530static unsigned long htlb_get_high_area(unsigned long len, u16 areamask)
485{ 531{
486 unsigned long addr = TASK_HPAGE_BASE; 532 unsigned long addr = 0x100000000UL;
487 struct vm_area_struct *vma; 533 struct vm_area_struct *vma;
488 534
489 vma = find_vma(current->mm, addr); 535 vma = find_vma(current->mm, addr);
490 for (vma = find_vma(current->mm, addr); 536 while (addr + len <= TASK_SIZE_USER64) {
491 addr + len <= TASK_HPAGE_END;
492 vma = vma->vm_next) {
493 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */ 537 BUG_ON(vma && (addr >= vma->vm_end)); /* invariant */
494 BUG_ON(! within_hugepage_high_range(addr, len)); 538
539 if (! __within_hugepage_high_range(addr, len, areamask)) {
540 addr = ALIGN(addr+1, 1UL<<HTLB_AREA_SHIFT);
541 vma = find_vma(current->mm, addr);
542 continue;
543 }
495 544
496 if (!vma || (addr + len) <= vma->vm_start) 545 if (!vma || (addr + len) <= vma->vm_start)
497 return addr; 546 return addr;
498 addr = ALIGN(vma->vm_end, HPAGE_SIZE); 547 addr = ALIGN(vma->vm_end, HPAGE_SIZE);
499 /* Because we're in a hugepage region, this alignment 548 /* Depending on segmask this might not be a confirmed
500 * should not skip us over any VMAs */ 549 * hugepage region, so the ALIGN could have skipped
550 * some VMAs */
551 vma = find_vma(current->mm, addr);
501 } 552 }
502 553
503 return -ENOMEM; 554 return -ENOMEM;
@@ -507,6 +558,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
507 unsigned long len, unsigned long pgoff, 558 unsigned long len, unsigned long pgoff,
508 unsigned long flags) 559 unsigned long flags)
509{ 560{
561 int lastshift;
562 u16 areamask, curareas;
563
510 if (len & ~HPAGE_MASK) 564 if (len & ~HPAGE_MASK)
511 return -EINVAL; 565 return -EINVAL;
512 566
@@ -514,67 +568,49 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
514 return -EINVAL; 568 return -EINVAL;
515 569
516 if (test_thread_flag(TIF_32BIT)) { 570 if (test_thread_flag(TIF_32BIT)) {
517 int lastshift = 0; 571 curareas = current->mm->context.low_htlb_areas;
518 u16 segmask, cursegs = current->mm->context.htlb_segs;
519 572
520 /* First see if we can do the mapping in the existing 573 /* First see if we can do the mapping in the existing
521 * low hpage segments */ 574 * low areas */
522 addr = htlb_get_low_area(len, cursegs); 575 addr = htlb_get_low_area(len, curareas);
523 if (addr != -ENOMEM) 576 if (addr != -ENOMEM)
524 return addr; 577 return addr;
525 578
526 for (segmask = LOW_ESID_MASK(0x100000000UL-len, len); 579 lastshift = 0;
527 ! lastshift; segmask >>=1) { 580 for (areamask = LOW_ESID_MASK(0x100000000UL-len, len);
528 if (segmask & 1) 581 ! lastshift; areamask >>=1) {
582 if (areamask & 1)
529 lastshift = 1; 583 lastshift = 1;
530 584
531 addr = htlb_get_low_area(len, cursegs | segmask); 585 addr = htlb_get_low_area(len, curareas | areamask);
532 if ((addr != -ENOMEM) 586 if ((addr != -ENOMEM)
533 && open_low_hpage_segs(current->mm, segmask) == 0) 587 && open_low_hpage_areas(current->mm, areamask) == 0)
534 return addr; 588 return addr;
535 } 589 }
536 printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
537 " enough segments\n");
538 return -ENOMEM;
539 } else { 590 } else {
540 return htlb_get_high_area(len); 591 curareas = current->mm->context.high_htlb_areas;
541 }
542}
543
544void hugetlb_mm_free_pgd(struct mm_struct *mm)
545{
546 int i;
547 pgd_t *pgdir;
548
549 spin_lock(&mm->page_table_lock);
550
551 pgdir = mm->context.huge_pgdir;
552 if (! pgdir)
553 goto out;
554
555 mm->context.huge_pgdir = NULL;
556 592
557 /* cleanup any hugepte pages leftover */ 593 /* First see if we can do the mapping in the existing
558 for (i = 0; i < PTRS_PER_HUGEPGD; i++) { 594 * high areas */
559 pud_t *pud = (pud_t *)(pgdir + i); 595 addr = htlb_get_high_area(len, curareas);
560 596 if (addr != -ENOMEM)
561 if (! pud_none(*pud)) { 597 return addr;
562 pte_t *pte = (pte_t *)pud_page(*pud);
563 struct page *ptepage = virt_to_page(pte);
564 598
565 ptepage->mapping = NULL; 599 lastshift = 0;
600 for (areamask = HTLB_AREA_MASK(TASK_SIZE_USER64-len, len);
601 ! lastshift; areamask >>=1) {
602 if (areamask & 1)
603 lastshift = 1;
566 604
567 BUG_ON(memcmp(pte, empty_zero_page, PAGE_SIZE)); 605 addr = htlb_get_high_area(len, curareas | areamask);
568 kmem_cache_free(zero_cache, pte); 606 if ((addr != -ENOMEM)
607 && open_high_hpage_areas(current->mm, areamask) == 0)
608 return addr;
569 } 609 }
570 pud_clear(pud);
571 } 610 }
572 611 printk(KERN_DEBUG "hugetlb_get_unmapped_area() unable to open"
573 BUG_ON(memcmp(pgdir, empty_zero_page, PAGE_SIZE)); 612 " enough areas\n");
574 kmem_cache_free(zero_cache, pgdir); 613 return -ENOMEM;
575
576 out:
577 spin_unlock(&mm->page_table_lock);
578} 614}
579 615
580int hash_huge_page(struct mm_struct *mm, unsigned long access, 616int hash_huge_page(struct mm_struct *mm, unsigned long access,
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index b6e75b891ac0..c65b87b92756 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -31,7 +31,7 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr)
31 break; 31 break;
32 if ((unsigned long)tmp->addr >= ioremap_bot) 32 if ((unsigned long)tmp->addr >= ioremap_bot)
33 addr = tmp->size + (unsigned long) tmp->addr; 33 addr = tmp->size + (unsigned long) tmp->addr;
34 if (addr > IMALLOC_END-size) 34 if (addr >= IMALLOC_END-size)
35 return 1; 35 return 1;
36 } 36 }
37 *im_addr = addr; 37 *im_addr = addr;
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index e58a24d42879..c02dc9809ca5 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -42,7 +42,6 @@
42 42
43#include <asm/pgalloc.h> 43#include <asm/pgalloc.h>
44#include <asm/page.h> 44#include <asm/page.h>
45#include <asm/abs_addr.h>
46#include <asm/prom.h> 45#include <asm/prom.h>
47#include <asm/lmb.h> 46#include <asm/lmb.h>
48#include <asm/rtas.h> 47#include <asm/rtas.h>
@@ -66,6 +65,14 @@
66#include <asm/vdso.h> 65#include <asm/vdso.h>
67#include <asm/imalloc.h> 66#include <asm/imalloc.h>
68 67
68#if PGTABLE_RANGE > USER_VSID_RANGE
69#warning Limited user VSID range means pagetable space is wasted
70#endif
71
72#if (TASK_SIZE_USER64 < PGTABLE_RANGE) && (TASK_SIZE_USER64 < USER_VSID_RANGE)
73#warning TASK_SIZE is smaller than it needs to be.
74#endif
75
69int mem_init_done; 76int mem_init_done;
70unsigned long ioremap_bot = IMALLOC_BASE; 77unsigned long ioremap_bot = IMALLOC_BASE;
71static unsigned long phbs_io_bot = PHBS_IO_BASE; 78static unsigned long phbs_io_bot = PHBS_IO_BASE;
@@ -159,7 +166,6 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
159 ptep = pte_alloc_kernel(&init_mm, pmdp, ea); 166 ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
160 if (!ptep) 167 if (!ptep)
161 return -ENOMEM; 168 return -ENOMEM;
162 pa = abs_to_phys(pa);
163 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, 169 set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
164 __pgprot(flags))); 170 __pgprot(flags)));
165 spin_unlock(&init_mm.page_table_lock); 171 spin_unlock(&init_mm.page_table_lock);
@@ -226,7 +232,7 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
226 * Before that, we map using addresses going 232 * Before that, we map using addresses going
227 * up from ioremap_bot. imalloc will use 233 * up from ioremap_bot. imalloc will use
228 * the addresses from ioremap_bot through 234 * the addresses from ioremap_bot through
229 * IMALLOC_END (0xE000001fffffffff) 235 * IMALLOC_END
230 * 236 *
231 */ 237 */
232 pa = addr & PAGE_MASK; 238 pa = addr & PAGE_MASK;
@@ -417,12 +423,6 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
417 int index; 423 int index;
418 int err; 424 int err;
419 425
420#ifdef CONFIG_HUGETLB_PAGE
421 /* We leave htlb_segs as it was, but for a fork, we need to
422 * clear the huge_pgdir. */
423 mm->context.huge_pgdir = NULL;
424#endif
425
426again: 426again:
427 if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL)) 427 if (!idr_pre_get(&mmu_context_idr, GFP_KERNEL))
428 return -ENOMEM; 428 return -ENOMEM;
@@ -453,8 +453,6 @@ void destroy_context(struct mm_struct *mm)
453 spin_unlock(&mmu_context_lock); 453 spin_unlock(&mmu_context_lock);
454 454
455 mm->context.id = NO_CONTEXT; 455 mm->context.id = NO_CONTEXT;
456
457 hugetlb_mm_free_pgd(mm);
458} 456}
459 457
460/* 458/*
@@ -484,9 +482,9 @@ void __init mm_init_ppc64(void)
484 for (i = 1; i < lmb.memory.cnt; i++) { 482 for (i = 1; i < lmb.memory.cnt; i++) {
485 unsigned long base, prevbase, prevsize; 483 unsigned long base, prevbase, prevsize;
486 484
487 prevbase = lmb.memory.region[i-1].physbase; 485 prevbase = lmb.memory.region[i-1].base;
488 prevsize = lmb.memory.region[i-1].size; 486 prevsize = lmb.memory.region[i-1].size;
489 base = lmb.memory.region[i].physbase; 487 base = lmb.memory.region[i].base;
490 if (base > (prevbase + prevsize)) { 488 if (base > (prevbase + prevsize)) {
491 io_hole_start = prevbase + prevsize; 489 io_hole_start = prevbase + prevsize;
492 io_hole_size = base - (prevbase + prevsize); 490 io_hole_size = base - (prevbase + prevsize);
@@ -513,11 +511,8 @@ int page_is_ram(unsigned long pfn)
513 for (i=0; i < lmb.memory.cnt; i++) { 511 for (i=0; i < lmb.memory.cnt; i++) {
514 unsigned long base; 512 unsigned long base;
515 513
516#ifdef CONFIG_MSCHUNKS
517 base = lmb.memory.region[i].physbase;
518#else
519 base = lmb.memory.region[i].base; 514 base = lmb.memory.region[i].base;
520#endif 515
521 if ((paddr >= base) && 516 if ((paddr >= base) &&
522 (paddr < (base + lmb.memory.region[i].size))) { 517 (paddr < (base + lmb.memory.region[i].size))) {
523 return 1; 518 return 1;
@@ -547,7 +542,7 @@ void __init do_init_bootmem(void)
547 */ 542 */
548 bootmap_pages = bootmem_bootmap_pages(total_pages); 543 bootmap_pages = bootmem_bootmap_pages(total_pages);
549 544
550 start = abs_to_phys(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE)); 545 start = lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE);
551 BUG_ON(!start); 546 BUG_ON(!start);
552 547
553 boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); 548 boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
@@ -558,25 +553,25 @@ void __init do_init_bootmem(void)
558 * present. 553 * present.
559 */ 554 */
560 for (i=0; i < lmb.memory.cnt; i++) { 555 for (i=0; i < lmb.memory.cnt; i++) {
561 unsigned long physbase, size; 556 unsigned long base, size;
562 unsigned long start_pfn, end_pfn; 557 unsigned long start_pfn, end_pfn;
563 558
564 physbase = lmb.memory.region[i].physbase; 559 base = lmb.memory.region[i].base;
565 size = lmb.memory.region[i].size; 560 size = lmb.memory.region[i].size;
566 561
567 start_pfn = physbase >> PAGE_SHIFT; 562 start_pfn = base >> PAGE_SHIFT;
568 end_pfn = start_pfn + (size >> PAGE_SHIFT); 563 end_pfn = start_pfn + (size >> PAGE_SHIFT);
569 memory_present(0, start_pfn, end_pfn); 564 memory_present(0, start_pfn, end_pfn);
570 565
571 free_bootmem(physbase, size); 566 free_bootmem(base, size);
572 } 567 }
573 568
574 /* reserve the sections we're already using */ 569 /* reserve the sections we're already using */
575 for (i=0; i < lmb.reserved.cnt; i++) { 570 for (i=0; i < lmb.reserved.cnt; i++) {
576 unsigned long physbase = lmb.reserved.region[i].physbase; 571 unsigned long base = lmb.reserved.region[i].base;
577 unsigned long size = lmb.reserved.region[i].size; 572 unsigned long size = lmb.reserved.region[i].size;
578 573
579 reserve_bootmem(physbase, size); 574 reserve_bootmem(base, size);
580 } 575 }
581} 576}
582 577
@@ -615,10 +610,10 @@ static int __init setup_kcore(void)
615 int i; 610 int i;
616 611
617 for (i=0; i < lmb.memory.cnt; i++) { 612 for (i=0; i < lmb.memory.cnt; i++) {
618 unsigned long physbase, size; 613 unsigned long base, size;
619 struct kcore_list *kcore_mem; 614 struct kcore_list *kcore_mem;
620 615
621 physbase = lmb.memory.region[i].physbase; 616 base = lmb.memory.region[i].base;
622 size = lmb.memory.region[i].size; 617 size = lmb.memory.region[i].size;
623 618
624 /* GFP_ATOMIC to avoid might_sleep warnings during boot */ 619 /* GFP_ATOMIC to avoid might_sleep warnings during boot */
@@ -626,7 +621,7 @@ static int __init setup_kcore(void)
626 if (!kcore_mem) 621 if (!kcore_mem)
627 panic("mem_init: kmalloc failed\n"); 622 panic("mem_init: kmalloc failed\n");
628 623
629 kclist_add(kcore_mem, __va(physbase), size); 624 kclist_add(kcore_mem, __va(base), size);
630 } 625 }
631 626
632 kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); 627 kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START);
@@ -686,9 +681,6 @@ void __init mem_init(void)
686 681
687 mem_init_done = 1; 682 mem_init_done = 1;
688 683
689#ifdef CONFIG_PPC_ISERIES
690 iommu_vio_init();
691#endif
692 /* Initialize the vDSO */ 684 /* Initialize the vDSO */
693 vdso_init(); 685 vdso_init();
694} 686}
@@ -833,23 +825,43 @@ void __iomem * reserve_phb_iospace(unsigned long size)
833 return virt_addr; 825 return virt_addr;
834} 826}
835 827
836kmem_cache_t *zero_cache; 828static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags)
837
838static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags)
839{ 829{
840 memset(pte, 0, PAGE_SIZE); 830 memset(addr, 0, kmem_cache_size(cache));
841} 831}
842 832
833static const int pgtable_cache_size[2] = {
834 PTE_TABLE_SIZE, PMD_TABLE_SIZE
835};
836static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = {
837 "pgd_pte_cache", "pud_pmd_cache",
838};
839
840kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)];
841
843void pgtable_cache_init(void) 842void pgtable_cache_init(void)
844{ 843{
845 zero_cache = kmem_cache_create("zero", 844 int i;
846 PAGE_SIZE, 845
847 0, 846 BUILD_BUG_ON(PTE_TABLE_SIZE != pgtable_cache_size[PTE_CACHE_NUM]);
848 SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, 847 BUILD_BUG_ON(PMD_TABLE_SIZE != pgtable_cache_size[PMD_CACHE_NUM]);
849 zero_ctor, 848 BUILD_BUG_ON(PUD_TABLE_SIZE != pgtable_cache_size[PUD_CACHE_NUM]);
850 NULL); 849 BUILD_BUG_ON(PGD_TABLE_SIZE != pgtable_cache_size[PGD_CACHE_NUM]);
851 if (!zero_cache) 850
852 panic("pgtable_cache_init(): could not create zero_cache!\n"); 851 for (i = 0; i < ARRAY_SIZE(pgtable_cache_size); i++) {
852 int size = pgtable_cache_size[i];
853 const char *name = pgtable_cache_name[i];
854
855 pgtable_cache[i] = kmem_cache_create(name,
856 size, size,
857 SLAB_HWCACHE_ALIGN
858 | SLAB_MUST_HWCACHE_ALIGN,
859 zero_ctor,
860 NULL);
861 if (! pgtable_cache[i])
862 panic("pgtable_cache_init(): could not create %s!\n",
863 name);
864 }
853} 865}
854 866
855pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, 867pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index 0b191f2de016..c3116f0d788c 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -671,7 +671,7 @@ new_range:
671 * Mark reserved regions on this node 671 * Mark reserved regions on this node
672 */ 672 */
673 for (i = 0; i < lmb.reserved.cnt; i++) { 673 for (i = 0; i < lmb.reserved.cnt; i++) {
674 unsigned long physbase = lmb.reserved.region[i].physbase; 674 unsigned long physbase = lmb.reserved.region[i].base;
675 unsigned long size = lmb.reserved.region[i].size; 675 unsigned long size = lmb.reserved.region[i].size;
676 676
677 if (pa_to_nid(physbase) != nid && 677 if (pa_to_nid(physbase) != nid &&
diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S
index 8379d678f70f..698d6b9ed6d1 100644
--- a/arch/ppc64/mm/slb_low.S
+++ b/arch/ppc64/mm/slb_low.S
@@ -89,32 +89,29 @@ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
89 b 9f 89 b 9f
90 90
910: /* user address: proto-VSID = context<<15 | ESID */ 910: /* user address: proto-VSID = context<<15 | ESID */
92 li r11,SLB_VSID_USER 92 srdi. r9,r3,USER_ESID_BITS
93
94 srdi. r9,r3,13
95 bne- 8f /* invalid ea bits set */ 93 bne- 8f /* invalid ea bits set */
96 94
97#ifdef CONFIG_HUGETLB_PAGE 95#ifdef CONFIG_HUGETLB_PAGE
98BEGIN_FTR_SECTION 96BEGIN_FTR_SECTION
99 /* check against the hugepage ranges */ 97 lhz r9,PACAHIGHHTLBAREAS(r13)
100 cmpldi r3,(TASK_HPAGE_END>>SID_SHIFT) 98 srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT)
101 bge 6f /* >= TASK_HPAGE_END */ 99 srd r9,r9,r11
102 cmpldi r3,(TASK_HPAGE_BASE>>SID_SHIFT) 100 lhz r11,PACALOWHTLBAREAS(r13)
103 bge 5f /* TASK_HPAGE_BASE..TASK_HPAGE_END */ 101 srd r11,r11,r3
104 cmpldi r3,16 102 or r9,r9,r11
105 bge 6f /* 4GB..TASK_HPAGE_BASE */ 103END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
106 104#endif /* CONFIG_HUGETLB_PAGE */
107 lhz r9,PACAHTLBSEGS(r13) 105
108 srd r9,r9,r3 106 li r11,SLB_VSID_USER
109 andi. r9,r9,1 107
110 beq 6f 108#ifdef CONFIG_HUGETLB_PAGE
111 109BEGIN_FTR_SECTION
1125: /* this is a hugepage user address */ 110 rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */
113 li r11,(SLB_VSID_USER|SLB_VSID_L)
114END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) 111END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE)
115#endif /* CONFIG_HUGETLB_PAGE */ 112#endif /* CONFIG_HUGETLB_PAGE */
116 113
1176: ld r9,PACACONTEXTID(r13) 114 ld r9,PACACONTEXTID(r13)
118 rldimi r3,r9,USER_ESID_BITS,0 115 rldimi r3,r9,USER_ESID_BITS,0
119 116
1209: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ 1179: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */
diff --git a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
index 26f0172c4527..d8a6593a13f0 100644
--- a/arch/ppc64/mm/tlb.c
+++ b/arch/ppc64/mm/tlb.c
@@ -41,7 +41,58 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
41DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); 41DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
42unsigned long pte_freelist_forced_free; 42unsigned long pte_freelist_forced_free;
43 43
44void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) 44struct pte_freelist_batch
45{
46 struct rcu_head rcu;
47 unsigned int index;
48 pgtable_free_t tables[0];
49};
50
51DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
52unsigned long pte_freelist_forced_free;
53
54#define PTE_FREELIST_SIZE \
55 ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
56 / sizeof(pgtable_free_t))
57
58#ifdef CONFIG_SMP
59static void pte_free_smp_sync(void *arg)
60{
61 /* Do nothing, just ensure we sync with all CPUs */
62}
63#endif
64
65/* This is only called when we are critically out of memory
66 * (and fail to get a page in pte_free_tlb).
67 */
68static void pgtable_free_now(pgtable_free_t pgf)
69{
70 pte_freelist_forced_free++;
71
72 smp_call_function(pte_free_smp_sync, NULL, 0, 1);
73
74 pgtable_free(pgf);
75}
76
77static void pte_free_rcu_callback(struct rcu_head *head)
78{
79 struct pte_freelist_batch *batch =
80 container_of(head, struct pte_freelist_batch, rcu);
81 unsigned int i;
82
83 for (i = 0; i < batch->index; i++)
84 pgtable_free(batch->tables[i]);
85
86 free_page((unsigned long)batch);
87}
88
89static void pte_free_submit(struct pte_freelist_batch *batch)
90{
91 INIT_RCU_HEAD(&batch->rcu);
92 call_rcu(&batch->rcu, pte_free_rcu_callback);
93}
94
95void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
45{ 96{
46 /* This is safe as we are holding page_table_lock */ 97 /* This is safe as we are holding page_table_lock */
47 cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id()); 98 cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
@@ -49,19 +100,19 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage)
49 100
50 if (atomic_read(&tlb->mm->mm_users) < 2 || 101 if (atomic_read(&tlb->mm->mm_users) < 2 ||
51 cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) { 102 cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
52 pte_free(ptepage); 103 pgtable_free(pgf);
53 return; 104 return;
54 } 105 }
55 106
56 if (*batchp == NULL) { 107 if (*batchp == NULL) {
57 *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC); 108 *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
58 if (*batchp == NULL) { 109 if (*batchp == NULL) {
59 pte_free_now(ptepage); 110 pgtable_free_now(pgf);
60 return; 111 return;
61 } 112 }
62 (*batchp)->index = 0; 113 (*batchp)->index = 0;
63 } 114 }
64 (*batchp)->pages[(*batchp)->index++] = ptepage; 115 (*batchp)->tables[(*batchp)->index++] = pgf;
65 if ((*batchp)->index == PTE_FREELIST_SIZE) { 116 if ((*batchp)->index == PTE_FREELIST_SIZE) {
66 pte_free_submit(*batchp); 117 pte_free_submit(*batchp);
67 *batchp = NULL; 118 *batchp = NULL;
@@ -132,42 +183,6 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
132 put_cpu(); 183 put_cpu();
133} 184}
134 185
135#ifdef CONFIG_SMP
136static void pte_free_smp_sync(void *arg)
137{
138 /* Do nothing, just ensure we sync with all CPUs */
139}
140#endif
141
142/* This is only called when we are critically out of memory
143 * (and fail to get a page in pte_free_tlb).
144 */
145void pte_free_now(struct page *ptepage)
146{
147 pte_freelist_forced_free++;
148
149 smp_call_function(pte_free_smp_sync, NULL, 0, 1);
150
151 pte_free(ptepage);
152}
153
154static void pte_free_rcu_callback(struct rcu_head *head)
155{
156 struct pte_freelist_batch *batch =
157 container_of(head, struct pte_freelist_batch, rcu);
158 unsigned int i;
159
160 for (i = 0; i < batch->index; i++)
161 pte_free(batch->pages[i]);
162 free_page((unsigned long)batch);
163}
164
165void pte_free_submit(struct pte_freelist_batch *batch)
166{
167 INIT_RCU_HEAD(&batch->rcu);
168 call_rcu(&batch->rcu, pte_free_rcu_callback);
169}
170
171void pte_free_finish(void) 186void pte_free_finish(void)
172{ 187{
173 /* This is safe as we are holding page_table_lock */ 188 /* This is safe as we are holding page_table_lock */
diff --git a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
index b28bfda23d94..4acd1a424933 100644
--- a/arch/ppc64/oprofile/common.c
+++ b/arch/ppc64/oprofile/common.c
@@ -153,6 +153,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
153 153
154 case PV_970: 154 case PV_970:
155 case PV_970FX: 155 case PV_970FX:
156 case PV_970MP:
156 model = &op_model_power4; 157 model = &op_model_power4;
157 model->num_counters = 8; 158 model->num_counters = 8;
158 ops->cpu_type = "ppc64/970"; 159 ops->cpu_type = "ppc64/970";
diff --git a/arch/ppc64/xmon/start.c b/arch/ppc64/xmon/start.c
index a9265bcc79b2..f86b584acd76 100644
--- a/arch/ppc64/xmon/start.c
+++ b/arch/ppc64/xmon/start.c
@@ -27,7 +27,7 @@ static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs,
27 struct tty_struct *tty) 27 struct tty_struct *tty)
28{ 28{
29 /* ensure xmon is enabled */ 29 /* ensure xmon is enabled */
30 xmon_init(); 30 xmon_init(1);
31 debugger(pt_regs); 31 debugger(pt_regs);
32} 32}
33 33
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 05539439e6bc..45908b10acd3 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -2496,15 +2496,25 @@ static void dump_stab(void)
2496 } 2496 }
2497} 2497}
2498 2498
2499void xmon_init(void) 2499void xmon_init(int enable)
2500{ 2500{
2501 __debugger = xmon; 2501 if (enable) {
2502 __debugger_ipi = xmon_ipi; 2502 __debugger = xmon;
2503 __debugger_bpt = xmon_bpt; 2503 __debugger_ipi = xmon_ipi;
2504 __debugger_sstep = xmon_sstep; 2504 __debugger_bpt = xmon_bpt;
2505 __debugger_iabr_match = xmon_iabr_match; 2505 __debugger_sstep = xmon_sstep;
2506 __debugger_dabr_match = xmon_dabr_match; 2506 __debugger_iabr_match = xmon_iabr_match;
2507 __debugger_fault_handler = xmon_fault_handler; 2507 __debugger_dabr_match = xmon_dabr_match;
2508 __debugger_fault_handler = xmon_fault_handler;
2509 } else {
2510 __debugger = NULL;
2511 __debugger_ipi = NULL;
2512 __debugger_bpt = NULL;
2513 __debugger_sstep = NULL;
2514 __debugger_iabr_match = NULL;
2515 __debugger_dabr_match = NULL;
2516 __debugger_fault_handler = NULL;
2517 }
2508} 2518}
2509 2519
2510void dump_segments(void) 2520void dump_segments(void)
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 55352ed85e8a..53c192a4982f 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -32,7 +32,6 @@
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/root_dev.h> 33#include <linux/root_dev.h>
34 34
35#include <asm/segment.h>
36#include <asm/system.h> 35#include <asm/system.h>
37#include <asm/io.h> 36#include <asm/io.h>
38#include <asm/processor.h> 37#include <asm/processor.h>
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c
index fd8005a3e6bd..591547af4c65 100644
--- a/arch/sparc/kernel/tick14.c
+++ b/arch/sparc/kernel/tick14.c
@@ -19,7 +19,6 @@
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20 20
21#include <asm/oplib.h> 21#include <asm/oplib.h>
22#include <asm/segment.h>
23#include <asm/timer.h> 22#include <asm/timer.h>
24#include <asm/mostek.h> 23#include <asm/mostek.h>
25#include <asm/system.h> 24#include <asm/system.h>
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 6486cbf2efe9..3b759aefc170 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -32,7 +32,6 @@
32#include <linux/profile.h> 32#include <linux/profile.h>
33 33
34#include <asm/oplib.h> 34#include <asm/oplib.h>
35#include <asm/segment.h>
36#include <asm/timer.h> 35#include <asm/timer.h>
37#include <asm/mostek.h> 36#include <asm/mostek.h>
38#include <asm/system.h> 37#include <asm/system.h>
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c
index 37f4107bae66..2bbd53f3cafb 100644
--- a/arch/sparc/mm/fault.c
+++ b/arch/sparc/mm/fault.c
@@ -23,7 +23,6 @@
23#include <linux/module.h> 23#include <linux/module.h>
24 24
25#include <asm/system.h> 25#include <asm/system.h>
26#include <asm/segment.h>
27#include <asm/page.h> 26#include <asm/page.h>
28#include <asm/pgtable.h> 27#include <asm/pgtable.h>
29#include <asm/memreg.h> 28#include <asm/memreg.h>
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index ec2e05028a10..c03babaa0498 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -25,7 +25,6 @@
25#include <linux/bootmem.h> 25#include <linux/bootmem.h>
26 26
27#include <asm/system.h> 27#include <asm/system.h>
28#include <asm/segment.h>
29#include <asm/vac-ops.h> 28#include <asm/vac-ops.h>
30#include <asm/page.h> 29#include <asm/page.h>
31#include <asm/pgtable.h> 30#include <asm/pgtable.h>
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 88332f00094a..cecdc0a7521f 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -21,6 +21,7 @@
21#include <asm/visasm.h> 21#include <asm/visasm.h>
22#include <asm/estate.h> 22#include <asm/estate.h>
23#include <asm/auxio.h> 23#include <asm/auxio.h>
24#include <asm/sfafsr.h>
24 25
25#define curptr g6 26#define curptr g6
26 27
@@ -690,14 +691,159 @@ netbsd_syscall:
690 retl 691 retl
691 nop 692 nop
692 693
693 /* These next few routines must be sure to clear the 694 /* We need to carefully read the error status, ACK
694 * SFSR FaultValid bit so that the fast tlb data protection 695 * the errors, prevent recursive traps, and pass the
695 * handler does not flush the wrong context and lock up the 696 * information on to C code for logging.
696 * box. 697 *
698 * We pass the AFAR in as-is, and we encode the status
699 * information as described in asm-sparc64/sfafsr.h
700 */
701 .globl __spitfire_access_error
702__spitfire_access_error:
703 /* Disable ESTATE error reporting so that we do not
704 * take recursive traps and RED state the processor.
705 */
706 stxa %g0, [%g0] ASI_ESTATE_ERROR_EN
707 membar #Sync
708
709 mov UDBE_UE, %g1
710 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
711
712 /* __spitfire_cee_trap branches here with AFSR in %g4 and
713 * UDBE_CE in %g1. It only clears ESTATE_ERR_CE in the
714 * ESTATE Error Enable register.
715 */
716__spitfire_cee_trap_continue:
717 ldxa [%g0] ASI_AFAR, %g5 ! Get AFAR
718
719 rdpr %tt, %g3
720 and %g3, 0x1ff, %g3 ! Paranoia
721 sllx %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
722 or %g4, %g3, %g4
723 rdpr %tl, %g3
724 cmp %g3, 1
725 mov 1, %g3
726 bleu %xcc, 1f
727 sllx %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
728
729 or %g4, %g3, %g4
730
731 /* Read in the UDB error register state, clearing the
732 * sticky error bits as-needed. We only clear them if
733 * the UE bit is set. Likewise, __spitfire_cee_trap
734 * below will only do so if the CE bit is set.
735 *
736 * NOTE: UltraSparc-I/II have high and low UDB error
737 * registers, corresponding to the two UDB units
738 * present on those chips. UltraSparc-IIi only
739 * has a single UDB, called "SDB" in the manual.
740 * For IIi the upper UDB register always reads
741 * as zero so for our purposes things will just
742 * work with the checks below.
697 */ 743 */
698 .globl __do_data_access_exception 7441: ldxa [%g0] ASI_UDBH_ERROR_R, %g3
699 .globl __do_data_access_exception_tl1 745 and %g3, 0x3ff, %g7 ! Paranoia
700__do_data_access_exception_tl1: 746 sllx %g7, SFSTAT_UDBH_SHIFT, %g7
747 or %g4, %g7, %g4
748 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
749 be,pn %xcc, 1f
750 nop
751 stxa %g3, [%g0] ASI_UDB_ERROR_W
752 membar #Sync
753
7541: mov 0x18, %g3
755 ldxa [%g3] ASI_UDBL_ERROR_R, %g3
756 and %g3, 0x3ff, %g7 ! Paranoia
757 sllx %g7, SFSTAT_UDBL_SHIFT, %g7
758 or %g4, %g7, %g4
759 andcc %g3, %g1, %g3 ! UDBE_UE or UDBE_CE
760 be,pn %xcc, 1f
761 nop
762 mov 0x18, %g7
763 stxa %g3, [%g7] ASI_UDB_ERROR_W
764 membar #Sync
765
7661: /* Ok, now that we've latched the error state,
767 * clear the sticky bits in the AFSR.
768 */
769 stxa %g4, [%g0] ASI_AFSR
770 membar #Sync
771
772 rdpr %tl, %g2
773 cmp %g2, 1
774 rdpr %pil, %g2
775 bleu,pt %xcc, 1f
776 wrpr %g0, 15, %pil
777
778 ba,pt %xcc, etraptl1
779 rd %pc, %g7
780
781 ba,pt %xcc, 2f
782 nop
783
7841: ba,pt %xcc, etrap_irq
785 rd %pc, %g7
786
7872: mov %l4, %o1
788 mov %l5, %o2
789 call spitfire_access_error
790 add %sp, PTREGS_OFF, %o0
791 ba,pt %xcc, rtrap
792 clr %l6
793
794 /* This is the trap handler entry point for ECC correctable
795 * errors. They are corrected, but we listen for the trap
796 * so that the event can be logged.
797 *
798 * Disrupting errors are either:
799 * 1) single-bit ECC errors during UDB reads to system
800 * memory
801 * 2) data parity errors during write-back events
802 *
803 * As far as I can make out from the manual, the CEE trap
804 * is only for correctable errors during memory read
805 * accesses by the front-end of the processor.
806 *
807 * The code below is only for trap level 1 CEE events,
808 * as it is the only situation where we can safely record
809 * and log. For trap level >1 we just clear the CE bit
810 * in the AFSR and return.
811 *
812 * This is just like __spiftire_access_error above, but it
813 * specifically handles correctable errors. If an
814 * uncorrectable error is indicated in the AFSR we
815 * will branch directly above to __spitfire_access_error
816 * to handle it instead. Uncorrectable therefore takes
817 * priority over correctable, and the error logging
818 * C code will notice this case by inspecting the
819 * trap type.
820 */
821 .globl __spitfire_cee_trap
822__spitfire_cee_trap:
823 ldxa [%g0] ASI_AFSR, %g4 ! Get AFSR
824 mov 1, %g3
825 sllx %g3, SFAFSR_UE_SHIFT, %g3
826 andcc %g4, %g3, %g0 ! Check for UE
827 bne,pn %xcc, __spitfire_access_error
828 nop
829
830 /* Ok, in this case we only have a correctable error.
831 * Indicate we only wish to capture that state in register
832 * %g1, and we only disable CE error reporting unlike UE
833 * handling which disables all errors.
834 */
835 ldxa [%g0] ASI_ESTATE_ERROR_EN, %g3
836 andn %g3, ESTATE_ERR_CE, %g3
837 stxa %g3, [%g0] ASI_ESTATE_ERROR_EN
838 membar #Sync
839
840 /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
841 ba,pt %xcc, __spitfire_cee_trap_continue
842 mov UDBE_CE, %g1
843
844 .globl __spitfire_data_access_exception
845 .globl __spitfire_data_access_exception_tl1
846__spitfire_data_access_exception_tl1:
701 rdpr %pstate, %g4 847 rdpr %pstate, %g4
702 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 848 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
703 mov TLB_SFSR, %g3 849 mov TLB_SFSR, %g3
@@ -706,9 +852,25 @@ __do_data_access_exception_tl1:
706 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR 852 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
707 stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit 853 stxa %g0, [%g3] ASI_DMMU ! Clear SFSR.FaultValid bit
708 membar #Sync 854 membar #Sync
855 rdpr %tt, %g3
856 cmp %g3, 0x80 ! first win spill/fill trap
857 blu,pn %xcc, 1f
858 cmp %g3, 0xff ! last win spill/fill trap
859 bgu,pn %xcc, 1f
860 nop
709 ba,pt %xcc, winfix_dax 861 ba,pt %xcc, winfix_dax
710 rdpr %tpc, %g3 862 rdpr %tpc, %g3
711__do_data_access_exception: 8631: sethi %hi(109f), %g7
864 ba,pt %xcc, etraptl1
865109: or %g7, %lo(109b), %g7
866 mov %l4, %o1
867 mov %l5, %o2
868 call spitfire_data_access_exception_tl1
869 add %sp, PTREGS_OFF, %o0
870 ba,pt %xcc, rtrap
871 clr %l6
872
873__spitfire_data_access_exception:
712 rdpr %pstate, %g4 874 rdpr %pstate, %g4
713 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 875 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
714 mov TLB_SFSR, %g3 876 mov TLB_SFSR, %g3
@@ -722,20 +884,19 @@ __do_data_access_exception:
722109: or %g7, %lo(109b), %g7 884109: or %g7, %lo(109b), %g7
723 mov %l4, %o1 885 mov %l4, %o1
724 mov %l5, %o2 886 mov %l5, %o2
725 call data_access_exception 887 call spitfire_data_access_exception
726 add %sp, PTREGS_OFF, %o0 888 add %sp, PTREGS_OFF, %o0
727 ba,pt %xcc, rtrap 889 ba,pt %xcc, rtrap
728 clr %l6 890 clr %l6
729 891
730 .globl __do_instruction_access_exception 892 .globl __spitfire_insn_access_exception
731 .globl __do_instruction_access_exception_tl1 893 .globl __spitfire_insn_access_exception_tl1
732__do_instruction_access_exception_tl1: 894__spitfire_insn_access_exception_tl1:
733 rdpr %pstate, %g4 895 rdpr %pstate, %g4
734 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 896 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
735 mov TLB_SFSR, %g3 897 mov TLB_SFSR, %g3
736 mov DMMU_SFAR, %g5 898 ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
737 ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR 899 rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
738 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
739 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit 900 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
740 membar #Sync 901 membar #Sync
741 sethi %hi(109f), %g7 902 sethi %hi(109f), %g7
@@ -743,18 +904,17 @@ __do_instruction_access_exception_tl1:
743109: or %g7, %lo(109b), %g7 904109: or %g7, %lo(109b), %g7
744 mov %l4, %o1 905 mov %l4, %o1
745 mov %l5, %o2 906 mov %l5, %o2
746 call instruction_access_exception_tl1 907 call spitfire_insn_access_exception_tl1
747 add %sp, PTREGS_OFF, %o0 908 add %sp, PTREGS_OFF, %o0
748 ba,pt %xcc, rtrap 909 ba,pt %xcc, rtrap
749 clr %l6 910 clr %l6
750 911
751__do_instruction_access_exception: 912__spitfire_insn_access_exception:
752 rdpr %pstate, %g4 913 rdpr %pstate, %g4
753 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate 914 wrpr %g4, PSTATE_MG|PSTATE_AG, %pstate
754 mov TLB_SFSR, %g3 915 mov TLB_SFSR, %g3
755 mov DMMU_SFAR, %g5 916 ldxa [%g3] ASI_IMMU, %g4 ! Get SFSR
756 ldxa [%g3] ASI_DMMU, %g4 ! Get SFSR 917 rdpr %tpc, %g5 ! IMMU has no SFAR, use TPC
757 ldxa [%g5] ASI_DMMU, %g5 ! Get SFAR
758 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit 918 stxa %g0, [%g3] ASI_IMMU ! Clear FaultValid bit
759 membar #Sync 919 membar #Sync
760 sethi %hi(109f), %g7 920 sethi %hi(109f), %g7
@@ -762,102 +922,11 @@ __do_instruction_access_exception:
762109: or %g7, %lo(109b), %g7 922109: or %g7, %lo(109b), %g7
763 mov %l4, %o1 923 mov %l4, %o1
764 mov %l5, %o2 924 mov %l5, %o2
765 call instruction_access_exception 925 call spitfire_insn_access_exception
766 add %sp, PTREGS_OFF, %o0 926 add %sp, PTREGS_OFF, %o0
767 ba,pt %xcc, rtrap 927 ba,pt %xcc, rtrap
768 clr %l6 928 clr %l6
769 929
770 /* This is the trap handler entry point for ECC correctable
771 * errors. They are corrected, but we listen for the trap
772 * so that the event can be logged.
773 *
774 * Disrupting errors are either:
775 * 1) single-bit ECC errors during UDB reads to system
776 * memory
777 * 2) data parity errors during write-back events
778 *
779 * As far as I can make out from the manual, the CEE trap
780 * is only for correctable errors during memory read
781 * accesses by the front-end of the processor.
782 *
783 * The code below is only for trap level 1 CEE events,
784 * as it is the only situation where we can safely record
785 * and log. For trap level >1 we just clear the CE bit
786 * in the AFSR and return.
787 */
788
789 /* Our trap handling infrastructure allows us to preserve
790 * two 64-bit values during etrap for arguments to
791 * subsequent C code. Therefore we encode the information
792 * as follows:
793 *
794 * value 1) Full 64-bits of AFAR
795 * value 2) Low 33-bits of AFSR, then bits 33-->42
796 * are UDBL error status and bits 43-->52
797 * are UDBH error status
798 */
799 .align 64
800 .globl cee_trap
801cee_trap:
802 ldxa [%g0] ASI_AFSR, %g1 ! Read AFSR
803 ldxa [%g0] ASI_AFAR, %g2 ! Read AFAR
804 sllx %g1, 31, %g1 ! Clear reserved bits
805 srlx %g1, 31, %g1 ! in AFSR
806
807 /* NOTE: UltraSparc-I/II have high and low UDB error
808 * registers, corresponding to the two UDB units
809 * present on those chips. UltraSparc-IIi only
810 * has a single UDB, called "SDB" in the manual.
811 * For IIi the upper UDB register always reads
812 * as zero so for our purposes things will just
813 * work with the checks below.
814 */
815 ldxa [%g0] ASI_UDBL_ERROR_R, %g3 ! Read UDB-Low error status
816 andcc %g3, (1 << 8), %g4 ! Check CE bit
817 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
818 srlx %g3, (64 - 10), %g3 ! in UDB-Low error status
819
820 sllx %g3, (33 + 0), %g3 ! Shift up to encoding area
821 or %g1, %g3, %g1 ! Or it in
822 be,pn %xcc, 1f ! Branch if CE bit was clear
823 nop
824 stxa %g4, [%g0] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBL
825 membar #Sync ! Synchronize ASI stores
8261: mov 0x18, %g5 ! Addr of UDB-High error status
827 ldxa [%g5] ASI_UDBH_ERROR_R, %g3 ! Read it
828
829 andcc %g3, (1 << 8), %g4 ! Check CE bit
830 sllx %g3, (64 - 10), %g3 ! Clear reserved bits
831 srlx %g3, (64 - 10), %g3 ! in UDB-High error status
832 sllx %g3, (33 + 10), %g3 ! Shift up to encoding area
833 or %g1, %g3, %g1 ! Or it in
834 be,pn %xcc, 1f ! Branch if CE bit was clear
835 nop
836 nop
837
838 stxa %g4, [%g5] ASI_UDB_ERROR_W ! Clear CE sticky bit in UDBH
839 membar #Sync ! Synchronize ASI stores
8401: mov 1, %g5 ! AFSR CE bit is
841 sllx %g5, 20, %g5 ! bit 20
842 stxa %g5, [%g0] ASI_AFSR ! Clear CE sticky bit in AFSR
843 membar #Sync ! Synchronize ASI stores
844 sllx %g2, (64 - 41), %g2 ! Clear reserved bits
845 srlx %g2, (64 - 41), %g2 ! in latched AFAR
846
847 andn %g2, 0x0f, %g2 ! Finish resv bit clearing
848 mov %g1, %g4 ! Move AFSR+UDB* into save reg
849 mov %g2, %g5 ! Move AFAR into save reg
850 rdpr %pil, %g2
851 wrpr %g0, 15, %pil
852 ba,pt %xcc, etrap_irq
853 rd %pc, %g7
854 mov %l4, %o0
855
856 mov %l5, %o1
857 call cee_log
858 add %sp, PTREGS_OFF, %o2
859 ba,a,pt %xcc, rtrap_irq
860
861 /* Capture I/D/E-cache state into per-cpu error scoreboard. 930 /* Capture I/D/E-cache state into per-cpu error scoreboard.
862 * 931 *
863 * %g1: (TL>=0) ? 1 : 0 932 * %g1: (TL>=0) ? 1 : 0
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 2803bc7c2c79..425c60cfea19 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -466,7 +466,7 @@ do_flush_sync:
466 if (!limit) 466 if (!limit)
467 break; 467 break;
468 udelay(1); 468 udelay(1);
469 membar("#LoadLoad"); 469 rmb();
470 } 470 }
471 if (!limit) 471 if (!limit)
472 printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout " 472 printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 07424b075938..66255434128a 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -103,7 +103,7 @@ void cpu_idle(void)
103 * other cpus see our increasing idleness for the buddy 103 * other cpus see our increasing idleness for the buddy
104 * redistribution algorithm. -DaveM 104 * redistribution algorithm. -DaveM
105 */ 105 */
106 membar("#StoreStore | #StoreLoad"); 106 membar_storeload_storestore();
107 } 107 }
108} 108}
109 109
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 89f5e019f24c..e09ddf927655 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -147,7 +147,7 @@ static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long
147 if (!limit) 147 if (!limit)
148 break; 148 break;
149 udelay(1); 149 udelay(1);
150 membar("#LoadLoad"); 150 rmb();
151 } 151 }
152 if (!limit) 152 if (!limit)
153 printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout " 153 printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index b7e6a91952b2..fbdfed3798d8 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -33,7 +33,6 @@
33#include <linux/cpu.h> 33#include <linux/cpu.h>
34#include <linux/initrd.h> 34#include <linux/initrd.h>
35 35
36#include <asm/segment.h>
37#include <asm/system.h> 36#include <asm/system.h>
38#include <asm/io.h> 37#include <asm/io.h>
39#include <asm/processor.h> 38#include <asm/processor.h>
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index b1ed23091fbb..aecccd0df1d1 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -877,11 +877,12 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
877 unsigned long page = (unsigned long) 877 unsigned long page = (unsigned long)
878 page_address(pte_page(*ptep)); 878 page_address(pte_page(*ptep));
879 879
880 __asm__ __volatile__( 880 wmb();
881 " membar #StoreStore\n" 881 __asm__ __volatile__("flush %0 + %1"
882 " flush %0 + %1" 882 : /* no outputs */
883 : : "r" (page), "r" (address & (PAGE_SIZE - 1)) 883 : "r" (page),
884 : "memory"); 884 "r" (address & (PAGE_SIZE - 1))
885 : "memory");
885 } 886 }
886 pte_unmap(ptep); 887 pte_unmap(ptep);
887 preempt_enable(); 888 preempt_enable();
@@ -1292,11 +1293,12 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
1292 unsigned long page = (unsigned long) 1293 unsigned long page = (unsigned long)
1293 page_address(pte_page(*ptep)); 1294 page_address(pte_page(*ptep));
1294 1295
1295 __asm__ __volatile__( 1296 wmb();
1296 " membar #StoreStore\n" 1297 __asm__ __volatile__("flush %0 + %1"
1297 " flush %0 + %1" 1298 : /* no outputs */
1298 : : "r" (page), "r" (address & (PAGE_SIZE - 1)) 1299 : "r" (page),
1299 : "memory"); 1300 "r" (address & (PAGE_SIZE - 1))
1301 : "memory");
1300 } 1302 }
1301 pte_unmap(ptep); 1303 pte_unmap(ptep);
1302 preempt_enable(); 1304 preempt_enable();
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index b9b42491e118..b4fc6a5462b2 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -144,7 +144,7 @@ void __init smp_callin(void)
144 current->active_mm = &init_mm; 144 current->active_mm = &init_mm;
145 145
146 while (!cpu_isset(cpuid, smp_commenced_mask)) 146 while (!cpu_isset(cpuid, smp_commenced_mask))
147 membar("#LoadLoad"); 147 rmb();
148 148
149 cpu_set(cpuid, cpu_online_map); 149 cpu_set(cpuid, cpu_online_map);
150} 150}
@@ -184,11 +184,11 @@ static inline long get_delta (long *rt, long *master)
184 for (i = 0; i < NUM_ITERS; i++) { 184 for (i = 0; i < NUM_ITERS; i++) {
185 t0 = tick_ops->get_tick(); 185 t0 = tick_ops->get_tick();
186 go[MASTER] = 1; 186 go[MASTER] = 1;
187 membar("#StoreLoad"); 187 membar_storeload();
188 while (!(tm = go[SLAVE])) 188 while (!(tm = go[SLAVE]))
189 membar("#LoadLoad"); 189 rmb();
190 go[SLAVE] = 0; 190 go[SLAVE] = 0;
191 membar("#StoreStore"); 191 wmb();
192 t1 = tick_ops->get_tick(); 192 t1 = tick_ops->get_tick();
193 193
194 if (t1 - t0 < best_t1 - best_t0) 194 if (t1 - t0 < best_t1 - best_t0)
@@ -221,7 +221,7 @@ void smp_synchronize_tick_client(void)
221 go[MASTER] = 1; 221 go[MASTER] = 1;
222 222
223 while (go[MASTER]) 223 while (go[MASTER])
224 membar("#LoadLoad"); 224 rmb();
225 225
226 local_irq_save(flags); 226 local_irq_save(flags);
227 { 227 {
@@ -273,21 +273,21 @@ static void smp_synchronize_one_tick(int cpu)
273 273
274 /* wait for client to be ready */ 274 /* wait for client to be ready */
275 while (!go[MASTER]) 275 while (!go[MASTER])
276 membar("#LoadLoad"); 276 rmb();
277 277
278 /* now let the client proceed into his loop */ 278 /* now let the client proceed into his loop */
279 go[MASTER] = 0; 279 go[MASTER] = 0;
280 membar("#StoreLoad"); 280 membar_storeload();
281 281
282 spin_lock_irqsave(&itc_sync_lock, flags); 282 spin_lock_irqsave(&itc_sync_lock, flags);
283 { 283 {
284 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) { 284 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; i++) {
285 while (!go[MASTER]) 285 while (!go[MASTER])
286 membar("#LoadLoad"); 286 rmb();
287 go[MASTER] = 0; 287 go[MASTER] = 0;
288 membar("#StoreStore"); 288 wmb();
289 go[SLAVE] = tick_ops->get_tick(); 289 go[SLAVE] = tick_ops->get_tick();
290 membar("#StoreLoad"); 290 membar_storeload();
291 } 291 }
292 } 292 }
293 spin_unlock_irqrestore(&itc_sync_lock, flags); 293 spin_unlock_irqrestore(&itc_sync_lock, flags);
@@ -927,11 +927,11 @@ void smp_capture(void)
927 smp_processor_id()); 927 smp_processor_id());
928#endif 928#endif
929 penguins_are_doing_time = 1; 929 penguins_are_doing_time = 1;
930 membar("#StoreStore | #LoadStore"); 930 membar_storestore_loadstore();
931 atomic_inc(&smp_capture_registry); 931 atomic_inc(&smp_capture_registry);
932 smp_cross_call(&xcall_capture, 0, 0, 0); 932 smp_cross_call(&xcall_capture, 0, 0, 0);
933 while (atomic_read(&smp_capture_registry) != ncpus) 933 while (atomic_read(&smp_capture_registry) != ncpus)
934 membar("#LoadLoad"); 934 rmb();
935#ifdef CAPTURE_DEBUG 935#ifdef CAPTURE_DEBUG
936 printk("done\n"); 936 printk("done\n");
937#endif 937#endif
@@ -947,7 +947,7 @@ void smp_release(void)
947 smp_processor_id()); 947 smp_processor_id());
948#endif 948#endif
949 penguins_are_doing_time = 0; 949 penguins_are_doing_time = 0;
950 membar("#StoreStore | #StoreLoad"); 950 membar_storeload_storestore();
951 atomic_dec(&smp_capture_registry); 951 atomic_dec(&smp_capture_registry);
952 } 952 }
953} 953}
@@ -970,9 +970,9 @@ void smp_penguin_jailcell(int irq, struct pt_regs *regs)
970 save_alternate_globals(global_save); 970 save_alternate_globals(global_save);
971 prom_world(1); 971 prom_world(1);
972 atomic_inc(&smp_capture_registry); 972 atomic_inc(&smp_capture_registry);
973 membar("#StoreLoad | #StoreStore"); 973 membar_storeload_storestore();
974 while (penguins_are_doing_time) 974 while (penguins_are_doing_time)
975 membar("#LoadLoad"); 975 rmb();
976 restore_alternate_globals(global_save); 976 restore_alternate_globals(global_save);
977 atomic_dec(&smp_capture_registry); 977 atomic_dec(&smp_capture_registry);
978 prom_world(0); 978 prom_world(0);
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 9202d925a9ce..a3ea697f1adb 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -99,17 +99,6 @@ extern int __ashrdi3(int, int);
99extern void dump_thread(struct pt_regs *, struct user *); 99extern void dump_thread(struct pt_regs *, struct user *);
100extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); 100extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs);
101 101
102#if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK)
103extern void _do_spin_lock (spinlock_t *lock, char *str);
104extern void _do_spin_unlock (spinlock_t *lock);
105extern int _spin_trylock (spinlock_t *lock);
106extern void _do_read_lock(rwlock_t *rw, char *str);
107extern void _do_read_unlock(rwlock_t *rw, char *str);
108extern void _do_write_lock(rwlock_t *rw, char *str);
109extern void _do_write_unlock(rwlock_t *rw);
110extern int _do_write_trylock(rwlock_t *rw, char *str);
111#endif
112
113extern unsigned long phys_base; 102extern unsigned long phys_base;
114extern unsigned long pfn_base; 103extern unsigned long pfn_base;
115 104
@@ -152,18 +141,6 @@ EXPORT_SYMBOL(_mcount);
152EXPORT_SYMBOL(cpu_online_map); 141EXPORT_SYMBOL(cpu_online_map);
153EXPORT_SYMBOL(phys_cpu_present_map); 142EXPORT_SYMBOL(phys_cpu_present_map);
154 143
155/* Spinlock debugging library, optional. */
156#ifdef CONFIG_DEBUG_SPINLOCK
157EXPORT_SYMBOL(_do_spin_lock);
158EXPORT_SYMBOL(_do_spin_unlock);
159EXPORT_SYMBOL(_spin_trylock);
160EXPORT_SYMBOL(_do_read_lock);
161EXPORT_SYMBOL(_do_read_unlock);
162EXPORT_SYMBOL(_do_write_lock);
163EXPORT_SYMBOL(_do_write_unlock);
164EXPORT_SYMBOL(_do_write_trylock);
165#endif
166
167EXPORT_SYMBOL(smp_call_function); 144EXPORT_SYMBOL(smp_call_function);
168#endif /* CONFIG_SMP */ 145#endif /* CONFIG_SMP */
169 146
@@ -429,3 +406,12 @@ EXPORT_SYMBOL(xor_vis_4);
429EXPORT_SYMBOL(xor_vis_5); 406EXPORT_SYMBOL(xor_vis_5);
430 407
431EXPORT_SYMBOL(prom_palette); 408EXPORT_SYMBOL(prom_palette);
409
410/* memory barriers */
411EXPORT_SYMBOL(mb);
412EXPORT_SYMBOL(rmb);
413EXPORT_SYMBOL(wmb);
414EXPORT_SYMBOL(membar_storeload);
415EXPORT_SYMBOL(membar_storeload_storestore);
416EXPORT_SYMBOL(membar_storeload_loadload);
417EXPORT_SYMBOL(membar_storestore_loadstore);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 0c9e54b2f0c8..b280b2ef674f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -33,6 +33,7 @@
33#include <asm/dcu.h> 33#include <asm/dcu.h>
34#include <asm/estate.h> 34#include <asm/estate.h>
35#include <asm/chafsr.h> 35#include <asm/chafsr.h>
36#include <asm/sfafsr.h>
36#include <asm/psrcompat.h> 37#include <asm/psrcompat.h>
37#include <asm/processor.h> 38#include <asm/processor.h>
38#include <asm/timer.h> 39#include <asm/timer.h>
@@ -143,8 +144,7 @@ void do_BUG(const char *file, int line)
143} 144}
144#endif 145#endif
145 146
146void instruction_access_exception(struct pt_regs *regs, 147void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
147 unsigned long sfsr, unsigned long sfar)
148{ 148{
149 siginfo_t info; 149 siginfo_t info;
150 150
@@ -153,8 +153,8 @@ void instruction_access_exception(struct pt_regs *regs,
153 return; 153 return;
154 154
155 if (regs->tstate & TSTATE_PRIV) { 155 if (regs->tstate & TSTATE_PRIV) {
156 printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n", 156 printk("spitfire_insn_access_exception: SFSR[%016lx] "
157 sfsr, sfar); 157 "SFAR[%016lx], going.\n", sfsr, sfar);
158 die_if_kernel("Iax", regs); 158 die_if_kernel("Iax", regs);
159 } 159 }
160 if (test_thread_flag(TIF_32BIT)) { 160 if (test_thread_flag(TIF_32BIT)) {
@@ -169,19 +169,17 @@ void instruction_access_exception(struct pt_regs *regs,
169 force_sig_info(SIGSEGV, &info, current); 169 force_sig_info(SIGSEGV, &info, current);
170} 170}
171 171
172void instruction_access_exception_tl1(struct pt_regs *regs, 172void spitfire_insn_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
173 unsigned long sfsr, unsigned long sfar)
174{ 173{
175 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs, 174 if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
176 0, 0x8, SIGTRAP) == NOTIFY_STOP) 175 0, 0x8, SIGTRAP) == NOTIFY_STOP)
177 return; 176 return;
178 177
179 dump_tl1_traplog((struct tl1_traplog *)(regs + 1)); 178 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
180 instruction_access_exception(regs, sfsr, sfar); 179 spitfire_insn_access_exception(regs, sfsr, sfar);
181} 180}
182 181
183void data_access_exception(struct pt_regs *regs, 182void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
184 unsigned long sfsr, unsigned long sfar)
185{ 183{
186 siginfo_t info; 184 siginfo_t info;
187 185
@@ -207,8 +205,8 @@ void data_access_exception(struct pt_regs *regs,
207 return; 205 return;
208 } 206 }
209 /* Shit... */ 207 /* Shit... */
210 printk("data_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n", 208 printk("spitfire_data_access_exception: SFSR[%016lx] "
211 sfsr, sfar); 209 "SFAR[%016lx], going.\n", sfsr, sfar);
212 die_if_kernel("Dax", regs); 210 die_if_kernel("Dax", regs);
213 } 211 }
214 212
@@ -220,6 +218,16 @@ void data_access_exception(struct pt_regs *regs,
220 force_sig_info(SIGSEGV, &info, current); 218 force_sig_info(SIGSEGV, &info, current);
221} 219}
222 220
221void spitfire_data_access_exception_tl1(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
222{
223 if (notify_die(DIE_TRAP_TL1, "data access exception tl1", regs,
224 0, 0x30, SIGTRAP) == NOTIFY_STOP)
225 return;
226
227 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
228 spitfire_data_access_exception(regs, sfsr, sfar);
229}
230
223#ifdef CONFIG_PCI 231#ifdef CONFIG_PCI
224/* This is really pathetic... */ 232/* This is really pathetic... */
225extern volatile int pci_poke_in_progress; 233extern volatile int pci_poke_in_progress;
@@ -253,54 +261,13 @@ static void spitfire_clean_and_reenable_l1_caches(void)
253 : "memory"); 261 : "memory");
254} 262}
255 263
256void do_iae(struct pt_regs *regs) 264static void spitfire_enable_estate_errors(void)
257{ 265{
258 siginfo_t info; 266 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
259 267 "membar #Sync"
260 spitfire_clean_and_reenable_l1_caches(); 268 : /* no outputs */
261 269 : "r" (ESTATE_ERR_ALL),
262 if (notify_die(DIE_TRAP, "instruction access exception", regs, 270 "i" (ASI_ESTATE_ERROR_EN));
263 0, 0x8, SIGTRAP) == NOTIFY_STOP)
264 return;
265
266 info.si_signo = SIGBUS;
267 info.si_errno = 0;
268 info.si_code = BUS_OBJERR;
269 info.si_addr = (void *)0;
270 info.si_trapno = 0;
271 force_sig_info(SIGBUS, &info, current);
272}
273
274void do_dae(struct pt_regs *regs)
275{
276 siginfo_t info;
277
278#ifdef CONFIG_PCI
279 if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
280 spitfire_clean_and_reenable_l1_caches();
281
282 pci_poke_faulted = 1;
283
284 /* Why the fuck did they have to change this? */
285 if (tlb_type == cheetah || tlb_type == cheetah_plus)
286 regs->tpc += 4;
287
288 regs->tnpc = regs->tpc + 4;
289 return;
290 }
291#endif
292 spitfire_clean_and_reenable_l1_caches();
293
294 if (notify_die(DIE_TRAP, "data access exception", regs,
295 0, 0x30, SIGTRAP) == NOTIFY_STOP)
296 return;
297
298 info.si_signo = SIGBUS;
299 info.si_errno = 0;
300 info.si_code = BUS_OBJERR;
301 info.si_addr = (void *)0;
302 info.si_trapno = 0;
303 force_sig_info(SIGBUS, &info, current);
304} 271}
305 272
306static char ecc_syndrome_table[] = { 273static char ecc_syndrome_table[] = {
@@ -338,65 +305,15 @@ static char ecc_syndrome_table[] = {
338 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a 305 0x0b, 0x48, 0x48, 0x4b, 0x48, 0x4b, 0x4b, 0x4a
339}; 306};
340 307
341/* cee_trap in entry.S encodes AFSR/UDBH/UDBL error status
342 * in the following format. The AFAR is left as is, with
343 * reserved bits cleared, and is a raw 40-bit physical
344 * address.
345 */
346#define CE_STATUS_UDBH_UE (1UL << (43 + 9))
347#define CE_STATUS_UDBH_CE (1UL << (43 + 8))
348#define CE_STATUS_UDBH_ESYNDR (0xffUL << 43)
349#define CE_STATUS_UDBH_SHIFT 43
350#define CE_STATUS_UDBL_UE (1UL << (33 + 9))
351#define CE_STATUS_UDBL_CE (1UL << (33 + 8))
352#define CE_STATUS_UDBL_ESYNDR (0xffUL << 33)
353#define CE_STATUS_UDBL_SHIFT 33
354#define CE_STATUS_AFSR_MASK (0x1ffffffffUL)
355#define CE_STATUS_AFSR_ME (1UL << 32)
356#define CE_STATUS_AFSR_PRIV (1UL << 31)
357#define CE_STATUS_AFSR_ISAP (1UL << 30)
358#define CE_STATUS_AFSR_ETP (1UL << 29)
359#define CE_STATUS_AFSR_IVUE (1UL << 28)
360#define CE_STATUS_AFSR_TO (1UL << 27)
361#define CE_STATUS_AFSR_BERR (1UL << 26)
362#define CE_STATUS_AFSR_LDP (1UL << 25)
363#define CE_STATUS_AFSR_CP (1UL << 24)
364#define CE_STATUS_AFSR_WP (1UL << 23)
365#define CE_STATUS_AFSR_EDP (1UL << 22)
366#define CE_STATUS_AFSR_UE (1UL << 21)
367#define CE_STATUS_AFSR_CE (1UL << 20)
368#define CE_STATUS_AFSR_ETS (0xfUL << 16)
369#define CE_STATUS_AFSR_ETS_SHIFT 16
370#define CE_STATUS_AFSR_PSYND (0xffffUL << 0)
371#define CE_STATUS_AFSR_PSYND_SHIFT 0
372
373/* Layout of Ecache TAG Parity Syndrome of AFSR */
374#define AFSR_ETSYNDROME_7_0 0x1UL /* E$-tag bus bits <7:0> */
375#define AFSR_ETSYNDROME_15_8 0x2UL /* E$-tag bus bits <15:8> */
376#define AFSR_ETSYNDROME_21_16 0x4UL /* E$-tag bus bits <21:16> */
377#define AFSR_ETSYNDROME_24_22 0x8UL /* E$-tag bus bits <24:22> */
378
379static char *syndrome_unknown = "<Unknown>"; 308static char *syndrome_unknown = "<Unknown>";
380 309
381asmlinkage void cee_log(unsigned long ce_status, 310static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long bit)
382 unsigned long afar,
383 struct pt_regs *regs)
384{ 311{
385 char memmod_str[64]; 312 unsigned short scode;
386 char *p; 313 char memmod_str[64], *p;
387 unsigned short scode, udb_reg;
388 314
389 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error " 315 if (udbl & bit) {
390 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx]\n", 316 scode = ecc_syndrome_table[udbl & 0xff];
391 smp_processor_id(),
392 (ce_status & CE_STATUS_AFSR_MASK),
393 afar,
394 ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL),
395 ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL));
396
397 udb_reg = ((ce_status >> CE_STATUS_UDBL_SHIFT) & 0x3ffUL);
398 if (udb_reg & (1 << 8)) {
399 scode = ecc_syndrome_table[udb_reg & 0xff];
400 if (prom_getunumber(scode, afar, 317 if (prom_getunumber(scode, afar,
401 memmod_str, sizeof(memmod_str)) == -1) 318 memmod_str, sizeof(memmod_str)) == -1)
402 p = syndrome_unknown; 319 p = syndrome_unknown;
@@ -407,9 +324,8 @@ asmlinkage void cee_log(unsigned long ce_status,
407 smp_processor_id(), scode, p); 324 smp_processor_id(), scode, p);
408 } 325 }
409 326
410 udb_reg = ((ce_status >> CE_STATUS_UDBH_SHIFT) & 0x3ffUL); 327 if (udbh & bit) {
411 if (udb_reg & (1 << 8)) { 328 scode = ecc_syndrome_table[udbh & 0xff];
412 scode = ecc_syndrome_table[udb_reg & 0xff];
413 if (prom_getunumber(scode, afar, 329 if (prom_getunumber(scode, afar,
414 memmod_str, sizeof(memmod_str)) == -1) 330 memmod_str, sizeof(memmod_str)) == -1)
415 p = syndrome_unknown; 331 p = syndrome_unknown;
@@ -419,6 +335,127 @@ asmlinkage void cee_log(unsigned long ce_status,
419 "Memory Module \"%s\"\n", 335 "Memory Module \"%s\"\n",
420 smp_processor_id(), scode, p); 336 smp_processor_id(), scode, p);
421 } 337 }
338
339}
340
341static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, int tl1, struct pt_regs *regs)
342{
343
344 printk(KERN_WARNING "CPU[%d]: Correctable ECC Error "
345 "AFSR[%lx] AFAR[%016lx] UDBL[%lx] UDBH[%lx] TL>1[%d]\n",
346 smp_processor_id(), afsr, afar, udbl, udbh, tl1);
347
348 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_CE);
349
350 /* We always log it, even if someone is listening for this
351 * trap.
352 */
353 notify_die(DIE_TRAP, "Correctable ECC Error", regs,
354 0, TRAP_TYPE_CEE, SIGTRAP);
355
356 /* The Correctable ECC Error trap does not disable I/D caches. So
357 * we only have to restore the ESTATE Error Enable register.
358 */
359 spitfire_enable_estate_errors();
360}
361
362static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
363{
364 siginfo_t info;
365
366 printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
367 "AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
368 smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
369
370 /* XXX add more human friendly logging of the error status
371 * XXX as is implemented for cheetah
372 */
373
374 spitfire_log_udb_syndrome(afar, udbh, udbl, UDBE_UE);
375
376 /* We always log it, even if someone is listening for this
377 * trap.
378 */
379 notify_die(DIE_TRAP, "Uncorrectable Error", regs,
380 0, tt, SIGTRAP);
381
382 if (regs->tstate & TSTATE_PRIV) {
383 if (tl1)
384 dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
385 die_if_kernel("UE", regs);
386 }
387
388 /* XXX need more intelligent processing here, such as is implemented
389 * XXX for cheetah errors, in fact if the E-cache still holds the
390 * XXX line with bad parity this will loop
391 */
392
393 spitfire_clean_and_reenable_l1_caches();
394 spitfire_enable_estate_errors();
395
396 if (test_thread_flag(TIF_32BIT)) {
397 regs->tpc &= 0xffffffff;
398 regs->tnpc &= 0xffffffff;
399 }
400 info.si_signo = SIGBUS;
401 info.si_errno = 0;
402 info.si_code = BUS_OBJERR;
403 info.si_addr = (void *)0;
404 info.si_trapno = 0;
405 force_sig_info(SIGBUS, &info, current);
406}
407
408void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
409{
410 unsigned long afsr, tt, udbh, udbl;
411 int tl1;
412
413 afsr = (status_encoded & SFSTAT_AFSR_MASK) >> SFSTAT_AFSR_SHIFT;
414 tt = (status_encoded & SFSTAT_TRAP_TYPE) >> SFSTAT_TRAP_TYPE_SHIFT;
415 tl1 = (status_encoded & SFSTAT_TL_GT_ONE) ? 1 : 0;
416 udbl = (status_encoded & SFSTAT_UDBL_MASK) >> SFSTAT_UDBL_SHIFT;
417 udbh = (status_encoded & SFSTAT_UDBH_MASK) >> SFSTAT_UDBH_SHIFT;
418
419#ifdef CONFIG_PCI
420 if (tt == TRAP_TYPE_DAE &&
421 pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
422 spitfire_clean_and_reenable_l1_caches();
423 spitfire_enable_estate_errors();
424
425 pci_poke_faulted = 1;
426 regs->tnpc = regs->tpc + 4;
427 return;
428 }
429#endif
430
431 if (afsr & SFAFSR_UE)
432 spitfire_ue_log(afsr, afar, udbh, udbl, tt, tl1, regs);
433
434 if (tt == TRAP_TYPE_CEE) {
435 /* Handle the case where we took a CEE trap, but ACK'd
436 * only the UE state in the UDB error registers.
437 */
438 if (afsr & SFAFSR_UE) {
439 if (udbh & UDBE_CE) {
440 __asm__ __volatile__(
441 "stxa %0, [%1] %2\n\t"
442 "membar #Sync"
443 : /* no outputs */
444 : "r" (udbh & UDBE_CE),
445 "r" (0x0), "i" (ASI_UDB_ERROR_W));
446 }
447 if (udbl & UDBE_CE) {
448 __asm__ __volatile__(
449 "stxa %0, [%1] %2\n\t"
450 "membar #Sync"
451 : /* no outputs */
452 : "r" (udbl & UDBE_CE),
453 "r" (0x18), "i" (ASI_UDB_ERROR_W));
454 }
455 }
456
457 spitfire_cee_log(afsr, afar, udbh, udbl, tl1, regs);
458 }
422} 459}
423 460
424int cheetah_pcache_forced_on; 461int cheetah_pcache_forced_on;
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 491bb3681f9d..8365bc1f81f3 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -18,9 +18,10 @@ sparc64_ttable_tl0:
18tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) 18tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
19tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) 19tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
20tl0_iax: membar #Sync 20tl0_iax: membar #Sync
21 TRAP_NOSAVE_7INSNS(__do_instruction_access_exception) 21 TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception)
22tl0_resv009: BTRAP(0x9) 22tl0_resv009: BTRAP(0x9)
23tl0_iae: TRAP(do_iae) 23tl0_iae: membar #Sync
24 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
24tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) 25tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
25tl0_ill: membar #Sync 26tl0_ill: membar #Sync
26 TRAP_7INSNS(do_illegal_instruction) 27 TRAP_7INSNS(do_illegal_instruction)
@@ -36,9 +37,10 @@ tl0_cwin: CLEAN_WINDOW
36tl0_div0: TRAP(do_div0) 37tl0_div0: TRAP(do_div0)
37tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) 38tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
38tl0_resv02f: BTRAP(0x2f) 39tl0_resv02f: BTRAP(0x2f)
39tl0_dax: TRAP_NOSAVE(__do_data_access_exception) 40tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception)
40tl0_resv031: BTRAP(0x31) 41tl0_resv031: BTRAP(0x31)
41tl0_dae: TRAP(do_dae) 42tl0_dae: membar #Sync
43 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
42tl0_resv033: BTRAP(0x33) 44tl0_resv033: BTRAP(0x33)
43tl0_mna: TRAP_NOSAVE(do_mna) 45tl0_mna: TRAP_NOSAVE(do_mna)
44tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) 46tl0_lddfmna: TRAP_NOSAVE(do_lddfmna)
@@ -73,7 +75,8 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f)
73tl0_ivec: TRAP_IVEC 75tl0_ivec: TRAP_IVEC
74tl0_paw: TRAP(do_paw) 76tl0_paw: TRAP(do_paw)
75tl0_vaw: TRAP(do_vaw) 77tl0_vaw: TRAP(do_vaw)
76tl0_cee: TRAP_NOSAVE(cee_trap) 78tl0_cee: membar #Sync
79 TRAP_NOSAVE_7INSNS(__spitfire_cee_trap)
77tl0_iamiss: 80tl0_iamiss:
78#include "itlb_base.S" 81#include "itlb_base.S"
79tl0_damiss: 82tl0_damiss:
@@ -175,9 +178,10 @@ tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8)
175sparc64_ttable_tl1: 178sparc64_ttable_tl1:
176tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) 179tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3)
177tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) 180tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7)
178tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1) 181tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1)
179tl1_resv009: BTRAPTL1(0x9) 182tl1_resv009: BTRAPTL1(0x9)
180tl1_iae: TRAPTL1(do_iae_tl1) 183tl1_iae: membar #Sync
184 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
181tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) 185tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
182tl1_ill: TRAPTL1(do_ill_tl1) 186tl1_ill: TRAPTL1(do_ill_tl1)
183tl1_privop: BTRAPTL1(0x11) 187tl1_privop: BTRAPTL1(0x11)
@@ -193,9 +197,10 @@ tl1_cwin: CLEAN_WINDOW
193tl1_div0: TRAPTL1(do_div0_tl1) 197tl1_div0: TRAPTL1(do_div0_tl1)
194tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) 198tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
195tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) 199tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
196tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1) 200tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1)
197tl1_resv031: BTRAPTL1(0x31) 201tl1_resv031: BTRAPTL1(0x31)
198tl1_dae: TRAPTL1(do_dae_tl1) 202tl1_dae: membar #Sync
203 TRAP_NOSAVE_7INSNS(__spitfire_access_error)
199tl1_resv033: BTRAPTL1(0x33) 204tl1_resv033: BTRAPTL1(0x33)
200tl1_mna: TRAP_NOSAVE(do_mna) 205tl1_mna: TRAP_NOSAVE(do_mna)
201tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) 206tl1_lddfmna: TRAPTL1(do_lddfmna_tl1)
@@ -219,8 +224,8 @@ tl1_paw: TRAPTL1(do_paw_tl1)
219tl1_vaw: TRAPTL1(do_vaw_tl1) 224tl1_vaw: TRAPTL1(do_vaw_tl1)
220 225
221 /* The grotty trick to save %g1 into current->thread.cee_stuff 226 /* The grotty trick to save %g1 into current->thread.cee_stuff
222 * is because when we take this trap we could be interrupting trap 227 * is because when we take this trap we could be interrupting
223 * code already using the trap alternate global registers. 228 * trap code already using the trap alternate global registers.
224 * 229 *
225 * We cross our fingers and pray that this store/load does 230 * We cross our fingers and pray that this store/load does
226 * not cause yet another CEE trap. 231 * not cause yet another CEE trap.
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 11c3e88732e4..da9739f0d437 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -349,9 +349,9 @@ int handle_popc(u32 insn, struct pt_regs *regs)
349 349
350extern void do_fpother(struct pt_regs *regs); 350extern void do_fpother(struct pt_regs *regs);
351extern void do_privact(struct pt_regs *regs); 351extern void do_privact(struct pt_regs *regs);
352extern void data_access_exception(struct pt_regs *regs, 352extern void spitfire_data_access_exception(struct pt_regs *regs,
353 unsigned long sfsr, 353 unsigned long sfsr,
354 unsigned long sfar); 354 unsigned long sfar);
355 355
356int handle_ldf_stq(u32 insn, struct pt_regs *regs) 356int handle_ldf_stq(u32 insn, struct pt_regs *regs)
357{ 357{
@@ -394,14 +394,14 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
394 break; 394 break;
395 } 395 }
396 default: 396 default:
397 data_access_exception(regs, 0, addr); 397 spitfire_data_access_exception(regs, 0, addr);
398 return 1; 398 return 1;
399 } 399 }
400 if (put_user (first >> 32, (u32 __user *)addr) || 400 if (put_user (first >> 32, (u32 __user *)addr) ||
401 __put_user ((u32)first, (u32 __user *)(addr + 4)) || 401 __put_user ((u32)first, (u32 __user *)(addr + 4)) ||
402 __put_user (second >> 32, (u32 __user *)(addr + 8)) || 402 __put_user (second >> 32, (u32 __user *)(addr + 8)) ||
403 __put_user ((u32)second, (u32 __user *)(addr + 12))) { 403 __put_user ((u32)second, (u32 __user *)(addr + 12))) {
404 data_access_exception(regs, 0, addr); 404 spitfire_data_access_exception(regs, 0, addr);
405 return 1; 405 return 1;
406 } 406 }
407 } else { 407 } else {
@@ -414,7 +414,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
414 do_privact(regs); 414 do_privact(regs);
415 return 1; 415 return 1;
416 } else if (asi > ASI_SNFL) { 416 } else if (asi > ASI_SNFL) {
417 data_access_exception(regs, 0, addr); 417 spitfire_data_access_exception(regs, 0, addr);
418 return 1; 418 return 1;
419 } 419 }
420 switch (insn & 0x180000) { 420 switch (insn & 0x180000) {
@@ -431,7 +431,7 @@ int handle_ldf_stq(u32 insn, struct pt_regs *regs)
431 err |= __get_user (data[i], (u32 __user *)(addr + 4*i)); 431 err |= __get_user (data[i], (u32 __user *)(addr + 4*i));
432 } 432 }
433 if (err && !(asi & 0x2 /* NF */)) { 433 if (err && !(asi & 0x2 /* NF */)) {
434 data_access_exception(regs, 0, addr); 434 spitfire_data_access_exception(regs, 0, addr);
435 return 1; 435 return 1;
436 } 436 }
437 if (asi & 0x8) /* Little */ { 437 if (asi & 0x8) /* Little */ {
@@ -534,7 +534,7 @@ void handle_lddfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
534 *(u64 *)(f->regs + freg) = value; 534 *(u64 *)(f->regs + freg) = value;
535 current_thread_info()->fpsaved[0] |= flag; 535 current_thread_info()->fpsaved[0] |= flag;
536 } else { 536 } else {
537daex: data_access_exception(regs, sfsr, sfar); 537daex: spitfire_data_access_exception(regs, sfsr, sfar);
538 return; 538 return;
539 } 539 }
540 advance(regs); 540 advance(regs);
@@ -578,7 +578,7 @@ void handle_stdfmna(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr
578 __put_user ((u32)value, (u32 __user *)(sfar + 4))) 578 __put_user ((u32)value, (u32 __user *)(sfar + 4)))
579 goto daex; 579 goto daex;
580 } else { 580 } else {
581daex: data_access_exception(regs, sfsr, sfar); 581daex: spitfire_data_access_exception(regs, sfsr, sfar);
582 return; 582 return;
583 } 583 }
584 advance(regs); 584 advance(regs);
diff --git a/arch/sparc64/kernel/winfixup.S b/arch/sparc64/kernel/winfixup.S
index dfbc7e0dcf70..99c809a1e5ac 100644
--- a/arch/sparc64/kernel/winfixup.S
+++ b/arch/sparc64/kernel/winfixup.S
@@ -318,7 +318,7 @@ fill_fixup_dax:
318 nop 318 nop
319 rdpr %pstate, %l1 ! Prepare to change globals. 319 rdpr %pstate, %l1 ! Prepare to change globals.
320 mov %g4, %o1 ! Setup args for 320 mov %g4, %o1 ! Setup args for
321 mov %g5, %o2 ! final call to data_access_exception. 321 mov %g5, %o2 ! final call to spitfire_data_access_exception.
322 andn %l1, PSTATE_MM, %l1 ! We want to be in RMO 322 andn %l1, PSTATE_MM, %l1 ! We want to be in RMO
323 323
324 mov %g6, %o7 ! Stash away current. 324 mov %g6, %o7 ! Stash away current.
@@ -330,7 +330,7 @@ fill_fixup_dax:
330 mov TSB_REG, %g1 330 mov TSB_REG, %g1
331 ldxa [%g1] ASI_IMMU, %g5 331 ldxa [%g1] ASI_IMMU, %g5
332#endif 332#endif
333 call data_access_exception 333 call spitfire_data_access_exception
334 add %sp, PTREGS_OFF, %o0 334 add %sp, PTREGS_OFF, %o0
335 335
336 b,pt %xcc, rtrap 336 b,pt %xcc, rtrap
@@ -391,7 +391,7 @@ window_dax_from_user_common:
391109: or %g7, %lo(109b), %g7 391109: or %g7, %lo(109b), %g7
392 mov %l4, %o1 392 mov %l4, %o1
393 mov %l5, %o2 393 mov %l5, %o2
394 call data_access_exception 394 call spitfire_data_access_exception
395 add %sp, PTREGS_OFF, %o0 395 add %sp, PTREGS_OFF, %o0
396 ba,pt %xcc, rtrap 396 ba,pt %xcc, rtrap
397 clr %l6 397 clr %l6
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index 40dbeec7e5d6..6201f1040982 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -12,7 +12,7 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \
12 U1memcpy.o U1copy_from_user.o U1copy_to_user.o \ 12 U1memcpy.o U1copy_from_user.o U1copy_to_user.o \
13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \ 13 U3memcpy.o U3copy_from_user.o U3copy_to_user.o U3patch.o \
14 copy_in_user.o user_fixup.o memmove.o \ 14 copy_in_user.o user_fixup.o memmove.o \
15 mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o 15 mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o mb.o
16 16
17lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o 17lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o
18lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o 18lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
index f03344cf784e..f5f0b5586f01 100644
--- a/arch/sparc64/lib/debuglocks.c
+++ b/arch/sparc64/lib/debuglocks.c
@@ -12,8 +12,6 @@
12 12
13#ifdef CONFIG_SMP 13#ifdef CONFIG_SMP
14 14
15#define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC))
16
17static inline void show (char *str, spinlock_t *lock, unsigned long caller) 15static inline void show (char *str, spinlock_t *lock, unsigned long caller)
18{ 16{
19 int cpu = smp_processor_id(); 17 int cpu = smp_processor_id();
@@ -51,20 +49,19 @@ static inline void show_write (char *str, rwlock_t *lock, unsigned long caller)
51#undef INIT_STUCK 49#undef INIT_STUCK
52#define INIT_STUCK 100000000 50#define INIT_STUCK 100000000
53 51
54void _do_spin_lock(spinlock_t *lock, char *str) 52void _do_spin_lock(spinlock_t *lock, char *str, unsigned long caller)
55{ 53{
56 unsigned long caller, val; 54 unsigned long val;
57 int stuck = INIT_STUCK; 55 int stuck = INIT_STUCK;
58 int cpu = get_cpu(); 56 int cpu = get_cpu();
59 int shown = 0; 57 int shown = 0;
60 58
61 GET_CALLER(caller);
62again: 59again:
63 __asm__ __volatile__("ldstub [%1], %0" 60 __asm__ __volatile__("ldstub [%1], %0"
64 : "=r" (val) 61 : "=r" (val)
65 : "r" (&(lock->lock)) 62 : "r" (&(lock->lock))
66 : "memory"); 63 : "memory");
67 membar("#StoreLoad | #StoreStore"); 64 membar_storeload_storestore();
68 if (val) { 65 if (val) {
69 while (lock->lock) { 66 while (lock->lock) {
70 if (!--stuck) { 67 if (!--stuck) {
@@ -72,7 +69,7 @@ again:
72 show(str, lock, caller); 69 show(str, lock, caller);
73 stuck = INIT_STUCK; 70 stuck = INIT_STUCK;
74 } 71 }
75 membar("#LoadLoad"); 72 rmb();
76 } 73 }
77 goto again; 74 goto again;
78 } 75 }
@@ -84,17 +81,16 @@ again:
84 put_cpu(); 81 put_cpu();
85} 82}
86 83
87int _do_spin_trylock(spinlock_t *lock) 84int _do_spin_trylock(spinlock_t *lock, unsigned long caller)
88{ 85{
89 unsigned long val, caller; 86 unsigned long val;
90 int cpu = get_cpu(); 87 int cpu = get_cpu();
91 88
92 GET_CALLER(caller);
93 __asm__ __volatile__("ldstub [%1], %0" 89 __asm__ __volatile__("ldstub [%1], %0"
94 : "=r" (val) 90 : "=r" (val)
95 : "r" (&(lock->lock)) 91 : "r" (&(lock->lock))
96 : "memory"); 92 : "memory");
97 membar("#StoreLoad | #StoreStore"); 93 membar_storeload_storestore();
98 if (!val) { 94 if (!val) {
99 lock->owner_pc = ((unsigned int)caller); 95 lock->owner_pc = ((unsigned int)caller);
100 lock->owner_cpu = cpu; 96 lock->owner_cpu = cpu;
@@ -111,21 +107,20 @@ void _do_spin_unlock(spinlock_t *lock)
111{ 107{
112 lock->owner_pc = 0; 108 lock->owner_pc = 0;
113 lock->owner_cpu = NO_PROC_ID; 109 lock->owner_cpu = NO_PROC_ID;
114 membar("#StoreStore | #LoadStore"); 110 membar_storestore_loadstore();
115 lock->lock = 0; 111 lock->lock = 0;
116 current->thread.smp_lock_count--; 112 current->thread.smp_lock_count--;
117} 113}
118 114
119/* Keep INIT_STUCK the same... */ 115/* Keep INIT_STUCK the same... */
120 116
121void _do_read_lock (rwlock_t *rw, char *str) 117void _do_read_lock(rwlock_t *rw, char *str, unsigned long caller)
122{ 118{
123 unsigned long caller, val; 119 unsigned long val;
124 int stuck = INIT_STUCK; 120 int stuck = INIT_STUCK;
125 int cpu = get_cpu(); 121 int cpu = get_cpu();
126 int shown = 0; 122 int shown = 0;
127 123
128 GET_CALLER(caller);
129wlock_again: 124wlock_again:
130 /* Wait for any writer to go away. */ 125 /* Wait for any writer to go away. */
131 while (((long)(rw->lock)) < 0) { 126 while (((long)(rw->lock)) < 0) {
@@ -134,7 +129,7 @@ wlock_again:
134 show_read(str, rw, caller); 129 show_read(str, rw, caller);
135 stuck = INIT_STUCK; 130 stuck = INIT_STUCK;
136 } 131 }
137 membar("#LoadLoad"); 132 rmb();
138 } 133 }
139 /* Try once to increment the counter. */ 134 /* Try once to increment the counter. */
140 __asm__ __volatile__( 135 __asm__ __volatile__(
@@ -147,7 +142,7 @@ wlock_again:
147"2:" : "=r" (val) 142"2:" : "=r" (val)
148 : "0" (&(rw->lock)) 143 : "0" (&(rw->lock))
149 : "g1", "g7", "memory"); 144 : "g1", "g7", "memory");
150 membar("#StoreLoad | #StoreStore"); 145 membar_storeload_storestore();
151 if (val) 146 if (val)
152 goto wlock_again; 147 goto wlock_again;
153 rw->reader_pc[cpu] = ((unsigned int)caller); 148 rw->reader_pc[cpu] = ((unsigned int)caller);
@@ -157,15 +152,13 @@ wlock_again:
157 put_cpu(); 152 put_cpu();
158} 153}
159 154
160void _do_read_unlock (rwlock_t *rw, char *str) 155void _do_read_unlock(rwlock_t *rw, char *str, unsigned long caller)
161{ 156{
162 unsigned long caller, val; 157 unsigned long val;
163 int stuck = INIT_STUCK; 158 int stuck = INIT_STUCK;
164 int cpu = get_cpu(); 159 int cpu = get_cpu();
165 int shown = 0; 160 int shown = 0;
166 161
167 GET_CALLER(caller);
168
169 /* Drop our identity _first_. */ 162 /* Drop our identity _first_. */
170 rw->reader_pc[cpu] = 0; 163 rw->reader_pc[cpu] = 0;
171 current->thread.smp_lock_count--; 164 current->thread.smp_lock_count--;
@@ -193,14 +186,13 @@ runlock_again:
193 put_cpu(); 186 put_cpu();
194} 187}
195 188
196void _do_write_lock (rwlock_t *rw, char *str) 189void _do_write_lock(rwlock_t *rw, char *str, unsigned long caller)
197{ 190{
198 unsigned long caller, val; 191 unsigned long val;
199 int stuck = INIT_STUCK; 192 int stuck = INIT_STUCK;
200 int cpu = get_cpu(); 193 int cpu = get_cpu();
201 int shown = 0; 194 int shown = 0;
202 195
203 GET_CALLER(caller);
204wlock_again: 196wlock_again:
205 /* Spin while there is another writer. */ 197 /* Spin while there is another writer. */
206 while (((long)rw->lock) < 0) { 198 while (((long)rw->lock) < 0) {
@@ -209,7 +201,7 @@ wlock_again:
209 show_write(str, rw, caller); 201 show_write(str, rw, caller);
210 stuck = INIT_STUCK; 202 stuck = INIT_STUCK;
211 } 203 }
212 membar("#LoadLoad"); 204 rmb();
213 } 205 }
214 206
215 /* Try to acuire the write bit. */ 207 /* Try to acuire the write bit. */
@@ -264,7 +256,7 @@ wlock_again:
264 show_write(str, rw, caller); 256 show_write(str, rw, caller);
265 stuck = INIT_STUCK; 257 stuck = INIT_STUCK;
266 } 258 }
267 membar("#LoadLoad"); 259 rmb();
268 } 260 }
269 goto wlock_again; 261 goto wlock_again;
270 } 262 }
@@ -278,14 +270,12 @@ wlock_again:
278 put_cpu(); 270 put_cpu();
279} 271}
280 272
281void _do_write_unlock(rwlock_t *rw) 273void _do_write_unlock(rwlock_t *rw, unsigned long caller)
282{ 274{
283 unsigned long caller, val; 275 unsigned long val;
284 int stuck = INIT_STUCK; 276 int stuck = INIT_STUCK;
285 int shown = 0; 277 int shown = 0;
286 278
287 GET_CALLER(caller);
288
289 /* Drop our identity _first_ */ 279 /* Drop our identity _first_ */
290 rw->writer_pc = 0; 280 rw->writer_pc = 0;
291 rw->writer_cpu = NO_PROC_ID; 281 rw->writer_cpu = NO_PROC_ID;
@@ -313,13 +303,11 @@ wlock_again:
313 } 303 }
314} 304}
315 305
316int _do_write_trylock (rwlock_t *rw, char *str) 306int _do_write_trylock(rwlock_t *rw, char *str, unsigned long caller)
317{ 307{
318 unsigned long caller, val; 308 unsigned long val;
319 int cpu = get_cpu(); 309 int cpu = get_cpu();
320 310
321 GET_CALLER(caller);
322
323 /* Try to acuire the write bit. */ 311 /* Try to acuire the write bit. */
324 __asm__ __volatile__( 312 __asm__ __volatile__(
325" mov 1, %%g3\n" 313" mov 1, %%g3\n"
diff --git a/arch/sparc64/lib/mb.S b/arch/sparc64/lib/mb.S
new file mode 100644
index 000000000000..4004f748619f
--- /dev/null
+++ b/arch/sparc64/lib/mb.S
@@ -0,0 +1,73 @@
1/* mb.S: Out of line memory barriers.
2 *
3 * Copyright (C) 2005 David S. Miller (davem@davemloft.net)
4 */
5
6 /* These are here in an effort to more fully work around
7 * Spitfire Errata #51. Essentially, if a memory barrier
8 * occurs soon after a mispredicted branch, the chip can stop
9 * executing instructions until a trap occurs. Therefore, if
10 * interrupts are disabled, the chip can hang forever.
11 *
12 * It used to be believed that the memory barrier had to be
13 * right in the delay slot, but a case has been traced
14 * recently wherein the memory barrier was one instruction
15 * after the branch delay slot and the chip still hung. The
16 * offending sequence was the following in sym_wakeup_done()
17 * of the sym53c8xx_2 driver:
18 *
19 * call sym_ccb_from_dsa, 0
20 * movge %icc, 0, %l0
21 * brz,pn %o0, .LL1303
22 * mov %o0, %l2
23 * membar #LoadLoad
24 *
25 * The branch has to be mispredicted for the bug to occur.
26 * Therefore, we put the memory barrier explicitly into a
27 * "branch always, predicted taken" delay slot to avoid the
28 * problem case.
29 */
30
31 .text
32
3399: retl
34 nop
35
36 .globl mb
37mb: ba,pt %xcc, 99b
38 membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad
39 .size mb, .-mb
40
41 .globl rmb
42rmb: ba,pt %xcc, 99b
43 membar #LoadLoad
44 .size rmb, .-rmb
45
46 .globl wmb
47wmb: ba,pt %xcc, 99b
48 membar #StoreStore
49 .size wmb, .-wmb
50
51 .globl membar_storeload
52membar_storeload:
53 ba,pt %xcc, 99b
54 membar #StoreLoad
55 .size membar_storeload, .-membar_storeload
56
57 .globl membar_storeload_storestore
58membar_storeload_storestore:
59 ba,pt %xcc, 99b
60 membar #StoreLoad | #StoreStore
61 .size membar_storeload_storestore, .-membar_storeload_storestore
62
63 .globl membar_storeload_loadload
64membar_storeload_loadload:
65 ba,pt %xcc, 99b
66 membar #StoreLoad | #LoadLoad
67 .size membar_storeload_loadload, .-membar_storeload_loadload
68
69 .globl membar_storestore_loadstore
70membar_storestore_loadstore:
71 ba,pt %xcc, 99b
72 membar #StoreStore | #LoadStore
73 .size membar_storestore_loadstore, .-membar_storestore_loadstore
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 15b4cfe07557..302efbcba70e 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -737,7 +737,8 @@ MODULE_LICENSE("GPL");
737extern u32 tl0_solaris[8]; 737extern u32 tl0_solaris[8];
738#define update_ttable(x) \ 738#define update_ttable(x) \
739 tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \ 739 tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
740 __asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3])) 740 wmb(); \
741 __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
741#else 742#else
742#endif 743#endif
743 744
@@ -761,7 +762,8 @@ int init_module(void)
761 entry64_personality_patch |= 762 entry64_personality_patch |=
762 (offsetof(struct task_struct, personality) + 763 (offsetof(struct task_struct, personality) +
763 (sizeof(unsigned long) - 1)); 764 (sizeof(unsigned long) - 1));
764 __asm__ __volatile__("membar #StoreStore; flush %0" 765 wmb();
766 __asm__ __volatile__("flush %0"
765 : : "r" (&entry64_personality_patch)); 767 : : "r" (&entry64_personality_patch));
766 return 0; 768 return 0;
767} 769}
diff --git a/arch/v850/configs/rte-ma1-cb_defconfig b/arch/v850/configs/rte-ma1-cb_defconfig
index 1b5ca3c3a658..1a5beda36e29 100644
--- a/arch/v850/configs/rte-ma1-cb_defconfig
+++ b/arch/v850/configs/rte-ma1-cb_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.12-uc0 3# Linux kernel version: 2.6.13-uc0
4# Thu Jul 21 11:08:27 2005 4# Fri Sep 2 13:54:27 2005
5# 5#
6# CONFIG_MMU is not set 6# CONFIG_MMU is not set
7# CONFIG_UID16 is not set 7# CONFIG_UID16 is not set
@@ -44,6 +44,8 @@ CONFIG_ZERO_BSS=y
44# CONFIG_V850E_HIGHRES_TIMER is not set 44# CONFIG_V850E_HIGHRES_TIMER is not set
45# CONFIG_RESET_GUARD is not set 45# CONFIG_RESET_GUARD is not set
46CONFIG_LARGE_ALLOCS=y 46CONFIG_LARGE_ALLOCS=y
47CONFIG_FLATMEM=y
48CONFIG_FLAT_NODE_MEM_MAP=y
47 49
48# 50#
49# Code maturity level options 51# Code maturity level options
@@ -111,6 +113,52 @@ CONFIG_BINFMT_FLAT=y
111# CONFIG_BINFMT_MISC is not set 113# CONFIG_BINFMT_MISC is not set
112 114
113# 115#
116# Networking
117#
118CONFIG_NET=y
119
120#
121# Networking options
122#
123# CONFIG_PACKET is not set
124# CONFIG_UNIX is not set
125# CONFIG_NET_KEY is not set
126CONFIG_INET=y
127# CONFIG_IP_MULTICAST is not set
128# CONFIG_IP_ADVANCED_ROUTER is not set
129CONFIG_IP_FIB_HASH=y
130# CONFIG_IP_PNP is not set
131# CONFIG_NET_IPIP is not set
132# CONFIG_NET_IPGRE is not set
133# CONFIG_SYN_COOKIES is not set
134# CONFIG_INET_AH is not set
135# CONFIG_INET_ESP is not set
136# CONFIG_INET_IPCOMP is not set
137# CONFIG_INET_TUNNEL is not set
138# CONFIG_IP_TCPDIAG is not set
139# CONFIG_IP_TCPDIAG_IPV6 is not set
140# CONFIG_TCP_CONG_ADVANCED is not set
141CONFIG_TCP_CONG_BIC=y
142# CONFIG_IPV6 is not set
143# CONFIG_NETFILTER is not set
144# CONFIG_BRIDGE is not set
145# CONFIG_VLAN_8021Q is not set
146# CONFIG_DECNET is not set
147# CONFIG_LLC2 is not set
148# CONFIG_IPX is not set
149# CONFIG_ATALK is not set
150# CONFIG_NET_SCHED is not set
151# CONFIG_NET_CLS_ROUTE is not set
152
153#
154# Network testing
155#
156# CONFIG_NET_PKTGEN is not set
157# CONFIG_HAMRADIO is not set
158# CONFIG_IRDA is not set
159# CONFIG_BT is not set
160
161#
114# Generic Driver Options 162# Generic Driver Options
115# 163#
116CONFIG_STANDALONE=y 164CONFIG_STANDALONE=y
@@ -158,6 +206,7 @@ CONFIG_MTD_CFI_I2=y
158# Mapping drivers for chip access 206# Mapping drivers for chip access
159# 207#
160# CONFIG_MTD_COMPLEX_MAPPINGS is not set 208# CONFIG_MTD_COMPLEX_MAPPINGS is not set
209# CONFIG_MTD_PLATRAM is not set
161 210
162# 211#
163# Self-contained MTD device drivers 212# Self-contained MTD device drivers
@@ -232,6 +281,7 @@ CONFIG_IOSCHED_NOOP=y
232# 281#
233# Fusion MPT device support 282# Fusion MPT device support
234# 283#
284# CONFIG_FUSION is not set
235 285
236# 286#
237# IEEE 1394 (FireWire) support 287# IEEE 1394 (FireWire) support
@@ -244,53 +294,8 @@ CONFIG_IOSCHED_NOOP=y
244# CONFIG_I2O is not set 294# CONFIG_I2O is not set
245 295
246# 296#
247# Networking support 297# Network device support
248#
249CONFIG_NET=y
250
251#
252# Networking options
253#
254# CONFIG_PACKET is not set
255# CONFIG_UNIX is not set
256# CONFIG_NET_KEY is not set
257CONFIG_INET=y
258# CONFIG_IP_MULTICAST is not set
259# CONFIG_IP_ADVANCED_ROUTER is not set
260# CONFIG_IP_PNP is not set
261# CONFIG_NET_IPIP is not set
262# CONFIG_NET_IPGRE is not set
263# CONFIG_SYN_COOKIES is not set
264# CONFIG_INET_AH is not set
265# CONFIG_INET_ESP is not set
266# CONFIG_INET_IPCOMP is not set
267# CONFIG_INET_TUNNEL is not set
268# CONFIG_IP_TCPDIAG is not set
269# CONFIG_IP_TCPDIAG_IPV6 is not set
270# CONFIG_IPV6 is not set
271# CONFIG_NETFILTER is not set
272# CONFIG_BRIDGE is not set
273# CONFIG_VLAN_8021Q is not set
274# CONFIG_DECNET is not set
275# CONFIG_LLC2 is not set
276# CONFIG_IPX is not set
277# CONFIG_ATALK is not set
278
279#
280# QoS and/or fair queueing
281#
282# CONFIG_NET_SCHED is not set
283# CONFIG_NET_CLS_ROUTE is not set
284
285#
286# Network testing
287# 298#
288# CONFIG_NET_PKTGEN is not set
289# CONFIG_NETPOLL is not set
290# CONFIG_NET_POLL_CONTROLLER is not set
291# CONFIG_HAMRADIO is not set
292# CONFIG_IRDA is not set
293# CONFIG_BT is not set
294CONFIG_NETDEVICES=y 299CONFIG_NETDEVICES=y
295# CONFIG_DUMMY is not set 300# CONFIG_DUMMY is not set
296# CONFIG_BONDING is not set 301# CONFIG_BONDING is not set
@@ -372,6 +377,8 @@ CONFIG_EEPRO100=y
372# CONFIG_FDDI is not set 377# CONFIG_FDDI is not set
373# CONFIG_PPP is not set 378# CONFIG_PPP is not set
374# CONFIG_SLIP is not set 379# CONFIG_SLIP is not set
380# CONFIG_NETPOLL is not set
381# CONFIG_NET_POLL_CONTROLLER is not set
375 382
376# 383#
377# ISDN subsystem 384# ISDN subsystem
@@ -472,6 +479,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
472# CONFIG_JBD is not set 479# CONFIG_JBD is not set
473# CONFIG_REISERFS_FS is not set 480# CONFIG_REISERFS_FS is not set
474# CONFIG_JFS_FS is not set 481# CONFIG_JFS_FS is not set
482# CONFIG_FS_POSIX_ACL is not set
475 483
476# 484#
477# XFS support 485# XFS support
@@ -479,6 +487,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
479# CONFIG_XFS_FS is not set 487# CONFIG_XFS_FS is not set
480# CONFIG_MINIX_FS is not set 488# CONFIG_MINIX_FS is not set
481CONFIG_ROMFS_FS=y 489CONFIG_ROMFS_FS=y
490# CONFIG_MAGIC_ROM_PTR is not set
491CONFIG_INOTIFY=y
482# CONFIG_QUOTA is not set 492# CONFIG_QUOTA is not set
483CONFIG_DNOTIFY=y 493CONFIG_DNOTIFY=y
484# CONFIG_AUTOFS_FS is not set 494# CONFIG_AUTOFS_FS is not set
@@ -524,9 +534,11 @@ CONFIG_RAMFS=y
524# 534#
525CONFIG_NFS_FS=y 535CONFIG_NFS_FS=y
526CONFIG_NFS_V3=y 536CONFIG_NFS_V3=y
537# CONFIG_NFS_V3_ACL is not set
527# CONFIG_NFSD is not set 538# CONFIG_NFSD is not set
528CONFIG_LOCKD=y 539CONFIG_LOCKD=y
529CONFIG_LOCKD_V4=y 540CONFIG_LOCKD_V4=y
541CONFIG_NFS_COMMON=y
530CONFIG_SUNRPC=y 542CONFIG_SUNRPC=y
531# CONFIG_SMB_FS is not set 543# CONFIG_SMB_FS is not set
532# CONFIG_CIFS is not set 544# CONFIG_CIFS is not set
diff --git a/arch/v850/configs/rte-me2-cb_defconfig b/arch/v850/configs/rte-me2-cb_defconfig
index 44becc065404..15e666478061 100644
--- a/arch/v850/configs/rte-me2-cb_defconfig
+++ b/arch/v850/configs/rte-me2-cb_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.12-uc0 3# Linux kernel version: 2.6.13-uc0
4# Thu Jul 21 11:30:08 2005 4# Fri Sep 2 13:47:50 2005
5# 5#
6# CONFIG_MMU is not set 6# CONFIG_MMU is not set
7# CONFIG_UID16 is not set 7# CONFIG_UID16 is not set
@@ -41,6 +41,8 @@ CONFIG_ZERO_BSS=y
41# CONFIG_V850E_HIGHRES_TIMER is not set 41# CONFIG_V850E_HIGHRES_TIMER is not set
42# CONFIG_RESET_GUARD is not set 42# CONFIG_RESET_GUARD is not set
43CONFIG_LARGE_ALLOCS=y 43CONFIG_LARGE_ALLOCS=y
44CONFIG_FLATMEM=y
45CONFIG_FLAT_NODE_MEM_MAP=y
44 46
45# 47#
46# Code maturity level options 48# Code maturity level options
@@ -56,7 +58,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
56CONFIG_LOCALVERSION="" 58CONFIG_LOCALVERSION=""
57# CONFIG_BSD_PROCESS_ACCT is not set 59# CONFIG_BSD_PROCESS_ACCT is not set
58# CONFIG_SYSCTL is not set 60# CONFIG_SYSCTL is not set
59# CONFIG_AUDIT is not set
60# CONFIG_HOTPLUG is not set 61# CONFIG_HOTPLUG is not set
61# CONFIG_IKCONFIG is not set 62# CONFIG_IKCONFIG is not set
62CONFIG_EMBEDDED=y 63CONFIG_EMBEDDED=y
@@ -104,6 +105,11 @@ CONFIG_BINFMT_FLAT=y
104# CONFIG_BINFMT_MISC is not set 105# CONFIG_BINFMT_MISC is not set
105 106
106# 107#
108# Networking
109#
110# CONFIG_NET is not set
111
112#
107# Generic Driver Options 113# Generic Driver Options
108# 114#
109CONFIG_STANDALONE=y 115CONFIG_STANDALONE=y
@@ -151,6 +157,7 @@ CONFIG_MTD_CFI_I2=y
151# Mapping drivers for chip access 157# Mapping drivers for chip access
152# 158#
153# CONFIG_MTD_COMPLEX_MAPPINGS is not set 159# CONFIG_MTD_COMPLEX_MAPPINGS is not set
160# CONFIG_MTD_PLATRAM is not set
154 161
155# 162#
156# Self-contained MTD device drivers 163# Self-contained MTD device drivers
@@ -218,6 +225,7 @@ CONFIG_IOSCHED_NOOP=y
218# 225#
219# Fusion MPT device support 226# Fusion MPT device support
220# 227#
228# CONFIG_FUSION is not set
221 229
222# 230#
223# IEEE 1394 (FireWire) support 231# IEEE 1394 (FireWire) support
@@ -228,9 +236,8 @@ CONFIG_IOSCHED_NOOP=y
228# 236#
229 237
230# 238#
231# Networking support 239# Network device support
232# 240#
233# CONFIG_NET is not set
234# CONFIG_NETPOLL is not set 241# CONFIG_NETPOLL is not set
235# CONFIG_NET_POLL_CONTROLLER is not set 242# CONFIG_NET_POLL_CONTROLLER is not set
236 243
@@ -311,7 +318,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y
311# 318#
312# Ftape, the floppy tape device driver 319# Ftape, the floppy tape device driver
313# 320#
314# CONFIG_DRM is not set
315# CONFIG_RAW_DRIVER is not set 321# CONFIG_RAW_DRIVER is not set
316 322
317# 323#
@@ -335,6 +341,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y
335# CONFIG_JBD is not set 341# CONFIG_JBD is not set
336# CONFIG_REISERFS_FS is not set 342# CONFIG_REISERFS_FS is not set
337# CONFIG_JFS_FS is not set 343# CONFIG_JFS_FS is not set
344# CONFIG_FS_POSIX_ACL is not set
338 345
339# 346#
340# XFS support 347# XFS support
@@ -342,6 +349,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
342# CONFIG_XFS_FS is not set 349# CONFIG_XFS_FS is not set
343# CONFIG_MINIX_FS is not set 350# CONFIG_MINIX_FS is not set
344CONFIG_ROMFS_FS=y 351CONFIG_ROMFS_FS=y
352# CONFIG_MAGIC_ROM_PTR is not set
353CONFIG_INOTIFY=y
345# CONFIG_QUOTA is not set 354# CONFIG_QUOTA is not set
346CONFIG_DNOTIFY=y 355CONFIG_DNOTIFY=y
347# CONFIG_AUTOFS_FS is not set 356# CONFIG_AUTOFS_FS is not set
diff --git a/arch/v850/configs/sim_defconfig b/arch/v850/configs/sim_defconfig
index d73f5f9d8383..f31ba7398ad0 100644
--- a/arch/v850/configs/sim_defconfig
+++ b/arch/v850/configs/sim_defconfig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.12-uc0 3# Linux kernel version: 2.6.13-uc0
4# Thu Jul 21 11:29:27 2005 4# Fri Sep 2 13:36:43 2005
5# 5#
6# CONFIG_MMU is not set 6# CONFIG_MMU is not set
7# CONFIG_UID16 is not set 7# CONFIG_UID16 is not set
@@ -36,6 +36,8 @@ CONFIG_NO_CACHE=y
36CONFIG_ZERO_BSS=y 36CONFIG_ZERO_BSS=y
37# CONFIG_RESET_GUARD is not set 37# CONFIG_RESET_GUARD is not set
38CONFIG_LARGE_ALLOCS=y 38CONFIG_LARGE_ALLOCS=y
39CONFIG_FLATMEM=y
40CONFIG_FLAT_NODE_MEM_MAP=y
39 41
40# 42#
41# Code maturity level options 43# Code maturity level options
@@ -51,7 +53,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
51CONFIG_LOCALVERSION="" 53CONFIG_LOCALVERSION=""
52# CONFIG_BSD_PROCESS_ACCT is not set 54# CONFIG_BSD_PROCESS_ACCT is not set
53# CONFIG_SYSCTL is not set 55# CONFIG_SYSCTL is not set
54# CONFIG_AUDIT is not set
55# CONFIG_HOTPLUG is not set 56# CONFIG_HOTPLUG is not set
56# CONFIG_IKCONFIG is not set 57# CONFIG_IKCONFIG is not set
57CONFIG_EMBEDDED=y 58CONFIG_EMBEDDED=y
@@ -99,6 +100,11 @@ CONFIG_BINFMT_FLAT=y
99# CONFIG_BINFMT_MISC is not set 100# CONFIG_BINFMT_MISC is not set
100 101
101# 102#
103# Networking
104#
105# CONFIG_NET is not set
106
107#
102# Generic Driver Options 108# Generic Driver Options
103# 109#
104CONFIG_STANDALONE=y 110CONFIG_STANDALONE=y
@@ -146,6 +152,7 @@ CONFIG_MTD_CFI_I2=y
146# Mapping drivers for chip access 152# Mapping drivers for chip access
147# 153#
148# CONFIG_MTD_COMPLEX_MAPPINGS is not set 154# CONFIG_MTD_COMPLEX_MAPPINGS is not set
155# CONFIG_MTD_PLATRAM is not set
149 156
150# 157#
151# Self-contained MTD device drivers 158# Self-contained MTD device drivers
@@ -213,6 +220,7 @@ CONFIG_IOSCHED_NOOP=y
213# 220#
214# Fusion MPT device support 221# Fusion MPT device support
215# 222#
223# CONFIG_FUSION is not set
216 224
217# 225#
218# IEEE 1394 (FireWire) support 226# IEEE 1394 (FireWire) support
@@ -223,9 +231,8 @@ CONFIG_IOSCHED_NOOP=y
223# 231#
224 232
225# 233#
226# Networking support 234# Network device support
227# 235#
228# CONFIG_NET is not set
229# CONFIG_NETPOLL is not set 236# CONFIG_NETPOLL is not set
230# CONFIG_NET_POLL_CONTROLLER is not set 237# CONFIG_NET_POLL_CONTROLLER is not set
231 238
@@ -300,7 +307,6 @@ CONFIG_SERIO=y
300# 307#
301# Ftape, the floppy tape device driver 308# Ftape, the floppy tape device driver
302# 309#
303# CONFIG_DRM is not set
304# CONFIG_RAW_DRIVER is not set 310# CONFIG_RAW_DRIVER is not set
305 311
306# 312#
@@ -324,6 +330,7 @@ CONFIG_SERIO=y
324# CONFIG_JBD is not set 330# CONFIG_JBD is not set
325# CONFIG_REISERFS_FS is not set 331# CONFIG_REISERFS_FS is not set
326# CONFIG_JFS_FS is not set 332# CONFIG_JFS_FS is not set
333# CONFIG_FS_POSIX_ACL is not set
327 334
328# 335#
329# XFS support 336# XFS support
@@ -331,6 +338,8 @@ CONFIG_SERIO=y
331# CONFIG_XFS_FS is not set 338# CONFIG_XFS_FS is not set
332# CONFIG_MINIX_FS is not set 339# CONFIG_MINIX_FS is not set
333CONFIG_ROMFS_FS=y 340CONFIG_ROMFS_FS=y
341# CONFIG_MAGIC_ROM_PTR is not set
342CONFIG_INOTIFY=y
334# CONFIG_QUOTA is not set 343# CONFIG_QUOTA is not set
335CONFIG_DNOTIFY=y 344CONFIG_DNOTIFY=y
336# CONFIG_AUTOFS_FS is not set 345# CONFIG_AUTOFS_FS is not set
diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c
index c41d72b01b88..abd48409dcca 100644
--- a/arch/v850/kernel/setup.c
+++ b/arch/v850/kernel/setup.c
@@ -1,8 +1,8 @@
1/* 1/*
2 * arch/v850/kernel/setup.c -- Arch-dependent initialization functions 2 * arch/v850/kernel/setup.c -- Arch-dependent initialization functions
3 * 3 *
4 * Copyright (C) 2001,02,03 NEC Electronics Corporation 4 * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
5 * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> 5 * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org>
6 * 6 *
7 * This file is subject to the terms and conditions of the GNU General 7 * This file is subject to the terms and conditions of the GNU General
8 * Public License. See the file COPYING in the main directory of this 8 * Public License. See the file COPYING in the main directory of this
@@ -98,10 +98,20 @@ void __init trap_init (void)
98} 98}
99 99
100#ifdef CONFIG_MTD 100#ifdef CONFIG_MTD
101
102/* From drivers/mtd/devices/slram.c */
103#define SLRAM_BLK_SZ 0x4000
104
101/* Set the root filesystem to be the given memory region. 105/* Set the root filesystem to be the given memory region.
102 Some parameter may be appended to CMD_LINE. */ 106 Some parameter may be appended to CMD_LINE. */
103void set_mem_root (void *addr, size_t len, char *cmd_line) 107void set_mem_root (void *addr, size_t len, char *cmd_line)
104{ 108{
109 /* Some sort of idiocy in MTD means we must supply a length that's
110 a multiple of SLRAM_BLK_SZ. We just round up the real length,
111 as the file system shouldn't attempt to access anything beyond
112 the end of the image anyway. */
113 len = (((len - 1) + SLRAM_BLK_SZ) / SLRAM_BLK_SZ) * SLRAM_BLK_SZ;
114
105 /* The only way to pass info to the MTD slram driver is via 115 /* The only way to pass info to the MTD slram driver is via
106 the command line. */ 116 the command line. */
107 if (*cmd_line) { 117 if (*cmd_line) {
@@ -284,3 +294,33 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len)
284 free_area_init_node (0, NODE_DATA(0), zones_size, 294 free_area_init_node (0, NODE_DATA(0), zones_size,
285 ADDR_TO_PAGE (PAGE_OFFSET), 0); 295 ADDR_TO_PAGE (PAGE_OFFSET), 0);
286} 296}
297
298
299
300/* Taken from m68knommu */
301void show_mem(void)
302{
303 unsigned long i;
304 int free = 0, total = 0, reserved = 0, shared = 0;
305 int cached = 0;
306
307 printk(KERN_INFO "\nMem-info:\n");
308 show_free_areas();
309 i = max_mapnr;
310 while (i-- > 0) {
311 total++;
312 if (PageReserved(mem_map+i))
313 reserved++;
314 else if (PageSwapCache(mem_map+i))
315 cached++;
316 else if (!page_count(mem_map+i))
317 free++;
318 else
319 shared += page_count(mem_map+i) - 1;
320 }
321 printk(KERN_INFO "%d pages of RAM\n",total);
322 printk(KERN_INFO "%d free pages\n",free);
323 printk(KERN_INFO "%d reserved pages\n",reserved);
324 printk(KERN_INFO "%d pages shared\n",shared);
325 printk(KERN_INFO "%d pages swap cached\n",cached);
326}