aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/boot/Makefile4
-rw-r--r--arch/powerpc/kernel/cputable.c45
-rw-r--r--arch/powerpc/kernel/of_platform.c17
-rw-r--r--arch/powerpc/kernel/prom.c3
-rw-r--r--arch/powerpc/kernel/setup_32.c3
-rw-r--r--arch/powerpc/kernel/setup_64.c3
-rw-r--r--arch/powerpc/kernel/systbl.S2
-rw-r--r--arch/powerpc/kernel/time.c16
-rw-r--r--arch/powerpc/kernel/vdso.c2
-rw-r--r--arch/powerpc/kernel/vio.c95
-rw-r--r--arch/powerpc/oprofile/cell/pr_util.h3
-rw-r--r--arch/powerpc/oprofile/op_model_cell.c2
-rw-r--r--arch/powerpc/platforms/40x/virtex.c5
-rw-r--r--arch/powerpc/platforms/40x/walnut.c5
-rw-r--r--arch/powerpc/platforms/44x/bamboo.c5
-rw-r--r--arch/powerpc/platforms/44x/ebony.c5
-rw-r--r--arch/powerpc/platforms/44x/sequoia.c5
-rw-r--r--arch/powerpc/platforms/52xx/efika.c9
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c2
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.c3
-rw-r--r--arch/powerpc/platforms/cell/cbe_regs.h271
-rw-r--r--arch/powerpc/platforms/cell/cbe_thermal.c2
-rw-r--r--arch/powerpc/platforms/cell/interrupt.c2
-rw-r--r--arch/powerpc/platforms/cell/iommu.c2
-rw-r--r--arch/powerpc/platforms/cell/pervasive.c2
-rw-r--r--arch/powerpc/platforms/cell/pmu.c2
-rw-r--r--arch/powerpc/platforms/cell/ras.c2
-rw-r--r--arch/powerpc/platforms/cell/setup.c17
-rw-r--r--arch/powerpc/platforms/celleb/setup.c5
-rw-r--r--arch/powerpc/platforms/chrp/setup.c10
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/dt.c17
-rw-r--r--arch/powerpc/platforms/iseries/iommu.c52
-rw-r--r--arch/powerpc/platforms/iseries/mf.c23
-rw-r--r--arch/powerpc/platforms/iseries/vio.c553
-rw-r--r--arch/powerpc/platforms/iseries/viopath.c8
-rw-r--r--arch/powerpc/platforms/pasemi/gpio_mdio.c4
-rw-r--r--arch/powerpc/platforms/powermac/setup.c77
-rw-r--r--arch/powerpc/platforms/ps3/os-area.c646
-rw-r--r--arch/powerpc/platforms/ps3/platform.h6
-rw-r--r--arch/powerpc/platforms/ps3/setup.c3
-rw-r--r--arch/powerpc/platforms/ps3/time.c14
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c14
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/sysdev/axonram.c8
-rw-r--r--arch/powerpc/sysdev/pmi.c6
-rw-r--r--arch/ppc/platforms/ev64360.c3
-rw-r--r--arch/ppc/platforms/katana.c3
50 files changed, 1370 insertions, 627 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index f3f7ce3d79a5..18e32719d0ed 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -25,6 +25,10 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
25 -isystem $(shell $(CROSS32CC) -print-file-name=include) 25 -isystem $(shell $(CROSS32CC) -print-file-name=include)
26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc 26BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
27 27
28ifdef CONFIG_DEBUG_INFO
29BOOTCFLAGS += -g
30endif
31
28ifeq ($(call cc-option-yn, -fstack-protector),y) 32ifeq ($(call cc-option-yn, -fstack-protector),y)
29BOOTCFLAGS += -fno-stack-protector 33BOOTCFLAGS += -fno-stack-protector
30endif 34endif
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index b03a442b7888..8662cf053fa0 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -71,7 +71,7 @@ extern void __restore_cpu_ppc970(void);
71#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ 71#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
72 PPC_FEATURE_BOOKE) 72 PPC_FEATURE_BOOKE)
73 73
74static struct cpu_spec cpu_specs[] = { 74static struct cpu_spec __initdata cpu_specs[] = {
75#ifdef CONFIG_PPC64 75#ifdef CONFIG_PPC64
76 { /* Power3 */ 76 { /* Power3 */
77 .pvr_mask = 0xffff0000, 77 .pvr_mask = 0xffff0000,
@@ -327,14 +327,6 @@ static struct cpu_spec cpu_specs[] = {
327 .cpu_user_features = COMMON_USER_POWER5_PLUS, 327 .cpu_user_features = COMMON_USER_POWER5_PLUS,
328 .icache_bsize = 128, 328 .icache_bsize = 128,
329 .dcache_bsize = 128, 329 .dcache_bsize = 128,
330 .num_pmcs = 6,
331 .pmc_type = PPC_PMC_IBM,
332 .oprofile_cpu_type = "ppc64/power6",
333 .oprofile_type = PPC_OPROFILE_POWER4,
334 .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
335 .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
336 .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
337 POWER6_MMCRA_OTHER,
338 .platform = "power5+", 330 .platform = "power5+",
339 }, 331 },
340 { /* Power6 */ 332 { /* Power6 */
@@ -364,14 +356,6 @@ static struct cpu_spec cpu_specs[] = {
364 .cpu_user_features = COMMON_USER_POWER6, 356 .cpu_user_features = COMMON_USER_POWER6,
365 .icache_bsize = 128, 357 .icache_bsize = 128,
366 .dcache_bsize = 128, 358 .dcache_bsize = 128,
367 .num_pmcs = 6,
368 .pmc_type = PPC_PMC_IBM,
369 .oprofile_cpu_type = "ppc64/power6",
370 .oprofile_type = PPC_OPROFILE_POWER4,
371 .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
372 .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
373 .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
374 POWER6_MMCRA_OTHER,
375 .platform = "power6", 359 .platform = "power6",
376 }, 360 },
377 { /* Cell Broadband Engine */ 361 { /* Cell Broadband Engine */
@@ -1316,18 +1300,37 @@ static struct cpu_spec cpu_specs[] = {
1316#endif /* CONFIG_PPC32 */ 1300#endif /* CONFIG_PPC32 */
1317}; 1301};
1318 1302
1319struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr) 1303static struct cpu_spec the_cpu_spec;
1304
1305struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
1320{ 1306{
1321 struct cpu_spec *s = cpu_specs; 1307 struct cpu_spec *s = cpu_specs;
1322 struct cpu_spec **cur = &cur_cpu_spec; 1308 struct cpu_spec *t = &the_cpu_spec;
1323 int i; 1309 int i;
1324 1310
1325 s = PTRRELOC(s); 1311 s = PTRRELOC(s);
1326 cur = PTRRELOC(cur); 1312 t = PTRRELOC(t);
1327 1313
1328 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) 1314 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
1329 if ((pvr & s->pvr_mask) == s->pvr_value) { 1315 if ((pvr & s->pvr_mask) == s->pvr_value) {
1330 *cur = cpu_specs + i; 1316 /*
1317 * If we are overriding a previous value derived
1318 * from the real PVR with a new value obtained
1319 * using a logical PVR value, don't modify the
1320 * performance monitor fields.
1321 */
1322 if (t->num_pmcs && !s->num_pmcs) {
1323 t->cpu_name = s->cpu_name;
1324 t->cpu_features = s->cpu_features;
1325 t->cpu_user_features = s->cpu_user_features;
1326 t->icache_bsize = s->icache_bsize;
1327 t->dcache_bsize = s->dcache_bsize;
1328 t->cpu_setup = s->cpu_setup;
1329 t->cpu_restore = s->cpu_restore;
1330 t->platform = s->platform;
1331 } else
1332 *t = *s;
1333 *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
1331#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) 1334#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
1332 /* ppc64 and booke expect identify_cpu to also call 1335 /* ppc64 and booke expect identify_cpu to also call
1333 * setup_cpu for that processor. I will consolidate 1336 * setup_cpu for that processor. I will consolidate
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index f70e787d556f..eca8ccc3fa12 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -19,11 +19,11 @@
19#include <linux/mod_devicetable.h> 19#include <linux/mod_devicetable.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/pci.h> 21#include <linux/pci.h>
22#include <linux/of_device.h>
23#include <linux/of_platform.h>
22 24
23#include <asm/errno.h> 25#include <asm/errno.h>
24#include <asm/dcr.h> 26#include <asm/dcr.h>
25#include <asm/of_device.h>
26#include <asm/of_platform.h>
27#include <asm/topology.h> 27#include <asm/topology.h>
28#include <asm/pci-bridge.h> 28#include <asm/pci-bridge.h>
29#include <asm/ppc-pci.h> 29#include <asm/ppc-pci.h>
@@ -70,7 +70,10 @@ postcore_initcall(of_bus_driver_init);
70int of_register_platform_driver(struct of_platform_driver *drv) 70int of_register_platform_driver(struct of_platform_driver *drv)
71{ 71{
72 /* initialize common driver fields */ 72 /* initialize common driver fields */
73 drv->driver.name = drv->name; 73 if (!drv->driver.name)
74 drv->driver.name = drv->name;
75 if (!drv->driver.owner)
76 drv->driver.owner = drv->owner;
74 drv->driver.bus = &of_platform_bus_type; 77 drv->driver.bus = &of_platform_bus_type;
75 78
76 /* register with core */ 79 /* register with core */
@@ -385,9 +388,11 @@ static struct of_device_id of_pci_phb_ids[] = {
385}; 388};
386 389
387static struct of_platform_driver of_pci_phb_driver = { 390static struct of_platform_driver of_pci_phb_driver = {
388 .name = "of-pci", 391 .match_table = of_pci_phb_ids,
389 .match_table = of_pci_phb_ids, 392 .probe = of_pci_phb_probe,
390 .probe = of_pci_phb_probe, 393 .driver = {
394 .name = "of-pci",
395 },
391}; 396};
392 397
393static __init int of_pci_phb_init(void) 398static __init int of_pci_phb_init(void)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 172dcc3849a0..9f329a8928ea 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -531,10 +531,7 @@ static struct ibm_pa_feature {
531 {CPU_FTR_CTRL, 0, 0, 3, 0}, 531 {CPU_FTR_CTRL, 0, 0, 3, 0},
532 {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, 532 {CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
533 {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, 533 {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
534#if 0
535 /* put this back once we know how to test if firmware does 64k IO */
536 {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, 534 {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
537#endif
538 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, 535 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
539}; 536};
540 537
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 7474502dace5..cd870a823d18 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -290,7 +290,8 @@ void __init setup_arch(char **cmdline_p)
290 conswitchp = &dummy_con; 290 conswitchp = &dummy_con;
291#endif 291#endif
292 292
293 ppc_md.setup_arch(); 293 if (ppc_md.setup_arch)
294 ppc_md.setup_arch();
294 if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); 295 if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
295 296
296 paging_init(); 297 paging_init();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 3089eaed3256..008ab6823b02 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -530,7 +530,8 @@ void __init setup_arch(char **cmdline_p)
530 conswitchp = &dummy_con; 530 conswitchp = &dummy_con;
531#endif 531#endif
532 532
533 ppc_md.setup_arch(); 533 if (ppc_md.setup_arch)
534 ppc_md.setup_arch();
534 535
535 paging_init(); 536 paging_init();
536 ppc64_boot_msg(0x15, "Setup Done"); 537 ppc64_boot_msg(0x15, "Setup Done");
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 579de70e0b4d..93219c34af32 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -39,6 +39,8 @@
39#ifdef CONFIG_PPC64 39#ifdef CONFIG_PPC64
40#define sys_sigpending sys_ni_syscall 40#define sys_sigpending sys_ni_syscall
41#define sys_old_getrlimit sys_ni_syscall 41#define sys_old_getrlimit sys_ni_syscall
42
43 .p2align 3
42#endif 44#endif
43 45
44_GLOBAL(sys_call_table) 46_GLOBAL(sys_call_table)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index d20947cf1735..9368da371f36 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -108,7 +108,7 @@ static void decrementer_set_mode(enum clock_event_mode mode,
108static struct clock_event_device decrementer_clockevent = { 108static struct clock_event_device decrementer_clockevent = {
109 .name = "decrementer", 109 .name = "decrementer",
110 .rating = 200, 110 .rating = 200,
111 .shift = 32, 111 .shift = 16,
112 .mult = 0, /* To be filled in */ 112 .mult = 0, /* To be filled in */
113 .irq = 0, 113 .irq = 0,
114 .set_next_event = decrementer_set_next_event, 114 .set_next_event = decrementer_set_next_event,
@@ -118,6 +118,7 @@ static struct clock_event_device decrementer_clockevent = {
118 118
119static DEFINE_PER_CPU(struct clock_event_device, decrementers); 119static DEFINE_PER_CPU(struct clock_event_device, decrementers);
120void init_decrementer_clockevent(void); 120void init_decrementer_clockevent(void);
121static DEFINE_PER_CPU(u64, decrementer_next_tb);
121 122
122#ifdef CONFIG_PPC_ISERIES 123#ifdef CONFIG_PPC_ISERIES
123static unsigned long __initdata iSeries_recal_titan; 124static unsigned long __initdata iSeries_recal_titan;
@@ -541,6 +542,7 @@ void timer_interrupt(struct pt_regs * regs)
541 struct pt_regs *old_regs; 542 struct pt_regs *old_regs;
542 int cpu = smp_processor_id(); 543 int cpu = smp_processor_id();
543 struct clock_event_device *evt = &per_cpu(decrementers, cpu); 544 struct clock_event_device *evt = &per_cpu(decrementers, cpu);
545 u64 now;
544 546
545 /* Ensure a positive value is written to the decrementer, or else 547 /* Ensure a positive value is written to the decrementer, or else
546 * some CPUs will continuue to take decrementer exceptions */ 548 * some CPUs will continuue to take decrementer exceptions */
@@ -551,6 +553,14 @@ void timer_interrupt(struct pt_regs * regs)
551 do_IRQ(regs); 553 do_IRQ(regs);
552#endif 554#endif
553 555
556 now = get_tb_or_rtc();
557 if (now < per_cpu(decrementer_next_tb, cpu)) {
558 /* not time for this event yet */
559 now = per_cpu(decrementer_next_tb, cpu) - now;
560 if (now <= DECREMENTER_MAX)
561 set_dec((unsigned int)now - 1);
562 return;
563 }
554 old_regs = set_irq_regs(regs); 564 old_regs = set_irq_regs(regs);
555 irq_enter(); 565 irq_enter();
556 566
@@ -797,6 +807,10 @@ void __init clocksource_init(void)
797static int decrementer_set_next_event(unsigned long evt, 807static int decrementer_set_next_event(unsigned long evt,
798 struct clock_event_device *dev) 808 struct clock_event_device *dev)
799{ 809{
810 __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
811 /* The decrementer interrupts on the 0 -> -1 transition */
812 if (evt)
813 --evt;
800 set_dec(evt); 814 set_dec(evt);
801 return 0; 815 return 0;
802} 816}
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 213fa31ac537..2322ba5cce4c 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -766,7 +766,9 @@ static int __init vdso_init(void)
766 766
767 return 0; 767 return 0;
768} 768}
769#ifdef CONFIG_PPC_MERGE
769arch_initcall(vdso_init); 770arch_initcall(vdso_init);
771#endif
770 772
771int in_gate_area_no_task(unsigned long addr) 773int in_gate_area_no_task(unsigned long addr)
772{ 774{
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 1d7b272b3737..cb22a3557c4e 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -48,66 +48,33 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */
48 .dev.bus = &vio_bus_type, 48 .dev.bus = &vio_bus_type,
49}; 49};
50 50
51#ifdef CONFIG_PPC_ISERIES 51static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
52struct device *iSeries_vio_dev = &vio_bus_device.dev; 52{
53EXPORT_SYMBOL(iSeries_vio_dev); 53 const unsigned char *dma_window;
54 struct iommu_table *tbl;
55 unsigned long offset, size;
54 56
55static struct iommu_table veth_iommu_table; 57 if (firmware_has_feature(FW_FEATURE_ISERIES))
56static struct iommu_table vio_iommu_table; 58 return vio_build_iommu_table_iseries(dev);
57 59
58static void __init iommu_vio_init(void) 60 dma_window = of_get_property(dev->dev.archdata.of_node,
59{ 61 "ibm,my-dma-window", NULL);
60 iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); 62 if (!dma_window)
61 veth_iommu_table.it_size /= 2; 63 return NULL;
62 vio_iommu_table = veth_iommu_table;
63 vio_iommu_table.it_offset += veth_iommu_table.it_size;
64
65 if (!iommu_init_table(&veth_iommu_table, -1))
66 printk("Virtual Bus VETH TCE table failed.\n");
67 if (!iommu_init_table(&vio_iommu_table, -1))
68 printk("Virtual Bus VIO TCE table failed.\n");
69 vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
70 vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
71}
72#else
73static void __init iommu_vio_init(void)
74{
75}
76#endif
77 64
78static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) 65 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
79{ 66
80#ifdef CONFIG_PPC_ISERIES 67 of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
81 if (firmware_has_feature(FW_FEATURE_ISERIES)) { 68 &tbl->it_index, &offset, &size);
82 if (strcmp(dev->type, "network") == 0) 69
83 return &veth_iommu_table; 70 /* TCE table size - measured in tce entries */
84 return &vio_iommu_table; 71 tbl->it_size = size >> IOMMU_PAGE_SHIFT;
85 } else 72 /* offset for VIO should always be 0 */
86#endif 73 tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
87 { 74 tbl->it_busno = 0;
88 const unsigned char *dma_window; 75 tbl->it_type = TCE_VB;
89 struct iommu_table *tbl; 76
90 unsigned long offset, size; 77 return iommu_init_table(tbl, -1);
91
92 dma_window = of_get_property(dev->dev.archdata.of_node,
93 "ibm,my-dma-window", NULL);
94 if (!dma_window)
95 return NULL;
96
97 tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
98
99 of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
100 &tbl->it_index, &offset, &size);
101
102 /* TCE table size - measured in tce entries */
103 tbl->it_size = size >> IOMMU_PAGE_SHIFT;
104 /* offset for VIO should always be 0 */
105 tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
106 tbl->it_busno = 0;
107 tbl->it_type = TCE_VB;
108
109 return iommu_init_table(tbl, -1);
110 }
111} 78}
112 79
113/** 80/**
@@ -168,16 +135,6 @@ static int vio_bus_remove(struct device *dev)
168 return 1; 135 return 1;
169} 136}
170 137
171/* convert from struct device to struct vio_dev and pass to driver. */
172static void vio_bus_shutdown(struct device *dev)
173{
174 struct vio_dev *viodev = to_vio_dev(dev);
175 struct vio_driver *viodrv = to_vio_driver(dev->driver);
176
177 if (dev->driver && viodrv->shutdown)
178 viodrv->shutdown(viodev);
179}
180
181/** 138/**
182 * vio_register_driver: - Register a new vio driver 139 * vio_register_driver: - Register a new vio driver
183 * @drv: The vio_driver structure to be registered. 140 * @drv: The vio_driver structure to be registered.
@@ -290,9 +247,6 @@ static int __init vio_bus_init(void)
290 int err; 247 int err;
291 struct device_node *node_vroot; 248 struct device_node *node_vroot;
292 249
293 if (firmware_has_feature(FW_FEATURE_ISERIES))
294 iommu_vio_init();
295
296 err = bus_register(&vio_bus_type); 250 err = bus_register(&vio_bus_type);
297 if (err) { 251 if (err) {
298 printk(KERN_ERR "failed to register VIO bus\n"); 252 printk(KERN_ERR "failed to register VIO bus\n");
@@ -397,7 +351,6 @@ static struct bus_type vio_bus_type = {
397 .match = vio_bus_match, 351 .match = vio_bus_match,
398 .probe = vio_bus_probe, 352 .probe = vio_bus_probe,
399 .remove = vio_bus_remove, 353 .remove = vio_bus_remove,
400 .shutdown = vio_bus_shutdown,
401}; 354};
402 355
403/** 356/**
diff --git a/arch/powerpc/oprofile/cell/pr_util.h b/arch/powerpc/oprofile/cell/pr_util.h
index e5704f00c8b4..22e4e8d4eb2c 100644
--- a/arch/powerpc/oprofile/cell/pr_util.h
+++ b/arch/powerpc/oprofile/cell/pr_util.h
@@ -17,10 +17,9 @@
17#include <linux/cpumask.h> 17#include <linux/cpumask.h>
18#include <linux/oprofile.h> 18#include <linux/oprofile.h>
19#include <asm/cell-pmu.h> 19#include <asm/cell-pmu.h>
20#include <asm/cell-regs.h>
20#include <asm/spu.h> 21#include <asm/spu.h>
21 22
22#include "../../platforms/cell/cbe_regs.h"
23
24/* Defines used for sync_start */ 23/* Defines used for sync_start */
25#define SKIP_GENERIC_SYNC 0 24#define SKIP_GENERIC_SYNC 0
26#define SYNC_START_ERROR -1 25#define SYNC_START_ERROR -1
diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c
index d928b54f3a0f..bb6bff51ce48 100644
--- a/arch/powerpc/oprofile/op_model_cell.c
+++ b/arch/powerpc/oprofile/op_model_cell.c
@@ -35,9 +35,9 @@
35#include <asm/reg.h> 35#include <asm/reg.h>
36#include <asm/rtas.h> 36#include <asm/rtas.h>
37#include <asm/system.h> 37#include <asm/system.h>
38#include <asm/cell-regs.h>
38 39
39#include "../platforms/cell/interrupt.h" 40#include "../platforms/cell/interrupt.h"
40#include "../platforms/cell/cbe_regs.h"
41#include "cell/pr_util.h" 41#include "cell/pr_util.h"
42 42
43static void cell_global_stop_spu(void); 43static void cell_global_stop_spu(void);
diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c
index b52aa94abd78..14bbc328170f 100644
--- a/arch/powerpc/platforms/40x/virtex.c
+++ b/arch/powerpc/platforms/40x/virtex.c
@@ -36,14 +36,9 @@ static int __init virtex_probe(void)
36 return 1; 36 return 1;
37} 37}
38 38
39static void __init virtex_setup_arch(void)
40{
41}
42
43define_machine(virtex) { 39define_machine(virtex) {
44 .name = "Xilinx Virtex", 40 .name = "Xilinx Virtex",
45 .probe = virtex_probe, 41 .probe = virtex_probe,
46 .setup_arch = virtex_setup_arch,
47 .init_IRQ = xilinx_intc_init_tree, 42 .init_IRQ = xilinx_intc_init_tree,
48 .get_irq = xilinx_intc_get_irq, 43 .get_irq = xilinx_intc_get_irq,
49 .calibrate_decr = generic_calibrate_decr, 44 .calibrate_decr = generic_calibrate_decr,
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index c17fdf23b492..eb0c136b1c44 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -53,14 +53,9 @@ static int __init walnut_probe(void)
53 return 1; 53 return 1;
54} 54}
55 55
56static void __init walnut_setup_arch(void)
57{
58}
59
60define_machine(walnut) { 56define_machine(walnut) {
61 .name = "Walnut", 57 .name = "Walnut",
62 .probe = walnut_probe, 58 .probe = walnut_probe,
63 .setup_arch = walnut_setup_arch,
64 .progress = udbg_progress, 59 .progress = udbg_progress,
65 .init_IRQ = uic_init_tree, 60 .init_IRQ = uic_init_tree,
66 .get_irq = uic_get_irq, 61 .get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
index 9bc45dea078f..470e1a3fd755 100644
--- a/arch/powerpc/platforms/44x/bamboo.c
+++ b/arch/powerpc/platforms/44x/bamboo.c
@@ -50,14 +50,9 @@ static int __init bamboo_probe(void)
50 return 1; 50 return 1;
51} 51}
52 52
53static void __init bamboo_setup_arch(void)
54{
55}
56
57define_machine(bamboo) { 53define_machine(bamboo) {
58 .name = "Bamboo", 54 .name = "Bamboo",
59 .probe = bamboo_probe, 55 .probe = bamboo_probe,
60 .setup_arch = bamboo_setup_arch,
61 .progress = udbg_progress, 56 .progress = udbg_progress,
62 .init_IRQ = uic_init_tree, 57 .init_IRQ = uic_init_tree,
63 .get_irq = uic_get_irq, 58 .get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 5a7fec8d10d3..40e18fcb666c 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -57,14 +57,9 @@ static int __init ebony_probe(void)
57 return 1; 57 return 1;
58} 58}
59 59
60static void __init ebony_setup_arch(void)
61{
62}
63
64define_machine(ebony) { 60define_machine(ebony) {
65 .name = "Ebony", 61 .name = "Ebony",
66 .probe = ebony_probe, 62 .probe = ebony_probe,
67 .setup_arch = ebony_setup_arch,
68 .progress = udbg_progress, 63 .progress = udbg_progress,
69 .init_IRQ = uic_init_tree, 64 .init_IRQ = uic_init_tree,
70 .get_irq = uic_get_irq, 65 .get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
index 7d0d9d567d25..30700b31d43b 100644
--- a/arch/powerpc/platforms/44x/sequoia.c
+++ b/arch/powerpc/platforms/44x/sequoia.c
@@ -50,14 +50,9 @@ static int __init sequoia_probe(void)
50 return 1; 50 return 1;
51} 51}
52 52
53static void __init sequoia_setup_arch(void)
54{
55}
56
57define_machine(sequoia) { 53define_machine(sequoia) {
58 .name = "Sequoia", 54 .name = "Sequoia",
59 .probe = sequoia_probe, 55 .probe = sequoia_probe,
60 .setup_arch = sequoia_setup_arch,
61 .progress = udbg_progress, 56 .progress = udbg_progress,
62 .init_IRQ = uic_init_tree, 57 .init_IRQ = uic_init_tree,
63 .get_irq = uic_get_irq, 58 .get_irq = uic_get_irq,
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 4263158b3274..0b1e60a010ba 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -197,15 +197,6 @@ static void __init efika_setup_arch(void)
197{ 197{
198 rtas_initialize(); 198 rtas_initialize();
199 199
200#ifdef CONFIG_BLK_DEV_INITRD
201 initrd_below_start_ok = 1;
202
203 if (initrd_start)
204 ROOT_DEV = Root_RAM0;
205 else
206#endif
207 ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
208
209 efika_pcisetup(); 200 efika_pcisetup();
210 201
211#ifdef CONFIG_PM 202#ifdef CONFIG_PM
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c
index 0b6e8ee85ab1..901236fa0f07 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c
@@ -24,7 +24,7 @@
24#include <asm/machdep.h> 24#include <asm/machdep.h>
25#include <asm/of_platform.h> 25#include <asm/of_platform.h>
26#include <asm/prom.h> 26#include <asm/prom.h>
27#include "cbe_regs.h" 27#include <asm/cell-regs.h>
28#include "cbe_cpufreq.h" 28#include "cbe_cpufreq.h"
29 29
30static DEFINE_MUTEX(cbe_switch_mutex); 30static DEFINE_MUTEX(cbe_switch_mutex);
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
index 163263b3e1cd..70fa7aef5edd 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
@@ -28,8 +28,8 @@
28#include <linux/time.h> 28#include <linux/time.h>
29#include <asm/machdep.h> 29#include <asm/machdep.h>
30#include <asm/hw_irq.h> 30#include <asm/hw_irq.h>
31#include <asm/cell-regs.h>
31 32
32#include "cbe_regs.h"
33#include "cbe_cpufreq.h" 33#include "cbe_cpufreq.h"
34 34
35/* to write to MIC register */ 35/* to write to MIC register */
diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
index fc6f38982ff4..6a2c1b0a9a94 100644
--- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
+++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
@@ -27,12 +27,12 @@
27#include <asm/processor.h> 27#include <asm/processor.h>
28#include <asm/prom.h> 28#include <asm/prom.h>
29#include <asm/pmi.h> 29#include <asm/pmi.h>
30#include <asm/cell-regs.h>
30 31
31#ifdef DEBUG 32#ifdef DEBUG
32#include <asm/time.h> 33#include <asm/time.h>
33#endif 34#endif
34 35
35#include "cbe_regs.h"
36#include "cbe_cpufreq.h" 36#include "cbe_cpufreq.h"
37 37
38static u8 pmi_slow_mode_limit[MAX_CBE]; 38static u8 pmi_slow_mode_limit[MAX_CBE];
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
index c8f7f0007422..16a9b07e7b0c 100644
--- a/arch/powerpc/platforms/cell/cbe_regs.c
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -16,8 +16,7 @@
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/of_device.h> 17#include <asm/of_device.h>
18#include <asm/of_platform.h> 18#include <asm/of_platform.h>
19 19#include <asm/cell-regs.h>
20#include "cbe_regs.h"
21 20
22/* 21/*
23 * Current implementation uses "cpu" nodes. We build our own mapping 22 * Current implementation uses "cpu" nodes. We build our own mapping
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
deleted file mode 100644
index b24025f2ac7a..000000000000
--- a/arch/powerpc/platforms/cell/cbe_regs.h
+++ /dev/null
@@ -1,271 +0,0 @@
1/*
2 * cbe_regs.h
3 *
4 * This file is intended to hold the various register definitions for CBE
5 * on-chip system devices (memory controller, IO controller, etc...)
6 *
7 * (C) Copyright IBM Corporation 2001,2006
8 *
9 * Authors: Maximino Aguilar (maguilar@us.ibm.com)
10 * David J. Erb (djerb@us.ibm.com)
11 *
12 * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
13 */
14
15#ifndef CBE_REGS_H
16#define CBE_REGS_H
17
18#include <asm/cell-pmu.h>
19
20/*
21 *
22 * Some HID register definitions
23 *
24 */
25
26/* CBE specific HID0 bits */
27#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul
28#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul
29#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
30#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
31
32#define MAX_CBE 2
33
34/*
35 *
36 * Pervasive unit register definitions
37 *
38 */
39
40union spe_reg {
41 u64 val;
42 u8 spe[8];
43};
44
45union ppe_spe_reg {
46 u64 val;
47 struct {
48 u32 ppe;
49 u32 spe;
50 };
51};
52
53
54struct cbe_pmd_regs {
55 /* Debug Bus Control */
56 u64 pad_0x0000; /* 0x0000 */
57
58 u64 group_control; /* 0x0008 */
59
60 u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */
61
62 u64 debug_bus_control; /* 0x00a8 */
63
64 u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */
65
66 u64 trace_aux_data; /* 0x0100 */
67 u64 trace_buffer_0_63; /* 0x0108 */
68 u64 trace_buffer_64_127; /* 0x0110 */
69 u64 trace_address; /* 0x0118 */
70 u64 ext_tr_timer; /* 0x0120 */
71
72 u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */
73
74 /* Performance Monitor */
75 u64 pm_status; /* 0x0400 */
76 u64 pm_control; /* 0x0408 */
77 u64 pm_interval; /* 0x0410 */
78 u64 pm_ctr[4]; /* 0x0418 */
79 u64 pm_start_stop; /* 0x0438 */
80 u64 pm07_control[8]; /* 0x0440 */
81
82 u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */
83
84 /* Thermal Sensor Registers */
85 union spe_reg ts_ctsr1; /* 0x0800 */
86 u64 ts_ctsr2; /* 0x0808 */
87 union spe_reg ts_mtsr1; /* 0x0810 */
88 u64 ts_mtsr2; /* 0x0818 */
89 union spe_reg ts_itr1; /* 0x0820 */
90 u64 ts_itr2; /* 0x0828 */
91 u64 ts_gitr; /* 0x0830 */
92 u64 ts_isr; /* 0x0838 */
93 u64 ts_imr; /* 0x0840 */
94 union spe_reg tm_cr1; /* 0x0848 */
95 u64 tm_cr2; /* 0x0850 */
96 u64 tm_simr; /* 0x0858 */
97 union ppe_spe_reg tm_tpr; /* 0x0860 */
98 union spe_reg tm_str1; /* 0x0868 */
99 u64 tm_str2; /* 0x0870 */
100 union ppe_spe_reg tm_tsr; /* 0x0878 */
101
102 /* Power Management */
103 u64 pmcr; /* 0x0880 */
104#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
105 u64 pmsr; /* 0x0888 */
106
107 /* Time Base Register */
108 u64 tbr; /* 0x0890 */
109
110 u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */
111
112 /* Fault Isolation Registers */
113 u64 checkstop_fir; /* 0x0c00 */
114 u64 recoverable_fir; /* 0x0c08 */
115 u64 spec_att_mchk_fir; /* 0x0c10 */
116 u32 fir_mode_reg; /* 0x0c18 */
117 u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */
118#define CBE_PMD_FIR_MODE_M8 0x00800
119 u64 fir_enable_mask; /* 0x0c20 */
120
121 u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */
122 u64 ras_esc_0; /* 0x0ca8 */
123 u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */
124};
125
126extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
127extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
128
129/*
130 * PMU shadow registers
131 *
132 * Many of the registers in the performance monitoring unit are write-only,
133 * so we need to save a copy of what we write to those registers.
134 *
135 * The actual data counters are read/write. However, writing to the counters
136 * only takes effect if the PMU is enabled. Otherwise the value is stored in
137 * a hardware latch until the next time the PMU is enabled. So we save a copy
138 * of the counter values if we need to read them back while the PMU is
139 * disabled. The counter_value_in_latch field is a bitmap indicating which
140 * counters currently have a value waiting to be written.
141 */
142
143struct cbe_pmd_shadow_regs {
144 u32 group_control;
145 u32 debug_bus_control;
146 u32 trace_address;
147 u32 ext_tr_timer;
148 u32 pm_status;
149 u32 pm_control;
150 u32 pm_interval;
151 u32 pm_start_stop;
152 u32 pm07_control[NR_CTRS];
153
154 u32 pm_ctr[NR_PHYS_CTRS];
155 u32 counter_value_in_latch;
156};
157
158extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
159extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
160
161/*
162 *
163 * IIC unit register definitions
164 *
165 */
166
167struct cbe_iic_pending_bits {
168 u32 data;
169 u8 flags;
170 u8 class;
171 u8 source;
172 u8 prio;
173};
174
175#define CBE_IIC_IRQ_VALID 0x80
176#define CBE_IIC_IRQ_IPI 0x40
177
178struct cbe_iic_thread_regs {
179 struct cbe_iic_pending_bits pending;
180 struct cbe_iic_pending_bits pending_destr;
181 u64 generate;
182 u64 prio;
183};
184
185struct cbe_iic_regs {
186 u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */
187
188 /* IIC interrupt registers */
189 struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
190
191 u64 iic_ir; /* 0x0440 */
192#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12)
193#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
194#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
195#define CBE_IIC_IR_IOC_0 0x0
196#define CBE_IIC_IR_IOC_1S 0xb
197#define CBE_IIC_IR_PT_0 0xe
198#define CBE_IIC_IR_PT_1 0xf
199
200 u64 iic_is; /* 0x0448 */
201#define CBE_IIC_IS_PMI 0x2
202
203 u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */
204
205 /* IOC FIR */
206 u64 ioc_fir_reset; /* 0x0500 */
207 u64 ioc_fir_set; /* 0x0508 */
208 u64 ioc_checkstop_enable; /* 0x0510 */
209 u64 ioc_fir_error_mask; /* 0x0518 */
210 u64 ioc_syserr_enable; /* 0x0520 */
211 u64 ioc_fir; /* 0x0528 */
212
213 u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
214};
215
216extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
217extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
218
219
220struct cbe_mic_tm_regs {
221 u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */
222
223 u64 mic_ctl_cnfg2; /* 0x0040 */
224#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL
225#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL
226#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL
227#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL
228
229 u64 pad_0x0048; /* 0x0048 */
230
231 u64 mic_aux_trc_base; /* 0x0050 */
232 u64 mic_aux_trc_max_addr; /* 0x0058 */
233 u64 mic_aux_trc_cur_addr; /* 0x0060 */
234 u64 mic_aux_trc_grf_addr; /* 0x0068 */
235 u64 mic_aux_trc_grf_data; /* 0x0070 */
236
237 u64 pad_0x0078; /* 0x0078 */
238
239 u64 mic_ctl_cnfg_0; /* 0x0080 */
240#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL
241
242 u64 pad_0x0088; /* 0x0088 */
243
244 u64 slow_fast_timer_0; /* 0x0090 */
245 u64 slow_next_timer_0; /* 0x0098 */
246
247 u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */
248
249 u64 mic_ctl_cnfg_1; /* 0x01c0 */
250#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL
251 u64 pad_0x01c8; /* 0x01c8 */
252
253 u64 slow_fast_timer_1; /* 0x01d0 */
254 u64 slow_next_timer_1; /* 0x01d8 */
255
256 u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */
257};
258
259extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
260extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
261
262/* some utility functions to deal with SMT */
263extern u32 cbe_get_hw_thread_id(int cpu);
264extern u32 cbe_cpu_to_node(int cpu);
265extern u32 cbe_node_to_cpu(int node);
266
267/* Init this module early */
268extern void cbe_regs_init(void);
269
270
271#endif /* CBE_REGS_H */
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c
index fb5eda48467d..4852bf312d83 100644
--- a/arch/powerpc/platforms/cell/cbe_thermal.c
+++ b/arch/powerpc/platforms/cell/cbe_thermal.c
@@ -52,8 +52,8 @@
52#include <asm/spu.h> 52#include <asm/spu.h>
53#include <asm/io.h> 53#include <asm/io.h>
54#include <asm/prom.h> 54#include <asm/prom.h>
55#include <asm/cell-regs.h>
55 56
56#include "cbe_regs.h"
57#include "spu_priv1_mmio.h" 57#include "spu_priv1_mmio.h"
58 58
59#define TEMP_MIN 65 59#define TEMP_MIN 65
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index c29e634177fa..151fd8b82d63 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -41,9 +41,9 @@
41#include <asm/prom.h> 41#include <asm/prom.h>
42#include <asm/ptrace.h> 42#include <asm/ptrace.h>
43#include <asm/machdep.h> 43#include <asm/machdep.h>
44#include <asm/cell-regs.h>
44 45
45#include "interrupt.h" 46#include "interrupt.h"
46#include "cbe_regs.h"
47 47
48struct iic { 48struct iic {
49 struct cbe_iic_thread_regs __iomem *regs; 49 struct cbe_iic_thread_regs __iomem *regs;
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 760caa76841a..faabc3fdc130 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -34,8 +34,8 @@
34#include <asm/udbg.h> 34#include <asm/udbg.h>
35#include <asm/of_platform.h> 35#include <asm/of_platform.h>
36#include <asm/lmb.h> 36#include <asm/lmb.h>
37#include <asm/cell-regs.h>
37 38
38#include "cbe_regs.h"
39#include "interrupt.h" 39#include "interrupt.h"
40 40
41/* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages 41/* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 4ede22d363fa..0304589c0a80 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -34,9 +34,9 @@
34#include <asm/prom.h> 34#include <asm/prom.h>
35#include <asm/pgtable.h> 35#include <asm/pgtable.h>
36#include <asm/reg.h> 36#include <asm/reg.h>
37#include <asm/cell-regs.h>
37 38
38#include "pervasive.h" 39#include "pervasive.h"
39#include "cbe_regs.h"
40 40
41static int sysreset_hack; 41static int sysreset_hack;
42 42
diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c
index 66ca4b5a1dbc..1ed303678887 100644
--- a/arch/powerpc/platforms/cell/pmu.c
+++ b/arch/powerpc/platforms/cell/pmu.c
@@ -30,8 +30,8 @@
30#include <asm/pmc.h> 30#include <asm/pmc.h>
31#include <asm/reg.h> 31#include <asm/reg.h>
32#include <asm/spu.h> 32#include <asm/spu.h>
33#include <asm/cell-regs.h>
33 34
34#include "cbe_regs.h"
35#include "interrupt.h" 35#include "interrupt.h"
36 36
37/* 37/*
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 3961a085b432..b2494ebcdbe9 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -10,9 +10,9 @@
10#include <asm/prom.h> 10#include <asm/prom.h>
11#include <asm/machdep.h> 11#include <asm/machdep.h>
12#include <asm/rtas.h> 12#include <asm/rtas.h>
13#include <asm/cell-regs.h>
13 14
14#include "ras.h" 15#include "ras.h"
15#include "cbe_regs.h"
16 16
17 17
18static void dump_fir(int cpu) 18static void dump_fir(int cpu)
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index db6654272e13..98e7ef8e6fc6 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -52,9 +52,9 @@
52#include <asm/udbg.h> 52#include <asm/udbg.h>
53#include <asm/mpic.h> 53#include <asm/mpic.h>
54#include <asm/of_platform.h> 54#include <asm/of_platform.h>
55#include <asm/cell-regs.h>
55 56
56#include "interrupt.h" 57#include "interrupt.h"
57#include "cbe_regs.h"
58#include "pervasive.h" 58#include "pervasive.h"
59#include "ras.h" 59#include "ras.h"
60 60
@@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex)
83 83
84static int __init cell_publish_devices(void) 84static int __init cell_publish_devices(void)
85{ 85{
86 int node;
87
86 if (!machine_is(cell)) 88 if (!machine_is(cell))
87 return 0; 89 return 0;
88 90
89 /* Publish OF platform devices for southbridge IOs */ 91 /* Publish OF platform devices for southbridge IOs */
90 of_platform_bus_probe(NULL, NULL, NULL); 92 of_platform_bus_probe(NULL, NULL, NULL);
91 93
94 /* There is no device for the MIC memory controller, thus we create
95 * a platform device for it to attach the EDAC driver to.
96 */
97 for_each_online_node(node) {
98 if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL)
99 continue;
100 platform_device_register_simple("cbe-mic", node, NULL, 0);
101 }
92 return 0; 102 return 0;
93} 103}
94device_initcall(cell_publish_devices); 104device_initcall(cell_publish_devices);
@@ -161,11 +171,6 @@ static void __init cell_setup_arch(void)
161 /* init to some ~sane value until calibrate_delay() runs */ 171 /* init to some ~sane value until calibrate_delay() runs */
162 loops_per_jiffy = 50000000; 172 loops_per_jiffy = 50000000;
163 173
164 if (ROOT_DEV == 0) {
165 printk("No ramdisk, default root is /dev/hda2\n");
166 ROOT_DEV = Root_HDA2;
167 }
168
169 /* Find and initialize PCI host bridges */ 174 /* Find and initialize PCI host bridges */
170 init_pci_config_tokens(); 175 init_pci_config_tokens();
171 find_and_init_phbs(); 176 find_and_init_phbs();
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 0f1dddb81cd2..1769d755eff3 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -101,11 +101,6 @@ static void __init celleb_setup_arch(void)
101 /* init to some ~sane value until calibrate_delay() runs */ 101 /* init to some ~sane value until calibrate_delay() runs */
102 loops_per_jiffy = 50000000; 102 loops_per_jiffy = 50000000;
103 103
104 if (ROOT_DEV == 0) {
105 printk("No ramdisk, default root is /dev/hda2\n");
106 ROOT_DEV = Root_HDA2;
107 }
108
109#ifdef CONFIG_DUMMY_CONSOLE 104#ifdef CONFIG_DUMMY_CONSOLE
110 conswitchp = &dummy_con; 105 conswitchp = &dummy_con;
111#endif 106#endif
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 96498ad7b943..59306261f5b2 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -290,16 +290,6 @@ void __init chrp_setup_arch(void)
290 ppc_md.set_rtc_time = rtas_set_rtc_time; 290 ppc_md.set_rtc_time = rtas_set_rtc_time;
291 } 291 }
292 292
293#ifdef CONFIG_BLK_DEV_INITRD
294 /* this is fine for chrp */
295 initrd_below_start_ok = 1;
296
297 if (initrd_start)
298 ROOT_DEV = Root_RAM0;
299 else
300#endif
301 ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
302
303 /* On pegasos, enable the L2 cache if not already done by OF */ 293 /* On pegasos, enable the L2 cache if not already done by OF */
304 pegasos_set_l2cr(); 294 pegasos_set_l2cr();
305 295
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 60db509638f1..a65f1b44abf8 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
7 hvcall.o proc.o htab.o iommu.o misc.o irq.o 7 hvcall.o proc.o htab.o iommu.o misc.o irq.o
8obj-$(CONFIG_PCI) += pci.o vpdinfo.o 8obj-$(CONFIG_PCI) += pci.o vpdinfo.o
9obj-$(CONFIG_SMP) += smp.o 9obj-$(CONFIG_SMP) += smp.o
10obj-$(CONFIG_VIOPATH) += viopath.o 10obj-$(CONFIG_VIOPATH) += viopath.o vio.o
11obj-$(CONFIG_MODULES) += ksyms.o 11obj-$(CONFIG_MODULES) += ksyms.o
12 12
13quiet_cmd_dt_strings = DT_STR $@ 13quiet_cmd_dt_strings = DT_STR $@
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 9e8a334a518a..4543c4bc3a56 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -72,8 +72,6 @@ static char __initdata device_type_cpu[] = "cpu";
72static char __initdata device_type_memory[] = "memory"; 72static char __initdata device_type_memory[] = "memory";
73static char __initdata device_type_serial[] = "serial"; 73static char __initdata device_type_serial[] = "serial";
74static char __initdata device_type_network[] = "network"; 74static char __initdata device_type_network[] = "network";
75static char __initdata device_type_block[] = "block";
76static char __initdata device_type_byte[] = "byte";
77static char __initdata device_type_pci[] = "pci"; 75static char __initdata device_type_pci[] = "pci";
78static char __initdata device_type_vdevice[] = "vdevice"; 76static char __initdata device_type_vdevice[] = "vdevice";
79static char __initdata device_type_vscsi[] = "vscsi"; 77static char __initdata device_type_vscsi[] = "vscsi";
@@ -375,21 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
375 373
376 dt_end_node(dt); 374 dt_end_node(dt);
377 } 375 }
378 reg += HVMAXARCHITECTEDVIRTUALLANS;
379
380 for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
381 dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
382 "IBM,iSeries-viodasd", 1);
383 reg += HVMAXARCHITECTEDVIRTUALDISKS;
384
385 for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
386 dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
387 "IBM,iSeries-viocd", 1);
388 reg += HVMAXARCHITECTEDVIRTUALCDROMS;
389
390 for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
391 dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
392 "IBM,iSeries-viotape", 1);
393 376
394 dt_end_node(dt); 377 dt_end_node(dt);
395} 378}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3b6a9666c2c0..49e9c664ea89 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -28,14 +28,17 @@
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/list.h> 29#include <linux/list.h>
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/module.h>
31 32
32#include <asm/iommu.h> 33#include <asm/iommu.h>
34#include <asm/vio.h>
33#include <asm/tce.h> 35#include <asm/tce.h>
34#include <asm/machdep.h> 36#include <asm/machdep.h>
35#include <asm/abs_addr.h> 37#include <asm/abs_addr.h>
36#include <asm/prom.h> 38#include <asm/prom.h>
37#include <asm/pci-bridge.h> 39#include <asm/pci-bridge.h>
38#include <asm/iseries/hv_call_xm.h> 40#include <asm/iseries/hv_call_xm.h>
41#include <asm/iseries/hv_call_event.h>
39#include <asm/iseries/iommu.h> 42#include <asm/iseries/iommu.h>
40 43
41static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, 44static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
@@ -189,6 +192,55 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn)
189} 192}
190#endif 193#endif
191 194
195static struct iommu_table veth_iommu_table;
196static struct iommu_table vio_iommu_table;
197
198void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
199{
200 return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
201 DMA_32BIT_MASK, flag, -1);
202}
203EXPORT_SYMBOL_GPL(iseries_hv_alloc);
204
205void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
206{
207 iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
208}
209EXPORT_SYMBOL_GPL(iseries_hv_free);
210
211dma_addr_t iseries_hv_map(void *vaddr, size_t size,
212 enum dma_data_direction direction)
213{
214 return iommu_map_single(&vio_iommu_table, vaddr, size,
215 DMA_32BIT_MASK, direction);
216}
217
218void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
219 enum dma_data_direction direction)
220{
221 iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
222}
223
224void __init iommu_vio_init(void)
225{
226 iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
227 veth_iommu_table.it_size /= 2;
228 vio_iommu_table = veth_iommu_table;
229 vio_iommu_table.it_offset += veth_iommu_table.it_size;
230
231 if (!iommu_init_table(&veth_iommu_table, -1))
232 printk("Virtual Bus VETH TCE table failed.\n");
233 if (!iommu_init_table(&vio_iommu_table, -1))
234 printk("Virtual Bus VIO TCE table failed.\n");
235}
236
237struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
238{
239 if (strcmp(dev->type, "network") == 0)
240 return &veth_iommu_table;
241 return &vio_iommu_table;
242}
243
192void iommu_init_early_iSeries(void) 244void iommu_init_early_iSeries(void)
193{ 245{
194 ppc_md.tce_build = tce_build_iSeries; 246 ppc_md.tce_build = tce_build_iSeries;
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index b1187d95e3b2..c0f2433bc16e 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -39,9 +39,9 @@
39#include <asm/paca.h> 39#include <asm/paca.h>
40#include <asm/abs_addr.h> 40#include <asm/abs_addr.h>
41#include <asm/firmware.h> 41#include <asm/firmware.h>
42#include <asm/iseries/vio.h>
43#include <asm/iseries/mf.h> 42#include <asm/iseries/mf.h>
44#include <asm/iseries/hv_lp_config.h> 43#include <asm/iseries/hv_lp_config.h>
44#include <asm/iseries/hv_lp_event.h>
45#include <asm/iseries/it_lp_queue.h> 45#include <asm/iseries/it_lp_queue.h>
46 46
47#include "setup.h" 47#include "setup.h"
@@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
870 if ((off + count) > 256) 870 if ((off + count) > 256)
871 count = 256 - off; 871 count = 256 - off;
872 872
873 dma_addr = dma_map_single(iSeries_vio_dev, page, off + count, 873 dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
874 DMA_FROM_DEVICE);
875 if (dma_mapping_error(dma_addr)) 874 if (dma_mapping_error(dma_addr))
876 return -ENOMEM; 875 return -ENOMEM;
877 memset(page, 0, off + count); 876 memset(page, 0, off + count);
@@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
883 vsp_cmd.sub_data.kern.length = off + count; 882 vsp_cmd.sub_data.kern.length = off + count;
884 mb(); 883 mb();
885 rc = signal_vsp_instruction(&vsp_cmd); 884 rc = signal_vsp_instruction(&vsp_cmd);
886 dma_unmap_single(iSeries_vio_dev, dma_addr, off + count, 885 iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE);
887 DMA_FROM_DEVICE);
888 if (rc) 886 if (rc)
889 return rc; 887 return rc;
890 if (vsp_cmd.result_code != 0) 888 if (vsp_cmd.result_code != 0)
@@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
919 int len = *size; 917 int len = *size;
920 dma_addr_t dma_addr; 918 dma_addr_t dma_addr;
921 919
922 dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, 920 dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE);
923 DMA_FROM_DEVICE);
924 memset(buffer, 0, len); 921 memset(buffer, 0, len);
925 memset(&vsp_cmd, 0, sizeof(vsp_cmd)); 922 memset(&vsp_cmd, 0, sizeof(vsp_cmd));
926 vsp_cmd.cmd = 32; 923 vsp_cmd.cmd = 32;
@@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
938 rc = -ENOMEM; 935 rc = -ENOMEM;
939 } 936 }
940 937
941 dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); 938 iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE);
942 939
943 return rc; 940 return rc;
944} 941}
@@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
1149 goto out; 1146 goto out;
1150 1147
1151 dma_addr = 0; 1148 dma_addr = 0;
1152 page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, 1149 page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
1153 GFP_ATOMIC);
1154 ret = -ENOMEM; 1150 ret = -ENOMEM;
1155 if (page == NULL) 1151 if (page == NULL)
1156 goto out; 1152 goto out;
@@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
1170 ret = count; 1166 ret = count;
1171 1167
1172out_free: 1168out_free:
1173 dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); 1169 iseries_hv_free(count, page, dma_addr);
1174out: 1170out:
1175 return ret; 1171 return ret;
1176} 1172}
@@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
1190 goto out; 1186 goto out;
1191 1187
1192 dma_addr = 0; 1188 dma_addr = 0;
1193 page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, 1189 page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
1194 GFP_ATOMIC);
1195 rc = -ENOMEM; 1190 rc = -ENOMEM;
1196 if (page == NULL) { 1191 if (page == NULL) {
1197 printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); 1192 printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");
@@ -1219,7 +1214,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
1219 *ppos += count; 1214 *ppos += count;
1220 rc = count; 1215 rc = count;
1221out_free: 1216out_free:
1222 dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); 1217 iseries_hv_free(count, page, dma_addr);
1223out: 1218out:
1224 return rc; 1219 return rc;
1225} 1220}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
new file mode 100644
index 000000000000..910b00b4703e
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -0,0 +1,553 @@
1/*
2 * Legacy iSeries specific vio initialisation
3 * that needs to be built in (not a module).
4 *
5 * © Copyright 2007 IBM Corporation
6 * Author: Stephen Rothwell
7 * Some parts collected from various other files
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 as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#include <linux/of.h>
24#include <linux/init.h>
25#include <linux/gfp.h>
26#include <linux/completion.h>
27#include <linux/proc_fs.h>
28#include <linux/module.h>
29
30#include <asm/firmware.h>
31#include <asm/vio.h>
32#include <asm/iseries/vio.h>
33#include <asm/iseries/iommu.h>
34#include <asm/iseries/hv_types.h>
35#include <asm/iseries/hv_lp_event.h>
36
37#define FIRST_VTY 0
38#define NUM_VTYS 1
39#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
40#define NUM_VSCSIS 1
41#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
42#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
43#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
44#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
45#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
46#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
47#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
48#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
49
50struct vio_waitevent {
51 struct completion com;
52 int rc;
53 u16 sub_result;
54};
55
56struct vio_resource {
57 char rsrcname[10];
58 char type[4];
59 char model[3];
60};
61
62static struct property *new_property(const char *name, int length,
63 const void *value)
64{
65 struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
66 GFP_KERNEL);
67
68 if (!np)
69 return NULL;
70 np->name = (char *)(np + 1);
71 np->value = np->name + strlen(name) + 1;
72 strcpy(np->name, name);
73 memcpy(np->value, value, length);
74 np->length = length;
75 return np;
76}
77
78static void __init free_property(struct property *np)
79{
80 kfree(np);
81}
82
83static struct device_node *new_node(const char *path,
84 struct device_node *parent)
85{
86 struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
87
88 if (!np)
89 return NULL;
90 np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
91 if (!np->full_name) {
92 kfree(np);
93 return NULL;
94 }
95 strcpy(np->full_name, path);
96 of_node_set_flag(np, OF_DYNAMIC);
97 kref_init(&np->kref);
98 np->parent = of_node_get(parent);
99 return np;
100}
101
102static void free_node(struct device_node *np)
103{
104 struct property *next;
105 struct property *prop;
106
107 next = np->properties;
108 while (next) {
109 prop = next;
110 next = prop->next;
111 free_property(prop);
112 }
113 of_node_put(np->parent);
114 kfree(np->full_name);
115 kfree(np);
116}
117
118static int add_string_property(struct device_node *np, const char *name,
119 const char *value)
120{
121 struct property *nprop = new_property(name, strlen(value) + 1, value);
122
123 if (!nprop)
124 return 0;
125 prom_add_property(np, nprop);
126 return 1;
127}
128
129static int add_raw_property(struct device_node *np, const char *name,
130 int length, const void *value)
131{
132 struct property *nprop = new_property(name, length, value);
133
134 if (!nprop)
135 return 0;
136 prom_add_property(np, nprop);
137 return 1;
138}
139
140static struct device_node *do_device_node(struct device_node *parent,
141 const char *name, u32 reg, u32 unit, const char *type,
142 const char *compat, struct vio_resource *res)
143{
144 struct device_node *np;
145 char path[32];
146
147 snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
148 np = new_node(path, parent);
149 if (!np)
150 return NULL;
151 if (!add_string_property(np, "name", name) ||
152 !add_string_property(np, "device_type", type) ||
153 !add_string_property(np, "compatible", compat) ||
154 !add_raw_property(np, "reg", sizeof(reg), &reg) ||
155 !add_raw_property(np, "linux,unit_address",
156 sizeof(unit), &unit)) {
157 goto node_free;
158 }
159 if (res) {
160 if (!add_raw_property(np, "linux,vio_rsrcname",
161 sizeof(res->rsrcname), res->rsrcname) ||
162 !add_raw_property(np, "linux,vio_type",
163 sizeof(res->type), res->type) ||
164 !add_raw_property(np, "linux,vio_model",
165 sizeof(res->model), res->model))
166 goto node_free;
167 }
168 np->name = of_get_property(np, "name", NULL);
169 np->type = of_get_property(np, "device_type", NULL);
170 of_attach_node(np);
171#ifdef CONFIG_PROC_DEVICETREE
172 if (parent->pde) {
173 struct proc_dir_entry *ent;
174
175 ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
176 if (ent)
177 proc_device_tree_add_node(np, ent);
178 }
179#endif
180 return np;
181
182 node_free:
183 free_node(np);
184 return NULL;
185}
186
187/*
188 * This is here so that we can dynamically add viodasd
189 * devices without exposing all the above infrastructure.
190 */
191struct vio_dev *vio_create_viodasd(u32 unit)
192{
193 struct device_node *vio_root;
194 struct device_node *np;
195 struct vio_dev *vdev = NULL;
196
197 vio_root = of_find_node_by_path("/vdevice");
198 if (!vio_root)
199 return NULL;
200 np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
201 "block", "IBM,iSeries-viodasd", NULL);
202 of_node_put(vio_root);
203 if (np) {
204 vdev = vio_register_device_node(np);
205 if (!vdev)
206 free_node(np);
207 }
208 return vdev;
209}
210EXPORT_SYMBOL_GPL(vio_create_viodasd);
211
212static void __init handle_block_event(struct HvLpEvent *event)
213{
214 struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
215 struct vio_waitevent *pwe;
216
217 if (event == NULL)
218 /* Notification that a partition went away! */
219 return;
220 /* First, we should NEVER get an int here...only acks */
221 if (hvlpevent_is_int(event)) {
222 printk(KERN_WARNING "handle_viod_request: "
223 "Yikes! got an int in viodasd event handler!\n");
224 if (hvlpevent_need_ack(event)) {
225 event->xRc = HvLpEvent_Rc_InvalidSubtype;
226 HvCallEvent_ackLpEvent(event);
227 }
228 return;
229 }
230
231 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
232 case vioblockopen:
233 /*
234 * Handle a response to an open request. We get all the
235 * disk information in the response, so update it. The
236 * correlation token contains a pointer to a waitevent
237 * structure that has a completion in it. update the
238 * return code in the waitevent structure and post the
239 * completion to wake up the guy who sent the request
240 */
241 pwe = (struct vio_waitevent *)event->xCorrelationToken;
242 pwe->rc = event->xRc;
243 pwe->sub_result = bevent->sub_result;
244 complete(&pwe->com);
245 break;
246 case vioblockclose:
247 break;
248 default:
249 printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
250 if (hvlpevent_need_ack(event)) {
251 event->xRc = HvLpEvent_Rc_InvalidSubtype;
252 HvCallEvent_ackLpEvent(event);
253 }
254 }
255}
256
257static void __init probe_disk(struct device_node *vio_root, u32 unit)
258{
259 HvLpEvent_Rc hvrc;
260 struct vio_waitevent we;
261 u16 flags = 0;
262
263retry:
264 init_completion(&we.com);
265
266 /* Send the open event to OS/400 */
267 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
268 HvLpEvent_Type_VirtualIo,
269 viomajorsubtype_blockio | vioblockopen,
270 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
271 viopath_sourceinst(viopath_hostLp),
272 viopath_targetinst(viopath_hostLp),
273 (u64)(unsigned long)&we, VIOVERSION << 16,
274 ((u64)unit << 48) | ((u64)flags<< 32),
275 0, 0, 0);
276 if (hvrc != 0) {
277 printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
278 (int)hvrc);
279 return;
280 }
281
282 wait_for_completion(&we.com);
283
284 if (we.rc != 0) {
285 if (flags != 0)
286 return;
287 /* try again with read only flag set */
288 flags = vioblockflags_ro;
289 goto retry;
290 }
291
292 /* Send the close event to OS/400. We DON'T expect a response */
293 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
294 HvLpEvent_Type_VirtualIo,
295 viomajorsubtype_blockio | vioblockclose,
296 HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
297 viopath_sourceinst(viopath_hostLp),
298 viopath_targetinst(viopath_hostLp),
299 0, VIOVERSION << 16,
300 ((u64)unit << 48) | ((u64)flags << 32),
301 0, 0, 0);
302 if (hvrc != 0) {
303 printk(KERN_WARNING "probe_disk: "
304 "bad rc sending event to OS/400 %d\n", (int)hvrc);
305 return;
306 }
307
308 do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
309 "block", "IBM,iSeries-viodasd", NULL);
310}
311
312static void __init get_viodasd_info(struct device_node *vio_root)
313{
314 int rc;
315 u32 unit;
316
317 rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
318 if (rc) {
319 printk(KERN_WARNING "get_viodasd_info: "
320 "error opening path to host partition %d\n",
321 viopath_hostLp);
322 return;
323 }
324
325 /* Initialize our request handler */
326 vio_setHandler(viomajorsubtype_blockio, handle_block_event);
327
328 for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
329 probe_disk(vio_root, unit);
330
331 vio_clearHandler(viomajorsubtype_blockio);
332 viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
333}
334
335static void __init handle_cd_event(struct HvLpEvent *event)
336{
337 struct viocdlpevent *bevent;
338 struct vio_waitevent *pwe;
339
340 if (!event)
341 /* Notification that a partition went away! */
342 return;
343
344 /* First, we should NEVER get an int here...only acks */
345 if (hvlpevent_is_int(event)) {
346 printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
347 if (hvlpevent_need_ack(event)) {
348 event->xRc = HvLpEvent_Rc_InvalidSubtype;
349 HvCallEvent_ackLpEvent(event);
350 }
351 return;
352 }
353
354 bevent = (struct viocdlpevent *)event;
355
356 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
357 case viocdgetinfo:
358 pwe = (struct vio_waitevent *)event->xCorrelationToken;
359 pwe->rc = event->xRc;
360 pwe->sub_result = bevent->sub_result;
361 complete(&pwe->com);
362 break;
363
364 default:
365 printk(KERN_WARNING "handle_cd_event: "
366 "message with unexpected subtype %0x04X!\n",
367 event->xSubtype & VIOMINOR_SUBTYPE_MASK);
368 if (hvlpevent_need_ack(event)) {
369 event->xRc = HvLpEvent_Rc_InvalidSubtype;
370 HvCallEvent_ackLpEvent(event);
371 }
372 }
373}
374
375static void __init get_viocd_info(struct device_node *vio_root)
376{
377 HvLpEvent_Rc hvrc;
378 u32 unit;
379 struct vio_waitevent we;
380 struct vio_resource *unitinfo;
381 dma_addr_t unitinfo_dmaaddr;
382 int ret;
383
384 ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
385 if (ret) {
386 printk(KERN_WARNING
387 "get_viocd_info: error opening path to host partition %d\n",
388 viopath_hostLp);
389 return;
390 }
391
392 /* Initialize our request handler */
393 vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
394
395 unitinfo = iseries_hv_alloc(
396 sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
397 &unitinfo_dmaaddr, GFP_ATOMIC);
398 if (!unitinfo) {
399 printk(KERN_WARNING
400 "get_viocd_info: error allocating unitinfo\n");
401 goto clear_handler;
402 }
403
404 memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
405
406 init_completion(&we.com);
407
408 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
409 HvLpEvent_Type_VirtualIo,
410 viomajorsubtype_cdio | viocdgetinfo,
411 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
412 viopath_sourceinst(viopath_hostLp),
413 viopath_targetinst(viopath_hostLp),
414 (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
415 sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
416 if (hvrc != HvLpEvent_Rc_Good) {
417 printk(KERN_WARNING
418 "get_viocd_info: cdrom error sending event. rc %d\n",
419 (int)hvrc);
420 goto hv_free;
421 }
422
423 wait_for_completion(&we.com);
424
425 if (we.rc) {
426 printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
427 we.rc, we.sub_result);
428 goto hv_free;
429 }
430
431 for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
432 unitinfo[unit].rsrcname[0]; unit++) {
433 if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
434 "block", "IBM,iSeries-viocd", &unitinfo[unit]))
435 break;
436 }
437
438 hv_free:
439 iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
440 unitinfo, unitinfo_dmaaddr);
441 clear_handler:
442 vio_clearHandler(viomajorsubtype_cdio);
443 viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
444}
445
446/* Handle interrupt events for tape */
447static void __init handle_tape_event(struct HvLpEvent *event)
448{
449 struct vio_waitevent *we;
450 struct viotapelpevent *tevent = (struct viotapelpevent *)event;
451
452 if (event == NULL)
453 /* Notification that a partition went away! */
454 return;
455
456 we = (struct vio_waitevent *)event->xCorrelationToken;
457 switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
458 case viotapegetinfo:
459 we->rc = tevent->sub_type_result;
460 complete(&we->com);
461 break;
462 default:
463 printk(KERN_WARNING "handle_tape_event: weird ack\n");
464 }
465}
466
467static void __init get_viotape_info(struct device_node *vio_root)
468{
469 HvLpEvent_Rc hvrc;
470 u32 unit;
471 struct vio_resource *unitinfo;
472 dma_addr_t unitinfo_dmaaddr;
473 size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
474 struct vio_waitevent we;
475 int ret;
476
477 ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
478 if (ret) {
479 printk(KERN_WARNING "get_viotape_info: "
480 "error on viopath_open to hostlp %d\n", ret);
481 return;
482 }
483
484 vio_setHandler(viomajorsubtype_tape, handle_tape_event);
485
486 unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
487 if (!unitinfo)
488 goto clear_handler;
489
490 memset(unitinfo, 0, len);
491
492 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
493 HvLpEvent_Type_VirtualIo,
494 viomajorsubtype_tape | viotapegetinfo,
495 HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
496 viopath_sourceinst(viopath_hostLp),
497 viopath_targetinst(viopath_hostLp),
498 (u64)(unsigned long)&we, VIOVERSION << 16,
499 unitinfo_dmaaddr, len, 0, 0);
500 if (hvrc != HvLpEvent_Rc_Good) {
501 printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
502 (int)hvrc);
503 goto hv_free;
504 }
505
506 wait_for_completion(&we.com);
507
508 for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
509 unitinfo[unit].rsrcname[0]; unit++) {
510 if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
511 unit, "byte", "IBM,iSeries-viotape",
512 &unitinfo[unit]))
513 break;
514 }
515
516 hv_free:
517 iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
518 clear_handler:
519 vio_clearHandler(viomajorsubtype_tape);
520 viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
521}
522
523static int __init iseries_vio_init(void)
524{
525 struct device_node *vio_root;
526
527 if (!firmware_has_feature(FW_FEATURE_ISERIES))
528 return -ENODEV;
529
530 iommu_vio_init();
531
532 vio_root = of_find_node_by_path("/vdevice");
533 if (!vio_root)
534 return -ENODEV;
535
536 if (viopath_hostLp == HvLpIndexInvalid) {
537 vio_set_hostlp();
538 /* If we don't have a host, bail out */
539 if (viopath_hostLp == HvLpIndexInvalid)
540 goto put_node;
541 }
542
543 get_viodasd_info(vio_root);
544 get_viocd_info(vio_root);
545 get_viotape_info(vio_root);
546
547 return 0;
548
549 put_node:
550 of_node_put(vio_root);
551 return -ENODEV;
552}
553arch_initcall(iseries_vio_init);
diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c
index 6a0060a5f2ec..df23331eb25c 100644
--- a/arch/powerpc/platforms/iseries/viopath.c
+++ b/arch/powerpc/platforms/iseries/viopath.c
@@ -124,8 +124,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
124 if (!buf) 124 if (!buf)
125 return 0; 125 return 0;
126 126
127 handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, 127 handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE);
128 DMA_FROM_DEVICE);
129 128
130 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, 129 hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
131 HvLpEvent_Type_VirtualIo, 130 HvLpEvent_Type_VirtualIo,
@@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
146 buf[HW_PAGE_SIZE-1] = '\0'; 145 buf[HW_PAGE_SIZE-1] = '\0';
147 seq_printf(m, "%s", buf); 146 seq_printf(m, "%s", buf);
148 147
149 dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE, 148 iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE);
150 DMA_FROM_DEVICE);
151 kfree(buf); 149 kfree(buf);
152 150
153 seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); 151 seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
@@ -596,7 +594,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
596 numOpen += viopathStatus[remoteLp].users[i]; 594 numOpen += viopathStatus[remoteLp].users[i];
597 595
598 if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { 596 if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
599 printk(VIOPATH_KERN_INFO "closing connection to partition %d", 597 printk(VIOPATH_KERN_INFO "closing connection to partition %d\n",
600 remoteLp); 598 remoteLp);
601 599
602 HvCallEvent_closeLpEventPath(remoteLp, 600 HvCallEvent_closeLpEventPath(remoteLp,
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index c91a33593bb8..dae9f658122e 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -320,10 +320,12 @@ static struct of_device_id gpio_mdio_match[] =
320 320
321static struct of_platform_driver gpio_mdio_driver = 321static struct of_platform_driver gpio_mdio_driver =
322{ 322{
323 .name = "gpio-mdio-bitbang",
324 .match_table = gpio_mdio_match, 323 .match_table = gpio_mdio_match,
325 .probe = gpio_mdio_probe, 324 .probe = gpio_mdio_probe,
326 .remove = gpio_mdio_remove, 325 .remove = gpio_mdio_remove,
326 .driver = {
327 .name = "gpio-mdio-bitbang",
328 },
327}; 329};
328 330
329int gpio_mdio_init(void) 331int gpio_mdio_init(void)
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 7ccb9236e8b4..02c533096627 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -387,69 +387,13 @@ static void __init pmac_setup_arch(void)
387#endif /* CONFIG_ADB */ 387#endif /* CONFIG_ADB */
388} 388}
389 389
390char *bootpath;
391char *bootdevice;
392void *boot_host;
393int boot_target;
394int boot_part;
395static dev_t boot_dev;
396
397#ifdef CONFIG_SCSI 390#ifdef CONFIG_SCSI
398void note_scsi_host(struct device_node *node, void *host) 391void note_scsi_host(struct device_node *node, void *host)
399{ 392{
400 int l;
401 char *p;
402
403 l = strlen(node->full_name);
404 if (bootpath != NULL && bootdevice != NULL
405 && strncmp(node->full_name, bootdevice, l) == 0
406 && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
407 boot_host = host;
408 /*
409 * There's a bug in OF 1.0.5. (Why am I not surprised.)
410 * If you pass a path like scsi/sd@1:0 to canon, it returns
411 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
412 * That is, the scsi target number doesn't get preserved.
413 * So we pick the target number out of bootpath and use that.
414 */
415 p = strstr(bootpath, "/sd@");
416 if (p != NULL) {
417 p += 4;
418 boot_target = simple_strtoul(p, NULL, 10);
419 p = strchr(p, ':');
420 if (p != NULL)
421 boot_part = simple_strtoul(p + 1, NULL, 10);
422 }
423 }
424} 393}
425EXPORT_SYMBOL(note_scsi_host); 394EXPORT_SYMBOL(note_scsi_host);
426#endif 395#endif
427 396
428#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
429static dev_t __init find_ide_boot(void)
430{
431 char *p;
432 int n;
433 dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
434
435 if (bootdevice == NULL)
436 return 0;
437 p = strrchr(bootdevice, '/');
438 if (p == NULL)
439 return 0;
440 n = p - bootdevice;
441
442 return pmac_find_ide_boot(bootdevice, n);
443}
444#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
445
446static void __init find_boot_device(void)
447{
448#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
449 boot_dev = find_ide_boot();
450#endif
451}
452
453static int initializing = 1; 397static int initializing = 1;
454 398
455static int pmac_late_init(void) 399static int pmac_late_init(void)
@@ -466,10 +410,14 @@ static int pmac_late_init(void)
466 410
467late_initcall(pmac_late_init); 411late_initcall(pmac_late_init);
468 412
469/* can't be __init - can be called whenever a disk is first accessed */ 413/*
470void note_bootable_part(dev_t dev, int part, int goodness) 414 * This is __init_refok because we check for "initializing" before
415 * touching any of the __init sensitive things and "initializing"
416 * will be false after __init time. This can't be __init because it
417 * can be called whenever a disk is first accessed.
418 */
419void __init_refok note_bootable_part(dev_t dev, int part, int goodness)
471{ 420{
472 static int found_boot = 0;
473 char *p; 421 char *p;
474 422
475 if (!initializing) 423 if (!initializing)
@@ -481,15 +429,8 @@ void note_bootable_part(dev_t dev, int part, int goodness)
481 if (p != NULL && (p == boot_command_line || p[-1] == ' ')) 429 if (p != NULL && (p == boot_command_line || p[-1] == ' '))
482 return; 430 return;
483 431
484 if (!found_boot) { 432 ROOT_DEV = dev + part;
485 find_boot_device(); 433 current_root_goodness = goodness;
486 found_boot = 1;
487 }
488 if (!boot_dev || dev == boot_dev) {
489 ROOT_DEV = dev + part;
490 boot_dev = 0;
491 current_root_goodness = goodness;
492 }
493} 434}
494 435
495#ifdef CONFIG_ADB_CUDA 436#ifdef CONFIG_ADB_CUDA
diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c
index b70e474014f0..766685ab26f8 100644
--- a/arch/powerpc/platforms/ps3/os-area.c
+++ b/arch/powerpc/platforms/ps3/os-area.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * PS3 'Other OS' area data. 2 * PS3 flash memory os area.
3 * 3 *
4 * Copyright (C) 2006 Sony Computer Entertainment Inc. 4 * Copyright (C) 2006 Sony Computer Entertainment Inc.
5 * Copyright 2006 Sony Corp. 5 * Copyright 2006 Sony Corp.
@@ -20,6 +20,9 @@
20 20
21#include <linux/kernel.h> 21#include <linux/kernel.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/workqueue.h>
24#include <linux/fs.h>
25#include <linux/syscalls.h>
23 26
24#include <asm/lmb.h> 27#include <asm/lmb.h>
25 28
@@ -29,7 +32,7 @@ enum {
29 OS_AREA_SEGMENT_SIZE = 0X200, 32 OS_AREA_SEGMENT_SIZE = 0X200,
30}; 33};
31 34
32enum { 35enum os_area_ldr_format {
33 HEADER_LDR_FORMAT_RAW = 0, 36 HEADER_LDR_FORMAT_RAW = 0,
34 HEADER_LDR_FORMAT_GZIP = 1, 37 HEADER_LDR_FORMAT_GZIP = 1,
35}; 38};
@@ -38,7 +41,7 @@ enum {
38 * struct os_area_header - os area header segment. 41 * struct os_area_header - os area header segment.
39 * @magic_num: Always 'cell_ext_os_area'. 42 * @magic_num: Always 'cell_ext_os_area'.
40 * @hdr_version: Header format version number. 43 * @hdr_version: Header format version number.
41 * @os_area_offset: Starting segment number of os image area. 44 * @db_area_offset: Starting segment number of other os database area.
42 * @ldr_area_offset: Starting segment number of bootloader image area. 45 * @ldr_area_offset: Starting segment number of bootloader image area.
43 * @ldr_format: HEADER_LDR_FORMAT flag. 46 * @ldr_format: HEADER_LDR_FORMAT flag.
44 * @ldr_size: Size of bootloader image in bytes. 47 * @ldr_size: Size of bootloader image in bytes.
@@ -50,9 +53,9 @@ enum {
50 */ 53 */
51 54
52struct os_area_header { 55struct os_area_header {
53 s8 magic_num[16]; 56 u8 magic_num[16];
54 u32 hdr_version; 57 u32 hdr_version;
55 u32 os_area_offset; 58 u32 db_area_offset;
56 u32 ldr_area_offset; 59 u32 ldr_area_offset;
57 u32 _reserved_1; 60 u32 _reserved_1;
58 u32 ldr_format; 61 u32 ldr_format;
@@ -60,12 +63,12 @@ struct os_area_header {
60 u32 _reserved_2[6]; 63 u32 _reserved_2[6];
61}; 64};
62 65
63enum { 66enum os_area_boot_flag {
64 PARAM_BOOT_FLAG_GAME_OS = 0, 67 PARAM_BOOT_FLAG_GAME_OS = 0,
65 PARAM_BOOT_FLAG_OTHER_OS = 1, 68 PARAM_BOOT_FLAG_OTHER_OS = 1,
66}; 69};
67 70
68enum { 71enum os_area_ctrl_button {
69 PARAM_CTRL_BUTTON_O_IS_YES = 0, 72 PARAM_CTRL_BUTTON_O_IS_YES = 0,
70 PARAM_CTRL_BUTTON_X_IS_YES = 1, 73 PARAM_CTRL_BUTTON_X_IS_YES = 1,
71}; 74};
@@ -84,6 +87,9 @@ enum {
84 * @dns_primary: User preference of static primary dns server. 87 * @dns_primary: User preference of static primary dns server.
85 * @dns_secondary: User preference of static secondary dns server. 88 * @dns_secondary: User preference of static secondary dns server.
86 * 89 *
90 * The ps3 rtc maintains a read-only value that approximates seconds since
91 * 2000-01-01 00:00:00 UTC.
92 *
87 * User preference of zero for static_ip_addr means use dhcp. 93 * User preference of zero for static_ip_addr means use dhcp.
88 */ 94 */
89 95
@@ -108,45 +114,172 @@ struct os_area_params {
108 u8 _reserved_5[8]; 114 u8 _reserved_5[8];
109}; 115};
110 116
117enum {
118 OS_AREA_DB_MAGIC_NUM = 0x2d64622dU,
119};
120
111/** 121/**
112 * struct saved_params - Static working copies of data from the 'Other OS' area. 122 * struct os_area_db - Shared flash memory database.
123 * @magic_num: Always '-db-' = 0x2d64622d.
124 * @version: os_area_db format version number.
125 * @index_64: byte offset of the database id index for 64 bit variables.
126 * @count_64: number of usable 64 bit index entries
127 * @index_32: byte offset of the database id index for 32 bit variables.
128 * @count_32: number of usable 32 bit index entries
129 * @index_16: byte offset of the database id index for 16 bit variables.
130 * @count_16: number of usable 16 bit index entries
113 * 131 *
114 * For the convinience of the guest, the HV makes a copy of the 'Other OS' area 132 * Flash rom storage for exclusive use by guests running in the other os lpar.
115 * in flash to a high address in the boot memory region and then puts that RAM 133 * The current system configuration allocates 1K (two segments) for other os
116 * address and the byte count into the repository for retreval by the guest. 134 * use.
117 * We copy the data we want into a static variable and allow the memory setup 135 */
118 * by the HV to be claimed by the lmb manager. 136
137struct os_area_db {
138 u32 magic_num;
139 u16 version;
140 u16 _reserved_1;
141 u16 index_64;
142 u16 count_64;
143 u16 index_32;
144 u16 count_32;
145 u16 index_16;
146 u16 count_16;
147 u32 _reserved_2;
148 u8 _db_data[1000];
149};
150
151/**
152 * enum os_area_db_owner - Data owners.
153 */
154
155enum os_area_db_owner {
156 OS_AREA_DB_OWNER_ANY = -1,
157 OS_AREA_DB_OWNER_NONE = 0,
158 OS_AREA_DB_OWNER_PROTOTYPE = 1,
159 OS_AREA_DB_OWNER_LINUX = 2,
160 OS_AREA_DB_OWNER_PETITBOOT = 3,
161 OS_AREA_DB_OWNER_MAX = 32,
162};
163
164enum os_area_db_key {
165 OS_AREA_DB_KEY_ANY = -1,
166 OS_AREA_DB_KEY_NONE = 0,
167 OS_AREA_DB_KEY_RTC_DIFF = 1,
168 OS_AREA_DB_KEY_VIDEO_MODE = 2,
169 OS_AREA_DB_KEY_MAX = 8,
170};
171
172struct os_area_db_id {
173 int owner;
174 int key;
175};
176
177static const struct os_area_db_id os_area_db_id_empty = {
178 .owner = OS_AREA_DB_OWNER_NONE,
179 .key = OS_AREA_DB_KEY_NONE
180};
181
182static const struct os_area_db_id os_area_db_id_any = {
183 .owner = OS_AREA_DB_OWNER_ANY,
184 .key = OS_AREA_DB_KEY_ANY
185};
186
187static const struct os_area_db_id os_area_db_id_rtc_diff = {
188 .owner = OS_AREA_DB_OWNER_LINUX,
189 .key = OS_AREA_DB_KEY_RTC_DIFF
190};
191
192static const struct os_area_db_id os_area_db_id_video_mode = {
193 .owner = OS_AREA_DB_OWNER_LINUX,
194 .key = OS_AREA_DB_KEY_VIDEO_MODE
195};
196
197#define SECONDS_FROM_1970_TO_2000 946684800LL
198
199/**
200 * struct saved_params - Static working copies of data from the PS3 'os area'.
201 *
202 * The order of preference we use for the rtc_diff source:
203 * 1) The database value.
204 * 2) The game os value.
205 * 3) The number of seconds from 1970 to 2000.
119 */ 206 */
120 207
121struct saved_params { 208struct saved_params {
122 /* param 0 */ 209 unsigned int valid;
123 s64 rtc_diff; 210 s64 rtc_diff;
124 unsigned int av_multi_out; 211 unsigned int av_multi_out;
125 unsigned int ctrl_button;
126 /* param 1 */
127 u8 static_ip_addr[4];
128 u8 network_mask[4];
129 u8 default_gateway[4];
130 /* param 2 */
131 u8 dns_primary[4];
132 u8 dns_secondary[4];
133} static saved_params; 212} static saved_params;
134 213
214static struct property property_rtc_diff = {
215 .name = "linux,rtc_diff",
216 .length = sizeof(saved_params.rtc_diff),
217 .value = &saved_params.rtc_diff,
218};
219
220static struct property property_av_multi_out = {
221 .name = "linux,av_multi_out",
222 .length = sizeof(saved_params.av_multi_out),
223 .value = &saved_params.av_multi_out,
224};
225
226/**
227 * os_area_set_property - Add or overwrite a saved_params value to the device tree.
228 *
229 * Overwrites an existing property.
230 */
231
232static void os_area_set_property(struct device_node *node,
233 struct property *prop)
234{
235 int result;
236 struct property *tmp = of_find_property(node, prop->name, NULL);
237
238 if (tmp) {
239 pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
240 prom_remove_property(node, tmp);
241 }
242
243 result = prom_add_property(node, prop);
244
245 if (result)
246 pr_debug("%s:%d prom_set_property failed\n", __func__,
247 __LINE__);
248}
249
250/**
251 * os_area_get_property - Get a saved_params value from the device tree.
252 *
253 */
254
255static void __init os_area_get_property(struct device_node *node,
256 struct property *prop)
257{
258 const struct property *tmp = of_find_property(node, prop->name, NULL);
259
260 if (tmp) {
261 BUG_ON(prop->length != tmp->length);
262 memcpy(prop->value, tmp->value, prop->length);
263 } else
264 pr_debug("%s:%d not found %s\n", __func__, __LINE__,
265 prop->name);
266}
267
135#define dump_header(_a) _dump_header(_a, __func__, __LINE__) 268#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
136static void _dump_header(const struct os_area_header *h, const char *func, 269static void _dump_header(const struct os_area_header *h, const char *func,
137 int line) 270 int line)
138{ 271{
139 pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, 272 pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
140 h->magic_num); 273 h->magic_num);
141 pr_debug("%s:%d: h.hdr_version: %u\n", func, line, 274 pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
142 h->hdr_version); 275 h->hdr_version);
143 pr_debug("%s:%d: h.os_area_offset: %u\n", func, line, 276 pr_debug("%s:%d: h.db_area_offset: %u\n", func, line,
144 h->os_area_offset); 277 h->db_area_offset);
145 pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line, 278 pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
146 h->ldr_area_offset); 279 h->ldr_area_offset);
147 pr_debug("%s:%d: h.ldr_format: %u\n", func, line, 280 pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
148 h->ldr_format); 281 h->ldr_format);
149 pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, 282 pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
150 h->ldr_size); 283 h->ldr_size);
151} 284}
152 285
@@ -176,7 +309,7 @@ static void _dump_params(const struct os_area_params *p, const char *func,
176 p->dns_secondary[2], p->dns_secondary[3]); 309 p->dns_secondary[2], p->dns_secondary[3]);
177} 310}
178 311
179static int __init verify_header(const struct os_area_header *header) 312static int verify_header(const struct os_area_header *header)
180{ 313{
181 if (memcmp(header->magic_num, "cell_ext_os_area", 16)) { 314 if (memcmp(header->magic_num, "cell_ext_os_area", 16)) {
182 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); 315 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
@@ -188,7 +321,7 @@ static int __init verify_header(const struct os_area_header *header)
188 return -1; 321 return -1;
189 } 322 }
190 323
191 if (header->os_area_offset > header->ldr_area_offset) { 324 if (header->db_area_offset > header->ldr_area_offset) {
192 pr_debug("%s:%d offsets failed\n", __func__, __LINE__); 325 pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
193 return -1; 326 return -1;
194 } 327 }
@@ -196,58 +329,477 @@ static int __init verify_header(const struct os_area_header *header)
196 return 0; 329 return 0;
197} 330}
198 331
199int __init ps3_os_area_init(void) 332static int db_verify(const struct os_area_db *db)
333{
334 if (db->magic_num != OS_AREA_DB_MAGIC_NUM) {
335 pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
336 return -1;
337 }
338
339 if (db->version != 1) {
340 pr_debug("%s:%d version failed\n", __func__, __LINE__);
341 return -1;
342 }
343
344 return 0;
345}
346
347struct db_index {
348 uint8_t owner:5;
349 uint8_t key:3;
350};
351
352struct db_iterator {
353 const struct os_area_db *db;
354 struct os_area_db_id match_id;
355 struct db_index *idx;
356 struct db_index *last_idx;
357 union {
358 uint64_t *value_64;
359 uint32_t *value_32;
360 uint16_t *value_16;
361 };
362};
363
364static unsigned int db_align_up(unsigned int val, unsigned int size)
365{
366 return (val + (size - 1)) & (~(size - 1));
367}
368
369/**
370 * db_for_each_64 - Iterator for 64 bit entries.
371 *
372 * A NULL value for id can be used to match all entries.
373 * OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all.
374 */
375
376static int db_for_each_64(const struct os_area_db *db,
377 const struct os_area_db_id *match_id, struct db_iterator *i)
378{
379next:
380 if (!i->db) {
381 i->db = db;
382 i->match_id = match_id ? *match_id : os_area_db_id_any;
383 i->idx = (void *)db + db->index_64;
384 i->last_idx = i->idx + db->count_64;
385 i->value_64 = (void *)db + db->index_64
386 + db_align_up(db->count_64, 8);
387 } else {
388 i->idx++;
389 i->value_64++;
390 }
391
392 if (i->idx >= i->last_idx) {
393 pr_debug("%s:%d: reached end\n", __func__, __LINE__);
394 return 0;
395 }
396
397 if (i->match_id.owner != OS_AREA_DB_OWNER_ANY
398 && i->match_id.owner != (int)i->idx->owner)
399 goto next;
400 if (i->match_id.key != OS_AREA_DB_KEY_ANY
401 && i->match_id.key != (int)i->idx->key)
402 goto next;
403
404 return 1;
405}
406
407static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id)
408{
409 struct db_iterator i;
410
411 for (i.db = NULL; db_for_each_64(db, id, &i); ) {
412
413 pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
414 i.idx->owner, i.idx->key,
415 (unsigned long long)*i.value_64);
416
417 i.idx->owner = 0;
418 i.idx->key = 0;
419 *i.value_64 = 0;
420 }
421 return 0;
422}
423
424static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,
425 uint64_t value)
426{
427 struct db_iterator i;
428
429 pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,
430 id->owner, id->key, (unsigned long long)value);
431
432 if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY
433 || id->key == OS_AREA_DB_KEY_ANY) {
434 pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,
435 __LINE__, id->owner, id->key);
436 return -1;
437 }
438
439 db_delete_64(db, id);
440
441 i.db = NULL;
442 if (db_for_each_64(db, &os_area_db_id_empty, &i)) {
443
444 pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
445 i.idx->owner, i.idx->key,
446 (unsigned long long)*i.value_64);
447
448 i.idx->owner = id->owner;
449 i.idx->key = id->key;
450 *i.value_64 = value;
451
452 pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,
453 i.idx->owner, i.idx->key,
454 (unsigned long long)*i.value_64);
455 return 0;
456 }
457 pr_debug("%s:%d: database full.\n",
458 __func__, __LINE__);
459 return -1;
460}
461
462static int db_get_64(const struct os_area_db *db,
463 const struct os_area_db_id *id, uint64_t *value)
464{
465 struct db_iterator i;
466
467 i.db = NULL;
468 if (db_for_each_64(db, id, &i)) {
469 *value = *i.value_64;
470 pr_debug("%s:%d: found %lld\n", __func__, __LINE__,
471 (long long int)*i.value_64);
472 return 0;
473 }
474 pr_debug("%s:%d: not found\n", __func__, __LINE__);
475 return -1;
476}
477
478static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff)
479{
480 return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);
481}
482
483#define dump_db(a) _dump_db(a, __func__, __LINE__)
484static void _dump_db(const struct os_area_db *db, const char *func,
485 int line)
486{
487 pr_debug("%s:%d: db.magic_num: '%s'\n", func, line,
488 (const char*)&db->magic_num);
489 pr_debug("%s:%d: db.version: %u\n", func, line,
490 db->version);
491 pr_debug("%s:%d: db.index_64: %u\n", func, line,
492 db->index_64);
493 pr_debug("%s:%d: db.count_64: %u\n", func, line,
494 db->count_64);
495 pr_debug("%s:%d: db.index_32: %u\n", func, line,
496 db->index_32);
497 pr_debug("%s:%d: db.count_32: %u\n", func, line,
498 db->count_32);
499 pr_debug("%s:%d: db.index_16: %u\n", func, line,
500 db->index_16);
501 pr_debug("%s:%d: db.count_16: %u\n", func, line,
502 db->count_16);
503}
504
505static void os_area_db_init(struct os_area_db *db)
506{
507 enum {
508 HEADER_SIZE = offsetof(struct os_area_db, _db_data),
509 INDEX_64_COUNT = 64,
510 VALUES_64_COUNT = 57,
511 INDEX_32_COUNT = 64,
512 VALUES_32_COUNT = 57,
513 INDEX_16_COUNT = 64,
514 VALUES_16_COUNT = 57,
515 };
516
517 memset(db, 0, sizeof(struct os_area_db));
518
519 db->magic_num = OS_AREA_DB_MAGIC_NUM;
520 db->version = 1;
521 db->index_64 = HEADER_SIZE;
522 db->count_64 = VALUES_64_COUNT;
523 db->index_32 = HEADER_SIZE
524 + INDEX_64_COUNT * sizeof(struct db_index)
525 + VALUES_64_COUNT * sizeof(u64);
526 db->count_32 = VALUES_32_COUNT;
527 db->index_16 = HEADER_SIZE
528 + INDEX_64_COUNT * sizeof(struct db_index)
529 + VALUES_64_COUNT * sizeof(u64)
530 + INDEX_32_COUNT * sizeof(struct db_index)
531 + VALUES_32_COUNT * sizeof(u32);
532 db->count_16 = VALUES_16_COUNT;
533
534 /* Rules to check db layout. */
535
536 BUILD_BUG_ON(sizeof(struct db_index) != 1);
537 BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);
538 BUILD_BUG_ON(INDEX_64_COUNT & 0x7);
539 BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);
540 BUILD_BUG_ON(INDEX_32_COUNT & 0x7);
541 BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);
542 BUILD_BUG_ON(INDEX_16_COUNT & 0x7);
543 BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);
544 BUILD_BUG_ON(HEADER_SIZE
545 + INDEX_64_COUNT * sizeof(struct db_index)
546 + VALUES_64_COUNT * sizeof(u64)
547 + INDEX_32_COUNT * sizeof(struct db_index)
548 + VALUES_32_COUNT * sizeof(u32)
549 + INDEX_16_COUNT * sizeof(struct db_index)
550 + VALUES_16_COUNT * sizeof(u16)
551 > sizeof(struct os_area_db));
552}
553
554/**
555 * update_flash_db - Helper for os_area_queue_work_handler.
556 *
557 */
558
559static void update_flash_db(void)
560{
561 int result;
562 int file;
563 off_t offset;
564 ssize_t count;
565 static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
566 const struct os_area_header *header;
567 struct os_area_db* db;
568
569 /* Read in header and db from flash. */
570
571 file = sys_open("/dev/ps3flash", O_RDWR, 0);
572
573 if (file < 0) {
574 pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
575 goto fail_open;
576 }
577
578 header = kmalloc(buf_len, GFP_KERNEL);
579
580 if (!header) {
581 pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
582 goto fail_malloc;
583 }
584
585 offset = sys_lseek(file, 0, SEEK_SET);
586
587 if (offset != 0) {
588 pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
589 goto fail_header_seek;
590 }
591
592 count = sys_read(file, (char __user *)header, buf_len);
593
594 result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
595 || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
596
597 if (result) {
598 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
599 dump_header(header);
600 goto fail_header;
601 }
602
603 /* Now got a good db offset and some maybe good db data. */
604
605 db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
606
607 result = db_verify(db);
608
609 if (result) {
610 printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
611 "formatting.\n", __func__, __LINE__);
612 dump_db(db);
613 os_area_db_init(db);
614 }
615
616 /* Now got good db data. */
617
618 db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
619
620 offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
621 SEEK_SET);
622
623 if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
624 pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
625 goto fail_db_seek;
626 }
627
628 count = sys_write(file, (const char __user *)db,
629 sizeof(struct os_area_db));
630
631 if (count < sizeof(struct os_area_db)) {
632 pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
633 }
634
635fail_db_seek:
636fail_header:
637fail_header_seek:
638 kfree(header);
639fail_malloc:
640 sys_close(file);
641fail_open:
642 return;
643}
644
645/**
646 * os_area_queue_work_handler - Asynchronous write handler.
647 *
648 * An asynchronous write for flash memory and the device tree. Do not
649 * call directly, use os_area_queue_work().
650 */
651
652static void os_area_queue_work_handler(struct work_struct *work)
653{
654 struct device_node *node;
655
656 pr_debug(" -> %s:%d\n", __func__, __LINE__);
657
658 node = of_find_node_by_path("/");
659
660 if (node) {
661 os_area_set_property(node, &property_rtc_diff);
662 of_node_put(node);
663 } else
664 pr_debug("%s:%d of_find_node_by_path failed\n",
665 __func__, __LINE__);
666
667#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
668 update_flash_db();
669#else
670 printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
671 __func__, __LINE__);
672#endif
673 pr_debug(" <- %s:%d\n", __func__, __LINE__);
674}
675
676static void os_area_queue_work(void)
677{
678 static DECLARE_WORK(q, os_area_queue_work_handler);
679
680 wmb();
681 schedule_work(&q);
682}
683
684/**
685 * ps3_os_area_save_params - Copy data from os area mirror to @saved_params.
686 *
687 * For the convenience of the guest the HV makes a copy of the os area in
688 * flash to a high address in the boot memory region and then puts that RAM
689 * address and the byte count into the repository for retrieval by the guest.
690 * We copy the data we want into a static variable and allow the memory setup
691 * by the HV to be claimed by the lmb manager.
692 *
693 * The os area mirror will not be available to a second stage kernel, and
694 * the header verify will fail. In this case, the saved_params values will
695 * be set from flash memory or the passed in device tree in ps3_os_area_init().
696 */
697
698void __init ps3_os_area_save_params(void)
200{ 699{
201 int result; 700 int result;
202 u64 lpar_addr; 701 u64 lpar_addr;
203 unsigned int size; 702 unsigned int size;
204 struct os_area_header *header; 703 struct os_area_header *header;
205 struct os_area_params *params; 704 struct os_area_params *params;
705 struct os_area_db *db;
706
707 pr_debug(" -> %s:%d\n", __func__, __LINE__);
206 708
207 result = ps3_repository_read_boot_dat_info(&lpar_addr, &size); 709 result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
208 710
209 if (result) { 711 if (result) {
210 pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n", 712 pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
211 __func__, __LINE__); 713 __func__, __LINE__);
212 return result; 714 return;
213 } 715 }
214 716
215 header = (struct os_area_header *)__va(lpar_addr); 717 header = (struct os_area_header *)__va(lpar_addr);
216 params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE); 718 params = (struct os_area_params *)__va(lpar_addr
719 + OS_AREA_SEGMENT_SIZE);
217 720
218 result = verify_header(header); 721 result = verify_header(header);
219 722
220 if (result) { 723 if (result) {
724 /* Second stage kernels exit here. */
221 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); 725 pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
222 dump_header(header); 726 dump_header(header);
223 return -EIO; 727 return;
224 } 728 }
225 729
730 db = (struct os_area_db *)__va(lpar_addr
731 + header->db_area_offset * OS_AREA_SEGMENT_SIZE);
732
226 dump_header(header); 733 dump_header(header);
227 dump_params(params); 734 dump_params(params);
735 dump_db(db);
228 736
229 saved_params.rtc_diff = params->rtc_diff; 737 result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);
738 if (result)
739 saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff
740 : SECONDS_FROM_1970_TO_2000;
230 saved_params.av_multi_out = params->av_multi_out; 741 saved_params.av_multi_out = params->av_multi_out;
231 saved_params.ctrl_button = params->ctrl_button; 742 saved_params.valid = 1;
232 memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4); 743
233 memcpy(saved_params.network_mask, params->network_mask, 4); 744 memset(header, 0, sizeof(*header));
234 memcpy(saved_params.default_gateway, params->default_gateway, 4);
235 memcpy(saved_params.dns_secondary, params->dns_secondary, 4);
236 745
237 return result; 746 pr_debug(" <- %s:%d\n", __func__, __LINE__);
238} 747}
239 748
240/** 749/**
241 * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value. 750 * ps3_os_area_init - Setup os area device tree properties as needed.
751 */
752
753void __init ps3_os_area_init(void)
754{
755 struct device_node *node;
756
757 pr_debug(" -> %s:%d\n", __func__, __LINE__);
758
759 node = of_find_node_by_path("/");
760
761 if (!saved_params.valid && node) {
762 /* Second stage kernels should have a dt entry. */
763 os_area_get_property(node, &property_rtc_diff);
764 os_area_get_property(node, &property_av_multi_out);
765 }
766
767 if(!saved_params.rtc_diff)
768 saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
769
770 if (node) {
771 os_area_set_property(node, &property_rtc_diff);
772 os_area_set_property(node, &property_av_multi_out);
773 of_node_put(node);
774 } else
775 pr_debug("%s:%d of_find_node_by_path failed\n",
776 __func__, __LINE__);
777
778 pr_debug(" <- %s:%d\n", __func__, __LINE__);
779}
780
781/**
782 * ps3_os_area_get_rtc_diff - Returns the rtc diff value.
783 */
784
785u64 ps3_os_area_get_rtc_diff(void)
786{
787 return saved_params.rtc_diff;
788}
789
790/**
791 * ps3_os_area_set_rtc_diff - Set the rtc diff value.
242 * 792 *
243 * The ps3 rtc maintains a value that approximates seconds since 793 * An asynchronous write is needed to support writing updates from
244 * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to 794 * the timer interrupt context.
245 * 2000 when saved_params.rtc_diff has not been properly set up.
246 */ 795 */
247 796
248u64 ps3_os_area_rtc_diff(void) 797void ps3_os_area_set_rtc_diff(u64 rtc_diff)
249{ 798{
250 return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL; 799 if (saved_params.rtc_diff != rtc_diff) {
800 saved_params.rtc_diff = rtc_diff;
801 os_area_queue_work();
802 }
251} 803}
252 804
253/** 805/**
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h
index 27c7d099816a..01f0c9506e11 100644
--- a/arch/powerpc/platforms/ps3/platform.h
+++ b/arch/powerpc/platforms/ps3/platform.h
@@ -62,8 +62,10 @@ int ps3_set_rtc_time(struct rtc_time *time);
62 62
63/* os area */ 63/* os area */
64 64
65int __init ps3_os_area_init(void); 65void __init ps3_os_area_save_params(void);
66u64 ps3_os_area_rtc_diff(void); 66void __init ps3_os_area_init(void);
67u64 ps3_os_area_get_rtc_diff(void);
68void ps3_os_area_set_rtc_diff(u64 rtc_diff);
67 69
68/* spu */ 70/* spu */
69 71
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 609945dbe394..5c2cbb08eb52 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -206,6 +206,7 @@ static void __init ps3_setup_arch(void)
206 prealloc_ps3flash_bounce_buffer(); 206 prealloc_ps3flash_bounce_buffer();
207 207
208 ppc_md.power_save = ps3_power_save; 208 ppc_md.power_save = ps3_power_save;
209 ps3_os_area_init();
209 210
210 DBG(" <- %s:%d\n", __func__, __LINE__); 211 DBG(" <- %s:%d\n", __func__, __LINE__);
211} 212}
@@ -228,7 +229,7 @@ static int __init ps3_probe(void)
228 229
229 powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; 230 powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
230 231
231 ps3_os_area_init(); 232 ps3_os_area_save_params();
232 ps3_mm_init(); 233 ps3_mm_init();
233 ps3_mm_vas_create(&htab_size); 234 ps3_mm_vas_create(&htab_size);
234 ps3_hpte_init(htab_size); 235 ps3_hpte_init(htab_size);
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index 802a9ccacb5e..d0daf7d6d3b2 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -50,12 +50,6 @@ static void __maybe_unused _dump_time(int time, const char *func,
50 _dump_tm(&tm, func, line); 50 _dump_tm(&tm, func, line);
51} 51}
52 52
53/**
54 * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value.
55 */
56
57static s64 rtc_shift;
58
59void __init ps3_calibrate_decr(void) 53void __init ps3_calibrate_decr(void)
60{ 54{
61 int result; 55 int result;
@@ -66,8 +60,6 @@ void __init ps3_calibrate_decr(void)
66 60
67 ppc_tb_freq = tmp; 61 ppc_tb_freq = tmp;
68 ppc_proc_freq = ppc_tb_freq * 40; 62 ppc_proc_freq = ppc_tb_freq * 40;
69
70 rtc_shift = ps3_os_area_rtc_diff();
71} 63}
72 64
73static u64 read_rtc(void) 65static u64 read_rtc(void)
@@ -87,18 +79,18 @@ int ps3_set_rtc_time(struct rtc_time *tm)
87 u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 79 u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
88 tm->tm_hour, tm->tm_min, tm->tm_sec); 80 tm->tm_hour, tm->tm_min, tm->tm_sec);
89 81
90 rtc_shift = now - read_rtc(); 82 ps3_os_area_set_rtc_diff(now - read_rtc());
91 return 0; 83 return 0;
92} 84}
93 85
94void ps3_get_rtc_time(struct rtc_time *tm) 86void ps3_get_rtc_time(struct rtc_time *tm)
95{ 87{
96 to_tm(read_rtc() + rtc_shift, tm); 88 to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm);
97 tm->tm_year -= 1900; 89 tm->tm_year -= 1900;
98 tm->tm_mon -= 1; 90 tm->tm_mon -= 1;
99} 91}
100 92
101unsigned long __init ps3_get_boot_time(void) 93unsigned long __init ps3_get_boot_time(void)
102{ 94{
103 return read_rtc() + rtc_shift; 95 return read_rtc() + ps3_os_area_get_rtc_diff();
104} 96}
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 9711eb0d5496..fc48b96c81bf 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -252,6 +252,20 @@ static struct notifier_block pseries_smp_nb = {
252 252
253static int __init pseries_cpu_hotplug_init(void) 253static int __init pseries_cpu_hotplug_init(void)
254{ 254{
255 struct device_node *np;
256 const char *typep;
257
258 for_each_node_by_name(np, "interrupt-controller") {
259 typep = of_get_property(np, "compatible", NULL);
260 if (strstr(typep, "open-pic")) {
261 of_node_put(np);
262
263 printk(KERN_INFO "CPU Hotplug not supported on "
264 "systems using MPIC\n");
265 return 0;
266 }
267 }
268
255 rtas_stop_self_args.token = rtas_token("stop-self"); 269 rtas_stop_self_args.token = rtas_token("stop-self");
256 qcss_tok = rtas_token("query-cpu-stopped-state"); 270 qcss_tok = rtas_token("query-cpu-stopped-state");
257 271
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index f0b7146a110f..fdb9b1c8f977 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -257,11 +257,6 @@ static void __init pSeries_setup_arch(void)
257 /* init to some ~sane value until calibrate_delay() runs */ 257 /* init to some ~sane value until calibrate_delay() runs */
258 loops_per_jiffy = 50000000; 258 loops_per_jiffy = 50000000;
259 259
260 if (ROOT_DEV == 0) {
261 printk("No ramdisk, default root is /dev/sda2\n");
262 ROOT_DEV = Root_SDA2;
263 }
264
265 fwnmi_init(); 260 fwnmi_init();
266 261
267 /* Find and initialize PCI host bridges */ 262 /* Find and initialize PCI host bridges */
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index ab037a3a40db..4d3ba63bba79 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -324,11 +324,13 @@ static struct of_device_id axon_ram_device_id[] = {
324}; 324};
325 325
326static struct of_platform_driver axon_ram_driver = { 326static struct of_platform_driver axon_ram_driver = {
327 .owner = THIS_MODULE,
328 .name = AXON_RAM_MODULE_NAME,
329 .match_table = axon_ram_device_id, 327 .match_table = axon_ram_device_id,
330 .probe = axon_ram_probe, 328 .probe = axon_ram_probe,
331 .remove = axon_ram_remove 329 .remove = axon_ram_remove,
330 .driver = {
331 .owner = THIS_MODULE,
332 .name = AXON_RAM_MODULE_NAME,
333 },
332}; 334};
333 335
334/** 336/**
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 2f91b55b7754..20edd1e94eff 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -205,10 +205,12 @@ static int pmi_of_remove(struct of_device *dev)
205} 205}
206 206
207static struct of_platform_driver pmi_of_platform_driver = { 207static struct of_platform_driver pmi_of_platform_driver = {
208 .name = "pmi",
209 .match_table = pmi_match, 208 .match_table = pmi_match,
210 .probe = pmi_of_probe, 209 .probe = pmi_of_probe,
211 .remove = pmi_of_remove 210 .remove = pmi_of_remove,
211 .driver = {
212 .name = "pmi",
213 },
212}; 214};
213 215
214static int __init pmi_module_init(void) 216static int __init pmi_module_init(void)
diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c
index f8baf05f16ce..6765676a5c6b 100644
--- a/arch/ppc/platforms/ev64360.c
+++ b/arch/ppc/platforms/ev64360.c
@@ -23,9 +23,6 @@
23#include <linux/mtd/physmap.h> 23#include <linux/mtd/physmap.h>
24#include <linux/mv643xx.h> 24#include <linux/mv643xx.h>
25#include <linux/platform_device.h> 25#include <linux/platform_device.h>
26#ifdef CONFIG_BOOTIMG
27#include <linux/bootimg.h>
28#endif
29#include <asm/page.h> 26#include <asm/page.h>
30#include <asm/time.h> 27#include <asm/time.h>
31#include <asm/smp.h> 28#include <asm/smp.h>
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
index c289e9f1b251..52f63e6f0856 100644
--- a/arch/ppc/platforms/katana.c
+++ b/arch/ppc/platforms/katana.c
@@ -27,9 +27,6 @@
27#include <linux/mtd/physmap.h> 27#include <linux/mtd/physmap.h>
28#include <linux/mv643xx.h> 28#include <linux/mv643xx.h>
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#ifdef CONFIG_BOOTIMG
31#include <linux/bootimg.h>
32#endif
33#include <asm/io.h> 30#include <asm/io.h>
34#include <asm/unistd.h> 31#include <asm/unistd.h>
35#include <asm/page.h> 32#include <asm/page.h>