diff options
59 files changed, 1606 insertions, 636 deletions
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index f3f7ce3d79a5..18e32719d0ed 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -25,6 +25,10 @@ BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -isystem $(shell $(CROSS32CC) -print-file-name=include) BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc +ifdef CONFIG_DEBUG_INFO +BOOTCFLAGS += -g +endif + ifeq ($(call cc-option-yn, -fstack-protector),y) BOOTCFLAGS += -fno-stack-protector endif diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index b03a442b7888..8662cf053fa0 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -71,7 +71,7 @@ extern void __restore_cpu_ppc970(void); #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ PPC_FEATURE_BOOKE) -static struct cpu_spec cpu_specs[] = { +static struct cpu_spec __initdata cpu_specs[] = { #ifdef CONFIG_PPC64 { /* Power3 */ .pvr_mask = 0xffff0000, @@ -327,14 +327,6 @@ static struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER5_PLUS, .icache_bsize = 128, .dcache_bsize = 128, - .num_pmcs = 6, - .pmc_type = PPC_PMC_IBM, - .oprofile_cpu_type = "ppc64/power6", - .oprofile_type = PPC_OPROFILE_POWER4, - .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, - .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, - .oprofile_mmcra_clear = POWER6_MMCRA_THRM | - POWER6_MMCRA_OTHER, .platform = "power5+", }, { /* Power6 */ @@ -364,14 +356,6 @@ static struct cpu_spec cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER6, .icache_bsize = 128, .dcache_bsize = 128, - .num_pmcs = 6, - .pmc_type = PPC_PMC_IBM, - .oprofile_cpu_type = "ppc64/power6", - .oprofile_type = PPC_OPROFILE_POWER4, - .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, - .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, - .oprofile_mmcra_clear = POWER6_MMCRA_THRM | - POWER6_MMCRA_OTHER, .platform = "power6", }, { /* Cell Broadband Engine */ @@ -1316,18 +1300,37 @@ static struct cpu_spec cpu_specs[] = { #endif /* CONFIG_PPC32 */ }; -struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr) +static struct cpu_spec the_cpu_spec; + +struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) { struct cpu_spec *s = cpu_specs; - struct cpu_spec **cur = &cur_cpu_spec; + struct cpu_spec *t = &the_cpu_spec; int i; s = PTRRELOC(s); - cur = PTRRELOC(cur); + t = PTRRELOC(t); for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) if ((pvr & s->pvr_mask) == s->pvr_value) { - *cur = cpu_specs + i; + /* + * If we are overriding a previous value derived + * from the real PVR with a new value obtained + * using a logical PVR value, don't modify the + * performance monitor fields. + */ + if (t->num_pmcs && !s->num_pmcs) { + t->cpu_name = s->cpu_name; + t->cpu_features = s->cpu_features; + t->cpu_user_features = s->cpu_user_features; + t->icache_bsize = s->icache_bsize; + t->dcache_bsize = s->dcache_bsize; + t->cpu_setup = s->cpu_setup; + t->cpu_restore = s->cpu_restore; + t->platform = s->platform; + } else + *t = *s; + *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) /* ppc64 and booke expect identify_cpu to also call * setup_cpu for that processor. I will consolidate diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index f70e787d556f..eca8ccc3fa12 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -19,11 +19,11 @@ #include <linux/mod_devicetable.h> #include <linux/slab.h> #include <linux/pci.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> #include <asm/errno.h> #include <asm/dcr.h> -#include <asm/of_device.h> -#include <asm/of_platform.h> #include <asm/topology.h> #include <asm/pci-bridge.h> #include <asm/ppc-pci.h> @@ -70,7 +70,10 @@ postcore_initcall(of_bus_driver_init); int of_register_platform_driver(struct of_platform_driver *drv) { /* initialize common driver fields */ - drv->driver.name = drv->name; + if (!drv->driver.name) + drv->driver.name = drv->name; + if (!drv->driver.owner) + drv->driver.owner = drv->owner; drv->driver.bus = &of_platform_bus_type; /* register with core */ @@ -385,9 +388,11 @@ static struct of_device_id of_pci_phb_ids[] = { }; static struct of_platform_driver of_pci_phb_driver = { - .name = "of-pci", - .match_table = of_pci_phb_ids, - .probe = of_pci_phb_probe, + .match_table = of_pci_phb_ids, + .probe = of_pci_phb_probe, + .driver = { + .name = "of-pci", + }, }; static __init int of_pci_phb_init(void) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 172dcc3849a0..9f329a8928ea 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -531,10 +531,7 @@ static struct ibm_pa_feature { {CPU_FTR_CTRL, 0, 0, 3, 0}, {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, -#if 0 - /* put this back once we know how to test if firmware does 64k IO */ {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, -#endif {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, }; diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 7474502dace5..cd870a823d18 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -290,7 +290,8 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif - ppc_md.setup_arch(); + if (ppc_md.setup_arch) + ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); paging_init(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 3089eaed3256..008ab6823b02 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -530,7 +530,8 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif - ppc_md.setup_arch(); + if (ppc_md.setup_arch) + ppc_md.setup_arch(); paging_init(); ppc64_boot_msg(0x15, "Setup Done"); diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 579de70e0b4d..93219c34af32 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -39,6 +39,8 @@ #ifdef CONFIG_PPC64 #define sys_sigpending sys_ni_syscall #define sys_old_getrlimit sys_ni_syscall + + .p2align 3 #endif _GLOBAL(sys_call_table) diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index d20947cf1735..9368da371f36 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -108,7 +108,7 @@ static void decrementer_set_mode(enum clock_event_mode mode, static struct clock_event_device decrementer_clockevent = { .name = "decrementer", .rating = 200, - .shift = 32, + .shift = 16, .mult = 0, /* To be filled in */ .irq = 0, .set_next_event = decrementer_set_next_event, @@ -118,6 +118,7 @@ static struct clock_event_device decrementer_clockevent = { static DEFINE_PER_CPU(struct clock_event_device, decrementers); void init_decrementer_clockevent(void); +static DEFINE_PER_CPU(u64, decrementer_next_tb); #ifdef CONFIG_PPC_ISERIES static unsigned long __initdata iSeries_recal_titan; @@ -541,6 +542,7 @@ void timer_interrupt(struct pt_regs * regs) struct pt_regs *old_regs; int cpu = smp_processor_id(); struct clock_event_device *evt = &per_cpu(decrementers, cpu); + u64 now; /* Ensure a positive value is written to the decrementer, or else * some CPUs will continuue to take decrementer exceptions */ @@ -551,6 +553,14 @@ void timer_interrupt(struct pt_regs * regs) do_IRQ(regs); #endif + now = get_tb_or_rtc(); + if (now < per_cpu(decrementer_next_tb, cpu)) { + /* not time for this event yet */ + now = per_cpu(decrementer_next_tb, cpu) - now; + if (now <= DECREMENTER_MAX) + set_dec((unsigned int)now - 1); + return; + } old_regs = set_irq_regs(regs); irq_enter(); @@ -797,6 +807,10 @@ void __init clocksource_init(void) static int decrementer_set_next_event(unsigned long evt, struct clock_event_device *dev) { + __get_cpu_var(decrementer_next_tb) = get_tb_or_rtc() + evt; + /* The decrementer interrupts on the 0 -> -1 transition */ + if (evt) + --evt; set_dec(evt); return 0; } diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 213fa31ac537..2322ba5cce4c 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -766,7 +766,9 @@ static int __init vdso_init(void) return 0; } +#ifdef CONFIG_PPC_MERGE arch_initcall(vdso_init); +#endif int in_gate_area_no_task(unsigned long addr) { diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 1d7b272b3737..cb22a3557c4e 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -48,66 +48,33 @@ static struct vio_dev vio_bus_device = { /* fake "parent" device */ .dev.bus = &vio_bus_type, }; -#ifdef CONFIG_PPC_ISERIES -struct device *iSeries_vio_dev = &vio_bus_device.dev; -EXPORT_SYMBOL(iSeries_vio_dev); +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) +{ + const unsigned char *dma_window; + struct iommu_table *tbl; + unsigned long offset, size; -static struct iommu_table veth_iommu_table; -static struct iommu_table vio_iommu_table; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return vio_build_iommu_table_iseries(dev); -static void __init iommu_vio_init(void) -{ - iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); - veth_iommu_table.it_size /= 2; - vio_iommu_table = veth_iommu_table; - vio_iommu_table.it_offset += veth_iommu_table.it_size; - - if (!iommu_init_table(&veth_iommu_table, -1)) - printk("Virtual Bus VETH TCE table failed.\n"); - if (!iommu_init_table(&vio_iommu_table, -1)) - printk("Virtual Bus VIO TCE table failed.\n"); - vio_bus_device.dev.archdata.dma_ops = &dma_iommu_ops; - vio_bus_device.dev.archdata.dma_data = &vio_iommu_table; -} -#else -static void __init iommu_vio_init(void) -{ -} -#endif + dma_window = of_get_property(dev->dev.archdata.of_node, + "ibm,my-dma-window", NULL); + if (!dma_window) + return NULL; -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ -#ifdef CONFIG_PPC_ISERIES - if (firmware_has_feature(FW_FEATURE_ISERIES)) { - if (strcmp(dev->type, "network") == 0) - return &veth_iommu_table; - return &vio_iommu_table; - } else -#endif - { - const unsigned char *dma_window; - struct iommu_table *tbl; - unsigned long offset, size; - - dma_window = of_get_property(dev->dev.archdata.of_node, - "ibm,my-dma-window", NULL); - if (!dma_window) - return NULL; - - tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); - - of_parse_dma_window(dev->dev.archdata.of_node, dma_window, - &tbl->it_index, &offset, &size); - - /* TCE table size - measured in tce entries */ - tbl->it_size = size >> IOMMU_PAGE_SHIFT; - /* offset for VIO should always be 0 */ - tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; - tbl->it_busno = 0; - tbl->it_type = TCE_VB; - - return iommu_init_table(tbl, -1); - } + tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); + + of_parse_dma_window(dev->dev.archdata.of_node, dma_window, + &tbl->it_index, &offset, &size); + + /* TCE table size - measured in tce entries */ + tbl->it_size = size >> IOMMU_PAGE_SHIFT; + /* offset for VIO should always be 0 */ + tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; + tbl->it_busno = 0; + tbl->it_type = TCE_VB; + + return iommu_init_table(tbl, -1); } /** @@ -168,16 +135,6 @@ static int vio_bus_remove(struct device *dev) return 1; } -/* convert from struct device to struct vio_dev and pass to driver. */ -static void vio_bus_shutdown(struct device *dev) -{ - struct vio_dev *viodev = to_vio_dev(dev); - struct vio_driver *viodrv = to_vio_driver(dev->driver); - - if (dev->driver && viodrv->shutdown) - viodrv->shutdown(viodev); -} - /** * vio_register_driver: - Register a new vio driver * @drv: The vio_driver structure to be registered. @@ -290,9 +247,6 @@ static int __init vio_bus_init(void) int err; struct device_node *node_vroot; - if (firmware_has_feature(FW_FEATURE_ISERIES)) - iommu_vio_init(); - err = bus_register(&vio_bus_type); if (err) { printk(KERN_ERR "failed to register VIO bus\n"); @@ -397,7 +351,6 @@ static struct bus_type vio_bus_type = { .match = vio_bus_match, .probe = vio_bus_probe, .remove = vio_bus_remove, - .shutdown = vio_bus_shutdown, }; /** diff --git a/arch/powerpc/oprofile/cell/pr_util.h b/arch/powerpc/oprofile/cell/pr_util.h index e5704f00c8b4..22e4e8d4eb2c 100644 --- a/arch/powerpc/oprofile/cell/pr_util.h +++ b/arch/powerpc/oprofile/cell/pr_util.h @@ -17,10 +17,9 @@ #include <linux/cpumask.h> #include <linux/oprofile.h> #include <asm/cell-pmu.h> +#include <asm/cell-regs.h> #include <asm/spu.h> -#include "../../platforms/cell/cbe_regs.h" - /* Defines used for sync_start */ #define SKIP_GENERIC_SYNC 0 #define SYNC_START_ERROR -1 diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index d928b54f3a0f..bb6bff51ce48 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -35,9 +35,9 @@ #include <asm/reg.h> #include <asm/rtas.h> #include <asm/system.h> +#include <asm/cell-regs.h> #include "../platforms/cell/interrupt.h" -#include "../platforms/cell/cbe_regs.h" #include "cell/pr_util.h" static void cell_global_stop_spu(void); diff --git a/arch/powerpc/platforms/40x/virtex.c b/arch/powerpc/platforms/40x/virtex.c index b52aa94abd78..14bbc328170f 100644 --- a/arch/powerpc/platforms/40x/virtex.c +++ b/arch/powerpc/platforms/40x/virtex.c @@ -36,14 +36,9 @@ static int __init virtex_probe(void) return 1; } -static void __init virtex_setup_arch(void) -{ -} - define_machine(virtex) { .name = "Xilinx Virtex", .probe = virtex_probe, - .setup_arch = virtex_setup_arch, .init_IRQ = xilinx_intc_init_tree, .get_irq = xilinx_intc_get_irq, .calibrate_decr = generic_calibrate_decr, diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c index c17fdf23b492..eb0c136b1c44 100644 --- a/arch/powerpc/platforms/40x/walnut.c +++ b/arch/powerpc/platforms/40x/walnut.c @@ -53,14 +53,9 @@ static int __init walnut_probe(void) return 1; } -static void __init walnut_setup_arch(void) -{ -} - define_machine(walnut) { .name = "Walnut", .probe = walnut_probe, - .setup_arch = walnut_setup_arch, .progress = udbg_progress, .init_IRQ = uic_init_tree, .get_irq = uic_get_irq, diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c index 9bc45dea078f..470e1a3fd755 100644 --- a/arch/powerpc/platforms/44x/bamboo.c +++ b/arch/powerpc/platforms/44x/bamboo.c @@ -50,14 +50,9 @@ static int __init bamboo_probe(void) return 1; } -static void __init bamboo_setup_arch(void) -{ -} - define_machine(bamboo) { .name = "Bamboo", .probe = bamboo_probe, - .setup_arch = bamboo_setup_arch, .progress = udbg_progress, .init_IRQ = uic_init_tree, .get_irq = uic_get_irq, diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c index 5a7fec8d10d3..40e18fcb666c 100644 --- a/arch/powerpc/platforms/44x/ebony.c +++ b/arch/powerpc/platforms/44x/ebony.c @@ -57,14 +57,9 @@ static int __init ebony_probe(void) return 1; } -static void __init ebony_setup_arch(void) -{ -} - define_machine(ebony) { .name = "Ebony", .probe = ebony_probe, - .setup_arch = ebony_setup_arch, .progress = udbg_progress, .init_IRQ = uic_init_tree, .get_irq = uic_get_irq, diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c index 7d0d9d567d25..30700b31d43b 100644 --- a/arch/powerpc/platforms/44x/sequoia.c +++ b/arch/powerpc/platforms/44x/sequoia.c @@ -50,14 +50,9 @@ static int __init sequoia_probe(void) return 1; } -static void __init sequoia_setup_arch(void) -{ -} - define_machine(sequoia) { .name = "Sequoia", .probe = sequoia_probe, - .setup_arch = sequoia_setup_arch, .progress = udbg_progress, .init_IRQ = uic_init_tree, .get_irq = uic_get_irq, diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 4263158b3274..0b1e60a010ba 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c @@ -197,15 +197,6 @@ static void __init efika_setup_arch(void) { rtas_initialize(); -#ifdef CONFIG_BLK_DEV_INITRD - initrd_below_start_ok = 1; - - if (initrd_start) - ROOT_DEV = Root_RAM0; - else -#endif - ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ - efika_pcisetup(); #ifdef CONFIG_PM diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq.c b/arch/powerpc/platforms/cell/cbe_cpufreq.c index 0b6e8ee85ab1..901236fa0f07 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq.c @@ -24,7 +24,7 @@ #include <asm/machdep.h> #include <asm/of_platform.h> #include <asm/prom.h> -#include "cbe_regs.h" +#include <asm/cell-regs.h> #include "cbe_cpufreq.h" static DEFINE_MUTEX(cbe_switch_mutex); diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c index 163263b3e1cd..70fa7aef5edd 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c @@ -28,8 +28,8 @@ #include <linux/time.h> #include <asm/machdep.h> #include <asm/hw_irq.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "cbe_cpufreq.h" /* to write to MIC register */ diff --git a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c index fc6f38982ff4..6a2c1b0a9a94 100644 --- a/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c +++ b/arch/powerpc/platforms/cell/cbe_cpufreq_pmi.c @@ -27,12 +27,12 @@ #include <asm/processor.h> #include <asm/prom.h> #include <asm/pmi.h> +#include <asm/cell-regs.h> #ifdef DEBUG #include <asm/time.h> #endif -#include "cbe_regs.h" #include "cbe_cpufreq.h" static u8 pmi_slow_mode_limit[MAX_CBE]; diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index c8f7f0007422..16a9b07e7b0c 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -16,8 +16,7 @@ #include <asm/ptrace.h> #include <asm/of_device.h> #include <asm/of_platform.h> - -#include "cbe_regs.h" +#include <asm/cell-regs.h> /* * Current implementation uses "cpu" nodes. We build our own mapping diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index fb5eda48467d..4852bf312d83 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c @@ -52,8 +52,8 @@ #include <asm/spu.h> #include <asm/io.h> #include <asm/prom.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "spu_priv1_mmio.h" #define TEMP_MIN 65 diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index c29e634177fa..151fd8b82d63 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -41,9 +41,9 @@ #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/machdep.h> +#include <asm/cell-regs.h> #include "interrupt.h" -#include "cbe_regs.h" struct iic { struct cbe_iic_thread_regs __iomem *regs; diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 760caa76841a..faabc3fdc130 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -34,8 +34,8 @@ #include <asm/udbg.h> #include <asm/of_platform.h> #include <asm/lmb.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "interrupt.h" /* Define CELL_IOMMU_REAL_UNMAP to actually unmap non-used pages diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 4ede22d363fa..0304589c0a80 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -34,9 +34,9 @@ #include <asm/prom.h> #include <asm/pgtable.h> #include <asm/reg.h> +#include <asm/cell-regs.h> #include "pervasive.h" -#include "cbe_regs.h" static int sysreset_hack; diff --git a/arch/powerpc/platforms/cell/pmu.c b/arch/powerpc/platforms/cell/pmu.c index 66ca4b5a1dbc..1ed303678887 100644 --- a/arch/powerpc/platforms/cell/pmu.c +++ b/arch/powerpc/platforms/cell/pmu.c @@ -30,8 +30,8 @@ #include <asm/pmc.h> #include <asm/reg.h> #include <asm/spu.h> +#include <asm/cell-regs.h> -#include "cbe_regs.h" #include "interrupt.h" /* diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 3961a085b432..b2494ebcdbe9 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c @@ -10,9 +10,9 @@ #include <asm/prom.h> #include <asm/machdep.h> #include <asm/rtas.h> +#include <asm/cell-regs.h> #include "ras.h" -#include "cbe_regs.h" static void dump_fir(int cpu) diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index db6654272e13..98e7ef8e6fc6 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -52,9 +52,9 @@ #include <asm/udbg.h> #include <asm/mpic.h> #include <asm/of_platform.h> +#include <asm/cell-regs.h> #include "interrupt.h" -#include "cbe_regs.h" #include "pervasive.h" #include "ras.h" @@ -83,12 +83,22 @@ static void cell_progress(char *s, unsigned short hex) static int __init cell_publish_devices(void) { + int node; + if (!machine_is(cell)) return 0; /* Publish OF platform devices for southbridge IOs */ of_platform_bus_probe(NULL, NULL, NULL); + /* There is no device for the MIC memory controller, thus we create + * a platform device for it to attach the EDAC driver to. + */ + for_each_online_node(node) { + if (cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(node)) == NULL) + continue; + platform_device_register_simple("cbe-mic", node, NULL, 0); + } return 0; } device_initcall(cell_publish_devices); @@ -161,11 +171,6 @@ static void __init cell_setup_arch(void) /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/hda2\n"); - ROOT_DEV = Root_HDA2; - } - /* Find and initialize PCI host bridges */ init_pci_config_tokens(); find_and_init_phbs(); diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index 0f1dddb81cd2..1769d755eff3 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -101,11 +101,6 @@ static void __init celleb_setup_arch(void) /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/hda2\n"); - ROOT_DEV = Root_HDA2; - } - #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 96498ad7b943..59306261f5b2 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -290,16 +290,6 @@ void __init chrp_setup_arch(void) ppc_md.set_rtc_time = rtas_set_rtc_time; } -#ifdef CONFIG_BLK_DEV_INITRD - /* this is fine for chrp */ - initrd_below_start_ok = 1; - - if (initrd_start) - ROOT_DEV = Root_RAM0; - else -#endif - ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ - /* On pegasos, enable the L2 cache if not already done by OF */ pegasos_set_l2cr(); diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 60db509638f1..a65f1b44abf8 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ hvcall.o proc.o htab.o iommu.o misc.o irq.o obj-$(CONFIG_PCI) += pci.o vpdinfo.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_VIOPATH) += viopath.o +obj-$(CONFIG_VIOPATH) += viopath.o vio.o obj-$(CONFIG_MODULES) += ksyms.o quiet_cmd_dt_strings = DT_STR $@ diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 9e8a334a518a..4543c4bc3a56 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -72,8 +72,6 @@ static char __initdata device_type_cpu[] = "cpu"; static char __initdata device_type_memory[] = "memory"; static char __initdata device_type_serial[] = "serial"; static char __initdata device_type_network[] = "network"; -static char __initdata device_type_block[] = "block"; -static char __initdata device_type_byte[] = "byte"; static char __initdata device_type_pci[] = "pci"; static char __initdata device_type_vdevice[] = "vdevice"; static char __initdata device_type_vscsi[] = "vscsi"; @@ -375,21 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) dt_end_node(dt); } - reg += HVMAXARCHITECTEDVIRTUALLANS; - - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, - "IBM,iSeries-viodasd", 1); - reg += HVMAXARCHITECTEDVIRTUALDISKS; - - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - dt_do_vdevice(dt, "viocd", reg, i, device_type_block, - "IBM,iSeries-viocd", 1); - reg += HVMAXARCHITECTEDVIRTUALCDROMS; - - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, - "IBM,iSeries-viotape", 1); dt_end_node(dt); } diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 3b6a9666c2c0..49e9c664ea89 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -28,14 +28,17 @@ #include <linux/dma-mapping.h> #include <linux/list.h> #include <linux/pci.h> +#include <linux/module.h> #include <asm/iommu.h> +#include <asm/vio.h> #include <asm/tce.h> #include <asm/machdep.h> #include <asm/abs_addr.h> #include <asm/prom.h> #include <asm/pci-bridge.h> #include <asm/iseries/hv_call_xm.h> +#include <asm/iseries/hv_call_event.h> #include <asm/iseries/iommu.h> static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, @@ -189,6 +192,55 @@ void iommu_devnode_init_iSeries(struct pci_dev *pdev, struct device_node *dn) } #endif +static struct iommu_table veth_iommu_table; +static struct iommu_table vio_iommu_table; + +void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag) +{ + return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle, + DMA_32BIT_MASK, flag, -1); +} +EXPORT_SYMBOL_GPL(iseries_hv_alloc); + +void iseries_hv_free(size_t size, void *vaddr, dma_addr_t dma_handle) +{ + iommu_free_coherent(&vio_iommu_table, size, vaddr, dma_handle); +} +EXPORT_SYMBOL_GPL(iseries_hv_free); + +dma_addr_t iseries_hv_map(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + return iommu_map_single(&vio_iommu_table, vaddr, size, + DMA_32BIT_MASK, direction); +} + +void iseries_hv_unmap(dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + iommu_unmap_single(&vio_iommu_table, dma_handle, size, direction); +} + +void __init iommu_vio_init(void) +{ + iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); + veth_iommu_table.it_size /= 2; + vio_iommu_table = veth_iommu_table; + vio_iommu_table.it_offset += veth_iommu_table.it_size; + + if (!iommu_init_table(&veth_iommu_table, -1)) + printk("Virtual Bus VETH TCE table failed.\n"); + if (!iommu_init_table(&vio_iommu_table, -1)) + printk("Virtual Bus VIO TCE table failed.\n"); +} + +struct iommu_table *vio_build_iommu_table_iseries(struct vio_dev *dev) +{ + if (strcmp(dev->type, "network") == 0) + return &veth_iommu_table; + return &vio_iommu_table; +} + void iommu_init_early_iSeries(void) { ppc_md.tce_build = tce_build_iSeries; diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index b1187d95e3b2..c0f2433bc16e 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -39,9 +39,9 @@ #include <asm/paca.h> #include <asm/abs_addr.h> #include <asm/firmware.h> -#include <asm/iseries/vio.h> #include <asm/iseries/mf.h> #include <asm/iseries/hv_lp_config.h> +#include <asm/iseries/hv_lp_event.h> #include <asm/iseries/it_lp_queue.h> #include "setup.h" @@ -870,8 +870,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off, if ((off + count) > 256) count = 256 - off; - dma_addr = dma_map_single(iSeries_vio_dev, page, off + count, - DMA_FROM_DEVICE); + dma_addr = iseries_hv_map(page, off + count, DMA_FROM_DEVICE); if (dma_mapping_error(dma_addr)) return -ENOMEM; memset(page, 0, off + count); @@ -883,8 +882,7 @@ static int proc_mf_dump_cmdline(char *page, char **start, off_t off, vsp_cmd.sub_data.kern.length = off + count; mb(); rc = signal_vsp_instruction(&vsp_cmd); - dma_unmap_single(iSeries_vio_dev, dma_addr, off + count, - DMA_FROM_DEVICE); + iseries_hv_unmap(dma_addr, off + count, DMA_FROM_DEVICE); if (rc) return rc; if (vsp_cmd.result_code != 0) @@ -919,8 +917,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) int len = *size; dma_addr_t dma_addr; - dma_addr = dma_map_single(iSeries_vio_dev, buffer, len, - DMA_FROM_DEVICE); + dma_addr = iseries_hv_map(buffer, len, DMA_FROM_DEVICE); memset(buffer, 0, len); memset(&vsp_cmd, 0, sizeof(vsp_cmd)); vsp_cmd.cmd = 32; @@ -938,7 +935,7 @@ static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) rc = -ENOMEM; } - dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE); + iseries_hv_unmap(dma_addr, len, DMA_FROM_DEVICE); return rc; } @@ -1149,8 +1146,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, goto out; dma_addr = 0; - page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, - GFP_ATOMIC); + page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC); ret = -ENOMEM; if (page == NULL) goto out; @@ -1170,7 +1166,7 @@ static int proc_mf_change_cmdline(struct file *file, const char __user *buffer, ret = count; out_free: - dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); + iseries_hv_free(count, page, dma_addr); out: return ret; } @@ -1190,8 +1186,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, goto out; dma_addr = 0; - page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr, - GFP_ATOMIC); + page = iseries_hv_alloc(count, &dma_addr, GFP_ATOMIC); rc = -ENOMEM; if (page == NULL) { printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n"); @@ -1219,7 +1214,7 @@ static ssize_t proc_mf_change_vmlinux(struct file *file, *ppos += count; rc = count; out_free: - dma_free_coherent(iSeries_vio_dev, count, page, dma_addr); + iseries_hv_free(count, page, dma_addr); out: return rc; } diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c new file mode 100644 index 000000000000..910b00b4703e --- /dev/null +++ b/arch/powerpc/platforms/iseries/vio.c @@ -0,0 +1,553 @@ +/* + * Legacy iSeries specific vio initialisation + * that needs to be built in (not a module). + * + * © Copyright 2007 IBM Corporation + * Author: Stephen Rothwell + * Some parts collected from various other files + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/of.h> +#include <linux/init.h> +#include <linux/gfp.h> +#include <linux/completion.h> +#include <linux/proc_fs.h> +#include <linux/module.h> + +#include <asm/firmware.h> +#include <asm/vio.h> +#include <asm/iseries/vio.h> +#include <asm/iseries/iommu.h> +#include <asm/iseries/hv_types.h> +#include <asm/iseries/hv_lp_event.h> + +#define FIRST_VTY 0 +#define NUM_VTYS 1 +#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS) +#define NUM_VSCSIS 1 +#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS) +#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS +#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS) +#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS +#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS) +#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS +#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS) +#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES + +struct vio_waitevent { + struct completion com; + int rc; + u16 sub_result; +}; + +struct vio_resource { + char rsrcname[10]; + char type[4]; + char model[3]; +}; + +static struct property *new_property(const char *name, int length, + const void *value) +{ + struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length, + GFP_KERNEL); + + if (!np) + return NULL; + np->name = (char *)(np + 1); + np->value = np->name + strlen(name) + 1; + strcpy(np->name, name); + memcpy(np->value, value, length); + np->length = length; + return np; +} + +static void __init free_property(struct property *np) +{ + kfree(np); +} + +static struct device_node *new_node(const char *path, + struct device_node *parent) +{ + struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL); + + if (!np) + return NULL; + np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL); + if (!np->full_name) { + kfree(np); + return NULL; + } + strcpy(np->full_name, path); + of_node_set_flag(np, OF_DYNAMIC); + kref_init(&np->kref); + np->parent = of_node_get(parent); + return np; +} + +static void free_node(struct device_node *np) +{ + struct property *next; + struct property *prop; + + next = np->properties; + while (next) { + prop = next; + next = prop->next; + free_property(prop); + } + of_node_put(np->parent); + kfree(np->full_name); + kfree(np); +} + +static int add_string_property(struct device_node *np, const char *name, + const char *value) +{ + struct property *nprop = new_property(name, strlen(value) + 1, value); + + if (!nprop) + return 0; + prom_add_property(np, nprop); + return 1; +} + +static int add_raw_property(struct device_node *np, const char *name, + int length, const void *value) +{ + struct property *nprop = new_property(name, length, value); + + if (!nprop) + return 0; + prom_add_property(np, nprop); + return 1; +} + +static struct device_node *do_device_node(struct device_node *parent, + const char *name, u32 reg, u32 unit, const char *type, + const char *compat, struct vio_resource *res) +{ + struct device_node *np; + char path[32]; + + snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg); + np = new_node(path, parent); + if (!np) + return NULL; + if (!add_string_property(np, "name", name) || + !add_string_property(np, "device_type", type) || + !add_string_property(np, "compatible", compat) || + !add_raw_property(np, "reg", sizeof(reg), ®) || + !add_raw_property(np, "linux,unit_address", + sizeof(unit), &unit)) { + goto node_free; + } + if (res) { + if (!add_raw_property(np, "linux,vio_rsrcname", + sizeof(res->rsrcname), res->rsrcname) || + !add_raw_property(np, "linux,vio_type", + sizeof(res->type), res->type) || + !add_raw_property(np, "linux,vio_model", + sizeof(res->model), res->model)) + goto node_free; + } + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); + of_attach_node(np); +#ifdef CONFIG_PROC_DEVICETREE + if (parent->pde) { + struct proc_dir_entry *ent; + + ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde); + if (ent) + proc_device_tree_add_node(np, ent); + } +#endif + return np; + + node_free: + free_node(np); + return NULL; +} + +/* + * This is here so that we can dynamically add viodasd + * devices without exposing all the above infrastructure. + */ +struct vio_dev *vio_create_viodasd(u32 unit) +{ + struct device_node *vio_root; + struct device_node *np; + struct vio_dev *vdev = NULL; + + vio_root = of_find_node_by_path("/vdevice"); + if (!vio_root) + return NULL; + np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit, + "block", "IBM,iSeries-viodasd", NULL); + of_node_put(vio_root); + if (np) { + vdev = vio_register_device_node(np); + if (!vdev) + free_node(np); + } + return vdev; +} +EXPORT_SYMBOL_GPL(vio_create_viodasd); + +static void __init handle_block_event(struct HvLpEvent *event) +{ + struct vioblocklpevent *bevent = (struct vioblocklpevent *)event; + struct vio_waitevent *pwe; + + if (event == NULL) + /* Notification that a partition went away! */ + return; + /* First, we should NEVER get an int here...only acks */ + if (hvlpevent_is_int(event)) { + printk(KERN_WARNING "handle_viod_request: " + "Yikes! got an int in viodasd event handler!\n"); + if (hvlpevent_need_ack(event)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { + case vioblockopen: + /* + * Handle a response to an open request. We get all the + * disk information in the response, so update it. The + * correlation token contains a pointer to a waitevent + * structure that has a completion in it. update the + * return code in the waitevent structure and post the + * completion to wake up the guy who sent the request + */ + pwe = (struct vio_waitevent *)event->xCorrelationToken; + pwe->rc = event->xRc; + pwe->sub_result = bevent->sub_result; + complete(&pwe->com); + break; + case vioblockclose: + break; + default: + printk(KERN_WARNING "handle_viod_request: unexpected subtype!"); + if (hvlpevent_need_ack(event)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } +} + +static void __init probe_disk(struct device_node *vio_root, u32 unit) +{ + HvLpEvent_Rc hvrc; + struct vio_waitevent we; + u16 flags = 0; + +retry: + init_completion(&we.com); + + /* Send the open event to OS/400 */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockopen, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&we, VIOVERSION << 16, + ((u64)unit << 48) | ((u64)flags<< 32), + 0, 0, 0); + if (hvrc != 0) { + printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n", + (int)hvrc); + return; + } + + wait_for_completion(&we.com); + + if (we.rc != 0) { + if (flags != 0) + return; + /* try again with read only flag set */ + flags = vioblockflags_ro; + goto retry; + } + + /* Send the close event to OS/400. We DON'T expect a response */ + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_blockio | vioblockclose, + HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + 0, VIOVERSION << 16, + ((u64)unit << 48) | ((u64)flags << 32), + 0, 0, 0); + if (hvrc != 0) { + printk(KERN_WARNING "probe_disk: " + "bad rc sending event to OS/400 %d\n", (int)hvrc); + return; + } + + do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit, + "block", "IBM,iSeries-viodasd", NULL); +} + +static void __init get_viodasd_info(struct device_node *vio_root) +{ + int rc; + u32 unit; + + rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2); + if (rc) { + printk(KERN_WARNING "get_viodasd_info: " + "error opening path to host partition %d\n", + viopath_hostLp); + return; + } + + /* Initialize our request handler */ + vio_setHandler(viomajorsubtype_blockio, handle_block_event); + + for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++) + probe_disk(vio_root, unit); + + vio_clearHandler(viomajorsubtype_blockio); + viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2); +} + +static void __init handle_cd_event(struct HvLpEvent *event) +{ + struct viocdlpevent *bevent; + struct vio_waitevent *pwe; + + if (!event) + /* Notification that a partition went away! */ + return; + + /* First, we should NEVER get an int here...only acks */ + if (hvlpevent_is_int(event)) { + printk(KERN_WARNING "handle_cd_event: got an unexpected int\n"); + if (hvlpevent_need_ack(event)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + bevent = (struct viocdlpevent *)event; + + switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { + case viocdgetinfo: + pwe = (struct vio_waitevent *)event->xCorrelationToken; + pwe->rc = event->xRc; + pwe->sub_result = bevent->sub_result; + complete(&pwe->com); + break; + + default: + printk(KERN_WARNING "handle_cd_event: " + "message with unexpected subtype %0x04X!\n", + event->xSubtype & VIOMINOR_SUBTYPE_MASK); + if (hvlpevent_need_ack(event)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + } +} + +static void __init get_viocd_info(struct device_node *vio_root) +{ + HvLpEvent_Rc hvrc; + u32 unit; + struct vio_waitevent we; + struct vio_resource *unitinfo; + dma_addr_t unitinfo_dmaaddr; + int ret; + + ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2); + if (ret) { + printk(KERN_WARNING + "get_viocd_info: error opening path to host partition %d\n", + viopath_hostLp); + return; + } + + /* Initialize our request handler */ + vio_setHandler(viomajorsubtype_cdio, handle_cd_event); + + unitinfo = iseries_hv_alloc( + sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, + &unitinfo_dmaaddr, GFP_ATOMIC); + if (!unitinfo) { + printk(KERN_WARNING + "get_viocd_info: error allocating unitinfo\n"); + goto clear_handler; + } + + memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS); + + init_completion(&we.com); + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_cdio | viocdgetinfo, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0, + sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0); + if (hvrc != HvLpEvent_Rc_Good) { + printk(KERN_WARNING + "get_viocd_info: cdrom error sending event. rc %d\n", + (int)hvrc); + goto hv_free; + } + + wait_for_completion(&we.com); + + if (we.rc) { + printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n", + we.rc, we.sub_result); + goto hv_free; + } + + for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) && + unitinfo[unit].rsrcname[0]; unit++) { + if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit, + "block", "IBM,iSeries-viocd", &unitinfo[unit])) + break; + } + + hv_free: + iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, + unitinfo, unitinfo_dmaaddr); + clear_handler: + vio_clearHandler(viomajorsubtype_cdio); + viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2); +} + +/* Handle interrupt events for tape */ +static void __init handle_tape_event(struct HvLpEvent *event) +{ + struct vio_waitevent *we; + struct viotapelpevent *tevent = (struct viotapelpevent *)event; + + if (event == NULL) + /* Notification that a partition went away! */ + return; + + we = (struct vio_waitevent *)event->xCorrelationToken; + switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) { + case viotapegetinfo: + we->rc = tevent->sub_type_result; + complete(&we->com); + break; + default: + printk(KERN_WARNING "handle_tape_event: weird ack\n"); + } +} + +static void __init get_viotape_info(struct device_node *vio_root) +{ + HvLpEvent_Rc hvrc; + u32 unit; + struct vio_resource *unitinfo; + dma_addr_t unitinfo_dmaaddr; + size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES; + struct vio_waitevent we; + int ret; + + ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2); + if (ret) { + printk(KERN_WARNING "get_viotape_info: " + "error on viopath_open to hostlp %d\n", ret); + return; + } + + vio_setHandler(viomajorsubtype_tape, handle_tape_event); + + unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC); + if (!unitinfo) + goto clear_handler; + + memset(unitinfo, 0, len); + + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_tape | viotapegetinfo, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&we, VIOVERSION << 16, + unitinfo_dmaaddr, len, 0, 0); + if (hvrc != HvLpEvent_Rc_Good) { + printk(KERN_WARNING "get_viotape_info: hv error on op %d\n", + (int)hvrc); + goto hv_free; + } + + wait_for_completion(&we.com); + + for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) && + unitinfo[unit].rsrcname[0]; unit++) { + if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit, + unit, "byte", "IBM,iSeries-viotape", + &unitinfo[unit])) + break; + } + + hv_free: + iseries_hv_free(len, unitinfo, unitinfo_dmaaddr); + clear_handler: + vio_clearHandler(viomajorsubtype_tape); + viopath_close(viopath_hostLp, viomajorsubtype_tape, 2); +} + +static int __init iseries_vio_init(void) +{ + struct device_node *vio_root; + + if (!firmware_has_feature(FW_FEATURE_ISERIES)) + return -ENODEV; + + iommu_vio_init(); + + vio_root = of_find_node_by_path("/vdevice"); + if (!vio_root) + return -ENODEV; + + if (viopath_hostLp == HvLpIndexInvalid) { + vio_set_hostlp(); + /* If we don't have a host, bail out */ + if (viopath_hostLp == HvLpIndexInvalid) + goto put_node; + } + + get_viodasd_info(vio_root); + get_viocd_info(vio_root); + get_viotape_info(vio_root); + + return 0; + + put_node: + of_node_put(vio_root); + return -ENODEV; +} +arch_initcall(iseries_vio_init); diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index 6a0060a5f2ec..df23331eb25c 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -124,8 +124,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) if (!buf) return 0; - handle = dma_map_single(iSeries_vio_dev, buf, HW_PAGE_SIZE, - DMA_FROM_DEVICE); + handle = iseries_hv_map(buf, HW_PAGE_SIZE, DMA_FROM_DEVICE); hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, HvLpEvent_Type_VirtualIo, @@ -146,8 +145,7 @@ static int proc_viopath_show(struct seq_file *m, void *v) buf[HW_PAGE_SIZE-1] = '\0'; seq_printf(m, "%s", buf); - dma_unmap_single(iSeries_vio_dev, handle, HW_PAGE_SIZE, - DMA_FROM_DEVICE); + iseries_hv_unmap(handle, HW_PAGE_SIZE, DMA_FROM_DEVICE); kfree(buf); seq_printf(m, "AVAILABLE_VETH=%x\n", vlanMap); @@ -596,7 +594,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) numOpen += viopathStatus[remoteLp].users[i]; if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { - printk(VIOPATH_KERN_INFO "closing connection to partition %d", + printk(VIOPATH_KERN_INFO "closing connection to partition %d\n", remoteLp); HvCallEvent_closeLpEventPath(remoteLp, diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index c91a33593bb8..dae9f658122e 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c @@ -320,10 +320,12 @@ static struct of_device_id gpio_mdio_match[] = static struct of_platform_driver gpio_mdio_driver = { - .name = "gpio-mdio-bitbang", .match_table = gpio_mdio_match, .probe = gpio_mdio_probe, .remove = gpio_mdio_remove, + .driver = { + .name = "gpio-mdio-bitbang", + }, }; int gpio_mdio_init(void) diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 7ccb9236e8b4..02c533096627 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -387,69 +387,13 @@ static void __init pmac_setup_arch(void) #endif /* CONFIG_ADB */ } -char *bootpath; -char *bootdevice; -void *boot_host; -int boot_target; -int boot_part; -static dev_t boot_dev; - #ifdef CONFIG_SCSI void note_scsi_host(struct device_node *node, void *host) { - int l; - char *p; - - l = strlen(node->full_name); - if (bootpath != NULL && bootdevice != NULL - && strncmp(node->full_name, bootdevice, l) == 0 - && (bootdevice[l] == '/' || bootdevice[l] == 0)) { - boot_host = host; - /* - * There's a bug in OF 1.0.5. (Why am I not surprised.) - * If you pass a path like scsi/sd@1:0 to canon, it returns - * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 - * That is, the scsi target number doesn't get preserved. - * So we pick the target number out of bootpath and use that. - */ - p = strstr(bootpath, "/sd@"); - if (p != NULL) { - p += 4; - boot_target = simple_strtoul(p, NULL, 10); - p = strchr(p, ':'); - if (p != NULL) - boot_part = simple_strtoul(p + 1, NULL, 10); - } - } } EXPORT_SYMBOL(note_scsi_host); #endif -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) -static dev_t __init find_ide_boot(void) -{ - char *p; - int n; - dev_t __init pmac_find_ide_boot(char *bootdevice, int n); - - if (bootdevice == NULL) - return 0; - p = strrchr(bootdevice, '/'); - if (p == NULL) - return 0; - n = p - bootdevice; - - return pmac_find_ide_boot(bootdevice, n); -} -#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ - -static void __init find_boot_device(void) -{ -#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) - boot_dev = find_ide_boot(); -#endif -} - static int initializing = 1; static int pmac_late_init(void) @@ -466,10 +410,14 @@ static int pmac_late_init(void) late_initcall(pmac_late_init); -/* can't be __init - can be called whenever a disk is first accessed */ -void note_bootable_part(dev_t dev, int part, int goodness) +/* + * This is __init_refok because we check for "initializing" before + * touching any of the __init sensitive things and "initializing" + * will be false after __init time. This can't be __init because it + * can be called whenever a disk is first accessed. + */ +void __init_refok note_bootable_part(dev_t dev, int part, int goodness) { - static int found_boot = 0; char *p; if (!initializing) @@ -481,15 +429,8 @@ void note_bootable_part(dev_t dev, int part, int goodness) if (p != NULL && (p == boot_command_line || p[-1] == ' ')) return; - if (!found_boot) { - find_boot_device(); - found_boot = 1; - } - if (!boot_dev || dev == boot_dev) { - ROOT_DEV = dev + part; - boot_dev = 0; - current_root_goodness = goodness; - } + ROOT_DEV = dev + part; + current_root_goodness = goodness; } #ifdef CONFIG_ADB_CUDA diff --git a/arch/powerpc/platforms/ps3/os-area.c b/arch/powerpc/platforms/ps3/os-area.c index b70e474014f0..766685ab26f8 100644 --- a/arch/powerpc/platforms/ps3/os-area.c +++ b/arch/powerpc/platforms/ps3/os-area.c @@ -1,5 +1,5 @@ /* - * PS3 'Other OS' area data. + * PS3 flash memory os area. * * Copyright (C) 2006 Sony Computer Entertainment Inc. * Copyright 2006 Sony Corp. @@ -20,6 +20,9 @@ #include <linux/kernel.h> #include <linux/io.h> +#include <linux/workqueue.h> +#include <linux/fs.h> +#include <linux/syscalls.h> #include <asm/lmb.h> @@ -29,7 +32,7 @@ enum { OS_AREA_SEGMENT_SIZE = 0X200, }; -enum { +enum os_area_ldr_format { HEADER_LDR_FORMAT_RAW = 0, HEADER_LDR_FORMAT_GZIP = 1, }; @@ -38,7 +41,7 @@ enum { * struct os_area_header - os area header segment. * @magic_num: Always 'cell_ext_os_area'. * @hdr_version: Header format version number. - * @os_area_offset: Starting segment number of os image area. + * @db_area_offset: Starting segment number of other os database area. * @ldr_area_offset: Starting segment number of bootloader image area. * @ldr_format: HEADER_LDR_FORMAT flag. * @ldr_size: Size of bootloader image in bytes. @@ -50,9 +53,9 @@ enum { */ struct os_area_header { - s8 magic_num[16]; + u8 magic_num[16]; u32 hdr_version; - u32 os_area_offset; + u32 db_area_offset; u32 ldr_area_offset; u32 _reserved_1; u32 ldr_format; @@ -60,12 +63,12 @@ struct os_area_header { u32 _reserved_2[6]; }; -enum { +enum os_area_boot_flag { PARAM_BOOT_FLAG_GAME_OS = 0, PARAM_BOOT_FLAG_OTHER_OS = 1, }; -enum { +enum os_area_ctrl_button { PARAM_CTRL_BUTTON_O_IS_YES = 0, PARAM_CTRL_BUTTON_X_IS_YES = 1, }; @@ -84,6 +87,9 @@ enum { * @dns_primary: User preference of static primary dns server. * @dns_secondary: User preference of static secondary dns server. * + * The ps3 rtc maintains a read-only value that approximates seconds since + * 2000-01-01 00:00:00 UTC. + * * User preference of zero for static_ip_addr means use dhcp. */ @@ -108,45 +114,172 @@ struct os_area_params { u8 _reserved_5[8]; }; +enum { + OS_AREA_DB_MAGIC_NUM = 0x2d64622dU, +}; + /** - * struct saved_params - Static working copies of data from the 'Other OS' area. + * struct os_area_db - Shared flash memory database. + * @magic_num: Always '-db-' = 0x2d64622d. + * @version: os_area_db format version number. + * @index_64: byte offset of the database id index for 64 bit variables. + * @count_64: number of usable 64 bit index entries + * @index_32: byte offset of the database id index for 32 bit variables. + * @count_32: number of usable 32 bit index entries + * @index_16: byte offset of the database id index for 16 bit variables. + * @count_16: number of usable 16 bit index entries * - * For the convinience of the guest, the HV makes a copy of the 'Other OS' area - * in flash to a high address in the boot memory region and then puts that RAM - * address and the byte count into the repository for retreval by the guest. - * We copy the data we want into a static variable and allow the memory setup - * by the HV to be claimed by the lmb manager. + * Flash rom storage for exclusive use by guests running in the other os lpar. + * The current system configuration allocates 1K (two segments) for other os + * use. + */ + +struct os_area_db { + u32 magic_num; + u16 version; + u16 _reserved_1; + u16 index_64; + u16 count_64; + u16 index_32; + u16 count_32; + u16 index_16; + u16 count_16; + u32 _reserved_2; + u8 _db_data[1000]; +}; + +/** + * enum os_area_db_owner - Data owners. + */ + +enum os_area_db_owner { + OS_AREA_DB_OWNER_ANY = -1, + OS_AREA_DB_OWNER_NONE = 0, + OS_AREA_DB_OWNER_PROTOTYPE = 1, + OS_AREA_DB_OWNER_LINUX = 2, + OS_AREA_DB_OWNER_PETITBOOT = 3, + OS_AREA_DB_OWNER_MAX = 32, +}; + +enum os_area_db_key { + OS_AREA_DB_KEY_ANY = -1, + OS_AREA_DB_KEY_NONE = 0, + OS_AREA_DB_KEY_RTC_DIFF = 1, + OS_AREA_DB_KEY_VIDEO_MODE = 2, + OS_AREA_DB_KEY_MAX = 8, +}; + +struct os_area_db_id { + int owner; + int key; +}; + +static const struct os_area_db_id os_area_db_id_empty = { + .owner = OS_AREA_DB_OWNER_NONE, + .key = OS_AREA_DB_KEY_NONE +}; + +static const struct os_area_db_id os_area_db_id_any = { + .owner = OS_AREA_DB_OWNER_ANY, + .key = OS_AREA_DB_KEY_ANY +}; + +static const struct os_area_db_id os_area_db_id_rtc_diff = { + .owner = OS_AREA_DB_OWNER_LINUX, + .key = OS_AREA_DB_KEY_RTC_DIFF +}; + +static const struct os_area_db_id os_area_db_id_video_mode = { + .owner = OS_AREA_DB_OWNER_LINUX, + .key = OS_AREA_DB_KEY_VIDEO_MODE +}; + +#define SECONDS_FROM_1970_TO_2000 946684800LL + +/** + * struct saved_params - Static working copies of data from the PS3 'os area'. + * + * The order of preference we use for the rtc_diff source: + * 1) The database value. + * 2) The game os value. + * 3) The number of seconds from 1970 to 2000. */ struct saved_params { - /* param 0 */ + unsigned int valid; s64 rtc_diff; unsigned int av_multi_out; - unsigned int ctrl_button; - /* param 1 */ - u8 static_ip_addr[4]; - u8 network_mask[4]; - u8 default_gateway[4]; - /* param 2 */ - u8 dns_primary[4]; - u8 dns_secondary[4]; } static saved_params; +static struct property property_rtc_diff = { + .name = "linux,rtc_diff", + .length = sizeof(saved_params.rtc_diff), + .value = &saved_params.rtc_diff, +}; + +static struct property property_av_multi_out = { + .name = "linux,av_multi_out", + .length = sizeof(saved_params.av_multi_out), + .value = &saved_params.av_multi_out, +}; + +/** + * os_area_set_property - Add or overwrite a saved_params value to the device tree. + * + * Overwrites an existing property. + */ + +static void os_area_set_property(struct device_node *node, + struct property *prop) +{ + int result; + struct property *tmp = of_find_property(node, prop->name, NULL); + + if (tmp) { + pr_debug("%s:%d found %s\n", __func__, __LINE__, prop->name); + prom_remove_property(node, tmp); + } + + result = prom_add_property(node, prop); + + if (result) + pr_debug("%s:%d prom_set_property failed\n", __func__, + __LINE__); +} + +/** + * os_area_get_property - Get a saved_params value from the device tree. + * + */ + +static void __init os_area_get_property(struct device_node *node, + struct property *prop) +{ + const struct property *tmp = of_find_property(node, prop->name, NULL); + + if (tmp) { + BUG_ON(prop->length != tmp->length); + memcpy(prop->value, tmp->value, prop->length); + } else + pr_debug("%s:%d not found %s\n", __func__, __LINE__, + prop->name); +} + #define dump_header(_a) _dump_header(_a, __func__, __LINE__) static void _dump_header(const struct os_area_header *h, const char *func, int line) { - pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, + pr_debug("%s:%d: h.magic_num: '%s'\n", func, line, h->magic_num); - pr_debug("%s:%d: h.hdr_version: %u\n", func, line, + pr_debug("%s:%d: h.hdr_version: %u\n", func, line, h->hdr_version); - pr_debug("%s:%d: h.os_area_offset: %u\n", func, line, - h->os_area_offset); + pr_debug("%s:%d: h.db_area_offset: %u\n", func, line, + h->db_area_offset); pr_debug("%s:%d: h.ldr_area_offset: %u\n", func, line, h->ldr_area_offset); - pr_debug("%s:%d: h.ldr_format: %u\n", func, line, + pr_debug("%s:%d: h.ldr_format: %u\n", func, line, h->ldr_format); - pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, + pr_debug("%s:%d: h.ldr_size: %xh\n", func, line, h->ldr_size); } @@ -176,7 +309,7 @@ static void _dump_params(const struct os_area_params *p, const char *func, p->dns_secondary[2], p->dns_secondary[3]); } -static int __init verify_header(const struct os_area_header *header) +static int verify_header(const struct os_area_header *header) { if (memcmp(header->magic_num, "cell_ext_os_area", 16)) { pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); @@ -188,7 +321,7 @@ static int __init verify_header(const struct os_area_header *header) return -1; } - if (header->os_area_offset > header->ldr_area_offset) { + if (header->db_area_offset > header->ldr_area_offset) { pr_debug("%s:%d offsets failed\n", __func__, __LINE__); return -1; } @@ -196,58 +329,477 @@ static int __init verify_header(const struct os_area_header *header) return 0; } -int __init ps3_os_area_init(void) +static int db_verify(const struct os_area_db *db) +{ + if (db->magic_num != OS_AREA_DB_MAGIC_NUM) { + pr_debug("%s:%d magic_num failed\n", __func__, __LINE__); + return -1; + } + + if (db->version != 1) { + pr_debug("%s:%d version failed\n", __func__, __LINE__); + return -1; + } + + return 0; +} + +struct db_index { + uint8_t owner:5; + uint8_t key:3; +}; + +struct db_iterator { + const struct os_area_db *db; + struct os_area_db_id match_id; + struct db_index *idx; + struct db_index *last_idx; + union { + uint64_t *value_64; + uint32_t *value_32; + uint16_t *value_16; + }; +}; + +static unsigned int db_align_up(unsigned int val, unsigned int size) +{ + return (val + (size - 1)) & (~(size - 1)); +} + +/** + * db_for_each_64 - Iterator for 64 bit entries. + * + * A NULL value for id can be used to match all entries. + * OS_AREA_DB_OWNER_ANY and OS_AREA_DB_KEY_ANY can be used to match all. + */ + +static int db_for_each_64(const struct os_area_db *db, + const struct os_area_db_id *match_id, struct db_iterator *i) +{ +next: + if (!i->db) { + i->db = db; + i->match_id = match_id ? *match_id : os_area_db_id_any; + i->idx = (void *)db + db->index_64; + i->last_idx = i->idx + db->count_64; + i->value_64 = (void *)db + db->index_64 + + db_align_up(db->count_64, 8); + } else { + i->idx++; + i->value_64++; + } + + if (i->idx >= i->last_idx) { + pr_debug("%s:%d: reached end\n", __func__, __LINE__); + return 0; + } + + if (i->match_id.owner != OS_AREA_DB_OWNER_ANY + && i->match_id.owner != (int)i->idx->owner) + goto next; + if (i->match_id.key != OS_AREA_DB_KEY_ANY + && i->match_id.key != (int)i->idx->key) + goto next; + + return 1; +} + +static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id) +{ + struct db_iterator i; + + for (i.db = NULL; db_for_each_64(db, id, &i); ) { + + pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__, + i.idx->owner, i.idx->key, + (unsigned long long)*i.value_64); + + i.idx->owner = 0; + i.idx->key = 0; + *i.value_64 = 0; + } + return 0; +} + +static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id, + uint64_t value) +{ + struct db_iterator i; + + pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__, + id->owner, id->key, (unsigned long long)value); + + if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY + || id->key == OS_AREA_DB_KEY_ANY) { + pr_debug("%s:%d: bad id: (%d:%d)\n", __func__, + __LINE__, id->owner, id->key); + return -1; + } + + db_delete_64(db, id); + + i.db = NULL; + if (db_for_each_64(db, &os_area_db_id_empty, &i)) { + + pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__, + i.idx->owner, i.idx->key, + (unsigned long long)*i.value_64); + + i.idx->owner = id->owner; + i.idx->key = id->key; + *i.value_64 = value; + + pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__, + i.idx->owner, i.idx->key, + (unsigned long long)*i.value_64); + return 0; + } + pr_debug("%s:%d: database full.\n", + __func__, __LINE__); + return -1; +} + +static int db_get_64(const struct os_area_db *db, + const struct os_area_db_id *id, uint64_t *value) +{ + struct db_iterator i; + + i.db = NULL; + if (db_for_each_64(db, id, &i)) { + *value = *i.value_64; + pr_debug("%s:%d: found %lld\n", __func__, __LINE__, + (long long int)*i.value_64); + return 0; + } + pr_debug("%s:%d: not found\n", __func__, __LINE__); + return -1; +} + +static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff) +{ + return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff); +} + +#define dump_db(a) _dump_db(a, __func__, __LINE__) +static void _dump_db(const struct os_area_db *db, const char *func, + int line) +{ + pr_debug("%s:%d: db.magic_num: '%s'\n", func, line, + (const char*)&db->magic_num); + pr_debug("%s:%d: db.version: %u\n", func, line, + db->version); + pr_debug("%s:%d: db.index_64: %u\n", func, line, + db->index_64); + pr_debug("%s:%d: db.count_64: %u\n", func, line, + db->count_64); + pr_debug("%s:%d: db.index_32: %u\n", func, line, + db->index_32); + pr_debug("%s:%d: db.count_32: %u\n", func, line, + db->count_32); + pr_debug("%s:%d: db.index_16: %u\n", func, line, + db->index_16); + pr_debug("%s:%d: db.count_16: %u\n", func, line, + db->count_16); +} + +static void os_area_db_init(struct os_area_db *db) +{ + enum { + HEADER_SIZE = offsetof(struct os_area_db, _db_data), + INDEX_64_COUNT = 64, + VALUES_64_COUNT = 57, + INDEX_32_COUNT = 64, + VALUES_32_COUNT = 57, + INDEX_16_COUNT = 64, + VALUES_16_COUNT = 57, + }; + + memset(db, 0, sizeof(struct os_area_db)); + + db->magic_num = OS_AREA_DB_MAGIC_NUM; + db->version = 1; + db->index_64 = HEADER_SIZE; + db->count_64 = VALUES_64_COUNT; + db->index_32 = HEADER_SIZE + + INDEX_64_COUNT * sizeof(struct db_index) + + VALUES_64_COUNT * sizeof(u64); + db->count_32 = VALUES_32_COUNT; + db->index_16 = HEADER_SIZE + + INDEX_64_COUNT * sizeof(struct db_index) + + VALUES_64_COUNT * sizeof(u64) + + INDEX_32_COUNT * sizeof(struct db_index) + + VALUES_32_COUNT * sizeof(u32); + db->count_16 = VALUES_16_COUNT; + + /* Rules to check db layout. */ + + BUILD_BUG_ON(sizeof(struct db_index) != 1); + BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE); + BUILD_BUG_ON(INDEX_64_COUNT & 0x7); + BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT); + BUILD_BUG_ON(INDEX_32_COUNT & 0x7); + BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT); + BUILD_BUG_ON(INDEX_16_COUNT & 0x7); + BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT); + BUILD_BUG_ON(HEADER_SIZE + + INDEX_64_COUNT * sizeof(struct db_index) + + VALUES_64_COUNT * sizeof(u64) + + INDEX_32_COUNT * sizeof(struct db_index) + + VALUES_32_COUNT * sizeof(u32) + + INDEX_16_COUNT * sizeof(struct db_index) + + VALUES_16_COUNT * sizeof(u16) + > sizeof(struct os_area_db)); +} + +/** + * update_flash_db - Helper for os_area_queue_work_handler. + * + */ + +static void update_flash_db(void) +{ + int result; + int file; + off_t offset; + ssize_t count; + static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE; + const struct os_area_header *header; + struct os_area_db* db; + + /* Read in header and db from flash. */ + + file = sys_open("/dev/ps3flash", O_RDWR, 0); + + if (file < 0) { + pr_debug("%s:%d sys_open failed\n", __func__, __LINE__); + goto fail_open; + } + + header = kmalloc(buf_len, GFP_KERNEL); + + if (!header) { + pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__); + goto fail_malloc; + } + + offset = sys_lseek(file, 0, SEEK_SET); + + if (offset != 0) { + pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__); + goto fail_header_seek; + } + + count = sys_read(file, (char __user *)header, buf_len); + + result = count < OS_AREA_SEGMENT_SIZE || verify_header(header) + || count < header->db_area_offset * OS_AREA_SEGMENT_SIZE; + + if (result) { + pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); + dump_header(header); + goto fail_header; + } + + /* Now got a good db offset and some maybe good db data. */ + + db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE; + + result = db_verify(db); + + if (result) { + printk(KERN_NOTICE "%s:%d: Verify of flash database failed, " + "formatting.\n", __func__, __LINE__); + dump_db(db); + os_area_db_init(db); + } + + /* Now got good db data. */ + + db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff); + + offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE, + SEEK_SET); + + if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) { + pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__); + goto fail_db_seek; + } + + count = sys_write(file, (const char __user *)db, + sizeof(struct os_area_db)); + + if (count < sizeof(struct os_area_db)) { + pr_debug("%s:%d sys_write failed\n", __func__, __LINE__); + } + +fail_db_seek: +fail_header: +fail_header_seek: + kfree(header); +fail_malloc: + sys_close(file); +fail_open: + return; +} + +/** + * os_area_queue_work_handler - Asynchronous write handler. + * + * An asynchronous write for flash memory and the device tree. Do not + * call directly, use os_area_queue_work(). + */ + +static void os_area_queue_work_handler(struct work_struct *work) +{ + struct device_node *node; + + pr_debug(" -> %s:%d\n", __func__, __LINE__); + + node = of_find_node_by_path("/"); + + if (node) { + os_area_set_property(node, &property_rtc_diff); + of_node_put(node); + } else + pr_debug("%s:%d of_find_node_by_path failed\n", + __func__, __LINE__); + +#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) + update_flash_db(); +#else + printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n", + __func__, __LINE__); +#endif + pr_debug(" <- %s:%d\n", __func__, __LINE__); +} + +static void os_area_queue_work(void) +{ + static DECLARE_WORK(q, os_area_queue_work_handler); + + wmb(); + schedule_work(&q); +} + +/** + * ps3_os_area_save_params - Copy data from os area mirror to @saved_params. + * + * For the convenience of the guest the HV makes a copy of the os area in + * flash to a high address in the boot memory region and then puts that RAM + * address and the byte count into the repository for retrieval by the guest. + * We copy the data we want into a static variable and allow the memory setup + * by the HV to be claimed by the lmb manager. + * + * The os area mirror will not be available to a second stage kernel, and + * the header verify will fail. In this case, the saved_params values will + * be set from flash memory or the passed in device tree in ps3_os_area_init(). + */ + +void __init ps3_os_area_save_params(void) { int result; u64 lpar_addr; unsigned int size; struct os_area_header *header; struct os_area_params *params; + struct os_area_db *db; + + pr_debug(" -> %s:%d\n", __func__, __LINE__); result = ps3_repository_read_boot_dat_info(&lpar_addr, &size); if (result) { pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n", __func__, __LINE__); - return result; + return; } header = (struct os_area_header *)__va(lpar_addr); - params = (struct os_area_params *)__va(lpar_addr + OS_AREA_SEGMENT_SIZE); + params = (struct os_area_params *)__va(lpar_addr + + OS_AREA_SEGMENT_SIZE); result = verify_header(header); if (result) { + /* Second stage kernels exit here. */ pr_debug("%s:%d verify_header failed\n", __func__, __LINE__); dump_header(header); - return -EIO; + return; } + db = (struct os_area_db *)__va(lpar_addr + + header->db_area_offset * OS_AREA_SEGMENT_SIZE); + dump_header(header); dump_params(params); + dump_db(db); - saved_params.rtc_diff = params->rtc_diff; + result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff); + if (result) + saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff + : SECONDS_FROM_1970_TO_2000; saved_params.av_multi_out = params->av_multi_out; - saved_params.ctrl_button = params->ctrl_button; - memcpy(saved_params.static_ip_addr, params->static_ip_addr, 4); - memcpy(saved_params.network_mask, params->network_mask, 4); - memcpy(saved_params.default_gateway, params->default_gateway, 4); - memcpy(saved_params.dns_secondary, params->dns_secondary, 4); + saved_params.valid = 1; + + memset(header, 0, sizeof(*header)); - return result; + pr_debug(" <- %s:%d\n", __func__, __LINE__); } /** - * ps3_os_area_rtc_diff - Returns the ps3 rtc diff value. + * ps3_os_area_init - Setup os area device tree properties as needed. + */ + +void __init ps3_os_area_init(void) +{ + struct device_node *node; + + pr_debug(" -> %s:%d\n", __func__, __LINE__); + + node = of_find_node_by_path("/"); + + if (!saved_params.valid && node) { + /* Second stage kernels should have a dt entry. */ + os_area_get_property(node, &property_rtc_diff); + os_area_get_property(node, &property_av_multi_out); + } + + if(!saved_params.rtc_diff) + saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000; + + if (node) { + os_area_set_property(node, &property_rtc_diff); + os_area_set_property(node, &property_av_multi_out); + of_node_put(node); + } else + pr_debug("%s:%d of_find_node_by_path failed\n", + __func__, __LINE__); + + pr_debug(" <- %s:%d\n", __func__, __LINE__); +} + +/** + * ps3_os_area_get_rtc_diff - Returns the rtc diff value. + */ + +u64 ps3_os_area_get_rtc_diff(void) +{ + return saved_params.rtc_diff; +} + +/** + * ps3_os_area_set_rtc_diff - Set the rtc diff value. * - * The ps3 rtc maintains a value that approximates seconds since - * 2000-01-01 00:00:00 UTC. Returns the exact number of seconds from 1970 to - * 2000 when saved_params.rtc_diff has not been properly set up. + * An asynchronous write is needed to support writing updates from + * the timer interrupt context. */ -u64 ps3_os_area_rtc_diff(void) +void ps3_os_area_set_rtc_diff(u64 rtc_diff) { - return saved_params.rtc_diff ? saved_params.rtc_diff : 946684800UL; + if (saved_params.rtc_diff != rtc_diff) { + saved_params.rtc_diff = rtc_diff; + os_area_queue_work(); + } } /** diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 27c7d099816a..01f0c9506e11 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h @@ -62,8 +62,10 @@ int ps3_set_rtc_time(struct rtc_time *time); /* os area */ -int __init ps3_os_area_init(void); -u64 ps3_os_area_rtc_diff(void); +void __init ps3_os_area_save_params(void); +void __init ps3_os_area_init(void); +u64 ps3_os_area_get_rtc_diff(void); +void ps3_os_area_set_rtc_diff(u64 rtc_diff); /* spu */ diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c index 609945dbe394..5c2cbb08eb52 100644 --- a/arch/powerpc/platforms/ps3/setup.c +++ b/arch/powerpc/platforms/ps3/setup.c @@ -206,6 +206,7 @@ static void __init ps3_setup_arch(void) prealloc_ps3flash_bounce_buffer(); ppc_md.power_save = ps3_power_save; + ps3_os_area_init(); DBG(" <- %s:%d\n", __func__, __LINE__); } @@ -228,7 +229,7 @@ static int __init ps3_probe(void) powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; - ps3_os_area_init(); + ps3_os_area_save_params(); ps3_mm_init(); ps3_mm_vas_create(&htab_size); ps3_hpte_init(htab_size); diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 802a9ccacb5e..d0daf7d6d3b2 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c @@ -50,12 +50,6 @@ static void __maybe_unused _dump_time(int time, const char *func, _dump_tm(&tm, func, line); } -/** - * rtc_shift - Difference in seconds between 1970 and the ps3 rtc value. - */ - -static s64 rtc_shift; - void __init ps3_calibrate_decr(void) { int result; @@ -66,8 +60,6 @@ void __init ps3_calibrate_decr(void) ppc_tb_freq = tmp; ppc_proc_freq = ppc_tb_freq * 40; - - rtc_shift = ps3_os_area_rtc_diff(); } static u64 read_rtc(void) @@ -87,18 +79,18 @@ int ps3_set_rtc_time(struct rtc_time *tm) u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - rtc_shift = now - read_rtc(); + ps3_os_area_set_rtc_diff(now - read_rtc()); return 0; } void ps3_get_rtc_time(struct rtc_time *tm) { - to_tm(read_rtc() + rtc_shift, tm); + to_tm(read_rtc() + ps3_os_area_get_rtc_diff(), tm); tm->tm_year -= 1900; tm->tm_mon -= 1; } unsigned long __init ps3_get_boot_time(void) { - return read_rtc() + rtc_shift; + return read_rtc() + ps3_os_area_get_rtc_diff(); } diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 9711eb0d5496..fc48b96c81bf 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -252,6 +252,20 @@ static struct notifier_block pseries_smp_nb = { static int __init pseries_cpu_hotplug_init(void) { + struct device_node *np; + const char *typep; + + for_each_node_by_name(np, "interrupt-controller") { + typep = of_get_property(np, "compatible", NULL); + if (strstr(typep, "open-pic")) { + of_node_put(np); + + printk(KERN_INFO "CPU Hotplug not supported on " + "systems using MPIC\n"); + return 0; + } + } + rtas_stop_self_args.token = rtas_token("stop-self"); qcss_tok = rtas_token("query-cpu-stopped-state"); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f0b7146a110f..fdb9b1c8f977 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -257,11 +257,6 @@ static void __init pSeries_setup_arch(void) /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; - if (ROOT_DEV == 0) { - printk("No ramdisk, default root is /dev/sda2\n"); - ROOT_DEV = Root_SDA2; - } - fwnmi_init(); /* Find and initialize PCI host bridges */ diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index ab037a3a40db..4d3ba63bba79 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c @@ -324,11 +324,13 @@ static struct of_device_id axon_ram_device_id[] = { }; static struct of_platform_driver axon_ram_driver = { - .owner = THIS_MODULE, - .name = AXON_RAM_MODULE_NAME, .match_table = axon_ram_device_id, .probe = axon_ram_probe, - .remove = axon_ram_remove + .remove = axon_ram_remove, + .driver = { + .owner = THIS_MODULE, + .name = AXON_RAM_MODULE_NAME, + }, }; /** diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 2f91b55b7754..20edd1e94eff 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -205,10 +205,12 @@ static int pmi_of_remove(struct of_device *dev) } static struct of_platform_driver pmi_of_platform_driver = { - .name = "pmi", .match_table = pmi_match, .probe = pmi_of_probe, - .remove = pmi_of_remove + .remove = pmi_of_remove, + .driver = { + .name = "pmi", + }, }; static int __init pmi_module_init(void) diff --git a/arch/ppc/platforms/ev64360.c b/arch/ppc/platforms/ev64360.c index f8baf05f16ce..6765676a5c6b 100644 --- a/arch/ppc/platforms/ev64360.c +++ b/arch/ppc/platforms/ev64360.c @@ -23,9 +23,6 @@ #include <linux/mtd/physmap.h> #include <linux/mv643xx.h> #include <linux/platform_device.h> -#ifdef CONFIG_BOOTIMG -#include <linux/bootimg.h> -#endif #include <asm/page.h> #include <asm/time.h> #include <asm/smp.h> diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c index c289e9f1b251..52f63e6f0856 100644 --- a/arch/ppc/platforms/katana.c +++ b/arch/ppc/platforms/katana.c @@ -27,9 +27,6 @@ #include <linux/mtd/physmap.h> #include <linux/mv643xx.h> #include <linux/platform_device.h> -#ifdef CONFIG_BOOTIMG -#include <linux/bootimg.h> -#endif #include <asm/io.h> #include <asm/unistd.h> #include <asm/page.h> diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index af3969a9c963..e824b672e05a 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -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; } diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e51550db1575..880b5dce3a62 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -56,30 +56,6 @@ #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); diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index e12275df6ea2..f1d60f0cef8f 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -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(); diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/include/asm-powerpc/cell-regs.h index b24025f2ac7a..fd6fd00434ef 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/include/asm-powerpc/cell-regs.h @@ -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); diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index c9b8f64bbb45..d913f460e710 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -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; diff --git a/include/asm-powerpc/iseries/hv_call_event.h b/include/asm-powerpc/iseries/hv_call_event.h index 4cec4762076d..cc029d388e11 100644 --- a/include/asm-powerpc/iseries/hv_call_event.h +++ b/include/asm-powerpc/iseries/hv_call_event.h @@ -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)); diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h index 6e323a13ac30..c59ee7e4bed1 100644 --- a/include/asm-powerpc/iseries/iommu.h +++ b/include/asm-powerpc/iseries/iommu.h @@ -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 */ diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h index 7a95d296abd1..f9ac0d00b951 100644 --- a/include/asm-powerpc/iseries/vio.h +++ b/include/asm-powerpc/iseries/vio.h @@ -51,6 +51,116 @@ */ #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 */ diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 71c6e7eb2a26..cc7c17f16a9a 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -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); diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h index 598d111e8098..9204c15839c5 100644 --- a/include/asm-powerpc/vio.h +++ b/include/asm-powerpc/vio.h @@ -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); |