diff options
author | Len Brown <len.brown@intel.com> | 2005-09-03 02:44:09 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-09-03 02:44:09 -0400 |
commit | 129521dcc94f781890f8f668219ab79f0073ff9f (patch) | |
tree | 9f70707c88da65577f38814fe37b24c4b4957d64 /arch | |
parent | 824b558bbe2c298b165cdb54c33718994dda30bb (diff) | |
parent | f505380ba7b98ec97bf25300c2a58aeae903530b (diff) |
Merge linux-2.6 into linux-acpi-2.6 test
Diffstat (limited to 'arch')
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 | ||
371 | config ARCH_DISCONTIGMEM_ENABLE | 371 | config 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 | ||
268 | sys_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 | } |
313 | EXPORT_SYMBOL(execve); | 313 | EXPORT_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 | */ | ||
319 | asmlinkage 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 | ||
442 | static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) | 444 | static 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 | ||
41 | enum ixp4xx_irq_type { | ||
42 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE | ||
43 | }; | ||
44 | static 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 | */ | ||
56 | void 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 | |||
123 | EXPORT_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 | **************************************************************************/ |
84 | enum ixp4xx_irq_type { | ||
85 | IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE | ||
86 | }; | ||
87 | |||
88 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); | ||
89 | |||
90 | /* | ||
91 | * IRQ -> GPIO mapping table | ||
92 | */ | ||
93 | static 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 | |||
100 | static 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 | |||
168 | static void ixp4xx_irq_mask(unsigned int irq) | 147 | static 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 | ||
184 | static void ixp4xx_irq_ack(unsigned int irq) | 163 | static 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 | ||
214 | static struct irqchip ixp4xx_irq_edge_chip = { | 188 | static 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 | ||
220 | static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) | 195 | static 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 | ||
31 | void __init coyote_pci_preinit(void) | 31 | void __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 | ||
27 | void __init coyote_map_io(void) | ||
28 | { | ||
29 | ixp4xx_map_io(); | ||
30 | } | ||
31 | |||
32 | static struct flash_platform_data coyote_flash_data = { | 27 | static 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); | |||
35 | extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); | 35 | extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); |
36 | extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); | 36 | extern 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 | |||
47 | static 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 | */ | ||
54 | void __init gtwx5715_pci_preinit(void) | 46 | void __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 | |||
105 | void __init gtwx5715_map_io(void) | ||
106 | { | ||
107 | ixp4xx_map_io(); | ||
108 | } | ||
109 | |||
110 | static struct flash_platform_data gtwx5715_flash_data = { | 104 | static 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 | ||
28 | void __init ixdp425_pci_preinit(void) | 28 | void __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 | ||
27 | void __init ixdp425_map_io(void) | ||
28 | { | ||
29 | ixp4xx_map_io(); | ||
30 | } | ||
31 | |||
32 | static struct flash_platform_data ixdp425_flash_data = { | 27 | static 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 | ||
30 | void __init ixdpg425_pci_preinit(void) | 30 | void __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 | ||
74 | static unsigned long initial_match; | ||
75 | static int match_posponed; | ||
76 | #endif | ||
77 | |||
73 | static irqreturn_t | 78 | static irqreturn_t |
74 | pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 79 | pxa_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 | ||
143 | static int pxa_dyn_tick_enable_disable(void) | ||
144 | { | ||
145 | /* nothing to do */ | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static 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 | |||
158 | static irqreturn_t | ||
159 | pxa_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 | |||
170 | static 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 |
130 | static unsigned long osmr[4], oier; | 179 | static 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 = { | |||
68 | static int s3c2440_clk_add(struct sys_device *sysdev) | 68 | static 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. | 74 | static unsigned long initial_match; |
75 | * | 75 | static 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 | */ | ||
82 | static irqreturn_t | 78 | static irqreturn_t |
83 | sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 79 | sa1100_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 | ||
135 | static int sa1100_dyn_tick_enable_disable(void) | ||
136 | { | ||
137 | /* nothing to do */ | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static 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 | |||
150 | static irqreturn_t | ||
151 | sa1100_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 | |||
162 | static 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 |
124 | unsigned long osmr[4], oier; | 171 | unsigned 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; | |||
68 | static unsigned long ai_skipped; | 68 | static unsigned long ai_skipped; |
69 | static unsigned long ai_half; | 69 | static unsigned long ai_half; |
70 | static unsigned long ai_word; | 70 | static unsigned long ai_word; |
71 | static unsigned long ai_dword; | ||
71 | static unsigned long ai_multi; | 72 | static unsigned long ai_multi; |
72 | static int ai_usermode; | 73 | static 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 | |
327 | static int | ||
328 | do_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 | */ |
584 | void setup_mm_for_reboot(char mode) | 578 | void 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) | |||
170 | static int __init pcibios_assign_resources(void) | 170 | static 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 | ||
358 | source "drivers/acpi/Kconfig" | 358 | source "drivers/acpi/Kconfig" |
359 | 359 | ||
360 | if PM | ||
361 | |||
362 | source "arch/ia64/kernel/cpufreq/Kconfig" | ||
363 | |||
364 | endif | ||
365 | |||
360 | endmenu | 366 | endmenu |
361 | 367 | ||
362 | if !IA64_HP_SIM | 368 | if !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 | */ | ||
245 | void * | ||
246 | id (long addr) | ||
247 | { | ||
248 | return (void *) addr; | ||
249 | } | ||
250 | |||
251 | struct ia64_boot_param * | 240 | struct ia64_boot_param * |
252 | sys_fw_init (const char *args, int arglen) | 241 | sys_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 | |||
20 | obj-$(CONFIG_NUMA) += numa.o | 20 | obj-$(CONFIG_NUMA) += numa.o |
21 | obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o | 21 | obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o |
22 | obj-$(CONFIG_IA64_CYCLONE) += cyclone.o | 22 | obj-$(CONFIG_IA64_CYCLONE) += cyclone.o |
23 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ | ||
23 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o | 24 | obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o |
24 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o | 25 | obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o |
25 | obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o | 26 | obj-$(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 | |||
6 | menu "CPU Frequency scaling" | ||
7 | |||
8 | source "drivers/cpufreq/Kconfig" | ||
9 | |||
10 | if CPU_FREQ | ||
11 | |||
12 | comment "CPUFreq processor drivers" | ||
13 | |||
14 | config 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 | |||
26 | endif # CPU_FREQ | ||
27 | |||
28 | endmenu | ||
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 | |||
28 | MODULE_AUTHOR("Venkatesh Pallipadi"); | ||
29 | MODULE_DESCRIPTION("ACPI Processor P-States Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | |||
33 | struct cpufreq_acpi_io { | ||
34 | struct acpi_processor_performance acpi_data; | ||
35 | struct cpufreq_frequency_table *freq_table; | ||
36 | unsigned int resume; | ||
37 | }; | ||
38 | |||
39 | static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; | ||
40 | |||
41 | static struct cpufreq_driver acpi_cpufreq_driver; | ||
42 | |||
43 | |||
44 | static int | ||
45 | processor_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 | |||
63 | static int | ||
64 | processor_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 */ | ||
84 | static unsigned | ||
85 | extract_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 | |||
102 | static unsigned int | ||
103 | processor_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 | |||
138 | migrate_end: | ||
139 | set_cpus_allowed(current, saved_mask); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | |||
144 | static int | ||
145 | processor_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 | |||
215 | migrate_end: | ||
216 | set_cpus_allowed(current, saved_mask); | ||
217 | return (retval); | ||
218 | } | ||
219 | |||
220 | |||
221 | static unsigned int | ||
222 | acpi_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 | |||
233 | static int | ||
234 | acpi_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 | |||
256 | static int | ||
257 | acpi_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 | */ | ||
282 | static void | ||
283 | processor_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 | |||
314 | static int | ||
315 | acpi_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 | |||
440 | static int | ||
441 | acpi_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 | |||
460 | static struct freq_attr* acpi_cpufreq_attr[] = { | ||
461 | &cpufreq_freq_attr_scaling_available_freqs, | ||
462 | NULL, | ||
463 | }; | ||
464 | |||
465 | |||
466 | static 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 | |||
478 | static int __init | ||
479 | acpi_cpufreq_init (void) | ||
480 | { | ||
481 | dprintk("acpi_cpufreq_init\n"); | ||
482 | |||
483 | return cpufreq_register_driver(&acpi_cpufreq_driver); | ||
484 | } | ||
485 | |||
486 | |||
487 | static void __exit | ||
488 | acpi_cpufreq_exit (void) | ||
489 | { | ||
490 | dprintk("acpi_cpufreq_exit\n"); | ||
491 | |||
492 | cpufreq_unregister_driver(&acpi_cpufreq_driver); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | |||
497 | late_initcall(acpi_cpufreq_init); | ||
498 | module_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 | ||
7 | lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ | 7 | lib-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 | |||
93 | setup_io_tlb_npages(char *str) | 93 | setup_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 | ||
64 | extern void hubdev_init_node(nodepda_t *, cnodeid_t); | 69 | extern 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 | ||
33 | static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface) | 34 | static 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 | ||
46 | static 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 | ||
45 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ | 46 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ |
46 | 47 | ||
48 | static int max_segment_number = 0; /* Default highest segment number */ | ||
49 | static 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) | |||
230 | void sn_pci_fixup_slot(struct pci_dev *dev) | 249 | void 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: | |||
445 | static int __init sn_pci_init(void) | 465 | static 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 | ||
77 | static void sn_ack_irq(unsigned int irq) | 77 | static 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 | ||
94 | static void sn_end_irq(unsigned int irq) | 92 | static 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 | ||
317 | static inline void | ||
318 | sn_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 | |||
320 | static void force_interrupt(int irq) | 327 | static 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); | |||
80 | DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); | 80 | DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); |
81 | EXPORT_PER_CPU_SYMBOL(__sn_nodepda); | 81 | EXPORT_PER_CPU_SYMBOL(__sn_nodepda); |
82 | 82 | ||
83 | partid_t sn_partid = -1; | ||
84 | EXPORT_SYMBOL(sn_partid); | ||
85 | char sn_system_serial_number_string[128]; | 83 | char sn_system_serial_number_string[128]; |
86 | EXPORT_SYMBOL(sn_system_serial_number_string); | 84 | EXPORT_SYMBOL(sn_system_serial_number_string); |
87 | u64 sn_partition_serial_number; | 85 | u64 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 | ||
40 | 1: | 41 | 1: |
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 | ||
45 | 5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. | 46 | 5: 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 | ||
59 | 5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. | 61 | 5: 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 | ||
69 | 5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. | 72 | 5: 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 | ||
42 | void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0, | 44 | DEFINE_PER_CPU(struct ptc_stats, ptcstats); |
43 | volatile unsigned long *, unsigned long data1); | 45 | DECLARE_PER_CPU(struct ptc_stats, ptcstats); |
44 | 46 | ||
45 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); | 47 | static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); |
46 | 48 | ||
47 | static unsigned long sn2_ptc_deadlock_count; | 49 | void 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 | |||
71 | static unsigned int sn2_ptctest = 0; | ||
72 | |||
73 | static int __init ptc_test(char *str) | ||
74 | { | ||
75 | get_option(&str, &sn2_ptctest); | ||
76 | return 1; | ||
77 | } | ||
78 | __setup("ptctest=", ptc_test); | ||
79 | |||
80 | static 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 | |||
108 | static 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 | |||
136 | static inline int ptc_lock(unsigned long *flagp) | ||
137 | { | ||
138 | spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static inline void ptc_unlock(unsigned long flags, int opt) | ||
143 | { | ||
144 | spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); | ||
145 | } | ||
146 | #endif | ||
147 | |||
148 | struct 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 | ||
49 | static inline unsigned long wait_piowc(void) | 159 | static inline unsigned long wait_piowc(void) |
50 | { | 160 | { |
@@ -89,9 +199,9 @@ void | |||
89 | sn2_global_tlb_purge(unsigned long start, unsigned long end, | 199 | sn2_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 | */ |
195 | void sn2_ptc_deadlock_recovery(volatile unsigned long *ptc0, unsigned long data0, | 317 | void 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 | |||
421 | static 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 | |||
428 | static 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 | |||
436 | static void sn2_ptc_seq_stop(struct seq_file *file, void *data) | ||
437 | { | ||
438 | } | ||
439 | |||
440 | static 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 | |||
465 | static 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 | |||
472 | int sn2_ptc_proc_open(struct inode *inode, struct file *file) | ||
473 | { | ||
474 | return seq_open(file, &sn2_ptc_seq_ops); | ||
475 | } | ||
476 | |||
477 | static 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 | |||
484 | static struct proc_dir_entry *proc_sn2_ptc; | ||
485 | |||
486 | static 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 | |||
497 | static void __exit sn2_ptc_exit(void) | ||
498 | { | ||
499 | remove_proc_entry(PTC_BASENAME, NULL); | ||
500 | } | ||
501 | |||
502 | module_init(sn2_ptc_init); | ||
503 | module_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 | ||
130 | static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) | 129 | static 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 | ||
177 | static void print_pci_topology(struct seq_file *s, | 178 | static 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 | |||
196 | static inline int sn_hwperf_has_cpus(cnodeid_t node) | ||
197 | { | ||
198 | return node_online(node) && nr_cpus_node(node); | ||
199 | } | ||
200 | |||
201 | static inline int sn_hwperf_has_mem(cnodeid_t node) | ||
202 | { | ||
203 | return node_online(node) && NODE_DATA(node)->node_present_pages; | ||
204 | } | ||
205 | |||
206 | static struct sn_hwperf_object_info * | ||
207 | sn_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 | |||
222 | static 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 | |||
366 | err: | ||
367 | return e; | ||
200 | } | 368 | } |
201 | 369 | ||
370 | |||
202 | static int sn_topology_show(struct seq_file *s, void *d) | 371 | static 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 | |||
955 | int 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 | |||
971 | static 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 | |||
990 | device_initcall(sn_hwperf_misc_register_init); /* after misc_init() */ | ||
991 | EXPORT_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 | ||
16 | static int partition_id_show(struct seq_file *s, void *p) | 16 | static 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 | ||
10 | obj-y := pci_dma.o tioca_provider.o pcibr/ | 10 | obj-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 * | |||
88 | pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) | 89 | pcibr_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 | ||
187 | void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info) | 201 | void 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 | ||
224 | int | 240 | int |
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 | */ | ||
83 | static uint64_t | ||
84 | tioce_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 | */ | ||
103 | static inline void | ||
104 | pcidev_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 | */ | ||
143 | static uint64_t | ||
144 | tioce_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 | */ | ||
254 | static uint64_t | ||
255 | tioce_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 | */ | ||
297 | static uint64_t | ||
298 | tioce_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 | */ | ||
324 | void | ||
325 | tioce_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 | */ | ||
387 | static uint64_t | ||
388 | tioce_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 | |||
487 | dma_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 | */ | ||
503 | static uint64_t | ||
504 | tioce_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 | ||
518 | tioce_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 | ||
532 | tioce_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 * | ||
550 | tioce_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 | */ | ||
611 | static void | ||
612 | tioce_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 | */ | ||
682 | static void | ||
683 | tioce_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 | */ | ||
719 | static void * | ||
720 | tioce_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 | |||
754 | static 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 | */ | ||
766 | int | ||
767 | tioce_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 | ||
74 | config M523x | ||
75 | bool "MCF523x" | ||
76 | help | ||
77 | Freescale Coldfire 5230/1/2/4/5 processor support | ||
78 | |||
74 | config M5249 | 79 | config 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 | ||
79 | config M527x | 84 | config 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 | ||
84 | config M5272 | 89 | config 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 | ||
94 | config M5275 | ||
95 | bool "MCF5275" | ||
96 | help | ||
97 | Freescale (Motorola) ColdFire 5274/5275 processor support. | ||
98 | |||
89 | config M528x | 99 | config M528x |
90 | bool "MCF528x" | 100 | bool "MCF528x" |
91 | help | 101 | help |
@@ -103,9 +113,14 @@ config M5407 | |||
103 | 113 | ||
104 | endchoice | 114 | endchoice |
105 | 115 | ||
116 | config M527x | ||
117 | bool | ||
118 | depends on (M5271 || M5275) | ||
119 | default y | ||
120 | |||
106 | config COLDFIRE | 121 | config 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 | ||
111 | choice | 126 | choice |
@@ -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 | ||
201 | config CLOCK_62_5MHz | ||
202 | bool "62.5MHz" | ||
203 | help | ||
204 | Select a 62.5MHz CPU clock frequency. | ||
205 | |||
186 | config CLOCK_64MHz | 206 | config 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 | ||
325 | config M5235EVB | ||
326 | bool "Freescale M5235EVB support" | ||
327 | depends on M523x | ||
328 | help | ||
329 | Support for the Freescale M5235EVB board. | ||
330 | |||
305 | config M5249C3 | 331 | config 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 | ||
311 | config M5271EVB | 337 | config 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 | ||
317 | config M5275EVB | 343 | config 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 | |||
373 | config SOM5282EM | ||
374 | bool "EMAC.Inc SOM5282EM board support" | ||
375 | depends on M528x | ||
376 | help | ||
377 | Support for the EMAC.Inc SOM5282EM module. | ||
346 | 378 | ||
347 | config ARN5307 | 379 | config 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 | ||
445 | config MOD5272 | ||
446 | bool "Netburner MOD-5272 board support" | ||
447 | depends on M5272 | ||
448 | help | ||
449 | Support for the Netburner MOD-5272 board. | ||
450 | |||
413 | config ROMFS_FROM_ROM | 451 | config 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 | |||
430 | config MOTOROLA | 468 | config 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 | ||
435 | config HW_FEITH | 473 | config 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 | |||
483 | config EMAC_INC | ||
484 | bool | ||
485 | default y | ||
486 | depends on (SOM5282EM) | ||
444 | 487 | ||
445 | config SNEHA | 488 | config 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 | ||
501 | config 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 | |||
458 | choice | 510 | choice |
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 | |||
14 | platform-$(CONFIG_M68360) := 68360 | 14 | platform-$(CONFIG_M68360) := 68360 |
15 | platform-$(CONFIG_M5206) := 5206 | 15 | platform-$(CONFIG_M5206) := 5206 |
16 | platform-$(CONFIG_M5206e) := 5206e | 16 | platform-$(CONFIG_M5206e) := 5206e |
17 | platform-$(CONFIG_M523x) := 523x | ||
17 | platform-$(CONFIG_M5249) := 5249 | 18 | platform-$(CONFIG_M5249) := 5249 |
18 | platform-$(CONFIG_M527x) := 527x | 19 | platform-$(CONFIG_M527x) := 527x |
19 | platform-$(CONFIG_M5272) := 5272 | 20 | platform-$(CONFIG_M5272) := 5272 |
@@ -29,6 +30,7 @@ board-$(CONFIG_UCQUICC) := uCquicc | |||
29 | board-$(CONFIG_DRAGEN2) := de2 | 30 | board-$(CONFIG_DRAGEN2) := de2 |
30 | board-$(CONFIG_ARNEWSH) := ARNEWSH | 31 | board-$(CONFIG_ARNEWSH) := ARNEWSH |
31 | board-$(CONFIG_MOTOROLA) := MOTOROLA | 32 | board-$(CONFIG_MOTOROLA) := MOTOROLA |
33 | board-$(CONFIG_M5235EVB) := M5235EVB | ||
32 | board-$(CONFIG_M5271EVB) := M5271EVB | 34 | board-$(CONFIG_M5271EVB) := M5271EVB |
33 | board-$(CONFIG_M5275EVB) := M5275EVB | 35 | board-$(CONFIG_M5275EVB) := M5275EVB |
34 | board-$(CONFIG_M5282EVB) := M5282EVB | 36 | board-$(CONFIG_M5282EVB) := M5282EVB |
@@ -39,6 +41,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3 | |||
39 | board-$(CONFIG_CLEOPATRA) := CLEOPATRA | 41 | board-$(CONFIG_CLEOPATRA) := CLEOPATRA |
40 | board-$(CONFIG_senTec) := senTec | 42 | board-$(CONFIG_senTec) := senTec |
41 | board-$(CONFIG_SNEHA) := SNEHA | 43 | board-$(CONFIG_SNEHA) := SNEHA |
44 | board-$(CONFIG_MOD5272) := MOD5272 | ||
42 | BOARD := $(board-y) | 45 | BOARD := $(board-y) |
43 | 46 | ||
44 | model-$(CONFIG_RAMKERNEL) := ram | 47 | model-$(CONFIG_RAMKERNEL) := ram |
@@ -53,6 +56,7 @@ MODEL := $(model-y) | |||
53 | # | 56 | # |
54 | cpuclass-$(CONFIG_M5206) := 5307 | 57 | cpuclass-$(CONFIG_M5206) := 5307 |
55 | cpuclass-$(CONFIG_M5206e) := 5307 | 58 | cpuclass-$(CONFIG_M5206e) := 5307 |
59 | cpuclass-$(CONFIG_M523x) := 5307 | ||
56 | cpuclass-$(CONFIG_M5249) := 5307 | 60 | cpuclass-$(CONFIG_M5249) := 5307 |
57 | cpuclass-$(CONFIG_M527x) := 5307 | 61 | cpuclass-$(CONFIG_M527x) := 5307 |
58 | cpuclass-$(CONFIG_M5272) := 5307 | 62 | cpuclass-$(CONFIG_M5272) := 5307 |
@@ -76,6 +80,7 @@ export PLATFORM BOARD MODEL CPUCLASS | |||
76 | # | 80 | # |
77 | cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 | 81 | cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 |
78 | cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 | 82 | cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 |
83 | cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307 | ||
79 | cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 | 84 | cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 |
80 | cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 | 85 | cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 |
81 | cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307 | 86 | cflags-$(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 | # |
6 | CONFIG_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 |
6 | CONFIG_UID16=y | 9 | CONFIG_UID16=y |
7 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 10 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
8 | # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set | 11 | # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set |
12 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
9 | 13 | ||
10 | # | 14 | # |
11 | # Code maturity level options | 15 | # Code maturity level options |
12 | # | 16 | # |
13 | CONFIG_EXPERIMENTAL=y | 17 | CONFIG_EXPERIMENTAL=y |
18 | CONFIG_CLEAN_COMPILE=y | ||
19 | CONFIG_BROKEN_ON_SMP=y | ||
20 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
14 | 21 | ||
15 | # | 22 | # |
16 | # General setup | 23 | # General setup |
17 | # | 24 | # |
18 | # CONFIG_SYSVIPC is not set | 25 | CONFIG_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 |
21 | CONFIG_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 | ||
33 | CONFIG_EMBEDDED=y | ||
34 | # CONFIG_KALLSYMS is not set | ||
35 | CONFIG_PRINTK=y | ||
36 | CONFIG_BUG=y | ||
37 | CONFIG_BASE_FULL=y | ||
38 | # CONFIG_FUTEX is not set | ||
39 | # CONFIG_EPOLL is not set | ||
40 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
41 | CONFIG_CC_ALIGN_FUNCTIONS=0 | ||
42 | CONFIG_CC_ALIGN_LABELS=0 | ||
43 | CONFIG_CC_ALIGN_LOOPS=0 | ||
44 | CONFIG_CC_ALIGN_JUMPS=0 | ||
45 | CONFIG_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 |
39 | CONFIG_M5272=y | 64 | CONFIG_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 | ||
57 | CONFIG_CLOCK_66MHz=y | 85 | CONFIG_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 | # |
67 | CONFIG_M5272C3=y | 95 | CONFIG_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 | ||
69 | CONFIG_MOTOROLA=y | 102 | CONFIG_MOTOROLA=y |
70 | # CONFIG_LARGE_ALLOCS is not set | 103 | # CONFIG_LARGE_ALLOCS is not set |
71 | # CONFIG_RAMAUTO is not set | 104 | CONFIG_4KSTACKS=y |
105 | CONFIG_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 |
74 | CONFIG_RAM16MB=y | 108 | # CONFIG_RAM16MB is not set |
75 | # CONFIG_RAM32MB is not set | 109 | # CONFIG_RAM32MB is not set |
76 | CONFIG_RAMAUTOBIT=y | 110 | CONFIG_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 |
80 | CONFIG_RAMKERNEL=y | 114 | CONFIG_RAMKERNEL=y |
81 | # CONFIG_ROMKERNEL is not set | 115 | # CONFIG_ROMKERNEL is not set |
82 | # CONFIG_HIMEMKERNEL is not set | 116 | CONFIG_SELECT_MEMORY_MODEL=y |
117 | CONFIG_FLATMEM_MANUAL=y | ||
118 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
119 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
120 | CONFIG_FLATMEM=y | ||
121 | CONFIG_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 | # |
93 | CONFIG_KCORE_AOUT=y | ||
94 | CONFIG_BINFMT_FLAT=y | 140 | CONFIG_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 | # | ||
153 | CONFIG_NET=y | ||
154 | |||
155 | # | ||
156 | # Networking options | ||
157 | # | ||
158 | CONFIG_PACKET=y | ||
159 | # CONFIG_PACKET_MMAP is not set | ||
160 | CONFIG_UNIX=y | ||
161 | # CONFIG_NET_KEY is not set | ||
162 | CONFIG_INET=y | ||
163 | # CONFIG_IP_MULTICAST is not set | ||
164 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
165 | CONFIG_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 | ||
178 | CONFIG_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 | # | ||
216 | CONFIG_STANDALONE=y | ||
217 | CONFIG_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 | # |
105 | CONFIG_MTD=y | 223 | CONFIG_MTD=y |
106 | # CONFIG_MTD_DEBUG is not set | 224 | # CONFIG_MTD_DEBUG is not set |
107 | CONFIG_MTD_PARTITIONS=y | ||
108 | # CONFIG_MTD_CONCAT is not set | 225 | # CONFIG_MTD_CONCAT is not set |
226 | CONFIG_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 | |||
116 | CONFIG_MTD_BLOCK=y | 234 | CONFIG_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 |
244 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
245 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
246 | CONFIG_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 | ||
250 | CONFIG_MTD_CFI_I1=y | ||
251 | CONFIG_MTD_CFI_I2=y | ||
252 | # CONFIG_MTD_CFI_I4 is not set | ||
253 | # CONFIG_MTD_CFI_I8 is not set | ||
125 | CONFIG_MTD_RAM=y | 254 | CONFIG_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 | ||
133 | CONFIG_MTD_UCLINUX=y | 262 | CONFIG_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 |
170 | CONFIG_BLK_DEV_RAM=y | 303 | CONFIG_BLK_DEV_RAM=y |
304 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
171 | CONFIG_BLK_DEV_RAM_SIZE=4096 | 305 | CONFIG_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 | 307 | CONFIG_INITRAMFS_SOURCE="" |
308 | # CONFIG_CDROM_PKTCDVD is not set | ||
174 | 309 | ||
175 | # | 310 | # |
176 | # ATA/IDE/MFM/RLL support | 311 | # IO Schedulers |
312 | # | ||
313 | CONFIG_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 | # | ||
201 | CONFIG_NET=y | ||
202 | |||
203 | # | ||
204 | # Networking options | ||
205 | # | ||
206 | CONFIG_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 | ||
211 | CONFIG_UNIX=y | ||
212 | # CONFIG_NET_KEY is not set | ||
213 | CONFIG_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 | # |
230 | CONFIG_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 | ||
253 | CONFIG_NETDEVICES=y | 350 | CONFIG_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 | # |
263 | CONFIG_NET_ETHERNET=y | 359 | CONFIG_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 | ||
265 | CONFIG_FEC=y | 364 | CONFIG_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 | ||
270 | CONFIG_PPP=y | 388 | CONFIG_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 | 439 | CONFIG_SERIAL_COLDFIRE=y |
440 | # CONFIG_UNIX98_PTYS is not set | ||
441 | CONFIG_LEGACY_PTYS=y | ||
442 | CONFIG_LEGACY_PTY_COUNT=256 | ||
313 | 443 | ||
314 | # | 444 | # |
315 | # Input device support | 445 | # IPMI |
316 | # | 446 | # |
317 | CONFIG_INPUT=y | 447 | # CONFIG_IPMI_HANDLER is not set |
318 | 448 | ||
319 | # | 449 | # |
320 | # Userland interfaces | 450 | # Watchdog Cards |
321 | # | 451 | # |
322 | CONFIG_INPUT_MOUSEDEV=y | 452 | # CONFIG_WATCHDOG is not set |
323 | CONFIG_INPUT_MOUSEDEV_PSAUX=y | 453 | # CONFIG_MCFWATCHDOG is not set |
324 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | 454 | # CONFIG_RTC is not set |
325 | CONFIG_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 |
335 | CONFIG_SOUND_GAMEPORT=y | ||
336 | CONFIG_SERIO=y | ||
337 | CONFIG_SERIO_I8042=y | ||
338 | CONFIG_SERIO_SERPORT=y | ||
339 | # CONFIG_SERIO_CT82C710 is not set | ||
340 | 463 | ||
341 | # | 464 | # |
342 | # Input Device Drivers | 465 | # TPM devices |
343 | # | 466 | # |
344 | CONFIG_INPUT_KEYBOARD=y | 467 | # CONFIG_MCF_QSPI is not set |
345 | CONFIG_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 | ||
349 | CONFIG_INPUT_MOUSE=y | ||
350 | CONFIG_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 | # |
371 | CONFIG_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 | # |
426 | CONFIG_EXT2_FS=y | 542 | CONFIG_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 |
434 | CONFIG_ROMFS_FS=y | 556 | CONFIG_ROMFS_FS=y |
557 | CONFIG_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 | # |
454 | CONFIG_PROC_FS=y | 580 | CONFIG_PROC_FS=y |
455 | # CONFIG_DEVFS_FS is not set | 581 | CONFIG_SYSFS=y |
456 | # CONFIG_TMPFS is not set | 582 | # CONFIG_TMPFS is not set |
583 | # CONFIG_HUGETLB_PAGE is not set | ||
457 | CONFIG_RAMFS=y | 584 | CONFIG_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 | |||
494 | CONFIG_MSDOS_PARTITION=y | 620 | CONFIG_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 | ||
632 | CONFIG_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; | |||
45 | unsigned long memory_start; | 46 | unsigned long memory_start; |
46 | unsigned long memory_end; | 47 | unsigned long memory_end; |
47 | 48 | ||
49 | EXPORT_SYMBOL(memory_start); | ||
50 | EXPORT_SYMBOL(memory_end); | ||
51 | |||
48 | char command_line[COMMAND_LINE_SIZE]; | 52 | char 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 | ||
41 | static char *vec_names[] = { | 42 | static 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 | ||
107 | int kstack_depth_to_print = 48; | 108 | int kstack_depth_to_print = 48; |
108 | 109 | ||
109 | void show_stack(struct task_struct *task, unsigned long *esp) | 110 | void 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 | ||
313 | EXPORT_SYMBOL(dump_stack); | ||
314 | |||
309 | #ifdef CONFIG_M68KFPU_EMU | 315 | #ifdef CONFIG_M68KFPU_EMU |
310 | asmlinkage void fpemu_signal(int signal, int code, void *addr) | 316 | asmlinkage 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 | |||
30 | void coldfire_pit_tick(void); | ||
31 | void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); | ||
32 | unsigned long coldfire_pit_offset(void); | ||
33 | void coldfire_trap_init(void); | ||
34 | void coldfire_reset(void); | ||
35 | |||
36 | /***************************************************************************/ | ||
37 | |||
38 | /* | ||
39 | * DMA channel base address table. | ||
40 | */ | ||
41 | unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { | ||
42 | MCF_MBAR + MCFDMA_BASE0, | ||
43 | }; | ||
44 | |||
45 | unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; | ||
46 | |||
47 | /***************************************************************************/ | ||
48 | |||
49 | void 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 | |||
57 | void mcf_autovector(unsigned int vec) | ||
58 | { | ||
59 | /* Everything is auto-vectored on the 5272 */ | ||
60 | } | ||
61 | |||
62 | /***************************************************************************/ | ||
63 | |||
64 | void 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 | |||
21 | endif | 21 | endif |
22 | 22 | ||
23 | LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic | 23 | LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic |
24 | CPPFLAGS += -Iarch/$(ARCH) | 24 | CPPFLAGS += -Iarch/$(ARCH) -Iinclude3 |
25 | AFLAGS += -Iarch/$(ARCH) | 25 | AFLAGS += -Iarch/$(ARCH) |
26 | CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ | 26 | CFLAGS += -Iarch/$(ARCH) -msoft-float -pipe \ |
27 | -ffixed-r2 -mmultiple | 27 | -ffixed-r2 -mmultiple |
28 | CPP = $(CC) -E $(CFLAGS) | 28 | CPP = $(CC) -E $(CFLAGS) |
29 | # Temporary hack until we have migrated to asm-powerpc | ||
30 | LINUXINCLUDE += -Iinclude3 | ||
29 | 31 | ||
30 | CHECKFLAGS += -D__powerpc__ | 32 | CHECKFLAGS += -D__powerpc__ |
31 | 33 | ||
@@ -101,6 +103,7 @@ endef | |||
101 | 103 | ||
102 | archclean: | 104 | archclean: |
103 | $(Q)$(MAKE) $(clean)=arch/ppc/boot | 105 | $(Q)$(MAKE) $(clean)=arch/ppc/boot |
106 | $(Q)rm -rf include3 | ||
104 | 107 | ||
105 | prepare: include/asm-$(ARCH)/offsets.h checkbin | 108 | prepare: include/asm-$(ARCH)/offsets.h checkbin |
106 | 109 | ||
@@ -110,6 +113,12 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ | |||
110 | include/asm-$(ARCH)/offsets.h: arch/$(ARCH)/kernel/asm-offsets.s | 113 | include/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 | ||
117 | include/asm: include3/asm | ||
118 | include3/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. |
115 | TOUT := .tmp_gas_check | 124 | TOUT := .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 | |||
13 | void 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 | |||
21 | void put4k(FILE *file, char *buf ) | ||
22 | { | ||
23 | fwrite(buf, 1, 4096, file); | ||
24 | } | ||
25 | |||
26 | void death(const char *msg, FILE *fdesc, const char *fname) | ||
27 | { | ||
28 | printf(msg); | ||
29 | fclose(fdesc); | ||
30 | unlink(fname); | ||
31 | exit(1); | ||
32 | } | ||
33 | |||
34 | int 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 | ||
159 | BEGIN_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 | ||
177 | END_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 */ | ||
255 | BEGIN_FTR_SECTION | ||
256 | mfspr r3,SPRN_MSSCR0 | ||
257 | ori r3,r3,3 | ||
258 | sync | ||
259 | mtspr SPRN_MSSCR0,r3 | ||
260 | sync | ||
261 | isync | ||
262 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
234 | 4: | 263 | 4: |
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)]; | |||
57 | extern void m8xx_ide_init(void); | 57 | extern void m8xx_ide_init(void); |
58 | 58 | ||
59 | extern unsigned long find_available_memory(void); | 59 | extern unsigned long find_available_memory(void); |
60 | extern void m8xx_cpm_reset(); | 60 | extern void m8xx_cpm_reset(void); |
61 | extern void m8xx_wdt_handler_install(bd_t *bp); | 61 | extern void m8xx_wdt_handler_install(bd_t *bp); |
62 | extern void rpxfb_alloc_pages(void); | 62 | extern void rpxfb_alloc_pages(void); |
63 | extern void cpm_interrupt_init(void); | 63 | extern 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 | ||
305 | config MSCHUNKS | ||
306 | bool | ||
307 | depends on PPC_ISERIES | ||
308 | default y | ||
309 | |||
310 | |||
311 | config PPC_RTAS | 305 | config 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 | ||
347 | source "fs/Kconfig.binfmt" | ||
348 | |||
349 | config 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 | |||
358 | config 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 | |||
366 | config CMDLINE_BOOL | ||
367 | bool "Default bootloader kernel arguments" | ||
368 | depends on !PPC_ISERIES | ||
369 | |||
370 | config 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 | |||
353 | endmenu | 380 | endmenu |
354 | 381 | ||
355 | config ISA_DMA_API | 382 | config ISA_DMA_API |
356 | bool | 383 | bool |
357 | default y | 384 | default y |
358 | 385 | ||
359 | menu "General setup" | 386 | menu "Bus Options" |
360 | 387 | ||
361 | config ISA | 388 | config ISA |
362 | bool | 389 | bool |
@@ -389,45 +416,12 @@ config PCI_DOMAINS | |||
389 | bool | 416 | bool |
390 | default PCI | 417 | default PCI |
391 | 418 | ||
392 | source "fs/Kconfig.binfmt" | ||
393 | |||
394 | source "drivers/pci/Kconfig" | 419 | source "drivers/pci/Kconfig" |
395 | 420 | ||
396 | config 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 | |||
405 | source "drivers/pcmcia/Kconfig" | 421 | source "drivers/pcmcia/Kconfig" |
406 | 422 | ||
407 | source "drivers/pci/hotplug/Kconfig" | 423 | source "drivers/pci/hotplug/Kconfig" |
408 | 424 | ||
409 | config 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 | |||
417 | config CMDLINE_BOOL | ||
418 | bool "Default bootloader kernel arguments" | ||
419 | depends on !PPC_ISERIES | ||
420 | |||
421 | config 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 | |||
431 | endmenu | 425 | endmenu |
432 | 426 | ||
433 | source "net/Kconfig" | 427 | source "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 | |||
55 | LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) | 55 | LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) |
56 | CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \ | 56 | CFLAGS += -msoft-float -pipe -mminimal-toc -mtraceback=none \ |
57 | -mcall-aixdesc | 57 | -mcall-aixdesc |
58 | # Temporary hack until we have migrated to asm-powerpc | ||
59 | CPPFLAGS += -Iinclude3 | ||
58 | 60 | ||
59 | GCC_VERSION := $(call cc-version) | 61 | GCC_VERSION := $(call cc-version) |
60 | GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;) | 62 | GCC_BROKEN_VEC := $(shell if [ $(GCC_VERSION) -lt 0400 ] ; then echo "y"; fi ;) |
@@ -112,6 +114,7 @@ all: $(KBUILD_IMAGE) | |||
112 | 114 | ||
113 | archclean: | 115 | archclean: |
114 | $(Q)$(MAKE) $(clean)=$(boot) | 116 | $(Q)$(MAKE) $(clean)=$(boot) |
117 | $(Q)rm -rf include3 | ||
115 | 118 | ||
116 | prepare: include/asm-ppc64/offsets.h | 119 | prepare: include/asm-ppc64/offsets.h |
117 | 120 | ||
@@ -121,6 +124,12 @@ arch/ppc64/kernel/asm-offsets.s: include/asm include/linux/version.h \ | |||
121 | include/asm-ppc64/offsets.h: arch/ppc64/kernel/asm-offsets.s | 124 | include/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 | ||
128 | include/asm: include3/asm | ||
129 | include3/asm: | ||
130 | $(Q)if [ ! -d include3 ]; then mkdir -p include3; fi; | ||
131 | $(Q)ln -fsn $(srctree)/include/asm-powerpc include3/asm | ||
132 | |||
124 | define archhelp | 133 | define 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 | ||
24 | HOSTCC := gcc | 24 | HOSTCC := gcc |
25 | BOOTCFLAGS := $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin | 25 | BOOTCFLAGS := $(HOSTCFLAGS) -fno-builtin -nostdinc -isystem $(shell $(CROSS32CC) -print-file-name=include) |
26 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional | 26 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc |
27 | BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds | 27 | BOOTLFLAGS := -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds |
28 | OBJCOPYFLAGS := contents,alloc,load,readonly,data | 28 | OBJCOPYFLAGS := 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. */ | ||
5 | typedef unsigned int Elf32_Addr; | ||
6 | typedef unsigned short Elf32_Half; | ||
7 | typedef unsigned int Elf32_Off; | ||
8 | typedef signed int Elf32_Sword; | ||
9 | typedef unsigned int Elf32_Word; | ||
10 | |||
11 | /* 64-bit ELF base types. */ | ||
12 | typedef unsigned long long Elf64_Addr; | ||
13 | typedef unsigned short Elf64_Half; | ||
14 | typedef signed short Elf64_SHalf; | ||
15 | typedef unsigned long long Elf64_Off; | ||
16 | typedef signed int Elf64_Sword; | ||
17 | typedef unsigned int Elf64_Word; | ||
18 | typedef unsigned long long Elf64_Xword; | ||
19 | typedef 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 | |||
54 | typedef 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 | |||
71 | typedef 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 | |||
94 | typedef 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 | |||
105 | typedef 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> | 20 | static void gunzip(void *, int, unsigned char *, int *); |
15 | #include <asm/processor.h> | 21 | extern void flush_cache(void *, unsigned long); |
16 | #include <asm/page.h> | 22 | |
17 | |||
18 | extern void *finddevice(const char *); | ||
19 | extern int getprop(void *, const char *, void *, int); | ||
20 | extern void printf(const char *fmt, ...); | ||
21 | extern int sprintf(char *buf, const char *fmt, ...); | ||
22 | void gunzip(void *, int, unsigned char *, int *); | ||
23 | void *claim(unsigned int, unsigned int, unsigned int); | ||
24 | void flush_cache(void *, unsigned long); | ||
25 | void pause(void); | ||
26 | extern void exit(void); | ||
27 | |||
28 | unsigned long strlen(const char *s); | ||
29 | void *memmove(void *dest, const void *src, unsigned long n); | ||
30 | void *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 | ||
36 | char *avail_ram; | 28 | static char *avail_ram; |
37 | char *begin_avail, *end_avail; | 29 | static char *begin_avail, *end_avail; |
38 | char *avail_high; | 30 | static char *avail_high; |
39 | unsigned int heap_use; | 31 | static unsigned int heap_use; |
40 | unsigned int heap_max; | 32 | static unsigned int heap_max; |
41 | 33 | ||
42 | extern char _start[]; | 34 | extern char _start[]; |
43 | extern char _vmlinux_start[]; | 35 | extern 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 | }; |
55 | struct addr_range vmlinux = {0, 0, 0}; | 47 | static struct addr_range vmlinux = {0, 0, 0}; |
56 | struct addr_range vmlinuz = {0, 0, 0}; | 48 | static struct addr_range vmlinuz = {0, 0, 0}; |
57 | struct addr_range initrd = {0, 0, 0}; | 49 | static struct addr_range initrd = {0, 0, 0}; |
58 | 50 | ||
59 | static char scratch[128<<10]; /* 128kB of scratch space for gunzip */ | 51 | static 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 | ||
67 | int (*prom)(void *); | ||
68 | |||
69 | void *chosen_handle; | ||
70 | void *stdin; | ||
71 | void *stdout; | ||
72 | void *stderr; | ||
73 | |||
74 | #undef DEBUG | 59 | #undef DEBUG |
75 | 60 | ||
76 | static unsigned long claim_base = PROG_START; | 61 | static 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 | ||
280 | void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) | 265 | static 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 | |||
4 | typedef __signed__ char __s8; | ||
5 | typedef unsigned char __u8; | ||
6 | |||
7 | typedef __signed__ short __s16; | ||
8 | typedef unsigned short __u16; | ||
9 | |||
10 | typedef __signed__ int __s32; | ||
11 | typedef unsigned int __u32; | ||
12 | |||
13 | typedef __signed__ long long __s64; | ||
14 | typedef unsigned long long __u64; | ||
15 | |||
16 | typedef signed char s8; | ||
17 | typedef unsigned char u8; | ||
18 | |||
19 | typedef signed short s16; | ||
20 | typedef unsigned short u16; | ||
21 | |||
22 | typedef signed int s32; | ||
23 | typedef unsigned int u32; | ||
24 | |||
25 | typedef signed long long s64; | ||
26 | typedef unsigned long long u64; | ||
27 | |||
28 | typedef struct { | ||
29 | __u32 u[4]; | ||
30 | } __attribute((aligned(16))) __vector128; | ||
31 | |||
32 | #define BITS_PER_LONG 32 | ||
33 | |||
34 | typedef __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" | |
14 | extern __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 | ||
31 | int (*prom)(void *); | 15 | int (*prom)(void *); |
32 | 16 | ||
33 | void *chosen_handle; | 17 | void *chosen_handle; |
18 | |||
34 | void *stdin; | 19 | void *stdin; |
35 | void *stdout; | 20 | void *stdout; |
36 | void *stderr; | 21 | void *stderr; |
37 | 22 | ||
38 | void exit(void); | ||
39 | void *finddevice(const char *name); | ||
40 | int getprop(void *phandle, const char *name, void *buf, int buflen); | ||
41 | void chrpboot(int a1, int a2, void *prom); /* in main.c */ | ||
42 | |||
43 | int printf(char *fmt, ...); | ||
44 | |||
45 | /* there is no convenient header to get this from... -- paulus */ | ||
46 | extern unsigned long strlen(const char *); | ||
47 | 23 | ||
48 | int | 24 | int |
49 | write(void *handle, void *ptr, int nb) | 25 | write(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 | ||
213 | int | ||
214 | readchar(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 | |||
229 | static char line[256]; | ||
230 | static char *lineptr; | ||
231 | static int lineleft; | ||
232 | |||
233 | int | ||
234 | getchar(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 */ | ||
288 | unsigned 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 */ | ||
305 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ | ||
306 | 0,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 | |||
314 | size_t strnlen(const char * s, size_t count) | 189 | size_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 | ||
323 | unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) | 198 | extern 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 | |||
348 | long 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 | ||
355 | static int skip_atoi(const char **s) | 216 | static 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... */ | ||
440 | int sprintf(char * buf, const char *fmt, ...); | ||
441 | |||
442 | int vsprintf(char *buf, const char *fmt, va_list args) | 300 | int 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, ...) | |||
628 | static char sprint_buf[1024]; | 486 | static char sprint_buf[1024]; |
629 | 487 | ||
630 | int | 488 | int |
631 | printf(char *fmt, ...) | 489 | printf(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 | |||
4 | extern int (*prom) (void *); | ||
5 | extern void *chosen_handle; | ||
6 | |||
7 | extern void *stdin; | ||
8 | extern void *stdout; | ||
9 | extern void *stderr; | ||
10 | |||
11 | extern int write(void *handle, void *ptr, int nb); | ||
12 | extern int read(void *handle, void *ptr, int nb); | ||
13 | extern void exit(void); | ||
14 | extern void pause(void); | ||
15 | extern void *finddevice(const char *); | ||
16 | extern void *claim(unsigned long virt, unsigned long size, unsigned long align); | ||
17 | extern 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 | |||
4 | extern int printf(const char *fmt, ...); | ||
5 | |||
6 | extern int sprintf(char *buf, const char *fmt, ...); | ||
7 | |||
8 | extern int vsprintf(char *buf, const char *fmt, va_list args); | ||
9 | |||
10 | extern int putc(int c, void *f); | ||
11 | extern int putchar(int c); | ||
12 | extern int getchar(void); | ||
13 | |||
14 | extern 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 | |||
4 | extern char *strcpy(char *dest, const char *src); | ||
5 | extern char *strncpy(char *dest, const char *src, size_t n); | ||
6 | extern char *strcat(char *dest, const char *src); | ||
7 | extern int strcmp(const char *s1, const char *s2); | ||
8 | extern size_t strlen(const char *s); | ||
9 | extern size_t strnlen(const char *s, size_t count); | ||
10 | |||
11 | extern void *memset(void *s, int c, size_t n); | ||
12 | extern void *memmove(void *dest, const void *src, unsigned long n); | ||
13 | extern void *memcpy(void *dest, const void *src, unsigned long n); | ||
14 | extern 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 |
106 | CONFIG_HZ_100=y | 106 | # CONFIG_HZ_100 is not set |
107 | # CONFIG_HZ_250 is not set | 107 | CONFIG_HZ_250=y |
108 | # CONFIG_HZ_1000 is not set | 108 | # CONFIG_HZ_1000 is not set |
109 | CONFIG_HZ=100 | 109 | CONFIG_HZ=250 |
110 | CONFIG_GENERIC_HARDIRQS=y | 110 | CONFIG_GENERIC_HARDIRQS=y |
111 | CONFIG_SECCOMP=y | 111 | CONFIG_SECCOMP=y |
112 | CONFIG_ISA_DMA_API=y | 112 | CONFIG_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 |
97 | CONFIG_HZ_100=y | 97 | # CONFIG_HZ_100 is not set |
98 | # CONFIG_HZ_250 is not set | 98 | CONFIG_HZ_250=y |
99 | # CONFIG_HZ_1000 is not set | 99 | # CONFIG_HZ_1000 is not set |
100 | CONFIG_HZ=100 | 100 | CONFIG_HZ=250 |
101 | CONFIG_GENERIC_HARDIRQS=y | 101 | CONFIG_GENERIC_HARDIRQS=y |
102 | CONFIG_MSCHUNKS=y | ||
103 | CONFIG_LPARCFG=y | 102 | CONFIG_LPARCFG=y |
104 | CONFIG_SECCOMP=y | 103 | CONFIG_SECCOMP=y |
105 | CONFIG_ISA_DMA_API=y | 104 | CONFIG_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 |
106 | CONFIG_HZ_100=y | 106 | # CONFIG_HZ_100 is not set |
107 | # CONFIG_HZ_250 is not set | 107 | CONFIG_HZ_250=y |
108 | # CONFIG_HZ_1000 is not set | 108 | # CONFIG_HZ_1000 is not set |
109 | CONFIG_HZ=100 | 109 | CONFIG_HZ=250 |
110 | CONFIG_GENERIC_HARDIRQS=y | 110 | CONFIG_GENERIC_HARDIRQS=y |
111 | CONFIG_SECCOMP=y | 111 | CONFIG_SECCOMP=y |
112 | CONFIG_ISA_DMA_API=y | 112 | CONFIG_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 |
115 | CONFIG_HZ_100=y | 115 | # CONFIG_HZ_100 is not set |
116 | # CONFIG_HZ_250 is not set | 116 | CONFIG_HZ_250=y |
117 | # CONFIG_HZ_1000 is not set | 117 | # CONFIG_HZ_1000 is not set |
118 | CONFIG_HZ=100 | 118 | CONFIG_HZ=250 |
119 | CONFIG_EEH=y | 119 | CONFIG_EEH=y |
120 | CONFIG_GENERIC_HARDIRQS=y | 120 | CONFIG_GENERIC_HARDIRQS=y |
121 | CONFIG_PPC_RTAS=y | 121 | CONFIG_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 |
117 | CONFIG_HZ_100=y | 117 | # CONFIG_HZ_100 is not set |
118 | # CONFIG_HZ_250 is not set | 118 | CONFIG_HZ_250=y |
119 | # CONFIG_HZ_1000 is not set | 119 | # CONFIG_HZ_1000 is not set |
120 | CONFIG_HZ=100 | 120 | CONFIG_HZ=250 |
121 | CONFIG_EEH=y | 121 | CONFIG_EEH=y |
122 | CONFIG_GENERIC_HARDIRQS=y | 122 | CONFIG_GENERIC_HARDIRQS=y |
123 | CONFIG_PPC_RTAS=y | 123 | CONFIG_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 | */ | ||
59 | struct naca_struct naca = { | ||
60 | .xItVpdAreas = &itVpdAreas, | ||
61 | .xRamDisk = 0, | ||
62 | .xRamDiskSize = 0, | ||
63 | }; | ||
64 | |||
54 | extern void system_reset_iSeries(void); | 65 | extern void system_reset_iSeries(void); |
55 | extern void machine_check_iSeries(void); | 66 | extern void machine_check_iSeries(void); |
56 | extern void data_access_iSeries(void); | 67 | extern void data_access_iSeries(void); |
@@ -214,29 +225,3 @@ struct ItVpdAreas itVpdAreas = { | |||
214 | 0,0 | 225 | 0,0 |
215 | } | 226 | } |
216 | }; | 227 | }; |
217 | |||
218 | struct msChunks msChunks; | ||
219 | EXPORT_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 | */ | ||
226 | unsigned long | ||
227 | msChunks_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 |
15 | obj-y += vdso32/ vdso64/ | 15 | obj-y += vdso32/ vdso64/ |
16 | 16 | ||
17 | obj-$(CONFIG_PPC_OF) += of_device.o | 17 | obj-$(CONFIG_PPC_OF) += of_device.o |
@@ -50,7 +50,10 @@ obj-$(CONFIG_LPARCFG) += lparcfg.o | |||
50 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 50 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
51 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 51 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
52 | obj-$(CONFIG_HVCS) += hvcserver.o | 52 | obj-$(CONFIG_HVCS) += hvcserver.o |
53 | obj-$(CONFIG_IBMVIO) += vio.o | 53 | |
54 | vio-obj-$(CONFIG_PPC_PSERIES) += pSeries_vio.o | ||
55 | vio-obj-$(CONFIG_PPC_ISERIES) += iSeries_vio.o | ||
56 | obj-$(CONFIG_IBMVIO) += vio.o $(vio-obj-y) | ||
54 | obj-$(CONFIG_XICS) += xics.o | 57 | obj-$(CONFIG_XICS) += xics.o |
55 | obj-$(CONFIG_MPIC) += mpic.o | 58 | obj-$(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 | |||
261 | firmware_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 | |||
22 | unsigned long ppc64_firmware_features; | ||
23 | |||
24 | #ifdef CONFIG_PPC_PSERIES | ||
25 | firmware_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: | |||
120 | embedded_sysmap_end: | 113 | embedded_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. */ |
159 | 100: ld r4,__secondary_hold_spinloop@l(0) | 152 | 100: 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. | 514 | system_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 | ||
525 | naca: | ||
526 | .llong itVpdAreas | ||
527 | .llong 0 /* xRamDisk */ | ||
528 | .llong 0 /* xRamDiskSize */ | ||
529 | 519 | ||
530 | . = 0x6100 | 520 | .globl machine_check_fwnmi |
521 | machine_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 | ||
632 | iSeries_secondary_smp_loop: | 626 | iSeries_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 | ||
681 | fwnmi_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 | ||
693 | system_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 | ||
699 | machine_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 | */ |
758 | bad_stack: | 709 | bad_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) | ||
896 | 1: | ||
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 |
911 | altivec_unavailable_common: | 918 | altivec_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) | ||
972 | 1: | ||
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 | ||
984 | 1: | ||
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 | ||
1262 | initial_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 | ||
1271 | fwnmi_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 | ||
1202 | 2: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | 1319 | 2: 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 |
1205 | 3: HMT_LOW | 1322 | 3: 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 |
1431 | copy_to_here: | 1546 | copy_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) | ||
1469 | 1: | ||
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) | ||
1525 | 1: | ||
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) | ||
1576 | 1: | ||
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 | ||
1588 | 1: | ||
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) | ||
1645 | 1: | ||
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 | |
2104 | sdata: | ||
2105 | .globl empty_zero_page | 1994 | .globl empty_zero_page |
2106 | empty_zero_page: | 1995 | empty_zero_page: |
2107 | .space 4096 | 1996 | .space PAGE_SIZE |
2108 | 1997 | ||
2109 | .globl swapper_pg_dir | 1998 | .globl swapper_pg_dir |
2110 | swapper_pg_dir: | 1999 | swapper_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 | ||
418 | struct 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 | }; | ||
424 | EXPORT_SYMBOL(mschunks_map); | ||
425 | |||
426 | void 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 | |||
24 | struct device *iSeries_vio_dev = &vio_bus_device.dev; | ||
25 | EXPORT_SYMBOL(iSeries_vio_dev); | ||
26 | |||
27 | static struct iommu_table veth_iommu_table; | ||
28 | static struct iommu_table vio_iommu_table; | ||
29 | |||
30 | static 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 | */ | ||
74 | static 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 | |||
98 | void __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 | */ | ||
128 | static 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 | |||
134 | static 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 | */ | ||
141 | static 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) | |||
108 | void __init | 102 | void __init |
109 | lmb_init(void) | 103 | lmb_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. */ |
127 | void __init | 119 | void __init |
128 | lmb_analyze(void) | 120 | lmb_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) | |||
213 | long __init | 184 | long __init |
214 | lmb_add(unsigned long base, unsigned long size) | 185 | lmb_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) | |||
227 | long __init | 197 | long __init |
228 | lmb_reserve(unsigned long base, unsigned long size) | 198 | lmb_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. */ | ||
295 | unsigned long __init | 262 | unsigned long __init |
296 | lmb_phys_mem_size(void) | 263 | lmb_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 | ||
313 | unsigned long __init | 268 | unsigned long __init |
314 | lmb_end_of_DRAM(void) | 269 | lmb_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 | |||
329 | unsigned long __init | ||
330 | lmb_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) | ||
719 | 1: | ||
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) | ||
768 | 1: | ||
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) | |||
236 | struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) | 236 | struct 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); | |||
52 | EXPORT_SYMBOL(plpar_hcall_norets); | 52 | EXPORT_SYMBOL(plpar_hcall_norets); |
53 | EXPORT_SYMBOL(plpar_hcall_8arg_2ret); | 53 | EXPORT_SYMBOL(plpar_hcall_8arg_2ret); |
54 | 54 | ||
55 | extern void fw_feature_init(void); | ||
56 | extern void pSeries_find_serial_port(void); | 55 | extern 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 | ||
191 | static 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 | |||
190 | static void __init pSeries_setup_arch(void) | 206 | static 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 | ||
252 | static int __init pSeries_init_panel(void) | 271 | static int __init pSeries_init_panel(void) |
@@ -260,11 +279,11 @@ static int __init pSeries_init_panel(void) | |||
260 | arch_initcall(pSeries_init_panel); | 279 | arch_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 | */ |
267 | void __init fw_feature_init(void) | 286 | static 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 | |||
26 | extern struct subsystem devices_subsys; /* needed for vio_find_name() */ | ||
27 | |||
28 | static 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 | */ | ||
52 | static 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 | |||
59 | static void vio_release_device_pseries(struct device *dev) | ||
60 | { | ||
61 | /* XXX free TCE table */ | ||
62 | of_node_put(dev->platform_data); | ||
63 | } | ||
64 | |||
65 | static 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 | } | ||
72 | DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); | ||
73 | |||
74 | static void vio_unregister_device_pseries(struct vio_dev *viodev) | ||
75 | { | ||
76 | device_remove_file(&viodev->dev, &dev_attr_devspec); | ||
77 | } | ||
78 | |||
79 | static 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 | */ | ||
88 | static 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 | */ | ||
108 | static 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 | */ | ||
147 | struct 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 | } | ||
204 | EXPORT_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 | */ | ||
215 | const 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 | } | ||
219 | EXPORT_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 | */ | ||
227 | static 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 | */ | ||
242 | struct 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 | } | ||
255 | EXPORT_SYMBOL(vio_find_node); | ||
256 | |||
257 | int 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 | } | ||
264 | EXPORT_SYMBOL(vio_enable_interrupts); | ||
265 | |||
266 | int 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 | } | ||
273 | EXPORT_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 | } |
67 | EXPORT_SYMBOL_GPL(release_pmc_hardware); | 67 | EXPORT_SYMBOL_GPL(release_pmc_hardware); |
68 | |||
69 | void 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 = ¤t->thread; | 204 | old_thread = ¤t->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 | ||
626 | static inline char *find_flat_dt_string(u32 offset) | 626 | static 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 | */ |
637 | static int __init scan_flat_dt(int (*it)(unsigned long node, | 637 | static 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 | ||
715 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 735 | static 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, | |||
727 | static unsigned long __init unflatten_dt_node(unsigned long mem, | 747 | static 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 | ||
882 | static int __init early_init_dt_scan_cpus(unsigned long node, | 995 | static 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 | ||
949 | static int __init early_init_dt_scan_chosen(unsigned long node, | 1062 | static 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 | ||
1005 | static int __init early_init_dt_scan_root(unsigned long node, | 1120 | static 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 | ||
1044 | static int __init early_init_dt_scan_memory(unsigned long node, | 1161 | static 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 | ||
1537 | static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, | 1540 | static 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, | |||
1580 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | 1589 | static 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 | ||
61 | static 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 | |||
61 | static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val) | 76 | static 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 | ||
110 | void ppc64_enable_pmcs(void) | 113 | void 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 */ | ||
165 | void ppc64_enable_pmcs(void) | ||
166 | { | ||
167 | /* XXX Implement for iseries */ | ||
168 | } | ||
169 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
170 | |||
171 | EXPORT_SYMBOL(ppc64_enable_pmcs); | 124 | EXPORT_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 | ||
71 | u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES; | 72 | u64 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 | |||
35 | extern struct subsystem devices_subsys; /* needed for vio_find_name() */ | ||
36 | 24 | ||
37 | static const struct vio_device_id *vio_match_device( | 25 | static 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 | 28 | struct vio_dev vio_bus_device = { /* fake "parent" device */ |
41 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *); | ||
42 | static int vio_num_address_cells; | ||
43 | #endif | ||
44 | #ifdef CONFIG_PPC_ISERIES | ||
45 | static struct iommu_table veth_iommu_table; | ||
46 | static struct iommu_table vio_iommu_table; | ||
47 | #endif | ||
48 | static 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 | 35 | static struct vio_bus_ops vio_bus_ops; |
59 | static struct vio_dev *__init vio_register_device_iseries(char *type, | ||
60 | uint32_t unit_num); | ||
61 | |||
62 | struct device *iSeries_vio_dev = &vio_bus_device.dev; | ||
63 | EXPORT_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 | */ | ||
72 | static int vio_bus_probe(struct device *dev) | 42 | static 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) | |||
135 | EXPORT_SYMBOL(vio_unregister_driver); | 99 | EXPORT_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 | */ |
146 | static const struct vio_device_id * vio_match_device(const struct vio_device_id *ids, | 111 | static 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 | ||
161 | void __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 | ||
203 | static 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 | ||
227 | static 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 | */ |
257 | static int __init vio_bus_init(void) | 125 | int __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 */ |
288 | static void __devinit vio_dev_release(struct device *dev) | 152 | static 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 | 159 | static ssize_t viodev_show_name(struct device *dev, |
300 | static 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 | } | ||
306 | DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); | ||
307 | #endif | ||
308 | |||
309 | static 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 | } |
313 | DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); | 164 | DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); |
314 | 165 | ||
315 | static struct vio_dev * __devinit vio_register_device_common( | 166 | struct 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 | */ | ||
351 | struct 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 | } | ||
408 | EXPORT_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 | */ | ||
416 | static 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 | |||
436 | void __devinit vio_unregister_device(struct vio_dev *viodev) | 184 | void __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 | } |
445 | EXPORT_SYMBOL(vio_unregister_device); | 191 | EXPORT_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 | */ | ||
457 | const 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 | } | ||
461 | EXPORT_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 | */ | ||
469 | static 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 | */ | ||
484 | struct 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 | } | ||
497 | EXPORT_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 | */ | ||
506 | static 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 | |||
536 | int 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 | } | ||
544 | EXPORT_SYMBOL(vio_enable_interrupts); | ||
545 | |||
546 | int 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 | } | ||
554 | EXPORT_SYMBOL(vio_disable_interrupts); | ||
555 | #endif | ||
556 | |||
557 | static dma_addr_t vio_map_single(struct device *dev, void *vaddr, | 193 | static 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 | ||
632 | struct bus_type vio_bus_type = { | 258 | struct 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 | */ |
131 | BEGIN_FTR_SECTION | 131 | BEGIN_FTR_SECTION |
132 | BEGIN_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 |
136 | END_FTR_SECTION_IFSET(CPU_FTR_NOEXECUTE) | 135 | END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) |
137 | END_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 | 34 | pte_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 | |||
40 | static inline int hugepgd_index(unsigned long addr) | ||
41 | { | ||
42 | return (addr & ~REGION_MASK) >> HUGEPGDIR_SHIFT; | ||
43 | } | ||
44 | |||
45 | static 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 | ||
58 | static inline pte_t *hugepte_offset(pud_t *dir, unsigned long addr) | 60 | pte_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 | |||
69 | static 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 | ||
93 | static 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 | ||
124 | pte_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)); | 89 | void 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 | ||
137 | pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) | 105 | pte_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 | ||
165 | static void flush_segments(void *parm) | 135 | static 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 | ||
181 | static int prepare_low_seg_for_htlb(struct mm_struct *mm, unsigned long seg) | 153 | static 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 | |||
173 | static 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 | ||
197 | static int open_low_hpage_segs(struct mm_struct *mm, u16 newsegs) | 189 | static 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 | |||
205 | static 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 | |||
234 | static 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 | ||
223 | int prepare_hugepage_range(unsigned long addr, unsigned long len) | 264 | int 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 | ||
243 | struct page * | 288 | struct 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 | ||
484 | static unsigned long htlb_get_high_area(unsigned long len) | 530 | static 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 | |||
544 | void 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 | ||
580 | int hash_huge_page(struct mm_struct *mm, unsigned long access, | 616 | int 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 | |||
69 | int mem_init_done; | 76 | int mem_init_done; |
70 | unsigned long ioremap_bot = IMALLOC_BASE; | 77 | unsigned long ioremap_bot = IMALLOC_BASE; |
71 | static unsigned long phbs_io_bot = PHBS_IO_BASE; | 78 | static 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 | |||
426 | again: | 426 | again: |
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 | ||
836 | kmem_cache_t *zero_cache; | 828 | static void zero_ctor(void *addr, kmem_cache_t *cache, unsigned long flags) |
837 | |||
838 | static 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 | ||
833 | static const int pgtable_cache_size[2] = { | ||
834 | PTE_TABLE_SIZE, PMD_TABLE_SIZE | ||
835 | }; | ||
836 | static const char *pgtable_cache_name[ARRAY_SIZE(pgtable_cache_size)] = { | ||
837 | "pgd_pte_cache", "pud_pmd_cache", | ||
838 | }; | ||
839 | |||
840 | kmem_cache_t *pgtable_cache[ARRAY_SIZE(pgtable_cache_size)]; | ||
841 | |||
843 | void pgtable_cache_init(void) | 842 | void 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 | ||
855 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | 867 | pgprot_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 | ||
91 | 0: /* user address: proto-VSID = context<<15 | ESID */ | 91 | 0: /* 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 |
98 | BEGIN_FTR_SECTION | 96 | BEGIN_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 */ | 103 | END_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 | 109 | BEGIN_FTR_SECTION | |
112 | 5: /* 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) | ||
114 | END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) | 111 | END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) |
115 | #endif /* CONFIG_HUGETLB_PAGE */ | 112 | #endif /* CONFIG_HUGETLB_PAGE */ |
116 | 113 | ||
117 | 6: 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 | ||
120 | 9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ | 117 | 9: /* 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); | |||
41 | DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); | 41 | DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); |
42 | unsigned long pte_freelist_forced_free; | 42 | unsigned long pte_freelist_forced_free; |
43 | 43 | ||
44 | void __pte_free_tlb(struct mmu_gather *tlb, struct page *ptepage) | 44 | struct pte_freelist_batch |
45 | { | ||
46 | struct rcu_head rcu; | ||
47 | unsigned int index; | ||
48 | pgtable_free_t tables[0]; | ||
49 | }; | ||
50 | |||
51 | DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); | ||
52 | unsigned 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 | ||
59 | static 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 | */ | ||
68 | static 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 | |||
77 | static 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 | |||
89 | static 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 | |||
95 | void 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 | ||
136 | static 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 | */ | ||
145 | void 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 | |||
154 | static 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 | |||
165 | void 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 | |||
171 | void pte_free_finish(void) | 186 | void 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 | ||
2499 | void xmon_init(void) | 2499 | void 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 | ||
2510 | void dump_segments(void) | 2520 | void 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 | 744 | 1: 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 | |||
754 | 1: 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 | |||
766 | 1: /* 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 | |||
784 | 1: ba,pt %xcc, etrap_irq | ||
785 | rd %pc, %g7 | ||
786 | |||
787 | 2: 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: | 863 | 1: sethi %hi(109f), %g7 |
864 | ba,pt %xcc, etraptl1 | ||
865 | 109: 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: | |||
722 | 109: or %g7, %lo(109b), %g7 | 884 | 109: 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: | |||
743 | 109: or %g7, %lo(109b), %g7 | 904 | 109: 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: | |||
762 | 109: or %g7, %lo(109b), %g7 | 922 | 109: 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 | ||
801 | cee_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 | ||
826 | 1: 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 | ||
840 | 1: 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); | |||
99 | extern void dump_thread(struct pt_regs *, struct user *); | 99 | extern void dump_thread(struct pt_regs *, struct user *); |
100 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); | 100 | extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); |
101 | 101 | ||
102 | #if defined(CONFIG_SMP) && defined(CONFIG_DEBUG_SPINLOCK) | ||
103 | extern void _do_spin_lock (spinlock_t *lock, char *str); | ||
104 | extern void _do_spin_unlock (spinlock_t *lock); | ||
105 | extern int _spin_trylock (spinlock_t *lock); | ||
106 | extern void _do_read_lock(rwlock_t *rw, char *str); | ||
107 | extern void _do_read_unlock(rwlock_t *rw, char *str); | ||
108 | extern void _do_write_lock(rwlock_t *rw, char *str); | ||
109 | extern void _do_write_unlock(rwlock_t *rw); | ||
110 | extern int _do_write_trylock(rwlock_t *rw, char *str); | ||
111 | #endif | ||
112 | |||
113 | extern unsigned long phys_base; | 102 | extern unsigned long phys_base; |
114 | extern unsigned long pfn_base; | 103 | extern unsigned long pfn_base; |
115 | 104 | ||
@@ -152,18 +141,6 @@ EXPORT_SYMBOL(_mcount); | |||
152 | EXPORT_SYMBOL(cpu_online_map); | 141 | EXPORT_SYMBOL(cpu_online_map); |
153 | EXPORT_SYMBOL(phys_cpu_present_map); | 142 | EXPORT_SYMBOL(phys_cpu_present_map); |
154 | 143 | ||
155 | /* Spinlock debugging library, optional. */ | ||
156 | #ifdef CONFIG_DEBUG_SPINLOCK | ||
157 | EXPORT_SYMBOL(_do_spin_lock); | ||
158 | EXPORT_SYMBOL(_do_spin_unlock); | ||
159 | EXPORT_SYMBOL(_spin_trylock); | ||
160 | EXPORT_SYMBOL(_do_read_lock); | ||
161 | EXPORT_SYMBOL(_do_read_unlock); | ||
162 | EXPORT_SYMBOL(_do_write_lock); | ||
163 | EXPORT_SYMBOL(_do_write_unlock); | ||
164 | EXPORT_SYMBOL(_do_write_trylock); | ||
165 | #endif | ||
166 | |||
167 | EXPORT_SYMBOL(smp_call_function); | 144 | EXPORT_SYMBOL(smp_call_function); |
168 | #endif /* CONFIG_SMP */ | 145 | #endif /* CONFIG_SMP */ |
169 | 146 | ||
@@ -429,3 +406,12 @@ EXPORT_SYMBOL(xor_vis_4); | |||
429 | EXPORT_SYMBOL(xor_vis_5); | 406 | EXPORT_SYMBOL(xor_vis_5); |
430 | 407 | ||
431 | EXPORT_SYMBOL(prom_palette); | 408 | EXPORT_SYMBOL(prom_palette); |
409 | |||
410 | /* memory barriers */ | ||
411 | EXPORT_SYMBOL(mb); | ||
412 | EXPORT_SYMBOL(rmb); | ||
413 | EXPORT_SYMBOL(wmb); | ||
414 | EXPORT_SYMBOL(membar_storeload); | ||
415 | EXPORT_SYMBOL(membar_storeload_storestore); | ||
416 | EXPORT_SYMBOL(membar_storeload_loadload); | ||
417 | EXPORT_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 | ||
146 | void instruction_access_exception(struct pt_regs *regs, | 147 | void 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 | ||
172 | void instruction_access_exception_tl1(struct pt_regs *regs, | 172 | void 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 | ||
183 | void data_access_exception(struct pt_regs *regs, | 182 | void 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 | ||
221 | void 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... */ |
225 | extern volatile int pci_poke_in_progress; | 233 | extern 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 | ||
256 | void do_iae(struct pt_regs *regs) | 264 | static 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 | |||
274 | void 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 | ||
306 | static char ecc_syndrome_table[] = { | 273 | static 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 | |||
379 | static char *syndrome_unknown = "<Unknown>"; | 308 | static char *syndrome_unknown = "<Unknown>"; |
380 | 309 | ||
381 | asmlinkage void cee_log(unsigned long ce_status, | 310 | static 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 | |||
341 | static 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 | |||
362 | static 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 | |||
408 | void 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 | ||
424 | int cheetah_pcache_forced_on; | 461 | int 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: | |||
18 | tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) | 18 | tl0_resv000: BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3) |
19 | tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) | 19 | tl0_resv004: BTRAP(0x4) BTRAP(0x5) BTRAP(0x6) BTRAP(0x7) |
20 | tl0_iax: membar #Sync | 20 | tl0_iax: membar #Sync |
21 | TRAP_NOSAVE_7INSNS(__do_instruction_access_exception) | 21 | TRAP_NOSAVE_7INSNS(__spitfire_insn_access_exception) |
22 | tl0_resv009: BTRAP(0x9) | 22 | tl0_resv009: BTRAP(0x9) |
23 | tl0_iae: TRAP(do_iae) | 23 | tl0_iae: membar #Sync |
24 | TRAP_NOSAVE_7INSNS(__spitfire_access_error) | ||
24 | tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) | 25 | tl0_resv00b: BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf) |
25 | tl0_ill: membar #Sync | 26 | tl0_ill: membar #Sync |
26 | TRAP_7INSNS(do_illegal_instruction) | 27 | TRAP_7INSNS(do_illegal_instruction) |
@@ -36,9 +37,10 @@ tl0_cwin: CLEAN_WINDOW | |||
36 | tl0_div0: TRAP(do_div0) | 37 | tl0_div0: TRAP(do_div0) |
37 | tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) | 38 | tl0_resv029: BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e) |
38 | tl0_resv02f: BTRAP(0x2f) | 39 | tl0_resv02f: BTRAP(0x2f) |
39 | tl0_dax: TRAP_NOSAVE(__do_data_access_exception) | 40 | tl0_dax: TRAP_NOSAVE(__spitfire_data_access_exception) |
40 | tl0_resv031: BTRAP(0x31) | 41 | tl0_resv031: BTRAP(0x31) |
41 | tl0_dae: TRAP(do_dae) | 42 | tl0_dae: membar #Sync |
43 | TRAP_NOSAVE_7INSNS(__spitfire_access_error) | ||
42 | tl0_resv033: BTRAP(0x33) | 44 | tl0_resv033: BTRAP(0x33) |
43 | tl0_mna: TRAP_NOSAVE(do_mna) | 45 | tl0_mna: TRAP_NOSAVE(do_mna) |
44 | tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) | 46 | tl0_lddfmna: TRAP_NOSAVE(do_lddfmna) |
@@ -73,7 +75,8 @@ tl0_resv05c: BTRAP(0x5c) BTRAP(0x5d) BTRAP(0x5e) BTRAP(0x5f) | |||
73 | tl0_ivec: TRAP_IVEC | 75 | tl0_ivec: TRAP_IVEC |
74 | tl0_paw: TRAP(do_paw) | 76 | tl0_paw: TRAP(do_paw) |
75 | tl0_vaw: TRAP(do_vaw) | 77 | tl0_vaw: TRAP(do_vaw) |
76 | tl0_cee: TRAP_NOSAVE(cee_trap) | 78 | tl0_cee: membar #Sync |
79 | TRAP_NOSAVE_7INSNS(__spitfire_cee_trap) | ||
77 | tl0_iamiss: | 80 | tl0_iamiss: |
78 | #include "itlb_base.S" | 81 | #include "itlb_base.S" |
79 | tl0_damiss: | 82 | tl0_damiss: |
@@ -175,9 +178,10 @@ tl0_resv1f0: BTRAPS(0x1f0) BTRAPS(0x1f8) | |||
175 | sparc64_ttable_tl1: | 178 | sparc64_ttable_tl1: |
176 | tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) | 179 | tl1_resv000: BOOT_KERNEL BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3) |
177 | tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) | 180 | tl1_resv004: BTRAPTL1(0x4) BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7) |
178 | tl1_iax: TRAP_NOSAVE(__do_instruction_access_exception_tl1) | 181 | tl1_iax: TRAP_NOSAVE(__spitfire_insn_access_exception_tl1) |
179 | tl1_resv009: BTRAPTL1(0x9) | 182 | tl1_resv009: BTRAPTL1(0x9) |
180 | tl1_iae: TRAPTL1(do_iae_tl1) | 183 | tl1_iae: membar #Sync |
184 | TRAP_NOSAVE_7INSNS(__spitfire_access_error) | ||
181 | tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) | 185 | tl1_resv00b: BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf) |
182 | tl1_ill: TRAPTL1(do_ill_tl1) | 186 | tl1_ill: TRAPTL1(do_ill_tl1) |
183 | tl1_privop: BTRAPTL1(0x11) | 187 | tl1_privop: BTRAPTL1(0x11) |
@@ -193,9 +197,10 @@ tl1_cwin: CLEAN_WINDOW | |||
193 | tl1_div0: TRAPTL1(do_div0_tl1) | 197 | tl1_div0: TRAPTL1(do_div0_tl1) |
194 | tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) | 198 | tl1_resv029: BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c) |
195 | tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) | 199 | tl1_resv02d: BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f) |
196 | tl1_dax: TRAP_NOSAVE(__do_data_access_exception_tl1) | 200 | tl1_dax: TRAP_NOSAVE(__spitfire_data_access_exception_tl1) |
197 | tl1_resv031: BTRAPTL1(0x31) | 201 | tl1_resv031: BTRAPTL1(0x31) |
198 | tl1_dae: TRAPTL1(do_dae_tl1) | 202 | tl1_dae: membar #Sync |
203 | TRAP_NOSAVE_7INSNS(__spitfire_access_error) | ||
199 | tl1_resv033: BTRAPTL1(0x33) | 204 | tl1_resv033: BTRAPTL1(0x33) |
200 | tl1_mna: TRAP_NOSAVE(do_mna) | 205 | tl1_mna: TRAP_NOSAVE(do_mna) |
201 | tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) | 206 | tl1_lddfmna: TRAPTL1(do_lddfmna_tl1) |
@@ -219,8 +224,8 @@ tl1_paw: TRAPTL1(do_paw_tl1) | |||
219 | tl1_vaw: TRAPTL1(do_vaw_tl1) | 224 | tl1_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 | ||
350 | extern void do_fpother(struct pt_regs *regs); | 350 | extern void do_fpother(struct pt_regs *regs); |
351 | extern void do_privact(struct pt_regs *regs); | 351 | extern void do_privact(struct pt_regs *regs); |
352 | extern void data_access_exception(struct pt_regs *regs, | 352 | extern 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 | ||
356 | int handle_ldf_stq(u32 insn, struct pt_regs *regs) | 356 | int 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 { |
537 | daex: data_access_exception(regs, sfsr, sfar); | 537 | daex: 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 { |
581 | daex: data_access_exception(regs, sfsr, sfar); | 581 | daex: 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: | |||
391 | 109: or %g7, %lo(109b), %g7 | 391 | 109: 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 | ||
17 | lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o | 17 | lib-$(CONFIG_DEBUG_SPINLOCK) += debuglocks.o |
18 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | 18 | lib-$(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 | |||
17 | static inline void show (char *str, spinlock_t *lock, unsigned long caller) | 15 | static 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 | ||
54 | void _do_spin_lock(spinlock_t *lock, char *str) | 52 | void _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); | ||
62 | again: | 59 | again: |
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 | ||
87 | int _do_spin_trylock(spinlock_t *lock) | 84 | int _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 | ||
121 | void _do_read_lock (rwlock_t *rw, char *str) | 117 | void _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); | ||
129 | wlock_again: | 124 | wlock_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 | ||
160 | void _do_read_unlock (rwlock_t *rw, char *str) | 155 | void _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 | ||
196 | void _do_write_lock (rwlock_t *rw, char *str) | 189 | void _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); | ||
204 | wlock_again: | 196 | wlock_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 | ||
281 | void _do_write_unlock(rwlock_t *rw) | 273 | void _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 | ||
316 | int _do_write_trylock (rwlock_t *rw, char *str) | 306 | int _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 | |||
33 | 99: retl | ||
34 | nop | ||
35 | |||
36 | .globl mb | ||
37 | mb: ba,pt %xcc, 99b | ||
38 | membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad | ||
39 | .size mb, .-mb | ||
40 | |||
41 | .globl rmb | ||
42 | rmb: ba,pt %xcc, 99b | ||
43 | membar #LoadLoad | ||
44 | .size rmb, .-rmb | ||
45 | |||
46 | .globl wmb | ||
47 | wmb: ba,pt %xcc, 99b | ||
48 | membar #StoreStore | ||
49 | .size wmb, .-wmb | ||
50 | |||
51 | .globl membar_storeload | ||
52 | membar_storeload: | ||
53 | ba,pt %xcc, 99b | ||
54 | membar #StoreLoad | ||
55 | .size membar_storeload, .-membar_storeload | ||
56 | |||
57 | .globl membar_storeload_storestore | ||
58 | membar_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 | ||
64 | membar_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 | ||
70 | membar_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"); | |||
737 | extern u32 tl0_solaris[8]; | 737 | extern 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 |
46 | CONFIG_LARGE_ALLOCS=y | 46 | CONFIG_LARGE_ALLOCS=y |
47 | CONFIG_FLATMEM=y | ||
48 | CONFIG_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 | # | ||
118 | CONFIG_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 | ||
126 | CONFIG_INET=y | ||
127 | # CONFIG_IP_MULTICAST is not set | ||
128 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
129 | CONFIG_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 | ||
141 | CONFIG_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 | # |
116 | CONFIG_STANDALONE=y | 164 | CONFIG_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 | # | ||
249 | CONFIG_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 | ||
257 | CONFIG_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 | ||
294 | CONFIG_NETDEVICES=y | 299 | CONFIG_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 |
481 | CONFIG_ROMFS_FS=y | 489 | CONFIG_ROMFS_FS=y |
490 | # CONFIG_MAGIC_ROM_PTR is not set | ||
491 | CONFIG_INOTIFY=y | ||
482 | # CONFIG_QUOTA is not set | 492 | # CONFIG_QUOTA is not set |
483 | CONFIG_DNOTIFY=y | 493 | CONFIG_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 | # |
525 | CONFIG_NFS_FS=y | 535 | CONFIG_NFS_FS=y |
526 | CONFIG_NFS_V3=y | 536 | CONFIG_NFS_V3=y |
537 | # CONFIG_NFS_V3_ACL is not set | ||
527 | # CONFIG_NFSD is not set | 538 | # CONFIG_NFSD is not set |
528 | CONFIG_LOCKD=y | 539 | CONFIG_LOCKD=y |
529 | CONFIG_LOCKD_V4=y | 540 | CONFIG_LOCKD_V4=y |
541 | CONFIG_NFS_COMMON=y | ||
530 | CONFIG_SUNRPC=y | 542 | CONFIG_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 |
43 | CONFIG_LARGE_ALLOCS=y | 43 | CONFIG_LARGE_ALLOCS=y |
44 | CONFIG_FLATMEM=y | ||
45 | CONFIG_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 | |||
56 | CONFIG_LOCALVERSION="" | 58 | CONFIG_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 |
62 | CONFIG_EMBEDDED=y | 63 | CONFIG_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 | # |
109 | CONFIG_STANDALONE=y | 115 | CONFIG_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 |
344 | CONFIG_ROMFS_FS=y | 351 | CONFIG_ROMFS_FS=y |
352 | # CONFIG_MAGIC_ROM_PTR is not set | ||
353 | CONFIG_INOTIFY=y | ||
345 | # CONFIG_QUOTA is not set | 354 | # CONFIG_QUOTA is not set |
346 | CONFIG_DNOTIFY=y | 355 | CONFIG_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 | |||
36 | CONFIG_ZERO_BSS=y | 36 | CONFIG_ZERO_BSS=y |
37 | # CONFIG_RESET_GUARD is not set | 37 | # CONFIG_RESET_GUARD is not set |
38 | CONFIG_LARGE_ALLOCS=y | 38 | CONFIG_LARGE_ALLOCS=y |
39 | CONFIG_FLATMEM=y | ||
40 | CONFIG_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 | |||
51 | CONFIG_LOCALVERSION="" | 53 | CONFIG_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 |
57 | CONFIG_EMBEDDED=y | 58 | CONFIG_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 | # |
104 | CONFIG_STANDALONE=y | 110 | CONFIG_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 |
333 | CONFIG_ROMFS_FS=y | 340 | CONFIG_ROMFS_FS=y |
341 | # CONFIG_MAGIC_ROM_PTR is not set | ||
342 | CONFIG_INOTIFY=y | ||
334 | # CONFIG_QUOTA is not set | 343 | # CONFIG_QUOTA is not set |
335 | CONFIG_DNOTIFY=y | 344 | CONFIG_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. */ |
103 | void set_mem_root (void *addr, size_t len, char *cmd_line) | 107 | void 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 */ | ||
301 | void 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 | } | ||