summaryrefslogtreecommitdiffstats
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 \
-isystem $(shell $(CROSS32CC) -print-file-name=include)
BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc
+ifdef CONFIG_DEBUG_INFO
+BOOTCFLAGS += -g
+endif
+
ifeq ($(call cc-option-yn, -fstack-protector),y)
BOOTCFLAGS += -fno-stack-protector
endif
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);
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
PPC_FEATURE_BOOKE)
-static struct cpu_spec cpu_specs[] = {
+static struct cpu_spec __initdata cpu_specs[] = {
#ifdef CONFIG_PPC64
{ /* Power3 */
.pvr_mask = 0xffff0000,
@@ -327,14 +327,6 @@ static struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power6",
- .oprofile_type = PPC_OPROFILE_POWER4,
- .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
- .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
- .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
- POWER6_MMCRA_OTHER,
.platform = "power5+",
},
{ /* Power6 */
@@ -364,14 +356,6 @@ static struct cpu_spec cpu_specs[] = {
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
- .num_pmcs = 6,
- .pmc_type = PPC_PMC_IBM,
- .oprofile_cpu_type = "ppc64/power6",
- .oprofile_type = PPC_OPROFILE_POWER4,
- .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV,
- .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
- .oprofile_mmcra_clear = POWER6_MMCRA_THRM |
- POWER6_MMCRA_OTHER,
.platform = "power6",
},
{ /* Cell Broadband Engine */
@@ -1316,18 +1300,37 @@ static struct cpu_spec cpu_specs[] = {
#endif /* CONFIG_PPC32 */
};
-struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr)
+static struct cpu_spec the_cpu_spec;
+
+struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
{
struct cpu_spec *s = cpu_specs;
- struct cpu_spec **cur = &cur_cpu_spec;
+ struct cpu_spec *t = &the_cpu_spec;
int i;
s = PTRRELOC(s);
- cur = PTRRELOC(cur);
+ t = PTRRELOC(t);
for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
if ((pvr & s->pvr_mask) == s->pvr_value) {
- *cur = cpu_specs + i;
+ /*
+ * If we are overriding a previous value derived
+ * from the real PVR with a new value obtained
+ * using a logical PVR value, don't modify the
+ * performance monitor fields.
+ */
+ if (t->num_pmcs && !s->num_pmcs) {
+ t->cpu_name = s->cpu_name;
+ t->cpu_features = s->cpu_features;
+ t->cpu_user_features = s->cpu_user_features;
+ t->icache_bsize = s->icache_bsize;
+ t->dcache_bsize = s->dcache_bsize;
+ t->cpu_setup = s->cpu_setup;
+ t->cpu_restore = s->cpu_restore;
+ t->platform = s->platform;
+ } else
+ *t = *s;
+ *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
#if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE)
/* ppc64 and booke expect identify_cpu to also call
* 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 @@
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
#include <asm/errno.h>
#include <asm/dcr.h>
-#include <asm/of_device.h>
-#include <asm/of_platform.h>
#include <asm/topology.h>
#include <asm/pci-bridge.h>
#include <asm/ppc-pci.h>
@@ -70,7 +70,10 @@ postcore_initcall(of_bus_driver_init);
int of_register_platform_driver(struct of_platform_driver *drv)
{
/* initialize common driver fields */
- drv->driver.name = drv->name;
+ if (!drv->driver.name)
+ drv->driver.name = drv->name;
+ if (!drv->driver.owner)
+ drv->driver.owner = drv->owner;
drv->driver.bus = &of_platform_bus_type;
/* register with core */
@@ -385,9 +388,11 @@ static struct of_device_id of_pci_phb_ids[] = {
};
static struct of_platform_driver of_pci_phb_driver = {
- .name = "of-pci",
- .match_table = of_pci_phb_ids,
- .probe = of_pci_phb_probe,
+ .match_table = of_pci_phb_ids,
+ .probe = of_pci_phb_probe,
+ .driver = {
+ .name = "of-pci",
+ },
};
static __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 {
{CPU_FTR_CTRL, 0, 0, 3, 0},
{CPU_FTR_NOEXECUTE, 0, 0, 6, 0},
{CPU_FTR_NODSISRALIGN, 0, 1, 1, 1},
-#if 0
- /* put this back once we know how to test if firmware does 64k IO */
{CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
-#endif
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
};
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)
conswitchp = &dummy_con;
#endif
- ppc_md.setup_arch();
+ if (ppc_md.setup_arch)
+ ppc_md.setup_arch();
if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
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)
conswitchp = &dummy_con;
#endif
- ppc_md.setup_arch();
+ if (ppc_md.setup_arch)
+ ppc_md.setup_arch();
paging_init();
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 @@
#ifdef CONFIG_PPC64
#define sys_sigpending sys_ni_syscall
#define sys_old_getrlimit sys_ni_syscall
+
+ .p2align 3
#endif
_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,
static struct clock_event_device decrementer_clockevent = {
.name = "decrementer",
.rating = 200,
- .shift = 32,
+ .shift = 16,
.mult = 0, /* To be filled in */
.irq = 0,
.set_next_event = decrementer_set_next_event,
@@ -118,6 +118,7 @@ static struct clock_event_device decrementer_clockevent = {
static DEFINE_PER_CPU(struct clock_event_device, decrementers);
void init_decrementer_clockevent(void);
+static DEFINE_PER_CPU(u64, decrementer_next_tb);
#ifdef CONFIG_PPC_ISERIES
static unsigned long __initdata iSeries_recal_titan;
@@ -541,6 +542,7 @@ void timer_interrupt(struct pt_regs * regs)
struct pt_regs *old_regs;
int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(decrementers, cpu);
+ u64 now;
/* Ensure a positive value is written to the decrementer, or else
* some CPUs will continuue to take decrementer exceptions */
@@ -551,6 +553,14 @@ void timer_interrupt(struct pt_regs * regs)
do_IRQ(regs);
#endif
+ now = get_tb_or_rtc();
+ if (now < per_cpu(decrementer_next_tb, cpu)) {
+ /* not time for this event yet */
+ now = per_cpu(decrementer_next_tb, cpu) - now;
+ if (now <= DECREMENTER_MAX)
+ set_dec((unsigned int)now - 1);
+ return;
+ }
old_regs = set_irq_regs(regs);
irq_enter();
@@ -797,6 +807,10 @@ void __init clocksource_init(void)
static int decrementer_set_next_event(unsigned long evt,
struct clock_event_device *dev)
{
+ __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt;
+ /* The decrementer interrupts on the 0 -> -1 transition */
+ if (evt)
+ --evt;
set_dec(evt);
return 0;
}
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)
return 0;
}
+#ifdef CONFIG_PPC_MERGE
arch_initcall(vdso_init);
+#endif
int in_gate_area_no_task(unsigned long addr)
{
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 */
.dev.bus = &vio_bus_type,
};
-#ifdef CONFIG_PPC_ISERIES
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+ const unsigned char *dma_window;
+ struct iommu_table *tbl;
+ unsigned long offset, size;
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return vio_build_iommu_table_iseries(dev);
-static void __init iommu_vio_init(void)
-{
- iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
- veth_iommu_table.it_size /= 2;
- vio_iommu_table = veth_iommu_table;
- vio_iommu_table.it_offset += veth_iommu_table.it_size;
-
- if (!iommu_init_table(&veth_iommu_table, -1))
- printk("Virtual Bus VETH TCE table failed.\n");
- if (!iommu_init_table(&vio_iommu_table, -1))
- printk("Virtual Bus VIO TCE table failed.\n");
- vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops;
- vio_bus_device.dev.archdata.dma_data = &vio_iommu_table;
-}
-#else
-static void __init iommu_vio_init(void)
-{
-}
-#endif
+ dma_window = of_get_property(dev->dev.archdata.of_node,
+ "ibm,my-dma-window", NULL);
+ if (!dma_window)
+ return NULL;
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
-{
-#ifdef CONFIG_PPC_ISERIES
- if (firmware_has_feature(FW_FEATURE_ISERIES)) {
- if (strcmp(dev->type, "network") == 0)
- return &veth_iommu_table;
- return &vio_iommu_table;
- } else
-#endif
- {
- const unsigned char *dma_window;
- struct iommu_table *tbl;
- unsigned long offset, size;
-
- dma_window = of_get_property(dev->dev.archdata.of_node,
- "ibm,my-dma-window", NULL);
- if (!dma_window)
- return NULL;
-
- tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
-
- of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
- &tbl->it_index, &offset, &size);
-
- /* TCE table size - measured in tce entries */
- tbl->it_size = size >> IOMMU_PAGE_SHIFT;
- /* offset for VIO should always be 0 */
- tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
- tbl->it_busno = 0;
- tbl->it_type = TCE_VB;
-
- return iommu_init_table(tbl, -1);
- }
+ tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+ of_parse_dma_window(dev->dev.archdata.of_node, dma_window,
+ &tbl->it_index, &offset, &size);
+
+ /* TCE table size - measured in tce entries */
+ tbl->it_size = size >> IOMMU_PAGE_SHIFT;
+ /* offset for VIO should always be 0 */
+ tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
+ tbl->it_busno = 0;
+ tbl->it_type = TCE_VB;
+
+ return iommu_init_table(tbl, -1);
}
/**
@@ -168,16 +135,6 @@ static int vio_bus_remove(struct device *dev)
return 1;
}
-/* convert from struct device to struct vio_dev and pass to driver. */
-static void vio_bus_shutdown(struct device *dev)
-{
- struct vio_dev *viodev = to_vio_dev(dev);
- struct vio_driver *viodrv = to_vio_driver(dev->driver);
-
- if (dev->driver && viodrv->shutdown)
- viodrv->shutdown(viodev);
-}
-
/**
* vio_register_driver: - Register a new vio driver
* @drv: The vio_driver structure to be registered.
@@ -290,9 +247,6 @@ static int __init vio_bus_init(void)
int err;
struct device_node *node_vroot;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iommu_vio_init();
-
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
@@ -397,7 +351,6 @@ static struct bus_type vio_bus_type = {
.match = vio_bus_match,
.probe = vio_bus_probe,
.remove = vio_bus_remove,
- .shutdown = vio_bus_shutdown,
};
/**
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 @@
#include <linux/cpumask.h>
#include <linux/oprofile.h>
#include <asm/cell-pmu.h>
+#include <asm/cell-regs.h>
#include <asm/spu.h>
-#include "../../platforms/cell/cbe_regs.h"
-
/* Defines used for sync_start */
#define SKIP_GENERIC_SYNC 0
#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 @@
#include <asm/reg.h>
#include <asm/rtas.h>
#include <asm/system.h>
+#include <asm/cell-regs.h>
#include "../platforms/cell/interrupt.h"
-#include "../platforms/cell/cbe_regs.h"
#include "cell/pr_util.h"
static 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)
return 1;
}
-static void __init virtex_setup_arch(void)
-{
-}
-
define_machine(virtex) {
.name = "Xilinx Virtex",
.probe = virtex_probe,
- .setup_arch = virtex_setup_arch,
.init_IRQ = xilinx_intc_init_tree,
.get_irq = xilinx_intc_get_irq,
.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)
return 1;
}
-static void __init walnut_setup_arch(void)
-{
-}
-
define_machine(walnut) {
.name = "Walnut",
.probe = walnut_probe,
- .setup_arch = walnut_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.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)
return 1;
}
-static void __init bamboo_setup_arch(void)
-{
-}
-
define_machine(bamboo) {
.name = "Bamboo",
.probe = bamboo_probe,
- .setup_arch = bamboo_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.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)
return 1;
}
-static void __init ebony_setup_arch(void)
-{
-}
-
define_machine(ebony) {
.name = "Ebony",
.probe = ebony_probe,
- .setup_arch = ebony_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.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)
return 1;
}
-static void __init sequoia_setup_arch(void)
-{
-}
-
define_machine(sequoia) {
.name = "Sequoia",
.probe = sequoia_probe,
- .setup_arch = sequoia_setup_arch,
.progress = udbg_progress,
.init_IRQ = uic_init_tree,
.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)
{
rtas_initialize();
-#ifdef CONFIG_BLK_DEV_INITRD
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
efika_pcisetup();
#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 @@
#include <asm/machdep.h>
#include <asm/of_platform.h>
#include <asm/prom.h>
-#include "cbe_regs.h"
+#include <asm/cell-regs.h>
#include "cbe_cpufreq.h"
static 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 @@
#include <linux/time.h>
#include <asm/machdep.h>
#include <asm/hw_irq.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "cbe_cpufreq.h"
/* 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 @@
#include <asm/processor.h>
#include <asm/prom.h>
#include <asm/pmi.h>
+#include <asm/cell-regs.h>
#ifdef DEBUG
#include <asm/time.h>
#endif
-#include "cbe_regs.h"
#include "cbe_cpufreq.h"
static 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 @@
#include <asm/ptrace.h>
#include <asm/of_device.h>
#include <asm/of_platform.h>
-
-#include "cbe_regs.h"
+#include <asm/cell-regs.h>
/*
* 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 @@
-/*
- * cbe_regs.h
- *
- * This file is intended to hold the various register definitions for CBE
- * on-chip system devices (memory controller, IO controller, etc...)
- *
- * (C) Copyright IBM Corporation 2001,2006
- *
- * Authors: Maximino Aguilar (maguilar@us.ibm.com)
- * David J. Erb (djerb@us.ibm.com)
- *
- * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- */
-
-#ifndef CBE_REGS_H
-#define CBE_REGS_H
-
-#include <asm/cell-pmu.h>
-
-/*
- *
- * Some HID register definitions
- *
- */
-
-/* CBE specific HID0 bits */
-#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul
-#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul
-#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul
-#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul
-
-#define MAX_CBE 2
-
-/*
- *
- * Pervasive unit register definitions
- *
- */
-
-union spe_reg {
- u64 val;
- u8 spe[8];
-};
-
-union ppe_spe_reg {
- u64 val;
- struct {
- u32 ppe;
- u32 spe;
- };
-};
-
-
-struct cbe_pmd_regs {
- /* Debug Bus Control */
- u64 pad_0x0000; /* 0x0000 */
-
- u64 group_control; /* 0x0008 */
-
- u8 pad_0x0010_0x00a8 [0x00a8 - 0x0010]; /* 0x0010 */
-
- u64 debug_bus_control; /* 0x00a8 */
-
- u8 pad_0x00b0_0x0100 [0x0100 - 0x00b0]; /* 0x00b0 */
-
- u64 trace_aux_data; /* 0x0100 */
- u64 trace_buffer_0_63; /* 0x0108 */
- u64 trace_buffer_64_127; /* 0x0110 */
- u64 trace_address; /* 0x0118 */
- u64 ext_tr_timer; /* 0x0120 */
-
- u8 pad_0x0128_0x0400 [0x0400 - 0x0128]; /* 0x0128 */
-
- /* Performance Monitor */
- u64 pm_status; /* 0x0400 */
- u64 pm_control; /* 0x0408 */
- u64 pm_interval; /* 0x0410 */
- u64 pm_ctr[4]; /* 0x0418 */
- u64 pm_start_stop; /* 0x0438 */
- u64 pm07_control[8]; /* 0x0440 */
-
- u8 pad_0x0480_0x0800 [0x0800 - 0x0480]; /* 0x0480 */
-
- /* Thermal Sensor Registers */
- union spe_reg ts_ctsr1; /* 0x0800 */
- u64 ts_ctsr2; /* 0x0808 */
- union spe_reg ts_mtsr1; /* 0x0810 */
- u64 ts_mtsr2; /* 0x0818 */
- union spe_reg ts_itr1; /* 0x0820 */
- u64 ts_itr2; /* 0x0828 */
- u64 ts_gitr; /* 0x0830 */
- u64 ts_isr; /* 0x0838 */
- u64 ts_imr; /* 0x0840 */
- union spe_reg tm_cr1; /* 0x0848 */
- u64 tm_cr2; /* 0x0850 */
- u64 tm_simr; /* 0x0858 */
- union ppe_spe_reg tm_tpr; /* 0x0860 */
- union spe_reg tm_str1; /* 0x0868 */
- u64 tm_str2; /* 0x0870 */
- union ppe_spe_reg tm_tsr; /* 0x0878 */
-
- /* Power Management */
- u64 pmcr; /* 0x0880 */
-#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000
- u64 pmsr; /* 0x0888 */
-
- /* Time Base Register */
- u64 tbr; /* 0x0890 */
-
- u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */
-
- /* Fault Isolation Registers */
- u64 checkstop_fir; /* 0x0c00 */
- u64 recoverable_fir; /* 0x0c08 */
- u64 spec_att_mchk_fir; /* 0x0c10 */
- u32 fir_mode_reg; /* 0x0c18 */
- u8 pad_0x0c1c_0x0c20 [4]; /* 0x0c1c */
-#define CBE_PMD_FIR_MODE_M8 0x00800
- u64 fir_enable_mask; /* 0x0c20 */
-
- u8 pad_0x0c28_0x0ca8 [0x0ca8 - 0x0c28]; /* 0x0c28 */
- u64 ras_esc_0; /* 0x0ca8 */
- u8 pad_0x0cb0_0x1000 [0x1000 - 0x0cb0]; /* 0x0cb0 */
-};
-
-extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
-extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
-
-/*
- * PMU shadow registers
- *
- * Many of the registers in the performance monitoring unit are write-only,
- * so we need to save a copy of what we write to those registers.
- *
- * The actual data counters are read/write. However, writing to the counters
- * only takes effect if the PMU is enabled. Otherwise the value is stored in
- * a hardware latch until the next time the PMU is enabled. So we save a copy
- * of the counter values if we need to read them back while the PMU is
- * disabled. The counter_value_in_latch field is a bitmap indicating which
- * counters currently have a value waiting to be written.
- */
-
-struct cbe_pmd_shadow_regs {
- u32 group_control;
- u32 debug_bus_control;
- u32 trace_address;
- u32 ext_tr_timer;
- u32 pm_status;
- u32 pm_control;
- u32 pm_interval;
- u32 pm_start_stop;
- u32 pm07_control[NR_CTRS];
-
- u32 pm_ctr[NR_PHYS_CTRS];
- u32 counter_value_in_latch;
-};
-
-extern struct cbe_pmd_shadow_regs *cbe_get_pmd_shadow_regs(struct device_node *np);
-extern struct cbe_pmd_shadow_regs *cbe_get_cpu_pmd_shadow_regs(int cpu);
-
-/*
- *
- * IIC unit register definitions
- *
- */
-
-struct cbe_iic_pending_bits {
- u32 data;
- u8 flags;
- u8 class;
- u8 source;
- u8 prio;
-};
-
-#define CBE_IIC_IRQ_VALID 0x80
-#define CBE_IIC_IRQ_IPI 0x40
-
-struct cbe_iic_thread_regs {
- struct cbe_iic_pending_bits pending;
- struct cbe_iic_pending_bits pending_destr;
- u64 generate;
- u64 prio;
-};
-
-struct cbe_iic_regs {
- u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */
-
- /* IIC interrupt registers */
- struct cbe_iic_thread_regs thread[2]; /* 0x0400 */
-
- u64 iic_ir; /* 0x0440 */
-#define CBE_IIC_IR_PRIO(x) (((x) & 0xf) << 12)
-#define CBE_IIC_IR_DEST_NODE(x) (((x) & 0xf) << 4)
-#define CBE_IIC_IR_DEST_UNIT(x) ((x) & 0xf)
-#define CBE_IIC_IR_IOC_0 0x0
-#define CBE_IIC_IR_IOC_1S 0xb
-#define CBE_IIC_IR_PT_0 0xe
-#define CBE_IIC_IR_PT_1 0xf
-
- u64 iic_is; /* 0x0448 */
-#define CBE_IIC_IS_PMI 0x2
-
- u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */
-
- /* IOC FIR */
- u64 ioc_fir_reset; /* 0x0500 */
- u64 ioc_fir_set; /* 0x0508 */
- u64 ioc_checkstop_enable; /* 0x0510 */
- u64 ioc_fir_error_mask; /* 0x0518 */
- u64 ioc_syserr_enable; /* 0x0520 */
- u64 ioc_fir; /* 0x0528 */
-
- u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */
-};
-
-extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
-extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
-
-
-struct cbe_mic_tm_regs {
- u8 pad_0x0000_0x0040[0x0040 - 0x0000]; /* 0x0000 */
-
- u64 mic_ctl_cnfg2; /* 0x0040 */
-#define CBE_MIC_ENABLE_AUX_TRC 0x8000000000000000LL
-#define CBE_MIC_DISABLE_PWR_SAV_2 0x0200000000000000LL
-#define CBE_MIC_DISABLE_AUX_TRC_WRAP 0x0100000000000000LL
-#define CBE_MIC_ENABLE_AUX_TRC_INT 0x0080000000000000LL
-
- u64 pad_0x0048; /* 0x0048 */
-
- u64 mic_aux_trc_base; /* 0x0050 */
- u64 mic_aux_trc_max_addr; /* 0x0058 */
- u64 mic_aux_trc_cur_addr; /* 0x0060 */
- u64 mic_aux_trc_grf_addr; /* 0x0068 */
- u64 mic_aux_trc_grf_data; /* 0x0070 */
-
- u64 pad_0x0078; /* 0x0078 */
-
- u64 mic_ctl_cnfg_0; /* 0x0080 */
-#define CBE_MIC_DISABLE_PWR_SAV_0 0x8000000000000000LL
-
- u64 pad_0x0088; /* 0x0088 */
-
- u64 slow_fast_timer_0; /* 0x0090 */
- u64 slow_next_timer_0; /* 0x0098 */
-
- u8 pad_0x00a0_0x01c0[0x01c0 - 0x0a0]; /* 0x00a0 */
-
- u64 mic_ctl_cnfg_1; /* 0x01c0 */
-#define CBE_MIC_DISABLE_PWR_SAV_1 0x8000000000000000LL
- u64 pad_0x01c8; /* 0x01c8 */
-
- u64 slow_fast_timer_1; /* 0x01d0 */
- u64 slow_next_timer_1; /* 0x01d8 */
-
- u8 pad_0x01e0_0x1000[0x1000 - 0x01e0]; /* 0x01e0 */
-};
-
-extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
-extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu);
-
-/* some utility functions to deal with SMT */
-extern u32 cbe_get_hw_thread_id(int cpu);
-extern u32 cbe_cpu_to_node(int cpu);
-extern u32 cbe_node_to_cpu(int node);
-
-/* Init this module early */
-extern void cbe_regs_init(void);
-
-
-#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 @@
#include <asm/spu.h>
#include <asm/io.h>
#include <asm/prom.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "spu_priv1_mmio.h"
#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 @@
#include <asm/prom.h>
#include <asm/ptrace.h>
#include <asm/machdep.h>
+#include <asm/cell-regs.h>
#include "interrupt.h"
-#include "cbe_regs.h"
struct iic {
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 @@
#include <asm/udbg.h>
#include <asm/of_platform.h>
#include <asm/lmb.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "interrupt.h"
/* 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 @@
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/reg.h>
+#include <asm/cell-regs.h>
#include "pervasive.h"
-#include "cbe_regs.h"
static int sysreset_hack;
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 @@
#include <asm/pmc.h>
#include <asm/reg.h>
#include <asm/spu.h>
+#include <asm/cell-regs.h>
-#include "cbe_regs.h"
#include "interrupt.h"
/*
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 @@
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/rtas.h>
+#include <asm/cell-regs.h>
#include "ras.h"
-#include "cbe_regs.h"
static 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 @@
#include <asm/udbg.h>
#include <asm/mpic.h>
#include <asm/of_platform.h>
+#include <asm/cell-regs.h>
#include "interrupt.h"
-#include "cbe_regs.h"
#include "pervasive.h"
#include "ras.h"
@@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex)
static int __init cell_publish_devices(void)
{
+ int node;
+
if (!machine_is(cell))
return 0;
/* Publish OF platform devices for southbridge IOs */
of_platform_bus_probe(NULL, NULL, NULL);
+ /* There is no device for the MIC memory controller, thus we create
+ * a platform device for it to attach the EDAC driver to.
+ */
+ for_each_online_node(node) {
+ if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL)
+ continue;
+ platform_device_register_simple("cbe-mic", node, NULL, 0);
+ }
return 0;
}
device_initcall(cell_publish_devices);
@@ -161,11 +171,6 @@ static void __init cell_setup_arch(void)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/hda2\n");
- ROOT_DEV = Root_HDA2;
- }
-
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
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)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/hda2\n");
- ROOT_DEV = Root_HDA2;
- }
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#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)
ppc_md.set_rtc_time = rtas_set_rtc_time;
}
-#ifdef CONFIG_BLK_DEV_INITRD
- /* this is fine for chrp */
- initrd_below_start_ok = 1;
-
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
- ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */
-
/* On pegasos, enable the L2 cache if not already done by OF */
pegasos_set_l2cr();
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 \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_VIOPATH) += viopath.o
+obj-$(CONFIG_VIOPATH) += viopath.o vio.o
obj-$(CONFIG_MODULES) += ksyms.o
quiet_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";
static char __initdata device_type_memory[] = "memory";
static char __initdata device_type_serial[] = "serial";
static char __initdata device_type_network[] = "network";
-static char __initdata device_type_block[] = "block";
-static char __initdata device_type_byte[] = "byte";
static char __initdata device_type_pci[] = "pci";
static char __initdata device_type_vdevice[] = "vdevice";
static char __initdata device_type_vscsi[] = "vscsi";
@@ -375,21 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
- reg += HVMAXARCHITECTEDVIRTUALLANS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
- dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
- "IBM,iSeries-viodasd", 1);
- reg += HVMAXARCHITECTEDVIRTUALDISKS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
- dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
- "IBM,iSeries-viocd", 1);
- reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
- dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
- "IBM,iSeries-viotape", 1);
dt_end_node(dt);
}
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 @@
#include <linux/dma-mapping.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <asm/iommu.h>
+#include <asm/vio.h>
#include <asm/tce.h>
#include <asm/machdep.h>
#include <asm/abs_addr.h>
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/hv_call_event.h>
#include <asm/iseries/iommu.h>
static 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)
}
#endif
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
+{
+ return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
+ DMA_32BIT_MASK, flag, -1);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_alloc);
+
+void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle)
+{
+ iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle);
+}
+EXPORT_SYMBOL_GPL(iseries_hv_free);
+
+dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ return iommu_map_single(&vio_iommu_table, vaddr, size,
+ DMA_32BIT_MASK, direction);
+}
+
+void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction);
+}
+
+void __init iommu_vio_init(void)
+{
+ iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+ veth_iommu_table.it_size /= 2;
+ vio_iommu_table = veth_iommu_table;
+ vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+ if (!iommu_init_table(&veth_iommu_table, -1))
+ printk("Virtual Bus VETH TCE table failed.\n");
+ if (!iommu_init_table(&vio_iommu_table, -1))
+ printk("Virtual Bus VIO TCE table failed.\n");
+}
+
+struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev)
+{
+ if (strcmp(dev->type, "network") == 0)
+ return &veth_iommu_table;
+ return &vio_iommu_table;
+}
+
void iommu_init_early_iSeries(void)
{
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 @@
#include <asm/paca.h>
#include <asm/abs_addr.h>
#include <asm/firmware.h>
-#include <asm/iseries/vio.h>
#include <asm/iseries/mf.h>
#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/it_lp_queue.h>
#include "setup.h"
@@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
if ((off + count) > 256)
count = 256 - off;
- dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE);
if (dma_mapping_error(dma_addr))
return -ENOMEM;
memset(page, 0, off + count);
@@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off,
vsp_cmd.sub_data.kern.length = off + count;
mb();
rc = signal_vsp_instruction(&vsp_cmd);
- dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE);
if (rc)
return rc;
if (vsp_cmd.result_code != 0)
@@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
int len = *size;
dma_addr_t dma_addr;
- dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,
- DMA_FROM_DEVICE);
+ dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE);
memset(buffer, 0, len);
memset(&vsp_cmd, 0, sizeof(vsp_cmd));
vsp_cmd.cmd = 32;
@@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side)
rc = -ENOMEM;
}
- dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);
+ iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE);
return rc;
}
@@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
ret = -ENOMEM;
if (page == NULL)
goto out;
@@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,
ret = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return ret;
}
@@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file,
goto out;
dma_addr = 0;
- page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,
- GFP_ATOMIC);
+ page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC);
rc = -ENOMEM;
if (page == NULL) {
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,
*ppos += count;
rc = count;
out_free:
- dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);
+ iseries_hv_free(count, page, dma_addr);
out:
return rc;
}
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 @@
+/*
+ * Legacy iSeries specific vio initialisation
+ * that needs to be built in (not a module).
+ *
+ * © Copyright 2007 IBM Corporation
+ * Author: Stephen Rothwell
+ * Some parts collected from various other files
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/completion.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+
+#include <asm/firmware.h>
+#include <asm/vio.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/iommu.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+
+#define FIRST_VTY 0
+#define NUM_VTYS 1
+#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
+#define NUM_VSCSIS 1
+#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
+#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
+#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
+#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
+#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
+#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
+#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
+#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+
+struct vio_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct vio_resource {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
+static struct property *new_property(const char *name, int length,
+ const void *value)
+{
+ struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
+ GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->name = (char *)(np + 1);
+ np->value = np->name + strlen(name) + 1;
+ strcpy(np->name, name);
+ memcpy(np->value, value, length);
+ np->length = length;
+ return np;
+}
+
+static void __init free_property(struct property *np)
+{
+ kfree(np);
+}
+
+static struct device_node *new_node(const char *path,
+ struct device_node *parent)
+{
+ struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+ if (!np->full_name) {
+ kfree(np);
+ return NULL;
+ }
+ strcpy(np->full_name, path);
+ of_node_set_flag(np, OF_DYNAMIC);
+ kref_init(&np->kref);
+ np->parent = of_node_get(parent);
+ return np;
+}
+
+static void free_node(struct device_node *np)
+{
+ struct property *next;
+ struct property *prop;
+
+ next = np->properties;
+ while (next) {
+ prop = next;
+ next = prop->next;
+ free_property(prop);
+ }
+ of_node_put(np->parent);
+ kfree(np->full_name);
+ kfree(np);
+}
+
+static int add_string_property(struct device_node *np, const char *name,
+ const char *value)
+{
+ struct property *nprop = new_property(name, strlen(value) + 1, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static int add_raw_property(struct device_node *np, const char *name,
+ int length, const void *value)
+{
+ struct property *nprop = new_property(name, length, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static struct device_node *do_device_node(struct device_node *parent,
+ const char *name, u32 reg, u32 unit, const char *type,
+ const char *compat, struct vio_resource *res)
+{
+ struct device_node *np;
+ char path[32];
+
+ snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
+ np = new_node(path, parent);
+ if (!np)
+ return NULL;
+ if (!add_string_property(np, "name", name) ||
+ !add_string_property(np, "device_type", type) ||
+ !add_string_property(np, "compatible", compat) ||
+ !add_raw_property(np, "reg", sizeof(reg), &reg) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit)) {
+ goto node_free;
+ }
+ if (res) {
+ if (!add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(res->rsrcname), res->rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(res->type), res->type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(res->model), res->model))
+ goto node_free;
+ }
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (parent->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ return np;
+
+ node_free:
+ free_node(np);
+ return NULL;
+}
+
+/*
+ * This is here so that we can dynamically add viodasd
+ * devices without exposing all the above infrastructure.
+ */
+struct vio_dev *vio_create_viodasd(u32 unit)
+{
+ struct device_node *vio_root;
+ struct device_node *np;
+ struct vio_dev *vdev = NULL;
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return NULL;
+ np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+ of_node_put(vio_root);
+ if (np) {
+ vdev = vio_register_device_node(np);
+ if (!vdev)
+ free_node(np);
+ }
+ return vdev;
+}
+EXPORT_SYMBOL_GPL(vio_create_viodasd);
+
+static void __init handle_block_event(struct HvLpEvent *event)
+{
+ struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
+ struct vio_waitevent *pwe;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_viod_request: "
+ "Yikes! got an int in viodasd event handler!\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case vioblockopen:
+ /*
+ * Handle a response to an open request. We get all the
+ * disk information in the response, so update it. The
+ * correlation token contains a pointer to a waitevent
+ * structure that has a completion in it. update the
+ * return code in the waitevent structure and post the
+ * completion to wake up the guy who sent the request
+ */
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+ case vioblockclose:
+ break;
+ default:
+ printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init probe_disk(struct device_node *vio_root, u32 unit)
+{
+ HvLpEvent_Rc hvrc;
+ struct vio_waitevent we;
+ u16 flags = 0;
+
+retry:
+ init_completion(&we.com);
+
+ /* Send the open event to OS/400 */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockopen,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags<< 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
+ (int)hvrc);
+ return;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc != 0) {
+ if (flags != 0)
+ return;
+ /* try again with read only flag set */
+ flags = vioblockflags_ro;
+ goto retry;
+ }
+
+ /* Send the close event to OS/400. We DON'T expect a response */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockclose,
+ HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ 0, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags << 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: "
+ "bad rc sending event to OS/400 %d\n", (int)hvrc);
+ return;
+ }
+
+ do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+}
+
+static void __init get_viodasd_info(struct device_node *vio_root)
+{
+ int rc;
+ u32 unit;
+
+ rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
+ if (rc) {
+ printk(KERN_WARNING "get_viodasd_info: "
+ "error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_blockio, handle_block_event);
+
+ for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
+ probe_disk(vio_root, unit);
+
+ vio_clearHandler(viomajorsubtype_blockio);
+ viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
+}
+
+static void __init handle_cd_event(struct HvLpEvent *event)
+{
+ struct viocdlpevent *bevent;
+ struct vio_waitevent *pwe;
+
+ if (!event)
+ /* Notification that a partition went away! */
+ return;
+
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ bevent = (struct viocdlpevent *)event;
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viocdgetinfo:
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+
+ default:
+ printk(KERN_WARNING "handle_cd_event: "
+ "message with unexpected subtype %0x04X!\n",
+ event->xSubtype & VIOMINOR_SUBTYPE_MASK);
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init get_viocd_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_waitevent we;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
+ if (ret) {
+ printk(KERN_WARNING
+ "get_viocd_info: error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
+
+ unitinfo = iseries_hv_alloc(
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo) {
+ printk(KERN_WARNING
+ "get_viocd_info: error allocating unitinfo\n");
+ goto clear_handler;
+ }
+
+ memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
+
+ init_completion(&we.com);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_cdio | viocdgetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING
+ "get_viocd_info: cdrom error sending event. rc %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc) {
+ printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
+ we.rc, we.sub_result);
+ goto hv_free;
+ }
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
+ "block", "IBM,iSeries-viocd", &unitinfo[unit]))
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_cdio);
+ viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
+}
+
+/* Handle interrupt events for tape */
+static void __init handle_tape_event(struct HvLpEvent *event)
+{
+ struct vio_waitevent *we;
+ struct viotapelpevent *tevent = (struct viotapelpevent *)event;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+
+ we = (struct vio_waitevent *)event->xCorrelationToken;
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viotapegetinfo:
+ we->rc = tevent->sub_type_result;
+ complete(&we->com);
+ break;
+ default:
+ printk(KERN_WARNING "handle_tape_event: weird ack\n");
+ }
+}
+
+static void __init get_viotape_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
+ struct vio_waitevent we;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
+ if (ret) {
+ printk(KERN_WARNING "get_viotape_info: "
+ "error on viopath_open to hostlp %d\n", ret);
+ return;
+ }
+
+ vio_setHandler(viomajorsubtype_tape, handle_tape_event);
+
+ unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo)
+ goto clear_handler;
+
+ memset(unitinfo, 0, len);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_tape | viotapegetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ unitinfo_dmaaddr, len, 0, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
+ unit, "byte", "IBM,iSeries-viotape",
+ &unitinfo[unit]))
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_tape);
+ viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
+}
+
+static int __init iseries_vio_init(void)
+{
+ struct device_node *vio_root;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
+ iommu_vio_init();
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return -ENODEV;
+
+ if (viopath_hostLp == HvLpIndexInvalid) {
+ vio_set_hostlp();
+ /* If we don't have a host, bail out */
+ if (viopath_hostLp == HvLpIndexInvalid)
+ goto put_node;
+ }
+
+ get_viodasd_info(vio_root);
+ get_viocd_info(vio_root);
+ get_viotape_info(vio_root);
+
+ return 0;
+
+ put_node:
+ of_node_put(vio_root);
+ return -ENODEV;
+}
+arch_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)
if (!buf)
return 0;
- handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE);
hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
HvLpEvent_Type_VirtualIo,
@@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v)
buf[HW_PAGE_SIZE-1] = '\0';
seq_printf(m, "%s", buf);
- dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE,
- DMA_FROM_DEVICE);
+ iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE);
kfree(buf);
seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap);
@@ -596,7 +594,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
numOpen += viopathStatus[remoteLp].users[i];
if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) {
- printk(VIOPATH_KERN_INFO "closing connection to partition %d",
+ printk(VIOPATH_KERN_INFO "closing connection to partition %d\n",
remoteLp);
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[] =
static struct of_platform_driver gpio_mdio_driver =
{
- .name = "gpio-mdio-bitbang",
.match_table = gpio_mdio_match,
.probe = gpio_mdio_probe,
.remove = gpio_mdio_remove,
+ .driver = {
+ .name = "gpio-mdio-bitbang",
+ },
};
int 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)
#endif /* CONFIG_ADB */
}
-char *bootpath;
-char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-static dev_t boot_dev;
-
#ifdef CONFIG_SCSI
void note_scsi_host(struct device_node *node, void *host)
{
- int l;
- char *p;
-
- l = strlen(node->full_name);
- if (bootpath != NULL && bootdevice != NULL
- && strncmp(node->full_name, bootdevice, l) == 0
- && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
- boot_host = host;
- /*
- * There's a bug in OF 1.0.5. (Why am I not surprised.)
- * If you pass a path like scsi/sd@1:0 to canon, it returns
- * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
- * That is, the scsi target number doesn't get preserved.
- * So we pick the target number out of bootpath and use that.
- */
- p = strstr(bootpath, "/sd@");
- if (p != NULL) {
- p += 4;
- boot_target = simple_strtoul(p, NULL, 10);
- p = strchr(p, ':');
- if (p != NULL)
- boot_part = simple_strtoul(p + 1, NULL, 10);
- }
- }
}
EXPORT_SYMBOL(note_scsi_host);
#endif
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-static dev_t __init find_ide_boot(void)
-{
- char *p;
- int n;
- dev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
- if (bootdevice == NULL)
- return 0;
- p = strrchr(bootdevice, '/');
- if (p == NULL)
- return 0;
- n = p - bootdevice;
-
- return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-static void __init find_boot_device(void)
-{
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
- boot_dev = find_ide_boot();
-#endif
-}
-
static int initializing = 1;
static int pmac_late_init(void)
@@ -466,10 +410,14 @@ static int pmac_late_init(void)
late_initcall(pmac_late_init);
-/* can't be __init - can be called whenever a disk is first accessed */
-void note_bootable_part(dev_t dev, int part, int goodness)
+/*
+ * This is __init_refok because we check for "initializing" before
+ * touching any of the __init sensitive things and "initializing"
+ * will be false after __init time. This can't be __init because it
+ * can be called whenever a disk is first accessed.
+ */
+void __init_refok note_bootable_part(dev_t dev, int part, int goodness)
{
- static int found_boot = 0;
char *p;
if (!initializing)
@@ -481,15 +429,8 @@ void note_bootable_part(dev_t dev, int part, int goodness)
if (p != NULL && (p == boot_command_line || p[-1] == ' '))
return;
- if (!found_boot) {
- find_boot_device();
- found_boot = 1;
- }
- if (!boot_dev || dev == boot_dev) {
- ROOT_DEV = dev + part;
- boot_dev = 0;
- current_root_goodness = goodness;
- }
+ ROOT_DEV = dev + part;
+ current_root_goodness = goodness;
}
#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 @@
/*
- * PS3 'Other OS' area data.
+ * PS3 flash memory os area.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
@@ -20,6 +20,9 @@
#include <linux/kernel.h>
#include <linux/io.h>
+#include <linux/workqueue.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
#include <asm/lmb.h>
@@ -29,7 +32,7 @@ enum {
OS_AREA_SEGMENT_SIZE = 0X200,
};
-enum {
+enum os_area_ldr_format {
HEADER_LDR_FORMAT_RAW = 0,
HEADER_LDR_FORMAT_GZIP = 1,
};
@@ -38,7 +41,7 @@ enum {
* struct os_area_header - os area header segment.
* @magic_num: Always 'cell_ext_os_area'.
* @hdr_version: Header format version number.
- * @os_area_offset: Starting segment number of os image area.
+ * @db_area_offset: Starting segment number of other os database area.
* @ldr_area_offset: Starting segment number of bootloader image area.
* @ldr_format: HEADER_LDR_FORMAT flag.
* @ldr_size: Size of bootloader image in bytes.
@@ -50,9 +53,9 @@ enum {
*/
struct os_area_header {
- s8 magic_num[16];
+ u8 magic_num[16];
u32 hdr_version;
- u32 os_area_offset;
+ u32 db_area_offset;
u32 ldr_area_offset;
u32 _reserved_1;
u32 ldr_format;
@@ -60,12 +63,12 @@ struct os_area_header {
u32 _reserved_2[6];
};
-enum {
+enum os_area_boot_flag {
PARAM_BOOT_FLAG_GAME_OS = 0,
PARAM_BOOT_FLAG_OTHER_OS = 1,
};
-enum {
+enum os_area_ctrl_button {
PARAM_CTRL_BUTTON_O_IS_YES = 0,
PARAM_CTRL_BUTTON_X_IS_YES = 1,
};
@@ -84,6 +87,9 @@ enum {
* @dns_primary: User preference of static primary dns server.
* @dns_secondary: User preference of static secondary dns server.
*
+ * The ps3 rtc maintains a read-only value that approximates seconds since
+ * 2000-01-01 00:00:00 UTC.
+ *
* User preference of zero for static_ip_addr means use dhcp.
*/
@@ -108,45 +114,172 @@ struct os_area_params {
u8 _reserved_5[8];
};
+enum {
+ OS_AREA_DB_MAGIC_NUM = 0x2d64622dU,
+};
+
/**
- * struct saved_params - Static working copies of data from the 'Other OS' area.
+ * struct os_area_db - Shared flash memory database.
+ * @magic_num: Always '-db-' = 0x2d64622d.
+ * @version: os_area_db format version number.
+ * @index_64: byte offset of the database id index for 64 bit variables.
+ * @count_64: number of usable 64 bit index entries
+ * @index_32: byte offset of the database id index for 32 bit variables.
+ * @count_32: number of usable 32 bit index entries
+ * @index_16: byte offset of the database id index for 16 bit variables.
+ * @count_16: number of usable 16 bit index entries
*
- * For the convinience of the guest, the HV makes a copy of the 'Other OS' area
- * in flash to a high address in the boot memory region and then puts that RAM
- * address and the byte count into the repository for retreval by the guest.
- * We copy the data we want into a static variable and allow the memory setup
- * by the HV to be claimed by the lmb manager.
+ * Flash rom storage for exclusive use by guests running in the other os lpar.
+ * The current system configuration allocates 1K (two segments) for other os
+ * use.
+ */
+
+struct os_area_db {
+ u32 magic_num;
+ u16 version;
+ u16 _reserved_1;
+ u16 index_64;
+ u16 count_64;
+ u16 index_32;
+ u16 count_32;
+ u16 index_16;
+ u16 count_16;
+ u32 _reserved_2;
+ u8 _db_data[1000];
+};
+
+/**
+ * enum os_area_db_owner - Data owners.
+ */
+
+enum os_area_db_owner {
+ OS_AREA_DB_OWNER_ANY = -1,
+ OS_AREA_DB_OWNER_NONE = 0,
+ OS_AREA_DB_OWNER_PROTOTYPE = 1,
+ OS_AREA_DB_OWNER_LINUX = 2,
+ OS_AREA_DB_OWNER_PETITBOOT = 3,
+ OS_AREA_DB_OWNER_MAX = 32,
+};
+
+enum os_area_db_key {
+ OS_AREA_DB_KEY_ANY = -1,
+ OS_AREA_DB_KEY_NONE = 0,
+ OS_AREA_DB_KEY_RTC_DIFF = 1,
+ OS_AREA_DB_KEY_VIDEO_MODE = 2,
+ OS_AREA_DB_KEY_MAX = 8,
+};
+
+struct os_area_db_id {
+ int owner;
+ int key;
+};
+
+static const struct os_area_db_id os_area_db_id_empty = {
+ .owner = OS_AREA_DB_OWNER_NONE,
+ .key = OS_AREA_DB_KEY_NONE
+};
+
+static const struct os_area_db_id os_area_db_id_any = {
+ .owner = OS_AREA_DB_OWNER_ANY,
+ .key = OS_AREA_DB_KEY_ANY
+};
+
+static const struct os_area_db_id os_area_db_id_rtc_diff = {
+ .owner = OS_AREA_DB_OWNER_LINUX,
+ .key = OS_AREA_DB_KEY_RTC_DIFF
+};
+
+static const struct os_area_db_id os_area_db_id_video_mode = {
+ .owner = OS_AREA_DB_OWNER_LINUX,
+ .key = OS_AREA_DB_KEY_VIDEO_MODE
+};
+
+#define SECONDS_FROM_1970_TO_2000 946684800LL
+
+/**
+ * struct saved_params - Static working copies of data from the PS3 'os area'.
+ *
+ * The order of preference we use for the rtc_diff source:
+ * 1) The database value.
+ * 2) The game os value.
+ * 3) The number of seconds from 1970 to 2000.
*/
struct saved_params {
- /* param 0 */
+ unsigned int valid;
s64 rtc_diff;
unsigned int av_multi_out;
- unsigned int ctrl_button;
- /* param 1 */
- u8 static_ip_addr[4];
- u8 network_mask[4];
- u8 default_gateway[4];
- /* param 2 */
- u8 dns_primary[4];
- u8 dns_secondary[4];
} static saved_params;
+static struct property property_rtc_diff = {
+ .name = "linux,rtc_diff",
+ .length = sizeof(saved_params.rtc_diff),
+ .value = &saved_params.rtc_diff,
+};
+
+static struct property property_av_multi_out = {
+ .name = "linux,av_multi_out",
+ .length = sizeof(saved_params.av_multi_out),
+ .value = &saved_params.av_multi_out,
+};
+
+/**
+ * os_area_set_property - Add or overwrite a saved_params value to the device tree.
+ *
+ * Overwrites an existing property.
+ */
+
+static void os_area_set_property(struct device_node *node,
+ struct property *prop)
+{
+ int result;
+ struct property *tmp = of_find_property(node, prop->name, NULL);
+
+ if (tmp) {
+ pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name);
+ prom_remove_property(node, tmp);
+ }
+
+ result = prom_add_property(node, prop);
+
+ if (result)
+ pr_debug("%s:%d prom_set_property failed\n", __func__,
+ __LINE__);
+}
+
+/**
+ * os_area_get_property - Get a saved_params value from the device tree.
+ *
+ */
+
+static void __init os_area_get_property(struct device_node *node,
+ struct property *prop)
+{
+ const struct property *tmp = of_find_property(node, prop->name, NULL);
+
+ if (tmp) {
+ BUG_ON(prop->length != tmp->length);
+ memcpy(prop->value, tmp->value, prop->length);
+ } else
+ pr_debug("%s:%d not found %s\n", __func__, __LINE__,
+ prop->name);
+}
+
#define dump_header(_a) _dump_header(_a, __func__, __LINE__)
static void _dump_header(const struct os_area_header *h, const char *func,
int line)
{
- pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
+ pr_debug("%s:%d: h.magic_num: '%s'\n", func, line,
h->magic_num);
- pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
+ pr_debug("%s:%d: h.hdr_version: %u\n", func, line,
h->hdr_version);
- pr_debug("%s:%d: h.os_area_offset: %u\n", func, line,
- h->os_area_offset);
+ pr_debug("%s:%d: h.db_area_offset: %u\n", func, line,
+ h->db_area_offset);
pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line,
h->ldr_area_offset);
- pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
+ pr_debug("%s:%d: h.ldr_format: %u\n", func, line,
h->ldr_format);
- pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
+ pr_debug("%s:%d: h.ldr_size: %xh\n", func, line,
h->ldr_size);
}
@@ -176,7 +309,7 @@ static void _dump_params(const struct os_area_params *p, const char *func,
p->dns_secondary[2], p->dns_secondary[3]);
}
-static int __init verify_header(const struct os_area_header *header)
+static int verify_header(const struct os_area_header *header)
{
if (memcmp(header->magic_num, "cell_ext_os_area", 16)) {
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)
return -1;
}
- if (header->os_area_offset > header->ldr_area_offset) {
+ if (header->db_area_offset > header->ldr_area_offset) {
pr_debug("%s:%d offsets failed\n", __func__, __LINE__);
return -1;
}
@@ -196,58 +329,477 @@ static int __init verify_header(const struct os_area_header *header)
return 0;
}
-int __init ps3_os_area_init(void)
+static int db_verify(const struct os_area_db *db)
+{
+ if (db->magic_num != OS_AREA_DB_MAGIC_NUM) {
+ pr_debug("%s:%d magic_num failed\n", __func__, __LINE__);
+ return -1;
+ }
+
+ if (db->version != 1) {
+ pr_debug("%s:%d version failed\n", __func__, __LINE__);
+ return -1;
+ }
+
+ return 0;
+}
+
+struct db_index {
+ uint8_t owner:5;
+ uint8_t key:3;
+};
+
+struct db_iterator {
+ const struct os_area_db *db;
+ struct os_area_db_id match_id;
+ struct db_index *idx;
+ struct db_index *last_idx;
+ union {
+ uint64_t *value_64;
+ uint32_t *value_32;
+ uint16_t *value_16;
+ };
+};
+
+static unsigned int db_align_up(unsigned int val, unsigned int size)
+{
+ return (val + (size - 1)) & (~(size - 1));
+}
+
+/**
+ * db_for_each_64 - Iterator for 64 bit entries.
+ *
+ * A NULL value for id can be used to match all entries.
+ * OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all.
+ */
+
+static int db_for_each_64(const struct os_area_db *db,
+ const struct os_area_db_id *match_id, struct db_iterator *i)
+{
+next:
+ if (!i->db) {
+ i->db = db;
+ i->match_id = match_id ? *match_id : os_area_db_id_any;
+ i->idx = (void *)db + db->index_64;
+ i->last_idx = i->idx + db->count_64;
+ i->value_64 = (void *)db + db->index_64
+ + db_align_up(db->count_64, 8);
+ } else {
+ i->idx++;
+ i->value_64++;
+ }
+
+ if (i->idx >= i->last_idx) {
+ pr_debug("%s:%d: reached end\n", __func__, __LINE__);
+ return 0;
+ }
+
+ if (i->match_id.owner != OS_AREA_DB_OWNER_ANY
+ && i->match_id.owner != (int)i->idx->owner)
+ goto next;
+ if (i->match_id.key != OS_AREA_DB_KEY_ANY
+ && i->match_id.key != (int)i->idx->key)
+ goto next;
+
+ return 1;
+}
+
+static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id)
+{
+ struct db_iterator i;
+
+ for (i.db = NULL; db_for_each_64(db, id, &i); ) {
+
+ pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+
+ i.idx->owner = 0;
+ i.idx->key = 0;
+ *i.value_64 = 0;
+ }
+ return 0;
+}
+
+static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,
+ uint64_t value)
+{
+ struct db_iterator i;
+
+ pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,
+ id->owner, id->key, (unsigned long long)value);
+
+ if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY
+ || id->key == OS_AREA_DB_KEY_ANY) {
+ pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,
+ __LINE__, id->owner, id->key);
+ return -1;
+ }
+
+ db_delete_64(db, id);
+
+ i.db = NULL;
+ if (db_for_each_64(db, &os_area_db_id_empty, &i)) {
+
+ pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+
+ i.idx->owner = id->owner;
+ i.idx->key = id->key;
+ *i.value_64 = value;
+
+ pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,
+ i.idx->owner, i.idx->key,
+ (unsigned long long)*i.value_64);
+ return 0;
+ }
+ pr_debug("%s:%d: database full.\n",
+ __func__, __LINE__);
+ return -1;
+}
+
+static int db_get_64(const struct os_area_db *db,
+ const struct os_area_db_id *id, uint64_t *value)
+{
+ struct db_iterator i;
+
+ i.db = NULL;
+ if (db_for_each_64(db, id, &i)) {
+ *value = *i.value_64;
+ pr_debug("%s:%d: found %lld\n", __func__, __LINE__,
+ (long long int)*i.value_64);
+ return 0;
+ }
+ pr_debug("%s:%d: not found\n", __func__, __LINE__);
+ return -1;
+}
+
+static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff)
+{
+ return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);
+}
+
+#define dump_db(a) _dump_db(a, __func__, __LINE__)
+static void _dump_db(const struct os_area_db *db, const char *func,
+ int line)
+{
+ pr_debug("%s:%d: db.magic_num: '%s'\n", func, line,
+ (const char*)&db->magic_num);
+ pr_debug("%s:%d: db.version: %u\n", func, line,
+ db->version);
+ pr_debug("%s:%d: db.index_64: %u\n", func, line,
+ db->index_64);
+ pr_debug("%s:%d: db.count_64: %u\n", func, line,
+ db->count_64);
+ pr_debug("%s:%d: db.index_32: %u\n", func, line,
+ db->index_32);
+ pr_debug("%s:%d: db.count_32: %u\n", func, line,
+ db->count_32);
+ pr_debug("%s:%d: db.index_16: %u\n", func, line,
+ db->index_16);
+ pr_debug("%s:%d: db.count_16: %u\n", func, line,
+ db->count_16);
+}
+
+static void os_area_db_init(struct os_area_db *db)
+{
+ enum {
+ HEADER_SIZE = offsetof(struct os_area_db, _db_data),
+ INDEX_64_COUNT = 64,
+ VALUES_64_COUNT = 57,
+ INDEX_32_COUNT = 64,
+ VALUES_32_COUNT = 57,
+ INDEX_16_COUNT = 64,
+ VALUES_16_COUNT = 57,
+ };
+
+ memset(db, 0, sizeof(struct os_area_db));
+
+ db->magic_num = OS_AREA_DB_MAGIC_NUM;
+ db->version = 1;
+ db->index_64 = HEADER_SIZE;
+ db->count_64 = VALUES_64_COUNT;
+ db->index_32 = HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64);
+ db->count_32 = VALUES_32_COUNT;
+ db->index_16 = HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64)
+ + INDEX_32_COUNT * sizeof(struct db_index)
+ + VALUES_32_COUNT * sizeof(u32);
+ db->count_16 = VALUES_16_COUNT;
+
+ /* Rules to check db layout. */
+
+ BUILD_BUG_ON(sizeof(struct db_index) != 1);
+ BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);
+ BUILD_BUG_ON(INDEX_64_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);
+ BUILD_BUG_ON(INDEX_32_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);
+ BUILD_BUG_ON(INDEX_16_COUNT & 0x7);
+ BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);
+ BUILD_BUG_ON(HEADER_SIZE
+ + INDEX_64_COUNT * sizeof(struct db_index)
+ + VALUES_64_COUNT * sizeof(u64)
+ + INDEX_32_COUNT * sizeof(struct db_index)
+ + VALUES_32_COUNT * sizeof(u32)
+ + INDEX_16_COUNT * sizeof(struct db_index)
+ + VALUES_16_COUNT * sizeof(u16)
+ > sizeof(struct os_area_db));
+}
+
+/**
+ * update_flash_db - Helper for os_area_queue_work_handler.
+ *
+ */
+
+static void update_flash_db(void)
+{
+ int result;
+ int file;
+ off_t offset;
+ ssize_t count;
+ static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;
+ const struct os_area_header *header;
+ struct os_area_db* db;
+
+ /* Read in header and db from flash. */
+
+ file = sys_open("/dev/ps3flash", O_RDWR, 0);
+
+ if (file < 0) {
+ pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);
+ goto fail_open;
+ }
+
+ header = kmalloc(buf_len, GFP_KERNEL);
+
+ if (!header) {
+ pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);
+ goto fail_malloc;
+ }
+
+ offset = sys_lseek(file, 0, SEEK_SET);
+
+ if (offset != 0) {
+ pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
+ goto fail_header_seek;
+ }
+
+ count = sys_read(file, (char __user *)header, buf_len);
+
+ result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)
+ || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;
+
+ if (result) {
+ pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
+ dump_header(header);
+ goto fail_header;
+ }
+
+ /* Now got a good db offset and some maybe good db data. */
+
+ db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;
+
+ result = db_verify(db);
+
+ if (result) {
+ printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "
+ "formatting.\n", __func__, __LINE__);
+ dump_db(db);
+ os_area_db_init(db);
+ }
+
+ /* Now got good db data. */
+
+ db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);
+
+ offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,
+ SEEK_SET);
+
+ if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {
+ pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);
+ goto fail_db_seek;
+ }
+
+ count = sys_write(file, (const char __user *)db,
+ sizeof(struct os_area_db));
+
+ if (count < sizeof(struct os_area_db)) {
+ pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);
+ }
+
+fail_db_seek:
+fail_header:
+fail_header_seek:
+ kfree(header);
+fail_malloc:
+ sys_close(file);
+fail_open:
+ return;
+}
+
+/**
+ * os_area_queue_work_handler - Asynchronous write handler.
+ *
+ * An asynchronous write for flash memory and the device tree. Do not
+ * call directly, use os_area_queue_work().
+ */
+
+static void os_area_queue_work_handler(struct work_struct *work)
+{
+ struct device_node *node;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ node = of_find_node_by_path("/");
+
+ if (node) {
+ os_area_set_property(node, &property_rtc_diff);
+ of_node_put(node);
+ } else
+ pr_debug("%s:%d of_find_node_by_path failed\n",
+ __func__, __LINE__);
+
+#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)
+ update_flash_db();
+#else
+ printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",
+ __func__, __LINE__);
+#endif
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+}
+
+static void os_area_queue_work(void)
+{
+ static DECLARE_WORK(q, os_area_queue_work_handler);
+
+ wmb();
+ schedule_work(&q);
+}
+
+/**
+ * ps3_os_area_save_params - Copy data from os area mirror to @saved_params.
+ *
+ * For the convenience of the guest the HV makes a copy of the os area in
+ * flash to a high address in the boot memory region and then puts that RAM
+ * address and the byte count into the repository for retrieval by the guest.
+ * We copy the data we want into a static variable and allow the memory setup
+ * by the HV to be claimed by the lmb manager.
+ *
+ * The os area mirror will not be available to a second stage kernel, and
+ * the header verify will fail. In this case, the saved_params values will
+ * be set from flash memory or the passed in device tree in ps3_os_area_init().
+ */
+
+void __init ps3_os_area_save_params(void)
{
int result;
u64 lpar_addr;
unsigned int size;
struct os_area_header *header;
struct os_area_params *params;
+ struct os_area_db *db;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);
if (result) {
pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",
__func__, __LINE__);
- return result;
+ return;
}
header = (struct os_area_header *)__va(lpar_addr);
- params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE);
+ params = (struct os_area_params *)__va(lpar_addr
+ + OS_AREA_SEGMENT_SIZE);
result = verify_header(header);
if (result) {
+ /* Second stage kernels exit here. */
pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);
dump_header(header);
- return -EIO;
+ return;
}
+ db = (struct os_area_db *)__va(lpar_addr
+ + header->db_area_offset * OS_AREA_SEGMENT_SIZE);
+
dump_header(header);
dump_params(params);
+ dump_db(db);
- saved_params.rtc_diff = params->rtc_diff;
+ result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);
+ if (result)
+ saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff
+ : SECONDS_FROM_1970_TO_2000;
saved_params.av_multi_out = params->av_multi_out;
- saved_params.ctrl_button = params->ctrl_button;
- memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4);
- memcpy(saved_params.network_mask, params->network_mask, 4);
- memcpy(saved_params.default_gateway, params->default_gateway, 4);
- memcpy(saved_params.dns_secondary, params->dns_secondary, 4);
+ saved_params.valid = 1;
+
+ memset(header, 0, sizeof(*header));
- return result;
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
}
/**
- * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value.
+ * ps3_os_area_init - Setup os area device tree properties as needed.
+ */
+
+void __init ps3_os_area_init(void)
+{
+ struct device_node *node;
+
+ pr_debug(" -> %s:%d\n", __func__, __LINE__);
+
+ node = of_find_node_by_path("/");
+
+ if (!saved_params.valid && node) {
+ /* Second stage kernels should have a dt entry. */
+ os_area_get_property(node, &property_rtc_diff);
+ os_area_get_property(node, &property_av_multi_out);
+ }
+
+ if(!saved_params.rtc_diff)
+ saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;
+
+ if (node) {
+ os_area_set_property(node, &property_rtc_diff);
+ os_area_set_property(node, &property_av_multi_out);
+ of_node_put(node);
+ } else
+ pr_debug("%s:%d of_find_node_by_path failed\n",
+ __func__, __LINE__);
+
+ pr_debug(" <- %s:%d\n", __func__, __LINE__);
+}
+
+/**
+ * ps3_os_area_get_rtc_diff - Returns the rtc diff value.
+ */
+
+u64 ps3_os_area_get_rtc_diff(void)
+{
+ return saved_params.rtc_diff;
+}
+
+/**
+ * ps3_os_area_set_rtc_diff - Set the rtc diff value.
*
- * The ps3 rtc maintains a value that approximates seconds since
- * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to
- * 2000 when saved_params.rtc_diff has not been properly set up.
+ * An asynchronous write is needed to support writing updates from
+ * the timer interrupt context.
*/
-u64 ps3_os_area_rtc_diff(void)
+void ps3_os_area_set_rtc_diff(u64 rtc_diff)
{
- return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL;
+ if (saved_params.rtc_diff != rtc_diff) {
+ saved_params.rtc_diff = rtc_diff;
+ os_area_queue_work();
+ }
}
/**
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);
/* os area */
-int __init ps3_os_area_init(void);
-u64 ps3_os_area_rtc_diff(void);
+void __init ps3_os_area_save_params(void);
+void __init ps3_os_area_init(void);
+u64 ps3_os_area_get_rtc_diff(void);
+void ps3_os_area_set_rtc_diff(u64 rtc_diff);
/* spu */
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)
prealloc_ps3flash_bounce_buffer();
ppc_md.power_save = ps3_power_save;
+ ps3_os_area_init();
DBG(" <- %s:%d\n", __func__, __LINE__);
}
@@ -228,7 +229,7 @@ static int __init ps3_probe(void)
powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE;
- ps3_os_area_init();
+ ps3_os_area_save_params();
ps3_mm_init();
ps3_mm_vas_create(&htab_size);
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,
_dump_tm(&tm, func, line);
}
-/**
- * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value.
- */
-
-static s64 rtc_shift;
-
void __init ps3_calibrate_decr(void)
{
int result;
@@ -66,8 +60,6 @@ void __init ps3_calibrate_decr(void)
ppc_tb_freq = tmp;
ppc_proc_freq = ppc_tb_freq * 40;
-
- rtc_shift = ps3_os_area_rtc_diff();
}
static u64 read_rtc(void)
@@ -87,18 +79,18 @@ int ps3_set_rtc_time(struct rtc_time *tm)
u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
- rtc_shift = now - read_rtc();
+ ps3_os_area_set_rtc_diff(now - read_rtc());
return 0;
}
void ps3_get_rtc_time(struct rtc_time *tm)
{
- to_tm(read_rtc() + rtc_shift, tm);
+ to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm);
tm->tm_year -= 1900;
tm->tm_mon -= 1;
}
unsigned long __init ps3_get_boot_time(void)
{
- return read_rtc() + rtc_shift;
+ return read_rtc() + ps3_os_area_get_rtc_diff();
}
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 = {
static int __init pseries_cpu_hotplug_init(void)
{
+ struct device_node *np;
+ const char *typep;
+
+ for_each_node_by_name(np, "interrupt-controller") {
+ typep = of_get_property(np, "compatible", NULL);
+ if (strstr(typep, "open-pic")) {
+ of_node_put(np);
+
+ printk(KERN_INFO "CPU Hotplug not supported on "
+ "systems using MPIC\n");
+ return 0;
+ }
+ }
+
rtas_stop_self_args.token = rtas_token("stop-self");
qcss_tok = rtas_token("query-cpu-stopped-state");
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)
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000;
- if (ROOT_DEV == 0) {
- printk("No ramdisk, default root is /dev/sda2\n");
- ROOT_DEV = Root_SDA2;
- }
-
fwnmi_init();
/* 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[] = {
};
static struct of_platform_driver axon_ram_driver = {
- .owner = THIS_MODULE,
- .name = AXON_RAM_MODULE_NAME,
.match_table = axon_ram_device_id,
.probe = axon_ram_probe,
- .remove = axon_ram_remove
+ .remove = axon_ram_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = AXON_RAM_MODULE_NAME,
+ },
};
/**
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)
}
static struct of_platform_driver pmi_of_platform_driver = {
- .name = "pmi",
.match_table = pmi_match,
.probe = pmi_of_probe,
- .remove = pmi_of_remove
+ .remove = pmi_of_remove,
+ .driver = {
+ .name = "pmi",
+ },
};
static 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 @@
#include <linux/mtd/physmap.h>
#include <linux/mv643xx.h>
#include <linux/platform_device.h>
-#ifdef CONFIG_BOOTIMG
-#include <linux/bootimg.h>
-#endif
#include <asm/page.h>
#include <asm/time.h>
#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 @@
#include <linux/mtd/physmap.h>
#include <linux/mv643xx.h>
#include <linux/platform_device.h>
-#ifdef CONFIG_BOOTIMG
-#include <linux/bootimg.h>
-#endif
#include <asm/io.h>
#include <asm/unistd.h>
#include <asm/page.h>