]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'virtex-for-2.6.24' of git://git.secretlab.ca/git/linux-2.6-virtex into...
authorJosh Boyer <jwboyer@linux.vnet.ibm.com>
Thu, 11 Oct 2007 12:45:20 +0000 (07:45 -0500)
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>
Thu, 11 Oct 2007 12:45:20 +0000 (07:45 -0500)
59 files changed:
arch/powerpc/boot/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/of_platform.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/systbl.S
arch/powerpc/kernel/time.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vio.c
arch/powerpc/oprofile/cell/pr_util.h
arch/powerpc/oprofile/op_model_cell.c
arch/powerpc/platforms/40x/virtex.c
arch/powerpc/platforms/40x/walnut.c
arch/powerpc/platforms/44x/bamboo.c
arch/powerpc/platforms/44x/ebony.c
arch/powerpc/platforms/44x/sequoia.c
arch/powerpc/platforms/52xx/efika.c
arch/powerpc/platforms/cell/cbe_cpufreq.c
arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c
arch/powerpc/platforms/cell/cbe_regs.c
arch/powerpc/platforms/cell/cbe_thermal.c
arch/powerpc/platforms/cell/interrupt.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/pervasive.c
arch/powerpc/platforms/cell/pmu.c
arch/powerpc/platforms/cell/ras.c
arch/powerpc/platforms/cell/setup.c
arch/powerpc/platforms/celleb/setup.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/iseries/Makefile
arch/powerpc/platforms/iseries/dt.c
arch/powerpc/platforms/iseries/iommu.c
arch/powerpc/platforms/iseries/mf.c
arch/powerpc/platforms/iseries/vio.c [new file with mode: 0644]
arch/powerpc/platforms/iseries/viopath.c
arch/powerpc/platforms/pasemi/gpio_mdio.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/ps3/os-area.c
arch/powerpc/platforms/ps3/platform.h
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/ps3/time.c
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/axonram.c
arch/powerpc/sysdev/pmi.c
arch/ppc/platforms/ev64360.c
arch/ppc/platforms/katana.c
drivers/block/viodasd.c
drivers/cdrom/viocd.c
drivers/char/viotape.c
include/asm-powerpc/cell-regs.h [moved from arch/powerpc/platforms/cell/cbe_regs.h with 76% similarity]
include/asm-powerpc/cputable.h
include/asm-powerpc/iseries/hv_call_event.h
include/asm-powerpc/iseries/iommu.h
include/asm-powerpc/iseries/vio.h
include/asm-powerpc/machdep.h
include/asm-powerpc/vio.h

index f3f7ce3d79a5e98e48ff1dfbd56d4854b0abb14c..18e32719d0ed4544202bae47cc9c1361e6116649 100644 (file)
@@ -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
index b03a442b7888a28dcae8b0da7cf9a840a7216ee0..8662cf053fa0557b645576a34dea95f921f94b5b 100644 (file)
@@ -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
index f70e787d556fc6d6b08ce662e8b7fec35272d920..eca8ccc3fa127065a5b10640dd08b42c8ae15cd2 100644 (file)
 #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)
index 172dcc3849a0f9ad32bc5838c3a847a4e6c6420a..9f329a8928eaed27f3192e27c729e24bb73ac888 100644 (file)
@@ -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},
 };
 
index 7474502dace5880cabc5046c49d5e3c7441481f9..cd870a823d18a89952d4b9d622bb080e3b5ffc5b 100644 (file)
@@ -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();
index 3089eaed3256c7dda38f6922679cfeef57693019..008ab6823b022a1793259b62697008f15feb90d5 100644 (file)
@@ -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");
index 579de70e0b4dc3d32f473576ee8cc125b0406a57..93219c34af327b3e113a344485310b8f2923a879 100644 (file)
@@ -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)
index d20947cf1735965a418f33f6bebba525c21d2028..9368da371f3691c86af57bb34adbd1d6a995ed94 100644 (file)
@@ -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;
 }
index 213fa31ac53785155b4293536b198437e6457182..2322ba5cce4ce23c3eca48336686518671d05283 100644 (file)
@@ -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)
 {
index 1d7b272b373789355326731b311604482a81ad8e..cb22a3557c4e88303535336d8859eb2f0da69a7c 100644 (file)
@@ -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,
 };
 
 /**
index e5704f00c8b4be2f4783a5ec7391b8a60be1853e..22e4e8d4eb2c706daa7ad3481e87e4cc10afaf2b 100644 (file)
 #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
index d928b54f3a0fb9df3b03bc475b05d0f643e19429..bb6bff51ce484e6dbc4b315cc1815e3fe04b0d1c 100644 (file)
@@ -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);
index b52aa94abd789b0895d8f97c2b12acd66fbdc649..14bbc328170fd76e26e1a5479b2aded9794e802a 100644 (file)
@@ -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,
index c17fdf23b4920418b6c2ccf86c3b4413a772ff45..eb0c136b1c4408f2bd64fe8c403389a17a7c8440 100644 (file)
@@ -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,
index 9bc45dea078f411ec261de38706e5a6689f57aed..470e1a3fd755cced07b812f6507908daab22fcd1 100644 (file)
@@ -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,
index 5a7fec8d10d386628a60e40a04cd3bc972b143a7..40e18fcb666c09ba0f1d7822ded77d560182cc5c 100644 (file)
@@ -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,
index 7d0d9d567d253c8e0e03d691043fc86757864fa7..30700b31d43b7687d94495e0653fffb0e7c88a9c 100644 (file)
@@ -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,
index 4263158b3274f7bb9a417dd10808d17d0d94c376..0b1e60a010ba579d5b18e242583740d48355905c 100644 (file)
@@ -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
index 0b6e8ee85ab10be1faf5f9d985d3e750deff46bf..901236fa0f07bed62c1e63c191a4b5debd90fcd4 100644 (file)
@@ -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);
index 163263b3e1cdba667aab23ed162da2b76a6bb55c..70fa7aef5edd9a6404f0fdc7b58e57565903821e 100644 (file)
@@ -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 */
index fc6f38982ff47cc95163fc77b9449e43e9fc5951..6a2c1b0a9a9448432fe1cc7375ca4e8665127d47 100644 (file)
 #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];
index c8f7f000742216a3a3f87852c6844e4c85b255b0..16a9b07e7b0c24b75b2a5c17b779a5f3e12f4a27 100644 (file)
@@ -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
index fb5eda48467df8e723689c29ff1948bb6c2111a6..4852bf312d83c0d60a224eb9ab292dd832c96a64 100644 (file)
@@ -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
index c29e634177fa738d39db22a73138d72a749f995d..151fd8b82d63b2e0878a7ee48118b3cda0ca0576 100644 (file)
@@ -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;
index 760caa76841a025e35969ef58b67002f228e91e7..faabc3fdc130220ff7aeb8bd3ddc139e20157654 100644 (file)
@@ -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
index 4ede22d363fa7b701e446193b6b97fb4ec7c5600..0304589c0a80550e07be726c6557538f7ee8ae03 100644 (file)
@@ -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;
 
index 66ca4b5a1dbc6cab284962aec94ac9a38f2da189..1ed3036788879d018c7dcdab5bf68925d87f9fce 100644 (file)
@@ -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"
 
 /*
index 3961a085b432b4046bd2525c2e850c708da49ae4..b2494ebcdbe9a131beb472f2ca45d04825a509d9 100644 (file)
@@ -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)
index db6654272e133112acecdc83f35ad20e5c80b914..98e7ef8e6fc66a5becd6c3cd18a676bd6ef96fdb 100644 (file)
@@ -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();
index 0f1dddb81cd2a36b2b11457b0d1ae02249fec22a..1769d755eff30670eee5bd58f0c498b618aec4ce 100644 (file)
@@ -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
index 96498ad7b94385cea4f728769763160f6546792b..59306261f5b2991a329be96680c771ef134a9852 100644 (file)
@@ -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();
 
index 60db509638f123882fda51ba09ad8bda33539f8e..a65f1b44abf85f139b93ff337445fe0de8949e73 100644 (file)
@@ -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  $@
index 9e8a334a518a8cc1dd9f9224c4e88399d1a45a59..4543c4bc3a56e158cb47a3387d97c715dabc515e 100644 (file)
@@ -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);
 }
index 3b6a9666c2c07c0407989a5a17d98e2cdcdf4179..49e9c664ea89b0745829dfd52058f620b35fdb27 100644 (file)
 #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;
index b1187d95e3b27fc6da3a873e374babcc1d265c4b..c0f2433bc16e75c20532982c65e581902b0e5481 100644 (file)
@@ -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 (file)
index 0000000..910b00b
--- /dev/null
@@ -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);
index 6a0060a5f2ecb5178ec476f1cebff3448ec3b174..df23331eb25c2416b99fd91c137fa62675c7bbb8 100644 (file)
@@ -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,
index c91a33593bb86b9b391f5bd15b68cae2b026b9bb..dae9f658122e4ef47dffa02ba5877cd73bac2c52 100644 (file)
@@ -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)
index 7ccb9236e8b485580c5be98f69ed5858e4cda3a5..02c533096627851363c3864232b53d130659ed8b 100644 (file)
@@ -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
index b70e474014f028c9da8c938d164e7c7d4defcd26..766685ab26f82b46116c46953bb51286455c7990 100644 (file)
@@ -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();
+       }
 }
 
 /**
index 27c7d099816a2213b05057cace7e0734e41ad8e6..01f0c9506e11efec1ea93777abf385b24a8a61c0 100644 (file)
@@ -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 */
 
index 609945dbe39401459a1592cd5d264c3b10ad0507..5c2cbb08eb52f82a212503137ebae0cf5d8dca55 100644 (file)
@@ -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);
index 802a9ccacb5ea130cecbd143616c5944adde1e2c..d0daf7d6d3b26407d5ec87c0d5caef127943c4fe 100644 (file)
@@ -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();
 }
index 9711eb0d549645fee11f198fcb1cdf4ddc9f8860..fc48b96c81bff2ee1ec79eef9d1f13f62b6693cf 100644 (file)
@@ -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");
 
index f0b7146a110f7238abcd39d633db63dd44711481..fdb9b1c8f977e06704c714ff5d0c54366923fef4 100644 (file)
@@ -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 */
index ab037a3a40db196b0e01f9a15ddf878c354be3d6..4d3ba63bba79ad6ee53cb1c49d1d1cfd23944be8 100644 (file)
@@ -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,
+       },
 };
 
 /**
index 2f91b55b775475a8c839299801b390b670c4e183..20edd1e94eff7111927fef861236f8827e002b4d 100644 (file)
@@ -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)
index f8baf05f16ce14378dd964835845d9cd1abbeda0..6765676a5c6b23b00cf918fdaba0733cbb1858fc 100644 (file)
@@ -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>
index c289e9f1b251c6e83747859ee119abd07e2151d0..52f63e6f085622ec6a36eb381562f86d3d40e16e 100644 (file)
@@ -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>
index af3969a9c96301d3ab515c44b1554c472ddcd4e3..e824b672e05a23c75473d6d2a04b4462eb709bec 100644 (file)
@@ -74,53 +74,9 @@ enum {
 static DEFINE_SPINLOCK(viodasd_spinlock);
 
 #define VIOMAXREQ              16
-#define VIOMAXBLOCKDMA         12
 
 #define DEVICE_NO(cell)        ((struct viodasd_device *)(cell) - &viodasd_devices[0])
 
-struct open_data {
-       u64     disk_size;
-       u16     max_disk;
-       u16     cylinders;
-       u16     tracks;
-       u16     sectors;
-       u16     bytes_per_sector;
-};
-
-struct rw_data {
-       u64     offset;
-       struct {
-               u32     token;
-               u32     reserved;
-               u64     len;
-       } dma_info[VIOMAXBLOCKDMA];
-};
-
-struct vioblocklpevent {
-       struct HvLpEvent        event;
-       u32                     reserved;
-       u16                     version;
-       u16                     sub_result;
-       u16                     disk;
-       u16                     flags;
-       union {
-               struct open_data        open_data;
-               struct rw_data          rw_data;
-               u64                     changed;
-       } u;
-};
-
-#define vioblockflags_ro   0x0001
-
-enum vioblocksubtype {
-       vioblockopen = 0x0001,
-       vioblockclose = 0x0002,
-       vioblockread = 0x0003,
-       vioblockwrite = 0x0004,
-       vioblockflush = 0x0005,
-       vioblockcheck = 0x0007
-};
-
 struct viodasd_waitevent {
        struct completion       com;
        int                     rc;
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q)
  * Probe a single disk and fill in the viodasd_device structure
  * for it.
  */
-static void probe_disk(struct viodasd_device *d)
+static int probe_disk(struct viodasd_device *d)
 {
        HvLpEvent_Rc hvrc;
        struct viodasd_waitevent we;
@@ -453,14 +409,14 @@ retry:
                        0, 0, 0);
        if (hvrc != 0) {
                printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc);
-               return;
+               return 0;
        }
 
        wait_for_completion(&we.com);
 
        if (we.rc != 0) {
                if (flags != 0)
-                       return;
+                       return 0;
                /* try again with read only flag set */
                flags = vioblockflags_ro;
                goto retry;
@@ -490,15 +446,32 @@ retry:
        if (hvrc != 0) {
                printk(VIOD_KERN_WARNING
                       "bad rc sending event to OS/400 %d\n", (int)hvrc);
-               return;
+               return 0;
        }
+
+       if (d->dev == NULL) {
+               /* this is when we reprobe for new disks */
+               if (vio_create_viodasd(dev_no) == NULL) {
+                       printk(VIOD_KERN_WARNING
+                               "cannot allocate virtual device for disk %d\n",
+                               dev_no);
+                       return 0;
+               }
+               /*
+                * The vio_create_viodasd will have recursed into this
+                * routine with d->dev set to the new vio device and
+                * will finish the setup of the disk below.
+                */
+               return 1;
+       }
+
        /* create the request queue for the disk */
        spin_lock_init(&d->q_lock);
        q = blk_init_queue(do_viodasd_request, &d->q_lock);
        if (q == NULL) {
                printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n",
                                dev_no);
-               return;
+               return 0;
        }
        g = alloc_disk(1 << PARTITION_SHIFT);
        if (g == NULL) {
@@ -506,7 +479,7 @@ retry:
                                "cannot allocate disk structure for disk %d\n",
                                dev_no);
                blk_cleanup_queue(q);
-               return;
+               return 0;
        }
 
        d->disk = g;
@@ -538,6 +511,7 @@ retry:
 
        /* register us in the global list */
        add_disk(g);
+       return 1;
 }
 
 /* returns the total number of scatterlist elements converted */
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        struct viodasd_device *d = &viodasd_devices[vdev->unit_address];
 
        d->dev = &vdev->dev;
-       probe_disk(d);
-       if (d->disk == NULL)
+       if (!probe_disk(d))
                return -ENODEV;
        return 0;
 }
index e51550db1575acf758ba313bc207f72658547afa..880b5dce3a62b8e1acfbd3a7aab8d98e837e8629 100644 (file)
 #define VIOCD_KERN_WARNING             KERN_WARNING "viocd: "
 #define VIOCD_KERN_INFO                        KERN_INFO "viocd: "
 
-struct viocdlpevent {
-       struct HvLpEvent        event;
-       u32                     reserved;
-       u16                     version;
-       u16                     sub_result;
-       u16                     disk;
-       u16                     flags;
-       u32                     token;
-       u64                     offset;         /* On open, max number of disks */
-       u64                     len;            /* On open, size of the disk */
-       u32                     block_size;     /* Only set on open */
-       u32                     media_size;     /* Only set on open */
-};
-
-enum viocdsubtype {
-       viocdopen = 0x0001,
-       viocdclose = 0x0002,
-       viocdread = 0x0003,
-       viocdwrite = 0x0004,
-       viocdlockdoor = 0x0005,
-       viocdgetinfo = 0x0006,
-       viocdcheck = 0x0007
-};
-
 /*
  * Should probably make this a module parameter....sigh
  */
@@ -131,22 +107,13 @@ static struct capability_entry capability_table[] __initdata = {
 /* These are our internal structures for keeping track of devices */
 static int viocd_numdev;
 
-struct cdrom_info {
-       char    rsrcname[10];
-       char    type[4];
-       char    model[3];
-};
-/*
- * This needs to be allocated since it is passed to the
- * Hypervisor and we may be a module.
- */
-static struct cdrom_info *viocd_unitinfo;
-static dma_addr_t unitinfo_dmaaddr;
-
 struct disk_info {
        struct gendisk                  *viocd_disk;
        struct cdrom_device_info        viocd_info;
        struct device                   *dev;
+       const char                      *rsrcname;
+       const char                      *type;
+       const char                      *model;
 };
 static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
 
@@ -164,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
        for (i = 0; i < viocd_numdev; i++) {
                seq_printf(m, "viocd device %d is iSeries resource %10.10s"
                                "type %4.4s, model %3.3s\n",
-                               i, viocd_unitinfo[i].rsrcname,
-                               viocd_unitinfo[i].type,
-                               viocd_unitinfo[i].model);
+                               i, viocd_diskinfo[i].rsrcname,
+                               viocd_diskinfo[i].type,
+                               viocd_diskinfo[i].model);
        }
        return 0;
 }
@@ -216,61 +183,6 @@ struct block_device_operations viocd_fops = {
        .media_changed =        viocd_blk_media_changed,
 };
 
-/* Get info on CD devices from OS/400 */
-static void __init get_viocd_info(void)
-{
-       HvLpEvent_Rc hvrc;
-       int i;
-       struct viocd_waitevent we;
-
-       viocd_unitinfo = dma_alloc_coherent(iSeries_vio_dev,
-                       sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
-                       &unitinfo_dmaaddr, GFP_ATOMIC);
-       if (viocd_unitinfo == NULL) {
-               printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
-               return;
-       }
-
-       memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
-
-       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(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
-       if (hvrc != HvLpEvent_Rc_Good) {
-               printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
-                               (int)hvrc);
-               goto error_ret;
-       }
-
-       wait_for_completion(&we.com);
-
-       if (we.rc) {
-               const struct vio_error_entry *err =
-                       vio_lookup_rc(viocd_err_table, we.sub_result);
-               printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
-                               we.rc, we.sub_result, err->msg);
-               goto error_ret;
-       }
-
-       for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++)
-               viocd_numdev++;
-
-error_ret:
-       if (viocd_numdev == 0) {
-               dma_free_coherent(iSeries_vio_dev,
-                               sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
-                               viocd_unitinfo, unitinfo_dmaaddr);
-               viocd_unitinfo = NULL;
-       }
-}
-
 static int viocd_open(struct cdrom_device_info *cdi, int purpose)
 {
         struct disk_info *diskinfo = cdi->handle;
@@ -581,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
                                        bevent->block_size / 512);
                }
                /* FALLTHROUGH !! */
-       case viocdgetinfo:
        case viocdlockdoor:
                pwe = (struct viocd_waitevent *)event->xCorrelationToken;
 return_complete:
@@ -665,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        int deviceno;
        struct disk_info *d;
        struct cdrom_device_info *c;
-       struct cdrom_info *ci;
        struct request_queue *q;
+       struct device_node *node = vdev->dev.archdata.of_node;
 
        deviceno = vdev->unit_address;
-       if (deviceno >= viocd_numdev)
+       if (deviceno > VIOCD_MAX_CD)
                return -ENODEV;
+       if (!node)
+               return -ENODEV;
+
+       if (deviceno >= viocd_numdev)
+               viocd_numdev = deviceno + 1;
 
        d = &viocd_diskinfo[deviceno];
+       d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
+       d->type = of_get_property(node, "linux,vio_type", NULL);
+       d->model = of_get_property(node, "linux,vio_model", NULL);
+
        c = &d->viocd_info;
-       ci = &viocd_unitinfo[deviceno];
 
        c->ops = &viocd_dops;
        c->speed = 4;
        c->capacity = 1;
        c->handle = d;
-       c->mask = ~find_capability(ci->type);
+       c->mask = ~find_capability(d->type);
        sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
 
        if (register_cdrom(c) != 0) {
@@ -690,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
        }
        printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s "
                        "type %4.4s, model %3.3s\n",
-                       c->name, ci->rsrcname, ci->type, ci->model);
+                       c->name, d->rsrcname, d->type, d->model);
        q = blk_init_queue(do_viocd_request, &viocd_reqlock);
        if (q == NULL) {
                printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n",
@@ -799,8 +718,6 @@ static int __init viocd_init(void)
        /* Initialize our request handler */
        vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
 
-       get_viocd_info();
-
        spin_lock_init(&viocd_reqlock);
 
        ret = vio_register_driver(&viocd_driver);
@@ -816,9 +733,6 @@ static int __init viocd_init(void)
        return 0;
 
 out_free_info:
-       dma_free_coherent(iSeries_vio_dev,
-                       sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
-                       viocd_unitinfo, unitinfo_dmaaddr);
        vio_clearHandler(viomajorsubtype_cdio);
        viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
 out_unregister:
@@ -830,10 +744,6 @@ static void __exit viocd_exit(void)
 {
        remove_proc_entry("iSeries/viocd", NULL);
        vio_unregister_driver(&viocd_driver);
-       if (viocd_unitinfo != NULL)
-               dma_free_coherent(iSeries_vio_dev,
-                               sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
-                               viocd_unitinfo, unitinfo_dmaaddr);
        viopath_close(viopath_hostLp, viomajorsubtype_cdio, MAX_CD_REQ + 2);
        vio_clearHandler(viomajorsubtype_cdio);
        unregister_blkdev(VIOCD_MAJOR, VIOCD_DEVICE);
index e12275df6ea2d271ec630f9c89945c6753bdf726..f1d60f0cef8f860b3b402a680e98f71214e975d7 100644 (file)
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
 #define VIOTAPOP_SETPART       14
 #define VIOTAPOP_UNLOAD        15
 
-struct viotapelpevent {
-       struct HvLpEvent event;
-       u32 reserved;
-       u16 version;
-       u16 sub_type_result;
-       u16 tape;
-       u16 flags;
-       u32 token;
-       u64 len;
-       union {
-               struct {
-                       u32 tape_op;
-                       u32 count;
-               } op;
-               struct {
-                       u32 type;
-                       u32 resid;
-                       u32 dsreg;
-                       u32 gstat;
-                       u32 erreg;
-                       u32 file_no;
-                       u32 block_no;
-               } get_status;
-               struct {
-                       u32 block_no;
-               } get_pos;
-       } u;
-};
-
-enum viotapesubtype {
-       viotapeopen = 0x0001,
-       viotapeclose = 0x0002,
-       viotaperead = 0x0003,
-       viotapewrite = 0x0004,
-       viotapegetinfo = 0x0005,
-       viotapeop = 0x0006,
-       viotapegetpos = 0x0007,
-       viotapesetpos = 0x0008,
-       viotapegetstatus = 0x0009
-};
-
 enum viotaperc {
        viotape_InvalidRange = 0x0601,
        viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
 #define VIOT_WRITING           2
 
 /* Our info on the tapes */
-struct tape_descr {
-       char rsrcname[10];
-       char type[4];
-       char model[3];
-};
-
-static struct tape_descr *viotape_unitinfo;
-static dma_addr_t viotape_unitinfo_token;
+static struct {
+       const char *rsrcname;
+       const char *type;
+       const char *model;
+} viotape_unitinfo[VIOTAPE_MAX_TAPE];
 
 static struct mtget viomtget[VIOTAPE_MAX_TAPE];
 
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
        return -err->errno;
 }
 
-/* Get info on all tapes from OS/400 */
-static int get_viotape_info(void)
-{
-       HvLpEvent_Rc hvrc;
-       int i;
-       size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
-       struct op_struct *op = get_op_struct();
-
-       if (op == NULL)
-               return -ENOMEM;
-
-       viotape_unitinfo = dma_alloc_coherent(iSeries_vio_dev, len,
-               &viotape_unitinfo_token, GFP_ATOMIC);
-       if (viotape_unitinfo == NULL) {
-               free_op_struct(op);
-               return -ENOMEM;
-       }
-
-       memset(viotape_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) op, VIOVERSION << 16,
-                       viotape_unitinfo_token, len, 0, 0);
-       if (hvrc != HvLpEvent_Rc_Good) {
-               printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
-                               (int)hvrc);
-               free_op_struct(op);
-               return -EIO;
-       }
-
-       wait_for_completion(&op->com);
-
-       free_op_struct(op);
-
-       for (i = 0;
-            ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
-            i++)
-               viotape_numdev++;
-       return 0;
-}
-
-
 /* Write */
 static ssize_t viotap_write(struct file *file, const char *buf,
                size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
        tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
        op = (struct op_struct *)event->xCorrelationToken;
        switch (tapeminor) {
-       case viotapegetinfo:
        case viotapeopen:
        case viotapeclose:
                op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 {
        int i = vdev->unit_address;
        int j;
+       struct device_node *node = vdev->dev.archdata.of_node;
 
-       if (i >= viotape_numdev)
+       if (i > VIOTAPE_MAX_TAPE)
+               return -ENODEV;
+       if (!node)
                return -ENODEV;
 
+       if (i >= viotape_numdev)
+               viotape_numdev = i + 1;
+
        tape_device[i] = &vdev->dev;
+       viotape_unitinfo[i].rsrcname = of_get_property(node,
+                                       "linux,vio_rsrcname", NULL);
+       viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
+                                       NULL);
+       viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
+                                       NULL);
 
        state[i].cur_part = 0;
        for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
                goto unreg_chrdev;
        }
 
-       if ((ret = get_viotape_info()) < 0) {
-               printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
-               goto unreg_class;
-       }
-
        ret = vio_register_driver(&viotape_driver);
        if (ret)
                goto unreg_class;
@@ -1102,10 +1017,6 @@ static void __exit viotap_exit(void)
        vio_unregister_driver(&viotape_driver);
        class_destroy(tape_class);
        unregister_chrdev(VIOTAPE_MAJOR, "viotape");
-       if (viotape_unitinfo)
-               dma_free_coherent(iSeries_vio_dev,
-                               sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
-                               viotape_unitinfo, viotape_unitinfo_token);
        viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
        vio_clearHandler(viomajorsubtype_tape);
        clear_op_struct_pool();
similarity index 76%
rename from arch/powerpc/platforms/cell/cbe_regs.h
rename to include/asm-powerpc/cell-regs.h
index b24025f2ac7aa0466a9b443e01975838db4ae226..fd6fd00434efc04e0e0bffdaeb98d4c9e1aac8dd 100644 (file)
@@ -244,16 +244,60 @@ struct cbe_mic_tm_regs {
        u64     slow_fast_timer_0;                              /* 0x0090 */
        u64     slow_next_timer_0;                              /* 0x0098 */
 
-       u8      pad_0x00a0_0x01c0[0x01c0 - 0x0a0];              /* 0x00a0 */
+       u8      pad_0x00a0_0x00f8[0x00f8 - 0x00a0];             /* 0x00a0 */
+       u64     mic_df_ecc_address_0;                           /* 0x00f8 */
+
+       u8      pad_0x0100_0x01b8[0x01b8 - 0x0100];             /* 0x0100 */
+       u64     mic_df_ecc_address_1;                           /* 0x01b8 */
 
        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 */
+       u8      pad_0x01e0_0x0208[0x0208 - 0x01e0];             /* 0x01e0 */
+       u64     mic_exc;                                        /* 0x0208 */
+#define CBE_MIC_EXC_BLOCK_SCRUB                0x0800000000000000ULL
+#define CBE_MIC_EXC_FAST_SCRUB         0x0100000000000000ULL
+
+       u64     mic_mnt_cfg;                                    /* 0x0210 */
+#define CBE_MIC_MNT_CFG_CHAN_0_POP     0x0002000000000000ULL
+#define CBE_MIC_MNT_CFG_CHAN_1_POP     0x0004000000000000ULL
+
+       u64     mic_df_config;                                  /* 0x0218 */
+#define CBE_MIC_ECC_DISABLE_0          0x4000000000000000ULL
+#define CBE_MIC_ECC_REP_SINGLE_0       0x2000000000000000ULL
+#define CBE_MIC_ECC_DISABLE_1          0x0080000000000000ULL
+#define CBE_MIC_ECC_REP_SINGLE_1       0x0040000000000000ULL
+
+       u8      pad_0x0220_0x0230[0x0230 - 0x0220];             /* 0x0220 */
+       u64     mic_fir;                                        /* 0x0230 */
+#define CBE_MIC_FIR_ECC_SINGLE_0_ERR   0x0200000000000000ULL
+#define CBE_MIC_FIR_ECC_MULTI_0_ERR    0x0100000000000000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_1_ERR   0x0080000000000000ULL
+#define CBE_MIC_FIR_ECC_MULTI_1_ERR    0x0040000000000000ULL
+#define CBE_MIC_FIR_ECC_ERR_MASK       0xffff000000000000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_0_CTE   0x0000020000000000ULL
+#define CBE_MIC_FIR_ECC_MULTI_0_CTE    0x0000010000000000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_1_CTE   0x0000008000000000ULL
+#define CBE_MIC_FIR_ECC_MULTI_1_CTE    0x0000004000000000ULL
+#define CBE_MIC_FIR_ECC_CTE_MASK       0x0000ffff00000000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_0_RESET 0x0000000002000000ULL
+#define CBE_MIC_FIR_ECC_MULTI_0_RESET  0x0000000001000000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_1_RESET 0x0000000000800000ULL
+#define CBE_MIC_FIR_ECC_MULTI_1_RESET  0x0000000000400000ULL
+#define CBE_MIC_FIR_ECC_RESET_MASK     0x00000000ffff0000ULL
+#define CBE_MIC_FIR_ECC_SINGLE_0_SET   0x0000000000000200ULL
+#define CBE_MIC_FIR_ECC_MULTI_0_SET    0x0000000000000100ULL
+#define CBE_MIC_FIR_ECC_SINGLE_1_SET   0x0000000000000080ULL
+#define CBE_MIC_FIR_ECC_MULTI_1_SET    0x0000000000000040ULL
+#define CBE_MIC_FIR_ECC_SET_MASK       0x000000000000ffffULL
+       u64     mic_fir_debug;                                  /* 0x0238 */
+
+       u8      pad_0x0240_0x1000[0x1000 - 0x0240];             /* 0x0240 */
 };
 
 extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np);
index c9b8f64bbb45d4c59a3e74d583fc98facadcfae2..d913f460e710be044663449c8bfc1ae44a78e2b3 100644 (file)
@@ -57,6 +57,7 @@ enum powerpc_pmc_type {
        PPC_PMC_PA6T = 2,
 };
 
+/* NOTE WELL: Update identify_cpu() if fields are added or removed! */
 struct cpu_spec {
        /* CPU is matched via (PVR & pvr_mask) == pvr_value */
        unsigned int    pvr_mask;
index 4cec4762076dffa99ce78ddc86401f2721af0ede..cc029d388e11a6bf3f5f1eda0bf53c91b0925c18 100644 (file)
@@ -21,6 +21,9 @@
 #ifndef _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
 #define _ASM_POWERPC_ISERIES_HV_CALL_EVENT_H
 
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/iseries/hv_call_sc.h>
 #include <asm/iseries/hv_types.h>
 #include <asm/abs_addr.h>
@@ -113,6 +116,13 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
                        eventData3, eventData4, eventData5);
 }
 
+extern void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag);
+extern void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle);
+extern dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+                       enum dma_data_direction direction);
+extern void iseries_hv_unmap(dma_addr_t dma_handle, size_t size,
+                       enum dma_data_direction direction);
+
 static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
 {
        return HvCall1(HvCallEventAckLpEvent, virt_to_abs(event));
index 6e323a13ac3031e760295b7583bb3dec24097a40..c59ee7e4bed117d7cf7fd960d8b56fffcbeef6ef 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 struct pci_dev;
+struct vio_dev;
 struct device_node;
 struct iommu_table;
 
@@ -34,4 +35,7 @@ extern void iommu_table_getparms_iSeries(unsigned long busno,
                unsigned char slotno, unsigned char virtbus,
                struct iommu_table *tbl);
 
+extern struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev);
+extern void iommu_vio_init(void);
+
 #endif /* _ASM_POWERPC_ISERIES_IOMMU_H */
index 7a95d296abd12201a0e75dff0d228c14a2770bbc..f9ac0d00b9517de34216580b741dc2013592f5f2 100644 (file)
  */
 #define VIO_MAX_SUBTYPES 8
 
+#define VIOMAXBLOCKDMA 12
+
+struct open_data {
+       u64     disk_size;
+       u16     max_disk;
+       u16     cylinders;
+       u16     tracks;
+       u16     sectors;
+       u16     bytes_per_sector;
+};
+
+struct rw_data {
+       u64     offset;
+       struct {
+               u32     token;
+               u32     reserved;
+               u64     len;
+       } dma_info[VIOMAXBLOCKDMA];
+};
+
+struct vioblocklpevent {
+       struct HvLpEvent        event;
+       u32                     reserved;
+       u16                     version;
+       u16                     sub_result;
+       u16                     disk;
+       u16                     flags;
+       union {
+               struct open_data        open_data;
+               struct rw_data          rw_data;
+               u64                     changed;
+       } u;
+};
+
+#define vioblockflags_ro   0x0001
+
+enum vioblocksubtype {
+       vioblockopen = 0x0001,
+       vioblockclose = 0x0002,
+       vioblockread = 0x0003,
+       vioblockwrite = 0x0004,
+       vioblockflush = 0x0005,
+       vioblockcheck = 0x0007
+};
+
+struct viocdlpevent {
+       struct HvLpEvent        event;
+       u32                     reserved;
+       u16                     version;
+       u16                     sub_result;
+       u16                     disk;
+       u16                     flags;
+       u32                     token;
+       u64                     offset;         /* On open, max number of disks */
+       u64                     len;            /* On open, size of the disk */
+       u32                     block_size;     /* Only set on open */
+       u32                     media_size;     /* Only set on open */
+};
+
+enum viocdsubtype {
+       viocdopen = 0x0001,
+       viocdclose = 0x0002,
+       viocdread = 0x0003,
+       viocdwrite = 0x0004,
+       viocdlockdoor = 0x0005,
+       viocdgetinfo = 0x0006,
+       viocdcheck = 0x0007
+};
+
+struct viotapelpevent {
+       struct HvLpEvent event;
+       u32 reserved;
+       u16 version;
+       u16 sub_type_result;
+       u16 tape;
+       u16 flags;
+       u32 token;
+       u64 len;
+       union {
+               struct {
+                       u32 tape_op;
+                       u32 count;
+               } op;
+               struct {
+                       u32 type;
+                       u32 resid;
+                       u32 dsreg;
+                       u32 gstat;
+                       u32 erreg;
+                       u32 file_no;
+                       u32 block_no;
+               } get_status;
+               struct {
+                       u32 block_no;
+               } get_pos;
+       } u;
+};
+
+enum viotapesubtype {
+       viotapeopen = 0x0001,
+       viotapeclose = 0x0002,
+       viotaperead = 0x0003,
+       viotapewrite = 0x0004,
+       viotapegetinfo = 0x0005,
+       viotapeop = 0x0006,
+       viotapegetpos = 0x0007,
+       viotapesetpos = 0x0008,
+       viotapegetstatus = 0x0009
+};
+
 /*
  * Each subtype can register a handler to process their events.
  * The handler must have this interface.
@@ -68,6 +178,8 @@ extern void vio_set_hostlp(void);
 extern void *vio_get_event_buffer(int subtype);
 extern void vio_free_event_buffer(int subtype, void *buffer);
 
+extern struct vio_dev *vio_create_viodasd(u32 unit);
+
 extern HvLpIndex viopath_hostLp;
 extern HvLpIndex viopath_ourLp;
 
@@ -150,8 +262,4 @@ enum viochar_rc {
        viochar_rc_ebusy = 1
 };
 
-struct device;
-
-extern struct device *iSeries_vio_dev;
-
 #endif /* _ASM_POWERPC_ISERIES_VIO_H */
index 71c6e7eb2a266798d56e3c6676d528fa1fa8be3f..cc7c17f16a9a71a2699d577ff644e63141ba5c32 100644 (file)
@@ -99,7 +99,7 @@ struct machdep_calls {
 #endif /* CONFIG_PPC64 */
 
        int             (*probe)(void);
-       void            (*setup_arch)(void);
+       void            (*setup_arch)(void); /* Optional, may be NULL */
        void            (*init_early)(void);
        /* Optional, may be NULL. */
        void            (*show_cpuinfo)(struct seq_file *m);
index 598d111e80981dd08adf1b4126557e1ae6d76b38..9204c15839c57a01e6fe31720ead644705a08069 100644 (file)
@@ -53,17 +53,12 @@ struct vio_dev {
 };
 
 struct vio_driver {
-       struct list_head node;
        const struct vio_device_id *id_table;
        int (*probe)(struct vio_dev *dev, const struct vio_device_id *id);
        int (*remove)(struct vio_dev *dev);
-       void (*shutdown)(struct vio_dev *dev);
-       unsigned long driver_data;
        struct device_driver driver;
 };
 
-extern struct dma_mapping_ops vio_dma_ops;
-
 extern int vio_register_driver(struct vio_driver *drv);
 extern void vio_unregister_driver(struct vio_driver *drv);