From 591f0a4287d0de243493fd0c133c862e1d1f1c97 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Sun, 2 Apr 2006 17:42:40 -0500 Subject: Add 85xx CDS to arch/powerpc This patch adds support for 85xx CDS support to arch/powerpc Signed-off-by: Andy Fleming Signed-off-by: Kumar Gala --- arch/powerpc/platforms/85xx/Kconfig | 9 +- arch/powerpc/platforms/85xx/Makefile | 1 + arch/powerpc/platforms/85xx/mpc85xx_cds.c | 359 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/85xx/mpc85xx_cds.h | 43 ++++ 4 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_cds.c create mode 100644 arch/powerpc/platforms/85xx/mpc85xx_cds.h (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 06e371282f57..454fc53289ab 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -11,13 +11,20 @@ config MPC8540_ADS help This option enables support for the MPC 8540 ADS board +config MPC85xx_CDS + bool "Freescale MPC85xx CDS" + select DEFAULT_UIMAGE + select PPC_I8259 if PCI + help + This option enables support for the MPC85xx CDS board + endchoice config MPC8540 bool select PPC_UDBG_16550 select PPC_INDIRECT_PCI - default y if MPC8540_ADS + default y if MPC8540_ADS || MPC85xx_CDS config PPC_INDIRECT_PCI_BE bool diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index ffc4139cb214..7615aa59c78b 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_PPC_85xx) += misc.o pci.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o +obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c new file mode 100644 index 000000000000..18e6e11f7020 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -0,0 +1,359 @@ +/* + * MPC85xx setup and early boot code plus other random bits. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "mpc85xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +static int cds_pci_slot = 2; +static volatile u8 *cadmus; + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + * + * Note: Likely, this table and the following function should be + * obtained and derived from the OF Device Tree. + */ +static u_char mpc85xx_cds_openpic_initsenses[] __initdata = { + MPC85XX_INTERNAL_IRQ_SENSES, +#if defined(CONFIG_PCI) + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Ext 0: PCI slot 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 3 */ +#else + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ +#endif + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + 0x0, /* External 8: */ + 0x0, /* External 9: */ + 0x0, /* External 10: */ +#ifdef CONFIG_PCI + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 11: PCI2 slot 0 */ +#else + 0x0, /* External 11: */ +#endif +}; + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ +int +mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); + + if (!hose->index) + { + /* Handle PCI1 interrupts */ + char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + + /* Note IRQ assignment for slots is based on which slot the elysium is + * in -- in this setup elysium is in slot #2 (this PIRQA as first + * interrupt on slot */ + { + { 0, 1, 2, 3 }, /* 16 - PMC */ + { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */ + { 0, 1, 2, 3 }, /* 18 - Slot 1 */ + { 1, 2, 3, 0 }, /* 19 - Slot 2 */ + { 2, 3, 0, 1 }, /* 20 - Slot 3 */ + { 3, 0, 1, 2 }, /* 21 - Slot 4 */ + }; + + const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4; + int i, j; + + for (i = 0; i < 6; i++) + for (j = 0; j < 4; j++) + pci_irq_table[i][j] = + ((pci_irq_table[i][j] + 5 - + cds_pci_slot) & 0x3) + PIRQ0A; + + return PCI_IRQ_TABLE_LOOKUP; + } else { + /* Handle PCI2 interrupts (if we have one) */ + char pci_irq_table[][4] = + { + /* + * We only have one slot and one interrupt + * going to PIRQA - PIRQD */ + { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */ + }; + + const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4; + + return PCI_IRQ_TABLE_LOOKUP; + } +} + +#define ARCADIA_HOST_BRIDGE_IDSEL 17 +#define ARCADIA_2ND_BRIDGE_IDSEL 3 + +extern int mpc85xx_pci2_busno; + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc85xx_pci2_busno) + if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + /* We explicitly do not go past the Tundra 320 Bridge */ + if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +void __init +mpc85xx_cds_pcibios_fixup(void) +{ + struct pci_dev *dev; + u_char c; + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { + /* + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. + */ + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset + */ + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_dev_put(dev); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + pci_dev_put(dev); + } + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + pci_dev_put(dev); + } +} +#endif /* CONFIG_PCI */ + +void __init mpc85xx_cds_pic_init(void) +{ + struct mpic *mpic1; + phys_addr_t OpenPIC_PAddr; + + /* Determine the Physical Address of the OpenPIC regs */ + OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; + + mpic1 = mpic_alloc(OpenPIC_PAddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc85xx_cds_openpic_initsenses, + sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC "); + BUG_ON(mpic1 == NULL); + mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); + mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); + mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300); + mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380); + mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400); + mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480); + mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500); + mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580); + + /* dummy mappings to get to 48 */ + mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600); + mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680); + mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700); + mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780); + + /* External ints */ + mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000); + mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080); + mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL); + + i8259_init(0,0); +#endif +} + + +/* + * Setup the architecture + */ +static void __init +mpc85xx_cds_setup_arch(void) +{ + struct device_node *cpu; +#ifdef CONFIG_PCI + struct device_node *np; +#endif + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_cds_setup_arch()", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 500000000 / HZ; + of_node_put(cpu); + } + + cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); + cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; + + if (ppc_md.progress) { + char buf[40]; + snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", + cadmus[CM_VER], cds_pci_slot); + ppc_md.progress(buf, 0); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc85xx_map_irq; + ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + + +void +mpc85xx_cds_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc85xx_cds_probe(void) +{ + /* We always match for now, eventually we should look at + * the flat dev tree to ensure this is the board we are + * supposed to run on + */ + return 1; +} + +define_machine(mpc85xx_cds) { + .name = "MPC85xx CDS", + .probe = mpc85xx_cds_probe, + .setup_arch = mpc85xx_cds_setup_arch, + .init_IRQ = mpc85xx_cds_pic_init, + .show_cpuinfo = mpc85xx_cds_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h new file mode 100644 index 000000000000..671f54ff185a --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h @@ -0,0 +1,43 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_cds_common.h + * + * MPC85xx CDS board definitions + * + * Maintainer: Kumar Gala + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * 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. + * + */ + +#ifndef __MACH_MPC85XX_CDS_H__ +#define __MACH_MPC85XX_CDS_H__ + +/* CADMUS info */ +#define CADMUS_BASE (0xf8004000) +#define CADMUS_SIZE (256) +#define CM_VER (0) +#define CM_CSR (1) +#define CM_RST (2) + +/* CDS NVRAM/RTC */ +#define CDS_RTC_ADDR (0xf8000000) +#define CDS_RTC_SIZE (8 * 1024) + +/* PCI interrupt controller */ +#define PIRQ0A MPC85xx_IRQ_EXT0 +#define PIRQ0B MPC85xx_IRQ_EXT1 +#define PIRQ0C MPC85xx_IRQ_EXT2 +#define PIRQ0D MPC85xx_IRQ_EXT3 +#define PIRQ1A MPC85xx_IRQ_EXT11 + +#define NR_8259_INTS 16 +#define CPM_IRQ_OFFSET NR_8259_INTS + +#define MPC85xx_OPENPIC_IRQ_OFFSET 80 + +#endif /* __MACH_MPC85XX_CDS_H__ */ -- cgit From 81bbbe92949b069c101e13d3acbd4bc7d088cb79 Mon Sep 17 00:00:00 2001 From: Haren Myneni Date: Wed, 5 Apr 2006 21:10:18 -0600 Subject: [PATCH] powerpc: clear IPIs on kdump In some crash scenarios, the kexec CPU is not responding to an IPI sent by secondary CPU after init thread is forked, causing the system to drop into xmon during kdump boot. This problem can be reproduced each time when the debugger is enabled and soft-reset is used to invoke kdump boot. The first CPU sends an IPI - setting the IPI priority for all secondary cpus (xics_cause_ipi()). But some CPUs will enter into the xmon via soft-reset, i.e, not executing xics_ipi_action(). Hence, IPI is not cleared. When exited from the debugger, one of these CPUs could become the primary kexec CPU. Since the IPI is not cleared, causing this issue in kdump boot. This patch clears and EOI IPI for kexec CPU as well before the kdump boot started. Signed-off-by: Haren Myneni Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/xics.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 2d60ea30fed6..6c17df5814b4 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -641,23 +641,26 @@ void xics_teardown_cpu(int secondary) ops->cppr_info(cpu, 0x00); iosync(); + /* Clear IPI */ + ops->qirr_info(cpu, 0xff); + + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + /* * Some machines need to have at least one cpu in the GIQ, * so leave the master cpu in the group. */ - if (secondary) { - /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? - */ - ops->xirr_info_set(cpu, XICS_IPI); + if (secondary) rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - } } #ifdef CONFIG_HOTPLUG_CPU -- cgit From c256f4b9598c71afd8eb0b7d3d3790a38734cf43 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Fri, 7 Apr 2006 15:23:03 +1000 Subject: [PATCH] powerpc: remove io_page_mask Cleanup patch which removes the io_page_mask. It fixes the reset on some e1000 devices which is needed for clean kexec reboots. The legacy devices which broke with this patch (parallel port and PC speaker) have now been fixed in Linus' tree. Signed-off-by: Anton Blanchard Acked-by: Michael Neuling Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 3 --- arch/powerpc/platforms/maple/pci.c | 3 --- arch/powerpc/platforms/powermac/pci.c | 3 --- 3 files changed, 9 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index a19833b880e4..5a61c6fdb33a 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -45,8 +45,6 @@ #include "call_pci.h" #include "iommu.h" -extern unsigned long io_page_mask; - /* * Forward declares of prototypes. */ @@ -277,7 +275,6 @@ void iSeries_pcibios_init(void) { iomm_table_initialize(); find_and_init_phbs(); - io_page_mask = -1; } /* diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 85d6c93659cc..9a4efc0c3b29 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -437,9 +437,6 @@ void __init maple_pci_init(void) /* Tell pci.c to not change any resource allocations. */ pci_probe_only = 1; - - /* Allow all IO */ - io_page_mask = -1; } int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel) diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index f5d8d15d74fa..3212618e7909 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -1068,9 +1068,6 @@ void __init pmac_pci_init(void) /* Tell pci.c to not use the common resource allocation mechanism */ pci_probe_only = 1; - /* Allow all IO */ - io_page_mask = -1; - #else /* CONFIG_PPC64 */ init_p2pbridge(); fixup_nec_usb2(); -- cgit From 4baaf0cfda7279e1adaedc203d7a09e8e44597ab Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:23:22 -0500 Subject: [PATCH] powerpc: Don't print chosen idle loop at every boot No need to write out what idle loop is used on every boot. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 4 ++-- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/powermac/feature.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a6fd9bedb074..0f5110659e60 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -536,10 +536,10 @@ static void __init iSeries_setup_arch(void) { if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); } else { ppc_md.idle_loop = iseries_dedicated_idle; - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); } /* Setup the Lp Event Queue */ diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 24c0aef4ea39..a0505ea48a86 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -189,7 +189,7 @@ void __init maple_setup_arch(void) conswitchp = &dummy_con; #endif - printk(KERN_INFO "Using native/NAP idle loop\n"); + printk(KERN_DEBUG "Using native/NAP idle loop\n"); } /* diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index a5063cd675c5..85e00cb0006e 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2510,7 +2510,7 @@ found: if (get_property(np, "flush-on-lock", NULL)) break; powersave_nap = 1; - printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); + printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; } diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 5eb55ef1c91c..9118d79b7b46 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -235,14 +235,14 @@ static void __init pSeries_setup_arch(void) if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); if (get_lppaca()->shared_proc) { - printk(KERN_INFO "Using shared processor idle loop\n"); + printk(KERN_DEBUG "Using shared processor idle loop\n"); ppc_md.power_save = pseries_shared_idle_sleep; } else { - printk(KERN_INFO "Using dedicated idle loop\n"); + printk(KERN_DEBUG "Using dedicated idle loop\n"); ppc_md.power_save = pseries_dedicated_idle_sleep; } } else { - printk(KERN_INFO "Using default idle loop\n"); + printk(KERN_DEBUG "Using default idle loop\n"); } if (firmware_has_feature(FW_FEATURE_LPAR)) -- cgit From cc98f70557bd08f2eea7b955dd918692a655d72e Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:26:00 -0500 Subject: [PATCH] powerpc: Lack of ISA interrupts on XICS isn't dangerous This isn't really a dangerous thing any more; most systems lack ISA interrupt controllers. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/xics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 6c17df5814b4..b14f9b5c114e 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -522,7 +522,7 @@ nextnode: np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { - printk(KERN_WARNING "xics: no ISA interrupt controller\n"); + printk(KERN_DEBUG "xics: no ISA interrupt controller\n"); xics_irq_8259_cascade_real = -1; xics_irq_8259_cascade = -1; } else { -- cgit From 90ddfebec1b450258f85d42f043cfbae450fe47e Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 12 Apr 2006 15:28:13 -0500 Subject: [PATCH] powerpc: Quiet rtasd output at boot Most users won't really know the difference between a started RTAS daemon and a missing event-scan. Move it to debug levels. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/rtasd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index e0000ce769e5..2e4e04042d85 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -348,7 +348,7 @@ static int enable_surveillance(int timeout) return 0; if (error == -EINVAL) { - printk(KERN_INFO "rtasd: surveillance not supported\n"); + printk(KERN_DEBUG "rtasd: surveillance not supported\n"); return 0; } @@ -440,7 +440,7 @@ static int rtasd(void *unused) goto error; } - printk(KERN_INFO "RTAS daemon started\n"); + printk(KERN_DEBUG "RTAS daemon started\n"); DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate)); @@ -487,7 +487,7 @@ static int __init rtas_init(void) /* No RTAS */ if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) { - printk(KERN_INFO "rtasd: no event-scan on system\n"); + printk(KERN_DEBUG "rtasd: no event-scan on system\n"); return -ENODEV; } -- cgit From 4bd174fe1cca738f53cf8bb9ac3cb327b1f516ed Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 18 Apr 2006 11:25:53 -0500 Subject: [PATCH] powerpc: Remove stale iseries global Not even the iSeries maintainer seems to have access to this legendary piranha simulator. It adds a bit of ugliness in the common time init code, and if it's no longer used we might as well be done with it and remove the bloat. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/mf.c | 9 +-------- arch/powerpc/platforms/iseries/setup.c | 5 ----- 2 files changed, 1 insertion(+), 13 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index d771b8ee857d..1a2c2a50f922 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -45,7 +45,6 @@ #include "setup.h" -extern int piranha_simulator; static int mf_initialized; /* @@ -658,7 +657,7 @@ static void mf_clear_src(void) void __init mf_display_progress(u16 value) { - if (piranha_simulator || !mf_initialized) + if (!mf_initialized) return; if (0xFFFF == value) @@ -1295,9 +1294,6 @@ __initcall(mf_proc_init); */ void iSeries_get_rtc_time(struct rtc_time *rtc_tm) { - if (piranha_simulator) - return; - mf_get_rtc(rtc_tm); rtc_tm->tm_mon--; } @@ -1316,9 +1312,6 @@ unsigned long iSeries_get_boot_time(void) { struct rtc_time tm; - if (piranha_simulator) - return 0; - mf_get_boot_rtc(&tm); return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0f5110659e60..3c51448a1855 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -81,9 +81,6 @@ extern void iSeries_pci_final_fixup(void); static void iSeries_pci_final_fixup(void) { } #endif -/* Global Variables */ -int piranha_simulator; - extern int rd_size; /* Defined in drivers/block/rd.c */ extern unsigned long embedded_sysmap_start; extern unsigned long embedded_sysmap_end; @@ -340,8 +337,6 @@ static void __init iSeries_init_early(void) #ifdef CONFIG_SMP smp_init_iSeries(); #endif - if (itLpNaca.xPirEnvironMode == 0) - piranha_simulator = 1; /* Associate Lp Event Queue 0 with processor 0 */ HvCallEvent_setLpEventQueueInterruptProc(0, 0); -- cgit From ac325acd50013fa8f4953208cbb96504dec9b12a Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Tue, 18 Apr 2006 21:05:21 -0700 Subject: [PATCH] powerpc/pseries: clear PCI failure counter if no new failures The current PCI error recovery system keeps track of the number of PCI card resets, and refuses to bring a card back up if this number is too large. The goal of doing this was to avoid an infinite loop of resets if a card is obviously dead. However, if the failures are rare, but the machine has a high uptime, this mechanism might still be triggered; this is too harsh. This patch will avoids this problem by decrementing the fail count after an hour. Thus, as long as a pci card BSOD's less than 6 times an hour, it will continue to be reset indefinitely. If it's failure rate is greater than that, it will be taken off-line permanently. This patch is larger than it might otherwise be because it changes indentation by removing a pointless while-loop. The while loop is not needed, as the handler is invoked once fo each event (by schedule_work()); the loop is leftover cruft from an earlier implementation. Signed-off-by: Linas Vepstas Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 13 ++++---- arch/powerpc/platforms/pseries/eeh_event.c | 50 ++++++++++++++++------------- 2 files changed, 35 insertions(+), 28 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 1fba695e32e8..2a9eb2630730 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -23,9 +23,8 @@ * */ #include -#include #include -#include +#include #include #include #include @@ -250,7 +249,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) */ #define MAX_WAIT_FOR_RECOVERY 15 -void handle_eeh_events (struct eeh_event *event) +struct pci_dn * handle_eeh_events (struct eeh_event *event) { struct device_node *frozen_dn; struct pci_dn *frozen_pdn; @@ -265,7 +264,7 @@ void handle_eeh_events (struct eeh_event *event) if (!frozen_dn) { printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", pci_name(event->dev)); - return; + return NULL; } /* There are two different styles for coming up with the PE. @@ -280,7 +279,7 @@ void handle_eeh_events (struct eeh_event *event) if (!frozen_bus) { printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", frozen_dn->full_name); - return; + return NULL; } #if 0 @@ -355,7 +354,7 @@ void handle_eeh_events (struct eeh_event *event) /* Tell all device drivers that they can resume operations */ pci_walk_bus(frozen_bus, eeh_report_resume, NULL); - return; + return frozen_pdn; excess_failures: /* @@ -384,6 +383,8 @@ perm_error: /* Shut down the device drivers for good. */ pcibios_remove_pci_devices(frozen_bus); + + return NULL; } /* ---------- end of file ---------- */ diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index a1bda6f96fd1..a0b39640a00f 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -18,6 +18,7 @@ * Copyright (c) 2005 Linas Vepstas */ +#include #include #include #include @@ -56,38 +57,43 @@ static int eeh_event_handler(void * dummy) { unsigned long flags; struct eeh_event *event; + struct pci_dn *pdn; daemonize ("eehd"); + set_current_state(TASK_INTERRUPTIBLE); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&eeh_eventlist_lock, flags); + event = NULL; - spin_lock_irqsave(&eeh_eventlist_lock, flags); - event = NULL; + /* Unqueue the event, get ready to process. */ + if (!list_empty(&eeh_eventlist)) { + event = list_entry(eeh_eventlist.next, struct eeh_event, list); + list_del(&event->list); + } + spin_unlock_irqrestore(&eeh_eventlist_lock, flags); - /* Unqueue the event, get ready to process. */ - if (!list_empty(&eeh_eventlist)) { - event = list_entry(eeh_eventlist.next, struct eeh_event, list); - list_del(&event->list); - } - spin_unlock_irqrestore(&eeh_eventlist_lock, flags); + if (event == NULL) + return 0; - if (event == NULL) - break; + /* Serialize processing of EEH events */ + mutex_lock(&eeh_event_mutex); + eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); - /* Serialize processing of EEH events */ - mutex_lock(&eeh_event_mutex); - eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); + printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", + pci_name(event->dev)); - printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", - pci_name(event->dev)); + pdn = handle_eeh_events(event); - handle_eeh_events(event); + eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); + pci_dev_put(event->dev); + kfree(event); + mutex_unlock(&eeh_event_mutex); - eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); - pci_dev_put(event->dev); - kfree(event); - mutex_unlock(&eeh_event_mutex); + /* If there are no new errors after an hour, clear the counter. */ + if (pdn && pdn->eeh_freeze_count>0) { + msleep_interruptible (3600*1000); + if (pdn->eeh_freeze_count>0) + pdn->eeh_freeze_count--; } return 0; -- cgit From 95a1ca6cd8e702a19ee56efae522a5816a56a205 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:09:02 +1000 Subject: [PATCH] powerpc: add all the iSeries virtual devices to the device tree We do this by putting them in the flattened device tree at setup time. This required the flattened device tree blob to be made bigger. Currenly we don't do anything with these. Also make a function static. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 88 +++++++++++++++++++++++++++++++++- arch/powerpc/platforms/iseries/vio.c | 2 +- 2 files changed, 88 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 3c51448a1855..4862b8e7c78c 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -28,6 +28,7 @@ #include #include #include +#include /* ETH_ALEN */ #include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -710,7 +712,7 @@ define_machine(iseries) { }; struct blob { - unsigned char data[PAGE_SIZE]; + unsigned char data[PAGE_SIZE * 2]; unsigned long next; }; @@ -911,6 +913,88 @@ void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } +void dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + char buf[32]; + + dt_start_node(dt, "vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + snprintf(buf, sizeof(buf), "viocons@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "serial"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vscsi"); + dt_prop_str(dt, "compatible", "IBM,v-scsi"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + snprintf(buf, 32, "vlan@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vlan"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { + snprintf(buf, 32, "viodasd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viodasd"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALDISKS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { + snprintf(buf, 32, "viocd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viocd"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { + snprintf(buf, 32, "viotape@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "viotape"); + dt_prop_empty(dt, "compatible"); + dt_prop_u32(dt, "reg", reg + i); + dt_end_node(dt); + } + + dt_end_node(dt); +} + void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; @@ -941,6 +1025,8 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) dt_cpus(dt); + dt_vdevices(dt); + dt_end_node(dt); dt_push_u32(dt, OF_DT_END); diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index ad36ab0639f0..22045a2829a9 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -71,7 +71,7 @@ static struct vio_dev *__init vio_register_device_iseries(char *type, return viodev; } -void __init probe_bus_iseries(void) +static void __init probe_bus_iseries(void) { HvLpIndexMap vlan_map; struct vio_dev *viodev; -- cgit From e10fa77368dff31140451fac04d78d9f51f0f3ac Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:18:21 +1000 Subject: [PATCH] powerpc: use the device tree for the iSeries vio bus probe As an added bonus, since every vio_dev now has a device_node associated with it, hotplug now works. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 4 + arch/powerpc/platforms/iseries/vio.c | 70 ++-------------- arch/powerpc/platforms/pseries/vio.c | 147 ++------------------------------- 3 files changed, 22 insertions(+), 199 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 4862b8e7c78c..901acbcc0888 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -951,6 +951,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "vlan"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); mac_addr[0] = 0x02; mac_addr[1] = 0x01; @@ -971,6 +972,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viodasd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALDISKS; @@ -980,6 +982,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viocd"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } reg += HVMAXARCHITECTEDVIRTUALCDROMS; @@ -989,6 +992,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "viotape"); dt_prop_empty(dt, "compatible"); dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); } diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index 22045a2829a9..a689da6f2b07 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -43,58 +43,11 @@ static void __init iommu_vio_init(void) printk("Virtual Bus VIO TCE table failed.\n"); } -/** - * vio_register_device_iseries: - Register a new iSeries vio device. - * @voidev: The device to register. - */ -static struct vio_dev *__init vio_register_device_iseries(char *type, - uint32_t unit_num) +static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) { - struct vio_dev *viodev; - - /* allocate a vio_dev for this device */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) - return NULL; - memset(viodev, 0, sizeof(struct vio_dev)); - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num); - - viodev->name = viodev->dev.bus_id; - viodev->type = type; - viodev->unit_address = unit_num; - viodev->iommu_table = &vio_iommu_table; - if (vio_register_device(viodev) == NULL) { - kfree(viodev); - return NULL; - } - return viodev; -} - -static void __init probe_bus_iseries(void) -{ - HvLpIndexMap vlan_map; - struct vio_dev *viodev; - int i; - - /* there is only one of each of these */ - vio_register_device_iseries("viocons", 0); - vio_register_device_iseries("vscsi", 0); - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - viodev = vio_register_device_iseries("vlan", i); - /* veth is special and has it own iommu_table */ - viodev->iommu_table = &veth_iommu_table; - } - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) - vio_register_device_iseries("viodasd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) - vio_register_device_iseries("viocd", i); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) - vio_register_device_iseries("viotape", i); + if (strcmp(dev->type, "vlan") == 0) + return &veth_iommu_table; + return &vio_iommu_table; } /** @@ -109,6 +62,7 @@ static int vio_match_device_iseries(const struct vio_device_id *id, static struct vio_bus_ops vio_bus_ops_iseries = { .match = vio_match_device_iseries, + .build_iommu_table = vio_build_iommu_table, }; /** @@ -116,16 +70,10 @@ static struct vio_bus_ops vio_bus_ops_iseries = { */ static int __init vio_bus_init_iseries(void) { - int err; - - err = vio_bus_init(&vio_bus_ops_iseries); - if (err == 0) { - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - probe_bus_iseries(); - } - return err; + iommu_vio_init(); + vio_bus_device.iommu_table = &vio_iommu_table; + iSeries_vio_dev = &vio_bus_device.dev; + return vio_bus_init(&vio_bus_ops_iseries); } __initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index 8e53e04ada8b..b3925aefdac6 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -26,26 +26,6 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -static void probe_bus_pseries(void) -{ - struct device_node *node_vroot, *of_node; - - node_vroot = find_devices("vdevice"); - if ((node_vroot == NULL) || (node_vroot->child == NULL)) - /* this machine doesn't do virtual IO, and that's ok */ - return; - - /* - * Create struct vio_devices for each virtual device in the device tree. - * Drivers will associate with them later. - */ - for (of_node = node_vroot->child; of_node != NULL; - of_node = of_node->sibling) { - printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node); - vio_register_device_node(of_node); - } -} - /** * vio_match_device_pseries: - Tell if a pSeries VIO device matches a * vio_device_id @@ -57,47 +37,6 @@ static int vio_match_device_pseries(const struct vio_device_id *id, device_is_compatible(dev->dev.platform_data, id->compat); } -static void vio_release_device_pseries(struct device *dev) -{ - /* XXX free TCE table */ - of_node_put(dev->platform_data); -} - -static ssize_t viodev_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct device_node *of_node = dev->platform_data; - - return sprintf(buf, "%s\n", of_node->full_name); -} -DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL); - -static void vio_unregister_device_pseries(struct vio_dev *viodev) -{ - device_remove_file(&viodev->dev, &dev_attr_devspec); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, - .unregister_device = vio_unregister_device_pseries, - .release_device = vio_release_device_pseries, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - int err; - - err = vio_bus_init(&vio_bus_ops_pseries); - if (err == 0) - probe_bus_pseries(); - return err; -} - -__initcall(vio_bus_init_pseries); - /** * vio_build_iommu_table: - gets the dma information from OF and * builds the TCE tree. @@ -136,88 +75,20 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) return iommu_init_table(newTceTable); } +static struct vio_bus_ops vio_bus_ops_pseries = { + .match = vio_match_device_pseries, + .build_iommu_table = vio_build_iommu_table, +}; + /** - * vio_register_device_node: - Register a new vio device. - * @of_node: The OF node for this device. - * - * Creates and initializes a vio_dev structure from the data in - * of_node (dev.platform_data) and adds it to the list of virtual devices. - * Returns a pointer to the created vio_dev or NULL if node has - * NULL device_type or compatible fields. + * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus */ -struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) +static int __init vio_bus_init_pseries(void) { - struct vio_dev *viodev; - unsigned int *unit_address; - unsigned int *irq_p; - - /* we need the 'device_type' property, in order to match with drivers */ - if ((NULL == of_node->type)) { - printk(KERN_WARNING - "%s: node %s missing 'device_type'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - unit_address = (unsigned int *)get_property(of_node, "reg", NULL); - if (!unit_address) { - printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, - of_node->name ? of_node->name : ""); - return NULL; - } - - /* allocate a vio_dev for this node */ - viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL); - if (!viodev) { - return NULL; - } - memset(viodev, 0, sizeof(struct vio_dev)); - - viodev->dev.platform_data = of_node_get(of_node); - - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } - - snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); - viodev->name = of_node->name; - viodev->type = of_node->type; - viodev->unit_address = *unit_address; - viodev->iommu_table = vio_build_iommu_table(viodev); - - /* register with generic device framework */ - if (vio_register_device(viodev) == NULL) { - /* XXX free TCE table */ - kfree(viodev); - return NULL; - } - device_create_file(&viodev->dev, &dev_attr_devspec); - - return viodev; + return vio_bus_init(&vio_bus_ops_pseries); } -EXPORT_SYMBOL(vio_register_device_node); -/** - * vio_get_attribute: - get attribute for virtual device - * @vdev: The vio device to get property. - * @which: The property/attribute to be extracted. - * @length: Pointer to length of returned data size (unused if NULL). - * - * Calls prom.c's get_property() to return the value of the - * attribute specified by the preprocessor constant @which -*/ -const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) -{ - return get_property(vdev->dev.platform_data, (char*)which, length); -} -EXPORT_SYMBOL(vio_get_attribute); +__initcall(vio_bus_init_pseries); /* vio_find_name() - internal because only vio.c knows how we formatted the * kobject name -- cgit From dd721ffd95d5e1516380da0b254ef737582a258f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:21:46 +1000 Subject: [PATCH] powerpc: use a common vio_match_device routine This requires the compatible properties having vaules that are empty strings instead of just being empty properties. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 10 +++++----- arch/powerpc/platforms/iseries/vio.c | 12 ------------ arch/powerpc/platforms/pseries/vio.c | 12 ------------ 3 files changed, 5 insertions(+), 29 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 901acbcc0888..befd36af7e32 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -927,7 +927,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, sizeof(buf), "viocons@%08x", reg); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "serial"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg); dt_end_node(dt); reg++; @@ -949,7 +949,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "vlan@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "vlan"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); @@ -970,7 +970,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viodasd@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viodasd"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -980,7 +980,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viocd@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viocd"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -990,7 +990,7 @@ void dt_vdevices(struct iseries_flat_dt *dt) snprintf(buf, 32, "viotape@%08x", reg + i); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "viotape"); - dt_prop_empty(dt, "compatible"); + dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c index a689da6f2b07..bdd2b7d97d15 100644 --- a/arch/powerpc/platforms/iseries/vio.c +++ b/arch/powerpc/platforms/iseries/vio.c @@ -50,18 +50,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) return &vio_iommu_table; } -/** - * vio_match_device_iseries: - Tell if a iSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_iseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return strncmp(dev->type, id->type, strlen(id->type)) == 0; -} - static struct vio_bus_ops vio_bus_ops_iseries = { - .match = vio_match_device_iseries, .build_iommu_table = vio_build_iommu_table, }; @@ -75,5 +64,4 @@ static int __init vio_bus_init_iseries(void) iSeries_vio_dev = &vio_bus_device.dev; return vio_bus_init(&vio_bus_ops_iseries); } - __initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c index b3925aefdac6..d2891661d87b 100644 --- a/arch/powerpc/platforms/pseries/vio.c +++ b/arch/powerpc/platforms/pseries/vio.c @@ -26,17 +26,6 @@ extern struct subsystem devices_subsys; /* needed for vio_find_name() */ -/** - * vio_match_device_pseries: - Tell if a pSeries VIO device matches a - * vio_device_id - */ -static int vio_match_device_pseries(const struct vio_device_id *id, - const struct vio_dev *dev) -{ - return (strncmp(dev->type, id->type, strlen(id->type)) == 0) && - device_is_compatible(dev->dev.platform_data, id->compat); -} - /** * vio_build_iommu_table: - gets the dma information from OF and * builds the TCE tree. @@ -76,7 +65,6 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) } static struct vio_bus_ops vio_bus_ops_pseries = { - .match = vio_match_device_pseries, .build_iommu_table = vio_build_iommu_table, }; -- cgit From c7f0e8cb5654a50986c6097b3c0cca972e406899 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Thu, 27 Apr 2006 17:23:32 +1000 Subject: [PATCH] powerpc: merge the rest of the vio code Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/Makefile | 1 - arch/powerpc/platforms/iseries/iommu.c | 3 +- arch/powerpc/platforms/iseries/iommu.h | 35 --------- arch/powerpc/platforms/iseries/pci.c | 2 +- arch/powerpc/platforms/iseries/vio.c | 67 ---------------- arch/powerpc/platforms/pseries/Makefile | 1 - arch/powerpc/platforms/pseries/vio.c | 133 -------------------------------- 7 files changed, 2 insertions(+), 240 deletions(-) delete mode 100644 arch/powerpc/platforms/iseries/iommu.h delete mode 100644 arch/powerpc/platforms/iseries/vio.c delete mode 100644 arch/powerpc/platforms/pseries/vio.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index ce8c0b943fa0..7e67a20c18ab 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -3,7 +3,6 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y += hvlog.o hvlpconfig.o lpardata.o setup.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_IBMVIO) += vio.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_MODULES) += ksyms.o diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index bea0b703f409..a8d96314c982 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -33,8 +33,7 @@ #include #include #include - -#include "iommu.h" +#include extern struct list_head iSeries_Global_Device_List; diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h deleted file mode 100644 index cb5658fbe657..000000000000 --- a/arch/powerpc/platforms/iseries/iommu.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PLATFORMS_ISERIES_IOMMU_H -#define _PLATFORMS_ISERIES_IOMMU_H - -/* - * Copyright (C) 2005 Stephen Rothwell, IBM Corporation - * - * 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 - */ - -struct device_node; -struct iommu_table; - -/* Creates table for an individual device node */ -extern void iommu_devnode_init_iSeries(struct device_node *dn); - -/* Get table parameters from HV */ -extern void iommu_table_getparms_iSeries(unsigned long busno, - unsigned char slotno, unsigned char virtbus, - struct iommu_table *tbl); - -#endif /* _PLATFORMS_ISERIES_IOMMU_H */ diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 5a61c6fdb33a..428ffb5cf044 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -37,13 +37,13 @@ #include #include +#include #include #include "irq.h" #include "pci.h" #include "call_pci.h" -#include "iommu.h" /* * Forward declares of prototypes. diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c deleted file mode 100644 index bdd2b7d97d15..000000000000 --- a/arch/powerpc/platforms/iseries/vio.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * IBM PowerPC iSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2005 Stephen Rothwell, IBM Corp. - * - * 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. - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iommu.h" - -struct device *iSeries_vio_dev = &vio_bus_device.dev; -EXPORT_SYMBOL(iSeries_vio_dev); - -static struct iommu_table veth_iommu_table; -static struct iommu_table vio_iommu_table; - -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)) - printk("Virtual Bus VETH TCE table failed.\n"); - if (!iommu_init_table(&vio_iommu_table)) - printk("Virtual Bus VIO TCE table failed.\n"); -} - -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ - if (strcmp(dev->type, "vlan") == 0) - return &veth_iommu_table; - return &vio_iommu_table; -} - -static struct vio_bus_ops vio_bus_ops_iseries = { - .build_iommu_table = vio_build_iommu_table, -}; - -/** - * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus - */ -static int __init vio_bus_init_iseries(void) -{ - iommu_vio_init(); - vio_bus_device.iommu_table = &vio_iommu_table; - iSeries_vio_dev = &vio_bus_device.dev; - return vio_bus_init(&vio_bus_ops_iseries); -} -__initcall(vio_bus_init_iseries); diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 930898635c9f..b46ce3b9bb3c 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,7 +2,6 @@ obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ firmware.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_IBMVIO) += vio.o obj-$(CONFIG_XICS) += xics.o obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c deleted file mode 100644 index d2891661d87b..000000000000 --- a/arch/powerpc/platforms/pseries/vio.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * IBM PowerPC pSeries Virtual I/O Infrastructure Support. - * - * Copyright (c) 2003-2005 IBM Corp. - * Dave Engebretsen engebret@us.ibm.com - * Santiago Leon santil@us.ibm.com - * Hollis Blanchard - * Stephen Rothwell - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct subsystem devices_subsys; /* needed for vio_find_name() */ - -/** - * vio_build_iommu_table: - gets the dma information from OF and - * builds the TCE tree. - * @dev: the virtual device. - * - * Returns a pointer to the built tce tree, or NULL if it can't - * find property. -*/ -static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) -{ - unsigned int *dma_window; - struct iommu_table *newTceTable; - unsigned long offset; - int dma_window_property_size; - - dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size); - if(!dma_window) { - return NULL; - } - - newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - - /* There should be some code to extract the phys-encoded offset - using prom_n_addr_cells(). However, according to a comment - on earlier versions, it's always zero, so we don't bother */ - offset = dma_window[1] >> PAGE_SHIFT; - - /* TCE table size - measured in tce entries */ - newTceTable->it_size = dma_window[4] >> PAGE_SHIFT; - /* offset for VIO should always be 0 */ - newTceTable->it_offset = offset; - newTceTable->it_busno = 0; - newTceTable->it_index = (unsigned long)dma_window[0]; - newTceTable->it_type = TCE_VB; - - return iommu_init_table(newTceTable); -} - -static struct vio_bus_ops vio_bus_ops_pseries = { - .build_iommu_table = vio_build_iommu_table, -}; - -/** - * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus - */ -static int __init vio_bus_init_pseries(void) -{ - return vio_bus_init(&vio_bus_ops_pseries); -} - -__initcall(vio_bus_init_pseries); - -/* vio_find_name() - internal because only vio.c knows how we formatted the - * kobject name - * XXX once vio_bus_type.devices is actually used as a kset in - * drivers/base/bus.c, this function should be removed in favor of - * "device_find(kobj_name, &vio_bus_type)" - */ -static struct vio_dev *vio_find_name(const char *kobj_name) -{ - struct kobject *found; - - found = kset_find_obj(&devices_subsys.kset, kobj_name); - if (!found) - return NULL; - - return to_vio_dev(container_of(found, struct device, kobj)); -} - -/** - * vio_find_node - find an already-registered vio_dev - * @vnode: device_node of the virtual device we're looking for - */ -struct vio_dev *vio_find_node(struct device_node *vnode) -{ - uint32_t *unit_address; - char kobj_name[BUS_ID_SIZE]; - - /* construct the kobject name from the device node */ - unit_address = (uint32_t *)get_property(vnode, "reg", NULL); - if (!unit_address) - return NULL; - snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); - - return vio_find_name(kobj_name); -} -EXPORT_SYMBOL(vio_find_node); - -int vio_enable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_enable_interrupts); - -int vio_disable_interrupts(struct vio_dev *dev) -{ - int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); - if (rc != H_SUCCESS) - printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); - return rc; -} -EXPORT_SYMBOL(vio_disable_interrupts); -- cgit From bc97ce951cfb697eaac9d5b6a2fbe4544fdf1a7c Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Fri, 28 Apr 2006 22:51:59 -0500 Subject: [PATCH] powerpc: kill union tce_entry It's been long overdue to kill the union tce_entry in the pSeries/iSeries TCE code, especially since I asked the Summit guys to do it on the code they copied from us. Also, while I was at it, I cleaned up some whitespace. Built and booted on pSeries, built on iSeries. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 21 +++--- arch/powerpc/platforms/pseries/iommu.c | 122 ++++++++++++++------------------- 2 files changed, 62 insertions(+), 81 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index a8d96314c982..3ac22065c424 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -4,6 +4,7 @@ * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, iSeries-specific parts. * @@ -42,30 +43,28 @@ static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 tce, rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; while (npages--) { - tce.te_word = 0; - tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + rpn = virt_to_abs(uaddr) >> TCE_SHIFT; + tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; if (tbl->it_type == TCE_VB) { /* Virtual Bus */ - tce.te_bits.tb_valid = 1; - tce.te_bits.tb_allio = 1; + tce |= TCE_VALID|TCE_ALLIO; if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_rdwr = 1; + tce |= TCE_VB_WRITE; } else { /* PCI Bus */ - tce.te_bits.tb_rdwr = 1; /* Read allowed */ + tce |= TCE_PCI_READ; /* Read allowed */ if (direction != DMA_TO_DEVICE) - tce.te_bits.tb_pciwr = 1; + tce |= TCE_PCI_WRITE; } - rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, - tce.te_word); + rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce); if (rc) panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n", rc); @@ -123,7 +122,7 @@ void iommu_table_getparms_iSeries(unsigned long busno, /* itc_size is in pages worth of table, it_size is in # of entries */ tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) / - sizeof(union tce_entry)) >> TCE_PAGE_FACTOR; + TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR; tbl->it_busno = parms->itc_busno; tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR; tbl->it_index = parms->itc_index; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2643078433f0..ed102f390689 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -1,23 +1,24 @@ /* * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation * - * Rewrite, cleanup: + * Rewrite, cleanup: * * Copyright (C) 2004 Olof Johansson , IBM Corporation + * Copyright (C) 2006 Olof Johansson * * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR. * - * + * * 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 @@ -49,52 +50,46 @@ #define DBG(fmt...) -static void tce_build_pSeries(struct iommu_table *tbl, long index, - long npages, unsigned long uaddr, +static void tce_build_pSeries(struct iommu_table *tbl, long index, + long npages, unsigned long uaddr, enum dma_data_direction direction) { - union tce_entry t; - union tce_entry *tp; + u64 proto_tce; + u64 *tcep; + u64 rpn; index <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - t.te_word = 0; - t.te_rdwr = 1; // Read allowed + proto_tce = TCE_PCI_READ; // Read allowed if (direction != DMA_TO_DEVICE) - t.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; - tp = ((union tce_entry *)tbl->it_base) + index; + tcep = ((u64 *)tbl->it_base) + index; while (npages--) { /* can't move this out since we might cross LMB boundary */ - t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - - tp->te_word = t.te_word; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; uaddr += TCE_PAGE_SIZE; - tp++; + tcep++; } } static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) { - union tce_entry t; - union tce_entry *tp; + u64 *tcep; npages <<= TCE_PAGE_FACTOR; index <<= TCE_PAGE_FACTOR; - t.te_word = 0; - tp = ((union tce_entry *)tbl->it_base) + index; - - while (npages--) { - tp->te_word = t.te_word; - - tp++; - } + tcep = ((u64 *)tbl->it_base) + index; + + while (npages--) + *(tcep++) = 0; } @@ -103,43 +98,44 @@ static void tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, enum dma_data_direction direction) { u64 rc; - union tce_entry tce; + u64 proto_tce, tce; + u64 rpn; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word ); - + tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce); + if (rc && printk_ratelimit()) { printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); + printk("\ttce val = 0x%lx\n", tce ); show_stack(current, (unsigned long *)__get_SP()); } - + tcenum++; - tce.te_rpn++; + rpn++; } } -static DEFINE_PER_CPU(void *, tce_page) = NULL; +static DEFINE_PER_CPU(u64 *, tce_page) = NULL; static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages, unsigned long uaddr, enum dma_data_direction direction) { u64 rc; - union tce_entry tce, *tcep; + u64 proto_tce; + u64 *tcep; + u64 rpn; long l, limit; if (TCE_PAGE_FACTOR == 0 && npages == 1) @@ -152,7 +148,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, * from iommu_alloc{,_sg}() */ if (!tcep) { - tcep = (void *)__get_free_page(GFP_ATOMIC); + tcep = (u64 *)__get_free_page(GFP_ATOMIC); /* If allocation fails, fall back to the loop implementation */ if (!tcep) return tce_build_pSeriesLP(tbl, tcenum, npages, @@ -163,11 +159,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; - tce.te_rdwr = 1; + rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT; + proto_tce = TCE_PCI_READ; if (direction != DMA_TO_DEVICE) - tce.te_pciwr = 1; + proto_tce |= TCE_PCI_WRITE; /* We can map max one pageful of TCEs at a time */ do { @@ -175,11 +170,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, * Set up the page with TCE data, looping through and setting * the values. */ - limit = min_t(long, npages, 4096/sizeof(union tce_entry)); + limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE); for (l = 0; l < limit; l++) { - tcep[l] = tce; - tce.te_rpn++; + tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; + rpn++; } rc = plpar_tce_put_indirect((u64)tbl->it_index, @@ -195,7 +190,7 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word); + printk("\ttce[0] val = 0x%lx\n", tcep[0]); show_stack(current, (unsigned long *)__get_SP()); } } @@ -203,23 +198,17 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - while (npages--) { - rc = plpar_tce_put((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word); + rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0); if (rc && printk_ratelimit()) { printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\ttcenum = 0x%lx\n", (u64)tcenum); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } @@ -231,31 +220,24 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; - union tce_entry tce; tcenum <<= TCE_PAGE_FACTOR; npages <<= TCE_PAGE_FACTOR; - tce.te_word = 0; - - rc = plpar_tce_stuff((u64)tbl->it_index, - (u64)tcenum << 12, - tce.te_word, - npages); + rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages); if (rc && printk_ratelimit()) { printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); printk("\trc = %ld\n", rc); printk("\tindex = 0x%lx\n", (u64)tbl->it_index); printk("\tnpages = 0x%lx\n", (u64)npages); - printk("\ttce val = 0x%lx\n", tce.te_word ); show_stack(current, (unsigned long *)__get_SP()); } } static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, - struct iommu_table *tbl) + struct iommu_table *tbl) { struct device_node *node; unsigned long *basep; @@ -275,16 +257,16 @@ static void iommu_table_setparms(struct pci_controller *phb, memset((void *)tbl->it_base, 0, *sizep); tbl->it_busno = phb->bus->number; - + /* Units of tce entries */ tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; - + /* Test if we are going over 2GB of DMA space */ if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); - panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); + panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); } - + phb->dma_window_base_cur += phb->dma_window_size; /* Set the tce table size - measured in entries */ @@ -442,7 +424,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - + iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); ppci->iommu_table = iommu_init_table(tbl); -- cgit From c5c4591375a10f6bc1bc55d86af7764033b10367 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Fri, 28 Apr 2006 16:37:47 +0800 Subject: [PATCH] powerpc: cell: use kzalloc in alloc_spu_context() Use kzalloc when allocating a new spu context, rather than kmalloc + zeroing. Booted & tested on cell. Signed-off-by: Jeremy Kerr Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/context.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 8bb33abfad17..36439c5e9f2d 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c @@ -30,7 +30,7 @@ struct spu_context *alloc_spu_context(void) { struct spu_context *ctx; - ctx = kmalloc(sizeof *ctx, GFP_KERNEL); + ctx = kzalloc(sizeof *ctx, GFP_KERNEL); if (!ctx) goto out; /* Binding to physical processor deferred @@ -48,17 +48,7 @@ struct spu_context *alloc_spu_context(void) init_waitqueue_head(&ctx->wbox_wq); init_waitqueue_head(&ctx->stop_wq); init_waitqueue_head(&ctx->mfc_wq); - ctx->ibox_fasync = NULL; - ctx->wbox_fasync = NULL; - ctx->mfc_fasync = NULL; - ctx->mfc = NULL; - ctx->tagwait = 0; ctx->state = SPU_STATE_SAVED; - ctx->local_store = NULL; - ctx->cntl = NULL; - ctx->signal1 = NULL; - ctx->signal2 = NULL; - ctx->spu = NULL; ctx->ops = &spu_backing_ops; ctx->owner = get_task_mm(current); goto out; -- cgit From 4240545661fc0ac25122f166e96633527150300c Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 28 Apr 2006 17:39:38 -0500 Subject: [PATCH] powerpc/pseries: Increment fail counter in PCI recovery When a PCI device driver does not support PCI error recovery, the powerpc/pseries code takes a walk through a branch of code that resets the failure counter. Because of this, if a broken PCI card is present, the kernel will attempt to reset it an infinite number of times. (This is annoying but mostly harmless: each reset takes about 10-20 seconds, and uses almost no CPU time). This patch preserves the failure count across resets. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 2a9eb2630730..4d45347afabc 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -201,7 +201,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { - int rc; + int cnt, rc; + + /* pcibios will clear the counter; save the value */ + cnt = pe_dn->eeh_freeze_count; + if (bus) pcibios_remove_pci_devices(bus); @@ -240,6 +244,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) ssleep (5); pcibios_add_pci_devices(bus); } + pe_dn->eeh_freeze_count = cnt; return 0; } -- cgit From 07fb3f454cc9e0f656e378a6feb5bdd6cac4bd41 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:39:47 +1000 Subject: [PATCH] powerpc: update iseries_veth device-tree information Make the device-tree information more generic and more like the pSeries virtual lan device. Also use the MAC address from the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index befd36af7e32..0a0825781937 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -946,10 +946,10 @@ void dt_vdevices(struct iseries_flat_dt *dt) if ((vlan_map & (0x8000 >> i)) == 0) continue; - snprintf(buf, 32, "vlan@%08x", reg + i); + snprintf(buf, 32, "l-lan@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vlan"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "network"); + dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); @@ -961,6 +961,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) mac_addr[5] = HvLpConfig_getLpIndex_outline(); dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); dt_end_node(dt); } -- cgit From fbabeb60ba783bf7a43858ecefc5066ac1f07162 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:41:22 +1000 Subject: [PATCH] powerpc: update iSeries viodasd device-tree entries These devices should have device_type block and a unique compatible entry. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0a0825781937..285f2b2e7d83 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -971,8 +971,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { snprintf(buf, 32, "viodasd@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viodasd"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); -- cgit From dc3c9b8ca2ec15cf56d071b85f3734a07bf5f808 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:42:29 +1000 Subject: [PATCH] powerpc: update iSeries vdevice Make it look more like the pSeries vdevice tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 285f2b2e7d83..d3f94b4f28a8 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -921,13 +921,14 @@ void dt_vdevices(struct iseries_flat_dt *dt) char buf[32]; dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); - snprintf(buf, sizeof(buf), "viocons@%08x", reg); + snprintf(buf, sizeof(buf), "vty@%08x", reg); dt_start_node(dt, buf); dt_prop_str(dt, "device_type", "serial"); - dt_prop_str(dt, "compatible", ""); dt_prop_u32(dt, "reg", reg); dt_end_node(dt); reg++; -- cgit From de0fe3b83f4bb47a0a6b47897bb3800862194016 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 15 May 2006 13:44:01 +1000 Subject: [PATCH] powerpc: update iSeries viocd and viotape device-tree Make their device_type entries more generic and their compatible entries more specific. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index d3f94b4f28a8..074d1d949708 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -982,8 +982,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { snprintf(buf, 32, "viocd@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viocd"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); @@ -992,8 +992,8 @@ void dt_vdevices(struct iseries_flat_dt *dt) for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { snprintf(buf, 32, "viotape@%08x", reg + i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "viotape"); - dt_prop_str(dt, "compatible", ""); + dt_prop_str(dt, "device_type", "byte"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); dt_prop_u32(dt, "reg", reg + i); dt_prop_u32(dt, "linux,unit_address", i); dt_end_node(dt); -- cgit From 2babf5c2ec2f2d5de3e38d20f7df7fd815fd10c9 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Wed, 17 May 2006 18:00:46 +1000 Subject: [PATCH] powerpc: Unify mem= handling We currently do mem= handling in three seperate places. And as benh pointed out I wrote two of them. Now that we parse command line parameters earlier we can clean this mess up. Moving the parsing out of prom_init means the device tree might be allocated above the memory limit. If that happens we'd have to move it. As it happens we already have logic to do that for kdump, so just genericise it. This also means we might have reserved regions above the memory limit, if we do the bootmem allocator will blow up, so we have to modify lmb_enforce_memory_limit() to truncate the reserves as well. Tested on P5 LPAR, iSeries, F50, 44p. Tested moving device tree on P5 and 44p and F50. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 074d1d949708..fd6d0ebe8ddd 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -90,8 +90,6 @@ extern unsigned long embedded_sysmap_end; extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static unsigned long cmd_mem_limit; - struct MemoryBlock { unsigned long absStart; unsigned long absEnd; @@ -1026,8 +1024,6 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) /* /chosen */ dt_start_node(dt, "chosen"); dt_prop_str(dt, "bootargs", cmd_line); - if (cmd_mem_limit) - dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); dt_end_node(dt); dt_cpus(dt); @@ -1053,29 +1049,11 @@ void * __init iSeries_early_setup(void) iSeries_get_cmdline(); - /* Save unparsed command line copy for /proc/cmdline */ - strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); - - /* Parse early parameters, in particular mem=x */ - parse_early_param(); - build_flat_dt(&iseries_dt, phys_mem_size); return (void *) __pa(&iseries_dt); } -/* - * On iSeries we just parse the mem=X option from the command line. - * On pSeries it's a bit more complicated, see prom_init_mem() - */ -static int __init early_parsemem(char *p) -{ - if (p) - cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE); - return 0; -} -early_param("mem", early_parsemem); - static void hvputc(char c) { if (c == '\n') -- cgit From 4c76e0bcdeac27b45d55955f073a97ff8452a42f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 18 May 2006 18:06:37 +1000 Subject: [PATCH] powerpc: pseries: Use generic dma-window parsing function Change the pseries iommu init code to use the new of_parse_dma_window() to parse the ibm,dma-window and ibm,my-dma-window properties of pci and virtual device nodes. Also, clean up vio_build_iommu_table() a little. Tested on pseries, with both vio and pci devices. Signed-off-by: Jeremy Kerr Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/iommu.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index ed102f390689..44a507e6fb34 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -281,30 +281,22 @@ static void iommu_table_setparms(struct pci_controller *phb, * iommu_table_setparms_lpar * * Function: On pSeries LPAR systems, return TCE table info, given a pci bus. - * - * ToDo: properly interpret the ibm,dma-window property. The definition is: - * logical-bus-number (1 word) - * phys-address (#address-cells words) - * size (#cell-size words) - * - * Currently we hard code these sizes (more or less). */ static void iommu_table_setparms_lpar(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl, - unsigned int *dma_window) + unsigned char *dma_window) { + unsigned long offset, size; + tbl->it_busno = PCI_DN(dn)->bussubno; + of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size); - /* TODO: Parse field size properties properly. */ - tbl->it_size = (((unsigned long)dma_window[4] << 32) | - (unsigned long)dma_window[5]) >> PAGE_SHIFT; - tbl->it_offset = (((unsigned long)dma_window[2] << 32) | - (unsigned long)dma_window[3]) >> PAGE_SHIFT; tbl->it_base = 0; - tbl->it_index = dma_window[0]; tbl->it_blocksize = 16; tbl->it_type = TCE_PCI; + tbl->it_offset = offset >> PAGE_SHIFT; + tbl->it_size = size >> PAGE_SHIFT; } static void iommu_bus_setup_pSeries(struct pci_bus *bus) @@ -396,7 +388,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) struct iommu_table *tbl; struct device_node *dn, *pdn; struct pci_dn *ppci; - unsigned int *dma_window = NULL; + unsigned char *dma_window = NULL; DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self); @@ -404,7 +396,7 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) /* Find nearest ibm,dma-window, walking up the device tree */ for (pdn = dn; pdn != NULL; pdn = pdn->parent) { - dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window != NULL) break; } @@ -498,7 +490,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; struct iommu_table *tbl; - int *dma_window = NULL; + unsigned char *dma_window = NULL; struct pci_dn *pci; DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev)); @@ -513,8 +505,7 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table; pdn = pdn->parent) { - dma_window = (unsigned int *) - get_property(pdn, "ibm,dma-window", NULL); + dma_window = get_property(pdn, "ibm,dma-window", NULL); if (dma_window) break; } -- cgit From b58b7f98670ab6dd7774b67ff1655a787321209f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:42:49 +1000 Subject: [PATCH] powerpc: tidy up iseries/pci.c Remove some unused counters. No need to allocate iomm_table and iobar_table, which means that iomm_table_initialize is not longer needed. Use kzalloc where sensible. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 78 +++++------------------------------- 1 file changed, 11 insertions(+), 67 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 428ffb5cf044..91a94747eda9 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -57,15 +57,6 @@ LIST_HEAD(iSeries_Global_Device_List); static int DeviceCount; -/* Counters and control flags. */ -static long Pci_Io_Read_Count; -static long Pci_Io_Write_Count; -#if 0 -static long Pci_Cfg_Read_Count; -static long Pci_Cfg_Write_Count; -#endif -static long Pci_Error_Count; - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -79,40 +70,18 @@ static struct pci_ops iSeries_pci_ops; #define IOMM_TABLE_ENTRY_SIZE 0x0000000000400000UL #define BASE_IO_MEMORY 0xE000000000000000UL -static unsigned long max_io_memory = 0xE000000000000000UL; +static unsigned long max_io_memory = BASE_IO_MEMORY; static long current_iomm_table_entry; /* * Lookup Tables. */ -static struct device_node **iomm_table; -static u8 *iobar_table; +static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES]; +static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES]; -/* - * Static and Global variables - */ -static char *pci_io_text = "iSeries PCI I/O"; +static const char pci_io_text[] = "iSeries PCI I/O"; static DEFINE_SPINLOCK(iomm_table_lock); -/* - * iomm_table_initialize - * - * Allocates and initalizes the Address Translation Table and Bar - * Tables to get them ready for use. Must be called before any - * I/O space is handed out to the device BARs. - */ -static void iomm_table_initialize(void) -{ - spin_lock(&iomm_table_lock); - iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES, - GFP_KERNEL); - spin_unlock(&iomm_table_lock); - if ((iomm_table == NULL) || (iobar_table == NULL)) - panic("PCI: I/O tables allocation failed.\n"); -} - /* * iomm_table_allocate_entry * @@ -140,9 +109,8 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) */ spin_lock(&iomm_table_lock); bar_res->name = pci_io_text; - bar_res->start = + bar_res->start = BASE_IO_MEMORY + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; - bar_res->start += BASE_IO_MEMORY; bar_res->end = bar_res->start + bar_size - 1; /* * Allocate the number of table entries needed for BAR. @@ -154,7 +122,7 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) ++current_iomm_table_entry; } max_io_memory = BASE_IO_MEMORY + - (IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry); + IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry; spin_unlock(&iomm_table_lock); } @@ -171,13 +139,10 @@ static void iomm_table_allocate_entry(struct pci_dev *dev, int bar_num) */ static void allocate_device_bars(struct pci_dev *dev) { - struct resource *bar_res; int bar_num; - for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) { - bar_res = &dev->resource[bar_num]; + for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) iomm_table_allocate_entry(dev, bar_num); - } } /* @@ -205,10 +170,9 @@ static struct device_node *build_device_node(HvBusNumber Bus, struct device_node *node; struct pci_dn *pdn; - node = kmalloc(sizeof(struct device_node), GFP_KERNEL); + node = kzalloc(sizeof(struct device_node), GFP_KERNEL); if (node == NULL) return NULL; - memset(node, 0, sizeof(struct device_node)); pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) { kfree(node); @@ -224,7 +188,7 @@ static struct device_node *build_device_node(HvBusNumber Bus, } /* - * unsigned long __init find_and_init_phbs(void) + * iSeries_pcibios_init * * Description: * This function checks for all possible system PCI host bridges that connect @@ -232,7 +196,7 @@ static struct device_node *build_device_node(HvBusNumber Bus, * ownership status. A pci_controller is built for any bus which is partially * owned or fully owned by this guest partition. */ -unsigned long __init find_and_init_phbs(void) +void iSeries_pcibios_init(void) { struct pci_controller *phb; HvBusNumber bus; @@ -263,18 +227,6 @@ unsigned long __init find_and_init_phbs(void) printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", bus, ret); } - return 0; -} - -/* - * iSeries_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - */ -void iSeries_pcibios_init(void) -{ - iomm_table_initialize(); - find_and_init_phbs(); } /* @@ -331,8 +283,7 @@ static void scan_PHB_slots(struct pci_controller *Phb) int IdSel; const int MaxAgents = 8; - DevInfo = (struct HvCallPci_DeviceInfo*) - kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); + DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); if (DevInfo == NULL) return; @@ -622,7 +573,6 @@ static int CheckReturnCode(char *TextHdr, struct device_node *DevNode, if (ret != 0) { struct pci_dn *pdn = PCI_DN(DevNode); - ++Pci_Error_Count; (*retry)++; printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", TextHdr, pdn->busno, pdn->devfn, @@ -704,7 +654,6 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) return 0xff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); @@ -734,7 +683,6 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) return 0xffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); @@ -765,7 +713,6 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) return 0xffffffff; } do { - ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, BarOffset, 0); } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); @@ -803,7 +750,6 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0); } @@ -831,7 +777,6 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); } @@ -859,7 +804,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) return; } do { - ++Pci_Io_Write_Count; rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); } -- cgit From 66b3851a6947482987b4c05aa781a33696287648 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:43:58 +1000 Subject: [PATCH] powerpc: reintroduce HvCallPci_configLoad32 This function was removed during iSeries cleanup but will prove useful in the following patches. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/call_pci.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h index 59d4e0ad5cf3..dbdf69850ed9 100644 --- a/arch/powerpc/platforms/iseries/call_pci.h +++ b/arch/powerpc/platforms/iseries/call_pci.h @@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, return retVal.rc; } +static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber, + u8 deviceId, u32 offset, u32 *value) +{ + struct HvCallPci_DsaAddr dsa; + struct HvCallPci_LoadReturn retVal; + + *((u64*)&dsa) = 0; + + dsa.busNumber = busNumber; + dsa.subBusNumber = subBusNumber; + dsa.deviceId = deviceId; + + HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0); + + *value = retVal.value; + + return retVal.rc; +} + static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber, u8 deviceId, u32 offset, u8 value) { -- cgit From 0d177df15d12926dc2ef7c814f317f02de52ce17 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:46:28 +1000 Subject: [PATCH] powerpc: move iSeries PCI devices to the device tree Move the probing of PCI devices to setup.c and put them all into the flattened device tree. The later probing is now done by traversing the device tree. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/irq.c | 7 +- arch/powerpc/platforms/iseries/irq.h | 2 +- arch/powerpc/platforms/iseries/pci.c | 273 ++++++++++----------------------- arch/powerpc/platforms/iseries/setup.c | 204 ++++++++++++++++++++++++ 4 files changed, 286 insertions(+), 200 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index be3fbfc24e6c..62bbbcf5ded3 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -42,6 +42,7 @@ #include #include "irq.h" +#include "pci.h" #include "call_pci.h" #if defined(CONFIG_SMP) @@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_handler = { * Note that sub_bus is always 0 (at the moment at least). */ int __init iSeries_allocate_IRQ(HvBusNumber bus, - HvSubBusNumber sub_bus, HvAgentId dev_id) + HvSubBusNumber sub_bus, u32 bsubbus) { int virtirq; unsigned int realirq; - u8 idsel = (dev_id >> 4); - u8 function = dev_id & 7; + u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus); + u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus); realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3) + function; diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h index b9c801ba5a47..188aa808abd7 100644 --- a/arch/powerpc/platforms/iseries/irq.h +++ b/arch/powerpc/platforms/iseries/irq.h @@ -2,7 +2,7 @@ #define _ISERIES_IRQ_H extern void iSeries_init_IRQ(void); -extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId); +extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32); extern void iSeries_activate_IRQs(void); extern int iSeries_get_irq(struct pt_regs *); diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 91a94747eda9..9d571e749098 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -49,14 +49,9 @@ * Forward declares of prototypes. */ static struct device_node *find_Device_Node(int bus, int devfn); -static void scan_PHB_slots(struct pci_controller *Phb); -static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); -static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info); LIST_HEAD(iSeries_Global_Device_List); -static int DeviceCount; - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -161,32 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, Error_Text, Bus, SubBus, AgentId, HvRc); } -/* - * build_device_node(u16 Bus, int SubBus, u8 DevFn) - */ -static struct device_node *build_device_node(HvBusNumber Bus, - HvSubBusNumber SubBus, int AgentId, int Function) -{ - struct device_node *node; - struct pci_dn *pdn; - - node = kzalloc(sizeof(struct device_node), GFP_KERNEL); - if (node == NULL) - return NULL; - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); - if (pdn == NULL) { - kfree(node); - return NULL; - } - node->data = pdn; - pdn->node = node; - list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List); - pdn->busno = Bus; - pdn->bussubno = SubBus; - pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); - return node; -} - /* * iSeries_pcibios_init * @@ -199,33 +168,86 @@ static struct device_node *build_device_node(HvBusNumber Bus, void iSeries_pcibios_init(void) { struct pci_controller *phb; - HvBusNumber bus; - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int ret = HvCallXm_testBus(bus); - if (ret == 0) { - printk("bus %d appears to exist\n", bus); - - phb = pcibios_alloc_controller(NULL); - if (phb == NULL) - return -ENOMEM; + struct device_node *node; + struct device_node *dn; + + for_each_node_by_type(node, "pci") { + HvBusNumber bus; + u32 *busp; + + busp = (u32 *)get_property(node, "bus-range", NULL); + if (busp == NULL) + continue; + bus = *busp; + printk("bus %d appears to exist\n", bus); + phb = pcibios_alloc_controller(node); + if (phb == NULL) + continue; + + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; + + /* Find and connect the devices. */ + for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { + struct pci_dn *pdn; + u8 irq; + int err; + u32 *agent; + u32 *reg; + u32 *lsn; + + reg = (u32 *)get_property(dn, "reg", NULL); + if (reg == NULL) { + printk(KERN_DEBUG "no reg property!\n"); + continue; + } + busp = (u32 *)get_property(dn, "linux,subbus", NULL); + if (busp == NULL) { + printk(KERN_DEBUG "no subbus property!\n"); + continue; + } + agent = (u32 *)get_property(dn, "linux,agent-id", NULL); + if (agent == NULL) { + printk(KERN_DEBUG "no agent-id\n"); + continue; + } + lsn = (u32 *)get_property(dn, + "linux,logical-slot-number", NULL); + if (lsn == NULL) { + printk(KERN_DEBUG "no logical-slot-number\n"); + continue; + } - phb->pci_mem_offset = phb->local_number = bus; - phb->first_busno = bus; - phb->last_busno = bus; - phb->ops = &iSeries_pci_ops; + irq = iSeries_allocate_IRQ(bus, 0, *busp); + err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq); + if (err) { + pci_Log_Error("Connect Bus Unit", + bus, *busp, *agent, err); + continue; + } + err = HvCallPci_configStore8(bus, *busp, *agent, + PCI_INTERRUPT_LINE, irq); + if (err) { + pci_Log_Error("PciCfgStore Irq Failed!", + bus, *busp, *agent, err); + continue; + } - /* Find and connect the devices. */ - scan_PHB_slots(phb); + pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); + if (pdn == NULL) + return; + dn->data = pdn; + pdn->node = dn; + pdn->busno = bus; + pdn->devfn = (reg[0] >> 8) & 0xff; + pdn->bussubno = *busp; + pdn->Irq = irq; + pdn->LogicalSlot = *lsn; + list_add_tail(&pdn->Device_List, + &iSeries_Global_Device_List); } - /* - * Check for Unexpected Return code, a clue that something - * has gone wrong. - */ - else if (ret != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", - bus, ret); } } @@ -271,147 +293,6 @@ void pcibios_fixup_resources(struct pci_dev *pdev) { } -/* - * Loop through each node function to find usable EADs bridges. - */ -static void scan_PHB_slots(struct pci_controller *Phb) -{ - struct HvCallPci_DeviceInfo *DevInfo; - HvBusNumber bus = Phb->local_number; /* System Bus */ - const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ - int HvRc = 0; - int IdSel; - const int MaxAgents = 8; - - DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); - if (DevInfo == NULL) - return; - - /* - * Probe for EADs Bridges - */ - for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, - iseries_hv_addr(DevInfo), - sizeof(struct HvCallPci_DeviceInfo)); - if (HvRc == 0) { - if (DevInfo->deviceType == HvCallPci_NodeDevice) - scan_EADS_bridge(bus, SubBus, IdSel); - else - printk("PCI: Invalid System Configuration(0x%02X)" - " for bus 0x%02x id 0x%02x.\n", - DevInfo->deviceType, bus, IdSel); - } - else - pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); - } - kfree(DevInfo); -} - -static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus, - int IdSel) -{ - struct HvCallPci_BridgeInfo *BridgeInfo; - HvAgentId AgentId; - int Function; - int HvRc; - - BridgeInfo = (struct HvCallPci_BridgeInfo *) - kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); - if (BridgeInfo == NULL) - return; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); - if (HvRc == 0) { - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, IdSel, Function, AgentId); - /* Connect EADs: 0x18.00.12 = 0x00 */ - HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, - iseries_hv_addr(BridgeInfo), - sizeof(struct HvCallPci_BridgeInfo)); - if (HvRc == 0) { - printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == - HvCallPci_BridgeDevice) { - /* Scan_Bridge_Slot...: 0x18.00.12 */ - scan_bridge_slot(bus, BridgeInfo); - } else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - BridgeInfo->busUnitInfo.deviceType); - } - } else if (HvRc != 0x000B) - pci_Log_Error("EADs Connect", - bus, SubBus, AgentId, HvRc); - } - kfree(BridgeInfo); -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static int scan_bridge_slot(HvBusNumber Bus, - struct HvCallPci_BridgeInfo *BridgeInfo) -{ - struct device_node *node; - HvSubBusNumber SubBus = BridgeInfo->subBusNumber; - u16 VendorId = 0; - int HvRc = 0; - u8 Irq = 0; - int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); - int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - - /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - - /* - * Connect all functions of any device found. - */ - for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { - for (Function = 0; Function < 8; ++Function) { - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, - AgentId, Irq); - if (HvRc != 0) { - pci_Log_Error("Connect Bus Unit", - Bus, SubBus, AgentId, HvRc); - continue; - } - - HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, - PCI_VENDOR_ID, &VendorId); - if (HvRc != 0) { - pci_Log_Error("Read Vendor", - Bus, SubBus, AgentId, HvRc); - continue; - } - printk("read vendor ID: %x\n", VendorId); - - /* FoundDevice: 0x18.28.10 = 0x12AE */ - HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, - PCI_INTERRUPT_LINE, Irq); - if (HvRc != 0) - pci_Log_Error("PciCfgStore Irq Failed!", - Bus, SubBus, AgentId, HvRc); - - ++DeviceCount; - node = build_device_node(Bus, SubBus, EADsIdSel, Function); - PCI_DN(node)->Irq = Irq; - PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber; - - } /* for (Function = 0; Function < 8; ++Function) */ - } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ - return HvRc; -} - /* * I/0 Memory copy MUST use mmio commands on iSeries * To do; For performance, include the hv call directly diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index fd6d0ebe8ddd..d83f5ed4ec1f 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -66,6 +66,8 @@ #include "main_store.h" #include "call_sm.h" #include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -1000,6 +1002,207 @@ void dt_vdevices(struct iseries_flat_dt *dt) dt_end_node(dt); } +/* + * This assumes that the node slot is always on the primary bus! + */ +static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, + struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + u8 devfn; + + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG + "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + printk(KERN_DEBUG + "ReadVendor(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + printk(KERN_DEBUG + "ReadDevice(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + printk(KERN_DEBUG + "ReadClass(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + if (function == 0) + snprintf(buf, sizeof(buf), "pci@%x", + PCI_SLOT(devfn)); + else + snprintf(buf, sizeof(buf), "pci@%x,%d", + PCI_SLOT(devfn), function); + dt_start_node(dt, buf); + reg[0] = (bus << 18) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + printk("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " + "== %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + printk(KERN_DEBUG "PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe" + "(0x%02X): 0x%04X", bus, err); + continue; + } + printk("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; @@ -1029,6 +1232,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) dt_cpus(dt); dt_vdevices(dt); + dt_pci_devices(dt); dt_end_node(dt); -- cgit From 96ff6afaf1c2fdd118139095dea66c0910379780 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:48:47 +1000 Subject: [PATCH] powerpc: remove iSeries_Global_Device_List We can now scan the list of device nodes instead. This also allows us to remove the Device_list member of struct pci_dn. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 15 +++++++++------ arch/powerpc/platforms/iseries/pci.c | 14 ++++++-------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 3ac22065c424..75a5a1e8abb8 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -32,13 +32,11 @@ #include #include #include +#include #include #include #include -extern struct list_head iSeries_Global_Device_List; - - static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages, unsigned long uaddr, enum dma_data_direction direction) { @@ -140,10 +138,15 @@ void iommu_table_getparms_iSeries(unsigned long busno, */ static struct iommu_table *iommu_table_find(struct iommu_table * tbl) { - struct pci_dn *pdn; + struct device_node *node; + + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); + struct iommu_table *it; - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - struct iommu_table *it = pdn->iommu_table; + if (pdn == NULL) + continue; + it = pdn->iommu_table; if ((it != NULL) && (it->it_type == TCE_PCI) && (it->it_offset == tbl->it_offset) && diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 9d571e749098..5bc08d4eef49 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -50,8 +50,6 @@ */ static struct device_node *find_Device_Node(int bus, int devfn); -LIST_HEAD(iSeries_Global_Device_List); - static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */ @@ -245,8 +243,6 @@ void iSeries_pcibios_init(void) pdn->bussubno = *busp; pdn->Irq = irq; pdn->LogicalSlot = *lsn; - list_add_tail(&pdn->Device_List, - &iSeries_Global_Device_List); } } } @@ -338,11 +334,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio); */ static struct device_node *find_Device_Node(int bus, int devfn) { - struct pci_dn *pdn; + struct device_node *node; + + for (node = NULL; (node = of_find_all_nodes(node)); ) { + struct pci_dn *pdn = PCI_DN(node); - list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) { - if ((bus == pdn->busno) && (devfn == pdn->devfn)) - return pdn->node; + if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn)) + return node; } return NULL; } -- cgit From b02527931672749d404b5f640b7e086afc37f4e0 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:50:39 +1000 Subject: [PATCH] powerpc: remove Irq from pci_dn As we now store enough information in the device_node to allocate the irq number in pcibios_final_fixup. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 53 +++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 5bc08d4eef49..edaafbb817b7 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -190,9 +190,6 @@ void iSeries_pcibios_init(void) /* Find and connect the devices. */ for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { struct pci_dn *pdn; - u8 irq; - int err; - u32 *agent; u32 *reg; u32 *lsn; @@ -206,11 +203,6 @@ void iSeries_pcibios_init(void) printk(KERN_DEBUG "no subbus property!\n"); continue; } - agent = (u32 *)get_property(dn, "linux,agent-id", NULL); - if (agent == NULL) { - printk(KERN_DEBUG "no agent-id\n"); - continue; - } lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL); if (lsn == NULL) { @@ -218,21 +210,6 @@ void iSeries_pcibios_init(void) continue; } - irq = iSeries_allocate_IRQ(bus, 0, *busp); - err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq); - if (err) { - pci_Log_Error("Connect Bus Unit", - bus, *busp, *agent, err); - continue; - } - err = HvCallPci_configStore8(bus, *busp, *agent, - PCI_INTERRUPT_LINE, irq); - if (err) { - pci_Log_Error("PciCfgStore Irq Failed!", - bus, *busp, *agent, err); - continue; - } - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) return; @@ -241,7 +218,6 @@ void iSeries_pcibios_init(void) pdn->busno = bus; pdn->devfn = (reg[0] >> 8) & 0xff; pdn->bussubno = *busp; - pdn->Irq = irq; pdn->LogicalSlot = *lsn; } } @@ -266,6 +242,34 @@ void __init iSeries_pci_final_fixup(void) pdev->bus->number, pdev->devfn, node); if (node != NULL) { + struct pci_dn *pdn = PCI_DN(node); + u32 *agent; + + agent = (u32 *)get_property(node, "linux,agent-id", + NULL); + if ((pdn != NULL) && (agent != NULL)) { + u8 irq = iSeries_allocate_IRQ(pdn->busno, 0, + pdn->bussubno); + int err; + + err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno, + *agent, irq); + if (err) + pci_Log_Error("Connect Bus Unit", + pdn->busno, pdn->bussubno, *agent, err); + else { + err = HvCallPci_configStore8(pdn->busno, pdn->bussubno, + *agent, + PCI_INTERRUPT_LINE, + irq); + if (err) + pci_Log_Error("PciCfgStore Irq Failed!", + pdn->busno, pdn->bussubno, *agent, err); + } + if (!err) + pdev->irq = irq; + } + ++DeviceCount; pdev->sysdata = (void *)node; PCI_DN(node)->pcidev = pdev; @@ -275,7 +279,6 @@ void __init iSeries_pci_final_fixup(void) } else printk("PCI: Device Tree not found for 0x%016lX\n", (unsigned long)pdev); - pdev->irq = PCI_DN(node)->Irq; } iSeries_activate_IRQs(); mf_display_src(0xC9000200); -- cgit From 403fac4f83bd8e089a192c542511fbeb2729a6c5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:51:57 +1000 Subject: [PATCH] powerpc: remove LogicalSlot from pci_dn As we now store enough information in the device_node. Also the Flags field was not used either, do remove that. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 5 ++++- arch/powerpc/platforms/iseries/pci.c | 8 -------- 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index 75a5a1e8abb8..a992f6af249f 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -162,10 +162,13 @@ void iommu_devnode_init_iSeries(struct device_node *dn) { struct iommu_table *tbl; struct pci_dn *pdn = PCI_DN(dn); + u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL); + + BUG_ON(lsn == NULL); tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); - iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl); + iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl); /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index edaafbb817b7..86a869839d34 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -191,7 +191,6 @@ void iSeries_pcibios_init(void) for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { struct pci_dn *pdn; u32 *reg; - u32 *lsn; reg = (u32 *)get_property(dn, "reg", NULL); if (reg == NULL) { @@ -203,12 +202,6 @@ void iSeries_pcibios_init(void) printk(KERN_DEBUG "no subbus property!\n"); continue; } - lsn = (u32 *)get_property(dn, - "linux,logical-slot-number", NULL); - if (lsn == NULL) { - printk(KERN_DEBUG "no logical-slot-number\n"); - continue; - } pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); if (pdn == NULL) @@ -218,7 +211,6 @@ void iSeries_pcibios_init(void) pdn->busno = bus; pdn->devfn = (reg[0] >> 8) & 0xff; pdn->bussubno = *busp; - pdn->LogicalSlot = *lsn; } } } -- cgit From 095eed4f8d0be13a7934031434b6e9ceddb87ff6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:54:42 +1000 Subject: [PATCH] powerpc: clean up iSeries PCI probe Only scan the host bridges and then use the existing pci_devs_phb_init() routine. Also fix typo in setup of reg property. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/pci.c | 42 ++++++++++++---------------------- arch/powerpc/platforms/iseries/setup.c | 2 +- 2 files changed, 15 insertions(+), 29 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 86a869839d34..35bcc98111f5 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c @@ -166,13 +166,21 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, void iSeries_pcibios_init(void) { struct pci_controller *phb; - struct device_node *node; - struct device_node *dn; + struct device_node *root = of_find_node_by_path("/"); + struct device_node *node = NULL; - for_each_node_by_type(node, "pci") { + if (root == NULL) { + printk(KERN_CRIT "iSeries_pcibios_init: can't find root " + "of device tree\n"); + return; + } + while ((node = of_get_next_child(root, node)) != NULL) { HvBusNumber bus; u32 *busp; + if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) + continue; + busp = (u32 *)get_property(node, "bus-range", NULL); if (busp == NULL) continue; @@ -186,33 +194,11 @@ void iSeries_pcibios_init(void) phb->first_busno = bus; phb->last_busno = bus; phb->ops = &iSeries_pci_ops; + } - /* Find and connect the devices. */ - for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) { - struct pci_dn *pdn; - u32 *reg; - - reg = (u32 *)get_property(dn, "reg", NULL); - if (reg == NULL) { - printk(KERN_DEBUG "no reg property!\n"); - continue; - } - busp = (u32 *)get_property(dn, "linux,subbus", NULL); - if (busp == NULL) { - printk(KERN_DEBUG "no subbus property!\n"); - continue; - } + of_node_put(root); - pdn = kzalloc(sizeof(*pdn), GFP_KERNEL); - if (pdn == NULL) - return; - dn->data = pdn; - pdn->node = dn; - pdn->busno = bus; - pdn->devfn = (reg[0] >> 8) & 0xff; - pdn->bussubno = *busp; - } - } + pci_devs_phb_init(); } /* diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index d83f5ed4ec1f..0f49412b438e 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -1073,7 +1073,7 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, snprintf(buf, sizeof(buf), "pci@%x,%d", PCI_SLOT(devfn), function); dt_start_node(dt, buf); - reg[0] = (bus << 18) | (devfn << 8); + reg[0] = (bus << 16) | (devfn << 8); reg[1] = 0; reg[2] = 0; reg[3] = 0; -- cgit From 29629b2972467f6cc00427a89008c09d010074c8 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:55:53 +1000 Subject: [PATCH] powerpc: make iSeries flat device tree stuff static Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 40 +++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 0f49412b438e..95864146b8f0 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -723,9 +723,9 @@ struct iseries_flat_dt { struct blob strings; }; -struct iseries_flat_dt iseries_dt; +static struct iseries_flat_dt iseries_dt; -void dt_init(struct iseries_flat_dt *dt) +static void dt_init(struct iseries_flat_dt *dt) { dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); @@ -748,7 +748,7 @@ void dt_init(struct iseries_flat_dt *dt) dt->reserve_map[1] = 0; } -void dt_check_blob(struct blob *b) +static void dt_check_blob(struct blob *b) { if (b->next >= (unsigned long)&b->next) { DBG("Ran out of space in flat device tree blob!\n"); @@ -756,7 +756,7 @@ void dt_check_blob(struct blob *b) } } -void dt_push_u32(struct iseries_flat_dt *dt, u32 value) +static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) { *((u32*)dt->dt.next) = value; dt->dt.next += sizeof(u32); @@ -764,15 +764,17 @@ void dt_push_u32(struct iseries_flat_dt *dt, u32 value) dt_check_blob(&dt->dt); } -void dt_push_u64(struct iseries_flat_dt *dt, u64 value) +#ifdef notyet +static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) { *((u64*)dt->dt.next) = value; dt->dt.next += sizeof(u64); dt_check_blob(&dt->dt); } +#endif -unsigned long dt_push_bytes(struct blob *blob, char *data, int len) +static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) { unsigned long start = blob->next - (unsigned long)blob->data; @@ -784,7 +786,7 @@ unsigned long dt_push_bytes(struct blob *blob, char *data, int len) return start; } -void dt_start_node(struct iseries_flat_dt *dt, char *name) +static void dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(&dt->dt, name, strlen(name) + 1); @@ -792,7 +794,7 @@ void dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) +static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) { unsigned long offset; @@ -811,37 +813,39 @@ void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) dt_push_bytes(&dt->dt, data, len); } -void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) +static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { dt_prop(dt, name, (char *)&data, sizeof(u32)); } -void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { dt_prop(dt, name, (char *)&data, sizeof(u64)); } -void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) +static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u64) * n); } -void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) +static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u32) * n); } -void dt_prop_empty(struct iseries_flat_dt *dt, char *name) +#ifdef notyet +static void dt_prop_empty(struct iseries_flat_dt *dt, char *name) { dt_prop(dt, name, NULL, 0); } +#endif -void dt_cpus(struct iseries_flat_dt *dt) +static void dt_cpus(struct iseries_flat_dt *dt) { unsigned char buf[32]; unsigned char *p; @@ -895,7 +899,7 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_end_node(dt); } -void dt_model(struct iseries_flat_dt *dt) +static void dt_model(struct iseries_flat_dt *dt) { char buf[16] = "IBM,"; @@ -913,7 +917,7 @@ void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } -void dt_vdevices(struct iseries_flat_dt *dt) +static void dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; @@ -1203,7 +1207,7 @@ static void dt_pci_devices(struct iseries_flat_dt *dt) } } -void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) +static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) { u64 tmp[2]; -- cgit From 9ceb19093b5e5f037c6b47df0607dd567283287d Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 16:58:13 +1000 Subject: [PATCH] powerpc: give iSeries device tree nodes better names Use the PCI class code to choose a name for the PCI device nodes and to guess a device_type. Failing that, base the name on the vendor and device ids as specified in the spec. Mark just about everything __init{data}. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/setup.c | 95 +++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 29 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 95864146b8f0..5661bd0d4279 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -725,7 +725,7 @@ struct iseries_flat_dt { static struct iseries_flat_dt iseries_dt; -static void dt_init(struct iseries_flat_dt *dt) +static void __init dt_init(struct iseries_flat_dt *dt) { dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); @@ -748,7 +748,7 @@ static void dt_init(struct iseries_flat_dt *dt) dt->reserve_map[1] = 0; } -static void dt_check_blob(struct blob *b) +static void __init dt_check_blob(struct blob *b) { if (b->next >= (unsigned long)&b->next) { DBG("Ran out of space in flat device tree blob!\n"); @@ -756,7 +756,7 @@ static void dt_check_blob(struct blob *b) } } -static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { *((u32*)dt->dt.next) = value; dt->dt.next += sizeof(u32); @@ -765,7 +765,7 @@ static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) } #ifdef notyet -static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { *((u64*)dt->dt.next) = value; dt->dt.next += sizeof(u64); @@ -774,7 +774,7 @@ static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) } #endif -static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) +static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) { unsigned long start = blob->next - (unsigned long)blob->data; @@ -786,7 +786,7 @@ static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) return start; } -static void dt_start_node(struct iseries_flat_dt *dt, char *name) +static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(&dt->dt, name, strlen(name) + 1); @@ -794,7 +794,8 @@ static void dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) +static void __init dt_prop(struct iseries_flat_dt *dt, char *name, + char *data, int len) { unsigned long offset; @@ -813,39 +814,42 @@ static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) dt_push_bytes(&dt->dt, data, len); } -static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) +static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, + char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { dt_prop(dt, name, (char *)&data, sizeof(u32)); } -static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { dt_prop(dt, name, (char *)&data, sizeof(u64)); } -static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, + u64 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u64) * n); } -static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, + u32 *data, int n) { dt_prop(dt, name, (char *)data, sizeof(u32) * n); } #ifdef notyet -static void dt_prop_empty(struct iseries_flat_dt *dt, char *name) +static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) { dt_prop(dt, name, NULL, 0); } #endif -static void dt_cpus(struct iseries_flat_dt *dt) +static void __init dt_cpus(struct iseries_flat_dt *dt) { unsigned char buf[32]; unsigned char *p; @@ -899,7 +903,7 @@ static void dt_cpus(struct iseries_flat_dt *dt) dt_end_node(dt); } -static void dt_model(struct iseries_flat_dt *dt) +static void __init dt_model(struct iseries_flat_dt *dt) { char buf[16] = "IBM,"; @@ -917,7 +921,7 @@ static void dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } -static void dt_vdevices(struct iseries_flat_dt *dt) +static void __init dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; @@ -1006,11 +1010,32 @@ static void dt_vdevices(struct iseries_flat_dt *dt) dt_end_node(dt); } +struct pci_class_name { + u16 code; + char *name; + char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + /* * This assumes that the node slot is always on the primary bus! */ -static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, - struct HvCallPci_BridgeInfo *bridge_info) +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) { HvSubBusNumber sub_bus = bridge_info->subBusNumber; u16 vendor_id; @@ -1022,14 +1047,14 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; /* * Connect all functions of any device found. */ for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { for (function = 0; function < 8; function++) { - u8 devfn; - HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, function); err = HvCallXm_connectBusUnit(bus, sub_bus, @@ -1070,12 +1095,20 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), function); - if (function == 0) - snprintf(buf, sizeof(buf), "pci@%x", - PCI_SLOT(devfn)); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); else - snprintf(buf, sizeof(buf), "pci@%x,%d", - PCI_SLOT(devfn), function); + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); dt_start_node(dt, buf); reg[0] = (bus << 16) | (devfn << 8); reg[1] = 0; @@ -1083,6 +1116,9 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, reg[3] = 0; reg[4] = 0; dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); dt_prop_u32(dt, "vendor-id", vendor_id); dt_prop_u32(dt, "device-id", device_id); dt_prop_u32(dt, "class-code", class_id >> 8); @@ -1097,7 +1133,7 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, } } -static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, HvSubBusNumber sub_bus, int id_sel) { struct HvCallPci_BridgeInfo bridge_info; @@ -1139,7 +1175,7 @@ static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, } } -static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) { struct HvCallPci_DeviceInfo dev_info; const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ @@ -1171,7 +1207,7 @@ static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) } } -static void dt_pci_devices(struct iseries_flat_dt *dt) +static void __init dt_pci_devices(struct iseries_flat_dt *dt) { HvBusNumber bus; char buf[32]; @@ -1207,7 +1243,8 @@ static void dt_pci_devices(struct iseries_flat_dt *dt) } } -static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) +static void __init build_flat_dt(struct iseries_flat_dt *dt, + unsigned long phys_mem_size) { u64 tmp[2]; -- cgit From c81014f603db26e1ed818decebd3b594606e20a6 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:00:04 +1000 Subject: [PATCH] powerpc: split device tree stuff out of iseries/setup.c Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/Makefile | 2 +- arch/powerpc/platforms/iseries/dt.c | 618 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/iseries/setup.c | 578 +---------------------------- arch/powerpc/platforms/iseries/setup.h | 2 + 4 files changed, 622 insertions(+), 578 deletions(-) create mode 100644 arch/powerpc/platforms/iseries/dt.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 7e67a20c18ab..32306214a301 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,6 +1,6 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \ +obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.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 diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c new file mode 100644 index 000000000000..93d4233e73e5 --- /dev/null +++ b/arch/powerpc/platforms/iseries/dt.c @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation + * + * Description: + * This file contains all the routines to build a flattened device + * tree for a legacy iSeries machine. + * + * 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. + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* ETH_ALEN */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "processor_vpd.h" +#include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +struct blob { + unsigned char data[PAGE_SIZE * 2]; + unsigned long next; +}; + +struct iseries_flat_dt { + struct boot_param_header header; + u64 reserve_map[2]; + struct blob dt; + struct blob strings; +}; + +static struct iseries_flat_dt iseries_dt; + +static void __init dt_init(struct iseries_flat_dt *dt) +{ + dt->header.off_mem_rsvmap = + offsetof(struct iseries_flat_dt, reserve_map); + dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); + dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); + dt->header.totalsize = sizeof(struct iseries_flat_dt); + dt->header.dt_strings_size = sizeof(struct blob); + + /* There is no notion of hardware cpu id on iSeries */ + dt->header.boot_cpuid_phys = smp_processor_id(); + + dt->dt.next = (unsigned long)&dt->dt.data; + dt->strings.next = (unsigned long)&dt->strings.data; + + dt->header.magic = OF_DT_HEADER; + dt->header.version = 0x10; + dt->header.last_comp_version = 0x10; + + dt->reserve_map[0] = 0; + dt->reserve_map[1] = 0; +} + +static void __init dt_check_blob(struct blob *b) +{ + if (b->next >= (unsigned long)&b->next) { + DBG("Ran out of space in flat device tree blob!\n"); + BUG(); + } +} + +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) +{ + *((u32*)dt->dt.next) = value; + dt->dt.next += sizeof(u32); + + dt_check_blob(&dt->dt); +} + +#ifdef notyet +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) +{ + *((u64*)dt->dt.next) = value; + dt->dt.next += sizeof(u64); + + dt_check_blob(&dt->dt); +} +#endif + +static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) +{ + unsigned long start = blob->next - (unsigned long)blob->data; + + memcpy((char *)blob->next, data, len); + blob->next = _ALIGN(blob->next + len, 4); + + dt_check_blob(blob); + + return start; +} + +static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) +{ + dt_push_u32(dt, OF_DT_BEGIN_NODE); + dt_push_bytes(&dt->dt, name, strlen(name) + 1); +} + +#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) + +static void __init dt_prop(struct iseries_flat_dt *dt, char *name, + char *data, int len) +{ + unsigned long offset; + + dt_push_u32(dt, OF_DT_PROP); + + /* Length of the data */ + dt_push_u32(dt, len); + + /* Put the property name in the string blob. */ + offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); + + /* The offset of the properties name in the string blob. */ + dt_push_u32(dt, (u32)offset); + + /* The actual data. */ + dt_push_bytes(&dt->dt, data, len); +} + +static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, + char *data) +{ + dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ +} + +static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +{ + dt_prop(dt, name, (char *)&data, sizeof(u32)); +} + +static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +{ + dt_prop(dt, name, (char *)&data, sizeof(u64)); +} + +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, + u64 *data, int n) +{ + dt_prop(dt, name, (char *)data, sizeof(u64) * n); +} + +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, + u32 *data, int n) +{ + dt_prop(dt, name, (char *)data, sizeof(u32) * n); +} + +#ifdef notyet +static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) +{ + dt_prop(dt, name, NULL, 0); +} +#endif + +static void __init dt_cpus(struct iseries_flat_dt *dt) +{ + unsigned char buf[32]; + unsigned char *p; + unsigned int i, index; + struct IoHriProcessorVpd *d; + u32 pft_size[2]; + + /* yuck */ + snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); + p = strchr(buf, ' '); + if (!p) p = buf + strlen(buf); + + dt_start_node(dt, "cpus"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ + pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + if (lppaca[i].dyn_proc_status >= 2) + continue; + + snprintf(p, 32 - (p - buf), "@%d", i); + dt_start_node(dt, buf); + + dt_prop_str(dt, "device_type", "cpu"); + + index = lppaca[i].dyn_hv_phys_proc_index; + d = &xIoHriProcessorVpd[index]; + + dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); + dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); + + dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); + dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); + + /* magic conversions to Hz copied from old code */ + dt_prop_u32(dt, "clock-frequency", + ((1UL << 34) * 1000000) / d->xProcFreq); + dt_prop_u32(dt, "timebase-frequency", + ((1UL << 32) * 1000000) / d->xTimeBaseFreq); + + dt_prop_u32(dt, "reg", i); + + dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); + + dt_end_node(dt); + } + + dt_end_node(dt); +} + +static void __init dt_model(struct iseries_flat_dt *dt) +{ + char buf[16] = "IBM,"; + + /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ + strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); + strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); + buf[11] = '\0'; + dt_prop_str(dt, "system-id", buf); + + /* "IBM," + machineType[0:4] */ + strne2a(buf + 4, xItExtVpdPanel.machineType, 4); + buf[8] = '\0'; + dt_prop_str(dt, "model", buf); + + dt_prop_str(dt, "compatible", "IBM,iSeries"); +} + +static void __init dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + char buf[32]; + + dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + snprintf(buf, sizeof(buf), "vty@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "serial"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "vscsi"); + dt_prop_str(dt, "compatible", "IBM,v-scsi"); + dt_prop_u32(dt, "reg", reg); + dt_end_node(dt); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + snprintf(buf, 32, "l-lan@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "network"); + dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { + snprintf(buf, 32, "viodasd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALDISKS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { + snprintf(buf, 32, "viocd@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "block"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { + snprintf(buf, 32, "viotape@%08x", reg + i); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "byte"); + dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); + dt_prop_u32(dt, "reg", reg + i); + dt_prop_u32(dt, "linux,unit_address", i); + dt_end_node(dt); + } + + dt_end_node(dt); +} + +struct pci_class_name { + u16 code; + char *name; + char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + +/* + * This assumes that the node slot is always on the primary bus! + */ +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG + "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + printk(KERN_DEBUG + "ReadVendor(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + printk(KERN_DEBUG + "ReadDevice(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + printk(KERN_DEBUG + "ReadClass(%x, %x, %x) == %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); + else + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); + dt_start_node(dt, buf); + reg[0] = (bus << 16) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " + "== %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + printk("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " + "== %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + printk(KERN_DEBUG "PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void __init dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe" + "(0x%02X): 0x%04X", bus, err); + continue; + } + printk("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + +void * __init build_flat_dt(unsigned long phys_mem_size) +{ + u64 tmp[2]; + + dt_init(&iseries_dt); + + dt_start_node(&iseries_dt, ""); + + dt_prop_u32(&iseries_dt, "#address-cells", 2); + dt_prop_u32(&iseries_dt, "#size-cells", 2); + dt_model(&iseries_dt); + + /* /memory */ + dt_start_node(&iseries_dt, "memory@0"); + dt_prop_str(&iseries_dt, "name", "memory"); + dt_prop_str(&iseries_dt, "device_type", "memory"); + tmp[0] = 0; + tmp[1] = phys_mem_size; + dt_prop_u64_list(&iseries_dt, "reg", tmp, 2); + dt_end_node(&iseries_dt); + + /* /chosen */ + dt_start_node(&iseries_dt, "chosen"); + dt_prop_str(&iseries_dt, "bootargs", cmd_line); + dt_end_node(&iseries_dt); + + dt_cpus(&iseries_dt); + + dt_vdevices(&iseries_dt); + dt_pci_devices(&iseries_dt); + + dt_end_node(&iseries_dt); + + dt_push_u32(&iseries_dt, OF_DT_END); + + return &iseries_dt; +} diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 5661bd0d4279..617c724c4590 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -28,7 +28,6 @@ #include #include #include -#include /* ETH_ALEN */ #include #include @@ -46,13 +45,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -66,8 +63,6 @@ #include "main_store.h" #include "call_sm.h" #include "call_hpt.h" -#include "call_pci.h" -#include "pci.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -711,575 +706,6 @@ define_machine(iseries) { /* XXX Implement enable_pmcs for iSeries */ }; -struct blob { - unsigned char data[PAGE_SIZE * 2]; - unsigned long next; -}; - -struct iseries_flat_dt { - struct boot_param_header header; - u64 reserve_map[2]; - struct blob dt; - struct blob strings; -}; - -static struct iseries_flat_dt iseries_dt; - -static void __init dt_init(struct iseries_flat_dt *dt) -{ - dt->header.off_mem_rsvmap = - offsetof(struct iseries_flat_dt, reserve_map); - dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); - dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); - dt->header.totalsize = sizeof(struct iseries_flat_dt); - dt->header.dt_strings_size = sizeof(struct blob); - - /* There is no notion of hardware cpu id on iSeries */ - dt->header.boot_cpuid_phys = smp_processor_id(); - - dt->dt.next = (unsigned long)&dt->dt.data; - dt->strings.next = (unsigned long)&dt->strings.data; - - dt->header.magic = OF_DT_HEADER; - dt->header.version = 0x10; - dt->header.last_comp_version = 0x10; - - dt->reserve_map[0] = 0; - dt->reserve_map[1] = 0; -} - -static void __init dt_check_blob(struct blob *b) -{ - if (b->next >= (unsigned long)&b->next) { - DBG("Ran out of space in flat device tree blob!\n"); - BUG(); - } -} - -static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) -{ - *((u32*)dt->dt.next) = value; - dt->dt.next += sizeof(u32); - - dt_check_blob(&dt->dt); -} - -#ifdef notyet -static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) -{ - *((u64*)dt->dt.next) = value; - dt->dt.next += sizeof(u64); - - dt_check_blob(&dt->dt); -} -#endif - -static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) -{ - unsigned long start = blob->next - (unsigned long)blob->data; - - memcpy((char *)blob->next, data, len); - blob->next = _ALIGN(blob->next + len, 4); - - dt_check_blob(blob); - - return start; -} - -static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) -{ - dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(&dt->dt, name, strlen(name) + 1); -} - -#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) - -static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - char *data, int len) -{ - unsigned long offset; - - dt_push_u32(dt, OF_DT_PROP); - - /* Length of the data */ - dt_push_u32(dt, len); - - /* Put the property name in the string blob. */ - offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); - - /* The offset of the properties name in the string blob. */ - dt_push_u32(dt, (u32)offset); - - /* The actual data. */ - dt_push_bytes(&dt->dt, data, len); -} - -static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, - char *data) -{ - dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ -} - -static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u32)); -} - -static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) -{ - dt_prop(dt, name, (char *)&data, sizeof(u64)); -} - -static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, - u64 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u64) * n); -} - -static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, - u32 *data, int n) -{ - dt_prop(dt, name, (char *)data, sizeof(u32) * n); -} - -#ifdef notyet -static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) -{ - dt_prop(dt, name, NULL, 0); -} -#endif - -static void __init dt_cpus(struct iseries_flat_dt *dt) -{ - unsigned char buf[32]; - unsigned char *p; - unsigned int i, index; - struct IoHriProcessorVpd *d; - u32 pft_size[2]; - - /* yuck */ - snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); - p = strchr(buf, ' '); - if (!p) p = buf + strlen(buf); - - dt_start_node(dt, "cpus"); - dt_prop_u32(dt, "#address-cells", 1); - dt_prop_u32(dt, "#size-cells", 0); - - pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ - pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); - - for (i = 0; i < NR_CPUS; i++) { - if (lppaca[i].dyn_proc_status >= 2) - continue; - - snprintf(p, 32 - (p - buf), "@%d", i); - dt_start_node(dt, buf); - - dt_prop_str(dt, "device_type", "cpu"); - - index = lppaca[i].dyn_hv_phys_proc_index; - d = &xIoHriProcessorVpd[index]; - - dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); - dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); - - dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); - dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); - - /* magic conversions to Hz copied from old code */ - dt_prop_u32(dt, "clock-frequency", - ((1UL << 34) * 1000000) / d->xProcFreq); - dt_prop_u32(dt, "timebase-frequency", - ((1UL << 32) * 1000000) / d->xTimeBaseFreq); - - dt_prop_u32(dt, "reg", i); - - dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); - - dt_end_node(dt); - } - - dt_end_node(dt); -} - -static void __init dt_model(struct iseries_flat_dt *dt) -{ - char buf[16] = "IBM,"; - - /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ - strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); - strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); - buf[11] = '\0'; - dt_prop_str(dt, "system-id", buf); - - /* "IBM," + machineType[0:4] */ - strne2a(buf + 4, xItExtVpdPanel.machineType, 4); - buf[8] = '\0'; - dt_prop_str(dt, "model", buf); - - dt_prop_str(dt, "compatible", "IBM,iSeries"); -} - -static void __init dt_vdevices(struct iseries_flat_dt *dt) -{ - u32 reg = 0; - HvLpIndexMap vlan_map; - int i; - char buf[32]; - - dt_start_node(dt, "vdevice"); - dt_prop_str(dt, "device_type", "vdevice"); - dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); - dt_prop_u32(dt, "#address-cells", 1); - dt_prop_u32(dt, "#size-cells", 0); - - snprintf(buf, sizeof(buf), "vty@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "serial"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); - reg++; - - snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vscsi"); - dt_prop_str(dt, "compatible", "IBM,v-scsi"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); - reg++; - - vlan_map = HvLpConfig_getVirtualLanIndexMap(); - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { - unsigned char mac_addr[ETH_ALEN]; - - if ((vlan_map & (0x8000 >> i)) == 0) - continue; - snprintf(buf, 32, "l-lan@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "network"); - dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - - mac_addr[0] = 0x02; - mac_addr[1] = 0x01; - mac_addr[2] = 0xff; - mac_addr[3] = i; - mac_addr[4] = 0xff; - mac_addr[5] = HvLpConfig_getLpIndex_outline(); - dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); - dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); - dt_prop_u32(dt, "max-frame-size", 9000); - dt_prop_u32(dt, "address-bits", 48); - - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALLANS; - - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { - snprintf(buf, 32, "viodasd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALDISKS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) { - snprintf(buf, 32, "viocd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - reg += HVMAXARCHITECTEDVIRTUALCDROMS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) { - snprintf(buf, 32, "viotape@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "byte"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } - - dt_end_node(dt); -} - -struct pci_class_name { - u16 code; - char *name; - char *type; -}; - -static struct pci_class_name __initdata pci_class_name[] = { - { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, -}; - -static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) -{ - struct pci_class_name *cp; - - for (cp = pci_class_name; - cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) - if (cp->code == class_code) - return cp; - return NULL; -} - -/* - * This assumes that the node slot is always on the primary bus! - */ -static void __init scan_bridge_slot(struct iseries_flat_dt *dt, - HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) -{ - HvSubBusNumber sub_bus = bridge_info->subBusNumber; - u16 vendor_id; - u16 device_id; - u32 class_id; - int err; - char buf[32]; - u32 reg[5]; - int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); - int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); - HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); - u8 devfn; - struct pci_class_name *cp; - - /* - * Connect all functions of any device found. - */ - for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { - for (function = 0; function < 8; function++) { - HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, - function); - err = HvCallXm_connectBusUnit(bus, sub_bus, - agent_id, 0); - if (err) { - if (err != 0x302) - printk(KERN_DEBUG - "connectBusUnit(%x, %x, %x) " - "== %x\n", - bus, sub_bus, agent_id, err); - continue; - } - - err = HvCallPci_configLoad16(bus, sub_bus, agent_id, - PCI_VENDOR_ID, &vendor_id); - if (err) { - printk(KERN_DEBUG - "ReadVendor(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - err = HvCallPci_configLoad16(bus, sub_bus, agent_id, - PCI_DEVICE_ID, &device_id); - if (err) { - printk(KERN_DEBUG - "ReadDevice(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - err = HvCallPci_configLoad32(bus, sub_bus, agent_id, - PCI_CLASS_REVISION , &class_id); - if (err) { - printk(KERN_DEBUG - "ReadClass(%x, %x, %x) == %x\n", - bus, sub_bus, agent_id, err); - continue; - } - - devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), - function); - cp = dt_find_pci_class_name(class_id >> 16); - if (cp && cp->name) - strncpy(buf, cp->name, sizeof(buf) - 1); - else - snprintf(buf, sizeof(buf), "pci%x,%x", - vendor_id, device_id); - buf[sizeof(buf) - 1] = '\0'; - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), - "@%x", PCI_SLOT(devfn)); - buf[sizeof(buf) - 1] = '\0'; - if (function != 0) - snprintf(buf + strlen(buf), - sizeof(buf) - strlen(buf), - ",%x", function); - dt_start_node(dt, buf); - reg[0] = (bus << 16) | (devfn << 8); - reg[1] = 0; - reg[2] = 0; - reg[3] = 0; - reg[4] = 0; - dt_prop_u32_list(dt, "reg", reg, 5); - if (cp && (cp->type || cp->name)) - dt_prop_str(dt, "device_type", - cp->type ? cp->type : cp->name); - dt_prop_u32(dt, "vendor-id", vendor_id); - dt_prop_u32(dt, "device-id", device_id); - dt_prop_u32(dt, "class-code", class_id >> 8); - dt_prop_u32(dt, "revision-id", class_id & 0xff); - dt_prop_u32(dt, "linux,subbus", sub_bus); - dt_prop_u32(dt, "linux,agent-id", agent_id); - dt_prop_u32(dt, "linux,logical-slot-number", - bridge_info->logicalSlotNumber); - dt_end_node(dt); - - } - } -} - -static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, - HvSubBusNumber sub_bus, int id_sel) -{ - struct HvCallPci_BridgeInfo bridge_info; - HvAgentId agent_id; - int function; - int ret; - - /* Note: hvSubBus and irq is always be 0 at this level! */ - for (function = 0; function < 8; ++function) { - agent_id = ISERIES_PCI_AGENTID(id_sel, function); - ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); - if (ret != 0) { - if (ret != 0xb) - printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " - "== %x\n", - bus, sub_bus, agent_id, ret); - continue; - } - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", - bus, id_sel, function, agent_id); - ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, - iseries_hv_addr(&bridge_info), - sizeof(struct HvCallPci_BridgeInfo)); - if (ret != 0) - continue; - printk("bridge info: type %x subbus %x " - "maxAgents %x maxsubbus %x logslot %x\n", - bridge_info.busUnitInfo.deviceType, - bridge_info.subBusNumber, - bridge_info.maxAgents, - bridge_info.maxSubBusNumber, - bridge_info.logicalSlotNumber); - if (bridge_info.busUnitInfo.deviceType == - HvCallPci_BridgeDevice) - scan_bridge_slot(dt, bus, &bridge_info); - else - printk("PCI: Invalid Bridge Configuration(0x%02X)", - bridge_info.busUnitInfo.deviceType); - } -} - -static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) -{ - struct HvCallPci_DeviceInfo dev_info; - const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ - int err; - int id_sel; - const int max_agents = 8; - - /* - * Probe for EADs Bridges - */ - for (id_sel = 1; id_sel < max_agents; ++id_sel) { - err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, - iseries_hv_addr(&dev_info), - sizeof(struct HvCallPci_DeviceInfo)); - if (err) { - if (err != 0x302) - printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " - "== %x\n", - bus, sub_bus, id_sel, err); - continue; - } - if (dev_info.deviceType != HvCallPci_NodeDevice) { - printk(KERN_DEBUG "PCI: Invalid System Configuration" - "(0x%02X) for bus 0x%02x id 0x%02x.\n", - dev_info.deviceType, bus, id_sel); - continue; - } - scan_bridge(dt, bus, sub_bus, id_sel); - } -} - -static void __init dt_pci_devices(struct iseries_flat_dt *dt) -{ - HvBusNumber bus; - char buf[32]; - u32 buses[2]; - int phb_num = 0; - - /* Check all possible buses. */ - for (bus = 0; bus < 256; bus++) { - int err = HvCallXm_testBus(bus); - - if (err) { - /* - * Check for Unexpected Return code, a clue that - * something has gone wrong. - */ - if (err != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe" - "(0x%02X): 0x%04X", bus, err); - continue; - } - printk("bus %d appears to exist\n", bus); - snprintf(buf, 32, "pci@%d", phb_num); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "pci"); - dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); - dt_prop_u32(dt, "#address-cells", 3); - dt_prop_u32(dt, "#size-cells", 2); - buses[0] = buses[1] = bus; - dt_prop_u32_list(dt, "bus-range", buses, 2); - scan_phb(dt, bus); - dt_end_node(dt); - phb_num++; - } -} - -static void __init build_flat_dt(struct iseries_flat_dt *dt, - unsigned long phys_mem_size) -{ - u64 tmp[2]; - - dt_init(dt); - - dt_start_node(dt, ""); - - dt_prop_u32(dt, "#address-cells", 2); - dt_prop_u32(dt, "#size-cells", 2); - dt_model(dt); - - /* /memory */ - dt_start_node(dt, "memory@0"); - dt_prop_str(dt, "name", "memory"); - dt_prop_str(dt, "device_type", "memory"); - tmp[0] = 0; - tmp[1] = phys_mem_size; - dt_prop_u64_list(dt, "reg", tmp, 2); - dt_end_node(dt); - - /* /chosen */ - dt_start_node(dt, "chosen"); - dt_prop_str(dt, "bootargs", cmd_line); - dt_end_node(dt); - - dt_cpus(dt); - - dt_vdevices(dt); - dt_pci_devices(dt); - - dt_end_node(dt); - - dt_push_u32(dt, OF_DT_END); -} - void * __init iSeries_early_setup(void) { unsigned long phys_mem_size; @@ -1294,9 +720,7 @@ void * __init iSeries_early_setup(void) iSeries_get_cmdline(); - build_flat_dt(&iseries_dt, phys_mem_size); - - return (void *) __pa(&iseries_dt); + return (void *) __pa(build_flat_dt(phys_mem_size)); } static void hvputc(char c) diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h index 5213044ec411..0a47ac53c959 100644 --- a/arch/powerpc/platforms/iseries/setup.h +++ b/arch/powerpc/platforms/iseries/setup.h @@ -21,4 +21,6 @@ extern unsigned long iSeries_get_boot_time(void); extern int iSeries_set_rtc_time(struct rtc_time *tm); extern void iSeries_get_rtc_time(struct rtc_time *tm); +extern void *build_flat_dt(unsigned long phys_mem_size); + #endif /* __ISERIES_SETUP_H__ */ -- cgit From c4e3ea2553308ba65fea582dc9a42221ef8b49e5 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:04:48 +1000 Subject: [PATCH] powerpc: make iSeries flattened device tree dynamic First we capture all the strings from dt.c statically by noting that gcc puts them in a special section of their own. Idea from Michael Ellerman. Then we move the flattened device tree to klimit. Still to come, making the values blob grow as needed. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/Makefile | 5 +- arch/powerpc/platforms/iseries/dt.c | 96 +++++++++++++++++++-------------- 2 files changed, 61 insertions(+), 40 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index 32306214a301..dee4eb4d8bec 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile @@ -1,8 +1,11 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ +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_MODULES) += ksyms.o + +$(obj)/dt_mod.o: $(obj)/dt.o + @$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 93d4233e73e5..0371329f82e1 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,9 @@ #define DBG(fmt...) #endif +extern char __dt_strings_start[]; +extern char __dt_strings_end[]; + struct blob { unsigned char data[PAGE_SIZE * 2]; unsigned long next; @@ -55,26 +59,34 @@ struct blob { struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - struct blob dt; - struct blob strings; + struct blob *dt; }; -static struct iseries_flat_dt iseries_dt; +static struct iseries_flat_dt *iseries_dt; -static void __init dt_init(struct iseries_flat_dt *dt) +static struct iseries_flat_dt * __init dt_init(void) { + struct iseries_flat_dt *dt; + unsigned long str_len; + + str_len = __dt_strings_end - __dt_strings_start; + dt = (struct iseries_flat_dt *)ALIGN(klimit, 8); dt->header.off_mem_rsvmap = offsetof(struct iseries_flat_dt, reserve_map); - dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); - dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); - dt->header.totalsize = sizeof(struct iseries_flat_dt); - dt->header.dt_strings_size = sizeof(struct blob); + dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); + dt->header.off_dt_struct = dt->header.off_dt_strings + + ALIGN(str_len, 8); + dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct); + klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8); + dt->header.totalsize = klimit - (unsigned long)dt; + dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ dt->header.boot_cpuid_phys = smp_processor_id(); - dt->dt.next = (unsigned long)&dt->dt.data; - dt->strings.next = (unsigned long)&dt->strings.data; + dt->dt->next = (unsigned long)&dt->dt->data; + memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, + str_len); dt->header.magic = OF_DT_HEADER; dt->header.version = 0x10; @@ -82,6 +94,8 @@ static void __init dt_init(struct iseries_flat_dt *dt) dt->reserve_map[0] = 0; dt->reserve_map[1] = 0; + + return dt; } static void __init dt_check_blob(struct blob *b) @@ -94,19 +108,19 @@ static void __init dt_check_blob(struct blob *b) static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32*)dt->dt.next) = value; - dt->dt.next += sizeof(u32); + *((u32*)dt->dt->next) = value; + dt->dt->next += sizeof(u32); - dt_check_blob(&dt->dt); + dt_check_blob(dt->dt); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64*)dt->dt.next) = value; - dt->dt.next += sizeof(u64); + *((u64*)dt->dt->next) = value; + dt->dt->next += sizeof(u64); - dt_check_blob(&dt->dt); + dt_check_blob(dt->dt); } #endif @@ -125,7 +139,7 @@ static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(&dt->dt, name, strlen(name) + 1); + dt_push_bytes(dt->dt, name, strlen(name) + 1); } #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) @@ -140,14 +154,13 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, /* Length of the data */ dt_push_u32(dt, len); - /* Put the property name in the string blob. */ - offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); + offset = name - __dt_strings_start; /* The offset of the properties name in the string blob. */ dt_push_u32(dt, (u32)offset); /* The actual data. */ - dt_push_bytes(&dt->dt, data, len); + dt_push_bytes(dt->dt, data, len); } static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, @@ -579,40 +592,45 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) } } +static void dt_finish(struct iseries_flat_dt *dt) +{ + dt_push_u32(dt, OF_DT_END); +} + void * __init build_flat_dt(unsigned long phys_mem_size) { u64 tmp[2]; - dt_init(&iseries_dt); + iseries_dt = dt_init(); - dt_start_node(&iseries_dt, ""); + dt_start_node(iseries_dt, ""); - dt_prop_u32(&iseries_dt, "#address-cells", 2); - dt_prop_u32(&iseries_dt, "#size-cells", 2); - dt_model(&iseries_dt); + dt_prop_u32(iseries_dt, "#address-cells", 2); + dt_prop_u32(iseries_dt, "#size-cells", 2); + dt_model(iseries_dt); /* /memory */ - dt_start_node(&iseries_dt, "memory@0"); - dt_prop_str(&iseries_dt, "name", "memory"); - dt_prop_str(&iseries_dt, "device_type", "memory"); + dt_start_node(iseries_dt, "memory@0"); + dt_prop_str(iseries_dt, "name", "memory"); + dt_prop_str(iseries_dt, "device_type", "memory"); tmp[0] = 0; tmp[1] = phys_mem_size; - dt_prop_u64_list(&iseries_dt, "reg", tmp, 2); - dt_end_node(&iseries_dt); + dt_prop_u64_list(iseries_dt, "reg", tmp, 2); + dt_end_node(iseries_dt); /* /chosen */ - dt_start_node(&iseries_dt, "chosen"); - dt_prop_str(&iseries_dt, "bootargs", cmd_line); - dt_end_node(&iseries_dt); + dt_start_node(iseries_dt, "chosen"); + dt_prop_str(iseries_dt, "bootargs", cmd_line); + dt_end_node(iseries_dt); - dt_cpus(&iseries_dt); + dt_cpus(iseries_dt); - dt_vdevices(&iseries_dt); - dt_pci_devices(&iseries_dt); + dt_vdevices(iseries_dt); + dt_pci_devices(iseries_dt); - dt_end_node(&iseries_dt); + dt_end_node(iseries_dt); - dt_push_u32(&iseries_dt, OF_DT_END); + dt_finish(iseries_dt); - return &iseries_dt; + return iseries_dt; } -- cgit From 72a14eafb243b1f31118ea55a7e8c2588b5ad468 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:04:12 +1000 Subject: [PATCH] powerpc: make iSeries flattened device tree dynamic - part 2 This actually simplies things as we just figure out how much space we used at the end and adjust klimit then. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/dt.c | 62 ++++++++++++------------------------- 1 file changed, 19 insertions(+), 43 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 0371329f82e1..2a51ec1e3359 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -51,15 +50,10 @@ extern char __dt_strings_start[]; extern char __dt_strings_end[]; -struct blob { - unsigned char data[PAGE_SIZE * 2]; - unsigned long next; -}; - struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - struct blob *dt; + void *data; }; static struct iseries_flat_dt *iseries_dt; @@ -76,15 +70,12 @@ static struct iseries_flat_dt * __init dt_init(void) dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); dt->header.off_dt_struct = dt->header.off_dt_strings + ALIGN(str_len, 8); - dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct); - klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8); - dt->header.totalsize = klimit - (unsigned long)dt; + dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct); dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ dt->header.boot_cpuid_phys = smp_processor_id(); - dt->dt->next = (unsigned long)&dt->dt->data; memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, str_len); @@ -98,54 +89,37 @@ static struct iseries_flat_dt * __init dt_init(void) return dt; } -static void __init dt_check_blob(struct blob *b) -{ - if (b->next >= (unsigned long)&b->next) { - DBG("Ran out of space in flat device tree blob!\n"); - BUG(); - } -} - static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32*)dt->dt->next) = value; - dt->dt->next += sizeof(u32); - - dt_check_blob(dt->dt); + *((u32 *)dt->data) = value; + dt->data += sizeof(u32); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64*)dt->dt->next) = value; - dt->dt->next += sizeof(u64); - - dt_check_blob(dt->dt); + *((u64 *)dt->data) = value; + dt->data += sizeof(u64); } #endif -static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) +static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data, + int len) { - unsigned long start = blob->next - (unsigned long)blob->data; - - memcpy((char *)blob->next, data, len); - blob->next = _ALIGN(blob->next + len, 4); - - dt_check_blob(blob); - - return start; + memcpy(dt->data, data, len); + dt->data += ALIGN(len, 4); } static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); - dt_push_bytes(dt->dt, name, strlen(name) + 1); + dt_push_bytes(dt, name, strlen(name) + 1); } #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - char *data, int len) + void *data, int len) { unsigned long offset; @@ -160,7 +134,7 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, dt_push_u32(dt, (u32)offset); /* The actual data. */ - dt_push_bytes(dt->dt, data, len); + dt_push_bytes(dt, data, len); } static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, @@ -171,24 +145,24 @@ static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) { - dt_prop(dt, name, (char *)&data, sizeof(u32)); + dt_prop(dt, name, &data, sizeof(u32)); } static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) { - dt_prop(dt, name, (char *)&data, sizeof(u64)); + dt_prop(dt, name, &data, sizeof(u64)); } static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) { - dt_prop(dt, name, (char *)data, sizeof(u64) * n); + dt_prop(dt, name, data, sizeof(u64) * n); } static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) { - dt_prop(dt, name, (char *)data, sizeof(u32) * n); + dt_prop(dt, name, data, sizeof(u32) * n); } #ifdef notyet @@ -595,6 +569,8 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) static void dt_finish(struct iseries_flat_dt *dt) { dt_push_u32(dt, OF_DT_END); + dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt->data, 8); } void * __init build_flat_dt(unsigned long phys_mem_size) -- cgit From 7499bf1a4cabde789e7694b33d01a1913ae1dddf Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 19 May 2006 17:06:38 +1000 Subject: [PATCH] powerpc: cleanup of iSeries flat device tree Consolidate the vio device node creation. Make some parameters const. Make a few more things __initdata. Get the device_type strings out of the device tree blob. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/dt.c | 199 ++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 98 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 2a51ec1e3359..d3444aabe76e 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c @@ -47,16 +47,34 @@ #define DBG(fmt...) #endif +/* + * These are created by the linker script at the start and end + * of the section containing all the strings from this file. + */ extern char __dt_strings_start[]; extern char __dt_strings_end[]; struct iseries_flat_dt { struct boot_param_header header; u64 reserve_map[2]; - void *data; }; -static struct iseries_flat_dt *iseries_dt; +static void * __initdata dt_data; + +/* + * Putting these strings here keeps them out of the section + * that we rename to .dt_strings using objcopy and capture + * for the strings blob of the flattened device tree. + */ +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"; static struct iseries_flat_dt * __init dt_init(void) { @@ -70,7 +88,7 @@ static struct iseries_flat_dt * __init dt_init(void) dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); dt->header.off_dt_struct = dt->header.off_dt_strings + ALIGN(str_len, 8); - dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct); + dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct); dt->header.dt_strings_size = str_len; /* There is no notion of hardware cpu id on iSeries */ @@ -91,26 +109,26 @@ static struct iseries_flat_dt * __init dt_init(void) static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) { - *((u32 *)dt->data) = value; - dt->data += sizeof(u32); + *((u32 *)dt_data) = value; + dt_data += sizeof(u32); } #ifdef notyet static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) { - *((u64 *)dt->data) = value; - dt->data += sizeof(u64); + *((u64 *)dt_data) = value; + dt_data += sizeof(u64); } #endif -static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data, +static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data, int len) { - memcpy(dt->data, data, len); - dt->data += ALIGN(len, 4); + memcpy(dt_data, data, len); + dt_data += ALIGN(len, 4); } -static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) +static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name) { dt_push_u32(dt, OF_DT_BEGIN_NODE); dt_push_bytes(dt, name, strlen(name) + 1); @@ -118,8 +136,8 @@ static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) -static void __init dt_prop(struct iseries_flat_dt *dt, char *name, - void *data, int len) +static void __init dt_prop(struct iseries_flat_dt *dt, const char *name, + const void *data, int len) { unsigned long offset; @@ -137,36 +155,40 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name, dt_push_bytes(dt, data, len); } -static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, - char *data) +static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name, + const char *data) { dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ } -static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) +static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, + u32 data) { dt_prop(dt, name, &data, sizeof(u32)); } -static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) +#ifdef notyet +static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, + u64 data) { dt_prop(dt, name, &data, sizeof(u64)); } +#endif -static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, - u64 *data, int n) +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, + const char *name, u64 *data, int n) { dt_prop(dt, name, data, sizeof(u64) * n); } -static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, - u32 *data, int n) +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, + const char *name, u32 *data, int n) { dt_prop(dt, name, data, sizeof(u32) * n); } #ifdef notyet -static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) +static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name) { dt_prop(dt, name, NULL, 0); } @@ -199,7 +221,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) snprintf(p, 32 - (p - buf), "@%d", i); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "cpu"); + dt_prop_str(dt, "device_type", device_type_cpu); index = lppaca[i].dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; @@ -244,32 +266,41 @@ static void __init dt_model(struct iseries_flat_dt *dt) dt_prop_str(dt, "compatible", "IBM,iSeries"); } +static void __init dt_do_vdevice(struct iseries_flat_dt *dt, + const char *name, u32 reg, int unit, + const char *type, const char *compat, int end) +{ + char buf[32]; + + snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0)); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", type); + if (compat) + dt_prop_str(dt, "compatible", compat); + dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0)); + if (unit >= 0) + dt_prop_u32(dt, "linux,unit_address", unit); + if (end) + dt_end_node(dt); +} + static void __init dt_vdevices(struct iseries_flat_dt *dt) { u32 reg = 0; HvLpIndexMap vlan_map; int i; - char buf[32]; dt_start_node(dt, "vdevice"); - dt_prop_str(dt, "device_type", "vdevice"); + dt_prop_str(dt, "device_type", device_type_vdevice); dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); dt_prop_u32(dt, "#address-cells", 1); dt_prop_u32(dt, "#size-cells", 0); - snprintf(buf, sizeof(buf), "vty@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "serial"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); + dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1); reg++; - snprintf(buf, sizeof(buf), "v-scsi@%08x", reg); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "vscsi"); - dt_prop_str(dt, "compatible", "IBM,v-scsi"); - dt_prop_u32(dt, "reg", reg); - dt_end_node(dt); + dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi, + "IBM,v-scsi", 1); reg++; vlan_map = HvLpConfig_getVirtualLanIndexMap(); @@ -278,13 +309,8 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) if ((vlan_map & (0x8000 >> i)) == 0) continue; - snprintf(buf, 32, "l-lan@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "network"); - dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - + dt_do_vdevice(dt, "l-lan", reg, i, device_type_network, + "IBM,iSeries-l-lan", 0); mac_addr[0] = 0x02; mac_addr[1] = 0x01; mac_addr[2] = 0xff; @@ -300,47 +326,31 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt) } reg += HVMAXARCHITECTEDVIRTUALLANS; - for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) { - snprintf(buf, 32, "viodasd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + 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++) { - snprintf(buf, 32, "viocd@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "block"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viocd"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + + 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++) { - snprintf(buf, 32, "viotape@%08x", reg + i); - dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "byte"); - dt_prop_str(dt, "compatible", "IBM,iSeries-viotape"); - dt_prop_u32(dt, "reg", reg + i); - dt_prop_u32(dt, "linux,unit_address", i); - dt_end_node(dt); - } + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) + dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, + "IBM,iSeries-viotape", 1); dt_end_node(dt); } struct pci_class_name { u16 code; - char *name; - char *type; + const char *name; + const char *type; }; static struct pci_class_name __initdata pci_class_name[] = { - { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network }, }; static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) @@ -384,9 +394,7 @@ static void __init scan_bridge_slot(struct iseries_flat_dt *dt, agent_id, 0); if (err) { if (err != 0x302) - printk(KERN_DEBUG - "connectBusUnit(%x, %x, %x) " - "== %x\n", + DBG("connectBusUnit(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } @@ -394,24 +402,21 @@ static void __init scan_bridge_slot(struct iseries_flat_dt *dt, err = HvCallPci_configLoad16(bus, sub_bus, agent_id, PCI_VENDOR_ID, &vendor_id); if (err) { - printk(KERN_DEBUG - "ReadVendor(%x, %x, %x) == %x\n", + DBG("ReadVendor(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } err = HvCallPci_configLoad16(bus, sub_bus, agent_id, PCI_DEVICE_ID, &device_id); if (err) { - printk(KERN_DEBUG - "ReadDevice(%x, %x, %x) == %x\n", + DBG("ReadDevice(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } err = HvCallPci_configLoad32(bus, sub_bus, agent_id, PCI_CLASS_REVISION , &class_id); if (err) { - printk(KERN_DEBUG - "ReadClass(%x, %x, %x) == %x\n", + DBG("ReadClass(%x, %x, %x) %x\n", bus, sub_bus, agent_id, err); continue; } @@ -470,19 +475,18 @@ static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); if (ret != 0) { if (ret != 0xb) - printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) " - "== %x\n", + DBG("connectBusUnit(%x, %x, %x) %x\n", bus, sub_bus, agent_id, ret); continue; } - printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + DBG("found device at bus %d idsel %d func %d (AgentId %x)\n", bus, id_sel, function, agent_id); ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, iseries_hv_addr(&bridge_info), sizeof(struct HvCallPci_BridgeInfo)); if (ret != 0) continue; - printk("bridge info: type %x subbus %x " + DBG("bridge info: type %x subbus %x " "maxAgents %x maxsubbus %x logslot %x\n", bridge_info.busUnitInfo.deviceType, bridge_info.subBusNumber, @@ -493,7 +497,7 @@ static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, HvCallPci_BridgeDevice) scan_bridge_slot(dt, bus, &bridge_info); else - printk("PCI: Invalid Bridge Configuration(0x%02X)", + DBG("PCI: Invalid Bridge Configuration(0x%02X)", bridge_info.busUnitInfo.deviceType); } } @@ -515,13 +519,12 @@ static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) sizeof(struct HvCallPci_DeviceInfo)); if (err) { if (err != 0x302) - printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) " - "== %x\n", + DBG("getDeviceInfo(%x, %x, %x) %x\n", bus, sub_bus, id_sel, err); continue; } if (dev_info.deviceType != HvCallPci_NodeDevice) { - printk(KERN_DEBUG "PCI: Invalid System Configuration" + DBG("PCI: Invalid System Configuration" "(0x%02X) for bus 0x%02x id 0x%02x.\n", dev_info.deviceType, bus, id_sel); continue; @@ -547,14 +550,14 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) * something has gone wrong. */ if (err != 0x0301) - printk(KERN_ERR "Unexpected Return on Probe" - "(0x%02X): 0x%04X", bus, err); + DBG("Unexpected Return on Probe(0x%02X) " + "0x%04X\n", bus, err); continue; } - printk("bus %d appears to exist\n", bus); + DBG("bus %d appears to exist\n", bus); snprintf(buf, 32, "pci@%d", phb_num); dt_start_node(dt, buf); - dt_prop_str(dt, "device_type", "pci"); + dt_prop_str(dt, "device_type", device_type_pci); dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); dt_prop_u32(dt, "#address-cells", 3); dt_prop_u32(dt, "#size-cells", 2); @@ -569,12 +572,13 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt) static void dt_finish(struct iseries_flat_dt *dt) { dt_push_u32(dt, OF_DT_END); - dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt; - klimit = ALIGN((unsigned long)dt->data, 8); + dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt_data, 8); } void * __init build_flat_dt(unsigned long phys_mem_size) { + struct iseries_flat_dt *iseries_dt; u64 tmp[2]; iseries_dt = dt_init(); @@ -587,8 +591,7 @@ void * __init build_flat_dt(unsigned long phys_mem_size) /* /memory */ dt_start_node(iseries_dt, "memory@0"); - dt_prop_str(iseries_dt, "name", "memory"); - dt_prop_str(iseries_dt, "device_type", "memory"); + dt_prop_str(iseries_dt, "device_type", device_type_memory); tmp[0] = 0; tmp[1] = phys_mem_size; dt_prop_u64_list(iseries_dt, "reg", tmp, 2); -- cgit From 6218a761bbc27acc65248c80024875bcc06d52b1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sun, 11 Jun 2006 14:15:17 +1000 Subject: powerpc: add context.vdso_base for 32-bit too This adds a vdso_base element to the mm_context_t for 32-bit compiles (both for ARCH=powerpc and ARCH=ppc). This fixes the compile errors that have been reported in arch/powerpc/kernel/signal_32.c. Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/cpufreq_32.c | 2 +- arch/powerpc/platforms/powermac/setup.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index cfd6527a0d7e..af2a8f9f1222 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -314,7 +314,7 @@ static int pmu_set_cpu_speed(int low_speed) _set_L3CR(save_l3cr); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); #ifdef DEBUG_FREQ printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b9200fb07815..9cc7db7a8bdc 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -458,7 +458,7 @@ static int pmac_pm_finish(suspend_state_t state) printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); /* Restore userland MMU context */ - set_context(current->active_mm->context, current->active_mm->pgd); + set_context(current->active_mm->context.id, current->active_mm->pgd); return 0; } -- cgit From 8555a0029b1b0840237b750e55d4835a52cc719b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:23:54 +1000 Subject: [POWERPC] Optimise some TOC usage Micro-optimisation - add no-minimal-toc to some more arch/powerpc Makefiles. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index b46ce3b9bb3c..e5e0ff466904 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -1,3 +1,7 @@ +ifeq ($(CONFIG_PPC64),y) +EXTRA_CFLAGS += -mno-minimal-toc +endif + obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ firmware.o -- cgit From ca1588e71b70534e18368a46a3aad9b25dff941d Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 20:58:08 +1000 Subject: [POWERPC] node local IOMMU tables Allocate IOMMU tables local to the relevant node. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/iseries/iommu.c | 2 +- arch/powerpc/platforms/pseries/iommu.c | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index a992f6af249f..e3bd2015f2c9 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -173,7 +173,7 @@ void iommu_devnode_init_iSeries(struct device_node *dn) /* Look for existing tce table */ pdn->iommu_table = iommu_table_find(tbl); if (pdn->iommu_table == NULL) - pdn->iommu_table = iommu_init_table(tbl); + pdn->iommu_table = iommu_init_table(tbl, -1); else kfree(tbl); } diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 44a507e6fb34..2f66dc6503ff 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -368,10 +368,11 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) pci->phb->dma_window_size = 0x8000000ul; pci->phb->dma_window_base_cur = 0x8000000ul; - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms(pci->phb, dn, tbl); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); /* Divide the rest (1.75GB) among the children */ pci->phb->dma_window_size = 0x80000000ul; @@ -414,12 +415,12 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) ppci->bussubno = bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + ppci->phb->node); iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window); - ppci->iommu_table = iommu_init_table(tbl); + ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node); } if (pdn != dn) @@ -442,9 +443,11 @@ static void iommu_dev_setup_pSeries(struct pci_dev *dev) */ if (!dev->bus->self) { DBG(" --> first child, no bridge. Allocating iommu table.\n"); - tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + PCI_DN(dn)->phb->node); iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); - PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); + PCI_DN(dn)->iommu_table = iommu_init_table(tbl, + PCI_DN(dn)->phb->node); return; } @@ -526,12 +529,12 @@ static void iommu_dev_setup_pSeriesLP(struct pci_dev *dev) /* iommu_table_setparms_lpar needs bussubno. */ pci->bussubno = pci->phb->bus->number; - tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table), - GFP_KERNEL); + tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL, + pci->phb->node); iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window); - pci->iommu_table = iommu_init_table(tbl); + pci->iommu_table = iommu_init_table(tbl, pci->phb->node); } if (pdn != dn) -- cgit From df310656c7552ae7b8252e4b3d8e300cff164b16 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 10 Jun 2006 23:04:39 +1000 Subject: [POWERPC] cleanup dma_mapping_ops For pseries IOMMU bypass I want to be able to fall back to the regular IOMMU ops. Do this by creating a dma_mapping_ops struct, and convert the others while at it. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/iommu.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index a49ceb799a8e..a35004e14c69 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -473,6 +473,16 @@ static int cell_dma_supported(struct device *dev, u64 mask) return mask < 0x100000000ull; } +static struct dma_mapping_ops cell_iommu_ops = { + .alloc_coherent = cell_alloc_coherent, + .free_coherent = cell_free_coherent, + .map_single = cell_map_single, + .unmap_single = cell_unmap_single, + .map_sg = cell_map_sg, + .unmap_sg = cell_unmap_sg, + .dma_supported = cell_dma_supported, +}; + void cell_init_iommu(void) { int setup_bus = 0; @@ -498,11 +508,5 @@ void cell_init_iommu(void) } } - pci_dma_ops.alloc_coherent = cell_alloc_coherent; - pci_dma_ops.free_coherent = cell_free_coherent; - pci_dma_ops.map_single = cell_map_single; - pci_dma_ops.unmap_single = cell_unmap_single; - pci_dma_ops.map_sg = cell_map_sg; - pci_dma_ops.unmap_sg = cell_unmap_sg; - pci_dma_ops.dma_supported = cell_dma_supported; + pci_dma_ops = cell_iommu_ops; } -- cgit From 4312dc76a88146c4f1d693fc4643d1df12aaf755 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 13 Jun 2006 17:43:42 +0200 Subject: [POWERPC] make pmf irq_client functions safe against pmf interrupts coming in This fixes the pmf irq_client functions to be safe against pmf interrupts coming in while a client is registered/unregistered. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/powermac/pfunc_core.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index f08173b0f065..047f954a89eb 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -871,10 +871,17 @@ int pmf_register_irq_client(struct device_node *target, spin_unlock_irqrestore(&pmf_lock, flags); if (func == NULL) return -ENODEV; + + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); if (list_empty(&func->irq_clients)) func->dev->handlers->irq_enable(func); + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_add(&client->link, &func->irq_clients); + spin_unlock_irqrestore(&pmf_lock, flags); + client->func = func; mutex_unlock(&pmf_irq_mutex); @@ -885,12 +892,19 @@ EXPORT_SYMBOL_GPL(pmf_register_irq_client); void pmf_unregister_irq_client(struct pmf_irq_client *client) { struct pmf_function *func = client->func; + unsigned long flags; BUG_ON(func == NULL); + /* guard against manipulations of list */ mutex_lock(&pmf_irq_mutex); client->func = NULL; + + /* guard against pmf_do_irq while changing list */ + spin_lock_irqsave(&pmf_lock, flags); list_del(&client->link); + spin_unlock_irqrestore(&pmf_lock, flags); + if (list_empty(&func->irq_clients)) func->dev->handlers->irq_disable(func); mutex_unlock(&pmf_irq_mutex); -- cgit From 7932f0b82ff1db35a5ed8d5825d51cafe15fa6db Mon Sep 17 00:00:00 2001 From: John Rose Date: Thu, 15 Jun 2006 17:32:15 -0500 Subject: [POWERPC] RTAS delay, fix module build breaks Export both news RTAS delay functions, and change the scanlog module to use the new delay functions. Signed-off-by: John Rose Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/scanlog.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 50643496eb63..77a5bb1d9c30 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c @@ -107,9 +107,9 @@ static ssize_t scanlog_read(struct file *file, char __user *buf, /* Break to sleep default time */ break; default: - if (status > 9900 && status <= 9905) { - wait_time = rtas_extended_busy_delay_time(status); - } else { + /* Assume extended busy */ + wait_time = rtas_busy_delay_time(status); + if (!wait_time) { printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status); return -EIO; } -- cgit From c9b484b5c1201321f40b04870e8b417033b6fe76 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:35 -0500 Subject: [POWERPC] Add the mpc8641 hpcn Kconfig and Makefiles. Signed-off-by: Xianghua Xiao Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/86xx/Kconfig | 36 ++++++++++++++++++++++++++++++++++++ arch/powerpc/platforms/86xx/Makefile | 10 ++++++++++ arch/powerpc/platforms/Makefile | 1 + 3 files changed, 47 insertions(+) create mode 100644 arch/powerpc/platforms/86xx/Kconfig create mode 100644 arch/powerpc/platforms/86xx/Makefile (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig new file mode 100644 index 000000000000..3a87863d2876 --- /dev/null +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -0,0 +1,36 @@ +menu "Platform Support" + depends on PPC_86xx + +choice + prompt "Machine Type" + default MPC8641_HPCN + +config MPC8641_HPCN + bool "Freescale MPC8641 HPCN" + help + This option enables support for the MPC8641 HPCN board. + +endchoice + + +config MPC8641 + bool + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + default y if MPC8641_HPCN + +config MPIC + bool + default y + +config PPC_INDIRECT_PCI_BE + bool + depends on PPC_86xx + default y + +config PPC_STD_MMU + bool + depends on PPC_86xx + default y + +endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile new file mode 100644 index 000000000000..7be796c5d5c9 --- /dev/null +++ b/arch/powerpc/platforms/86xx/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the PowerPC 86xx linux kernel. +# + + +ifeq ($(CONFIG_PPC_86xx),y) +obj-$(CONFIG_SMP) += mpc86xx_smp.o +endif +obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o +obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index c4f6b0d2d140..292863694562 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_PPC_85xx) += 85xx/ +obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_PSERIES) += pseries/ obj-$(CONFIG_PPC_ISERIES) += iseries/ obj-$(CONFIG_PPC_MAPLE) += maple/ -- cgit From 4ca4b6274c30d53d22014fb6974efe2b3e52cfdc Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:45 -0500 Subject: [POWERPC] Add the MPC8641 HPCN platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Haiying Wang Signed-off-by: Wei Zhang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/86xx/mpc8641_hpcn.h | 54 +++++ arch/powerpc/platforms/86xx/mpc86xx.h | 28 +++ arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 326 +++++++++++++++++++++++++++++ arch/powerpc/platforms/86xx/mpc86xx_smp.c | 117 +++++++++++ 4 files changed, 525 insertions(+) create mode 100644 arch/powerpc/platforms/86xx/mpc8641_hpcn.h create mode 100644 arch/powerpc/platforms/86xx/mpc86xx.h create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_hpcn.c create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_smp.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file mode 100644 index 000000000000..5042253758b7 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h @@ -0,0 +1,54 @@ +/* + * MPC8641 HPCN board definitions + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * 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. + * + * Author: Xianghua Xiao + */ + +#ifndef __MPC8641_HPCN_H__ +#define __MPC8641_HPCN_H__ + +#include +#include + +/* PCI interrupt controller */ +#define PIRQA 3 +#define PIRQB 4 +#define PIRQC 5 +#define PIRQD 6 +#define PIRQ7 7 +#define PIRQE 9 +#define PIRQF 10 +#define PIRQG 11 +#define PIRQH 12 + +/* PCI-Express memory map */ +#define MPC86XX_PCIE_LOWER_IO 0x00000000 +#define MPC86XX_PCIE_UPPER_IO 0x00ffffff + +#define MPC86XX_PCIE_LOWER_MEM 0x80000000 +#define MPC86XX_PCIE_UPPER_MEM 0x9fffffff + +#define MPC86XX_PCIE_IO_BASE 0xe2000000 +#define MPC86XX_PCIE_MEM_OFFSET 0x00000000 + +#define MPC86XX_PCIE_IO_SIZE 0x01000000 + +#define PCIE1_CFG_ADDR_OFFSET (0x8000) +#define PCIE1_CFG_DATA_OFFSET (0x8004) + +#define PCIE2_CFG_ADDR_OFFSET (0x9000) +#define PCIE2_CFG_DATA_OFFSET (0x9004) + +#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET +#define MPC86xx_PCIE_SIZE (0x1000) + +#define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */ + +#endif /* __MPC8641_HPCN_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h new file mode 100644 index 000000000000..e3c9e4f417d3 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx.h @@ -0,0 +1,28 @@ +/* + * Copyright 2006 Freescale Semiconductor Inc. + * + * 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. + */ + +#ifndef __MPC86XX_H__ +#define __MPC86XX_H__ + +/* + * Declaration for the various functions exported by the + * mpc86xx_* files. Mostly for use by mpc86xx_setup(). + */ + +extern int __init add_bridge(struct device_node *dev); + +extern void __init setup_indirect_pcie(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, + void __iomem *cfg_data); + +extern void __init mpc86xx_smp_init(void); + +#endif /* __MPC86XX_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file mode 100644 index 000000000000..483c21df181e --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -0,0 +1,326 @@ +/* + * MPC86xx HPCN board specific routines + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "mpc86xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +#endif + + +/* + * Internal interrupts are all Level Sensitive, and Positive Polarity + */ + +static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: MCM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCIE1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: PCIE2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: Reserved */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: DUART2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 1 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 1 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: TSEC 3 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: TSEC 3 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: TSEC 3 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 1 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 2 Transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 2 Receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: TSEC 4 transmit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: TSEC 4 receive */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: TSEC 4 error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 2 Receive/Transmit Error */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 32: SRIO error/write-port unit */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 33: SRIO outbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 34: SRIO inbound doorbell */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 35: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 36: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 37: SRIO outbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 38: SRIO inbound message unit 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 39: SRIO outbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 40: SRIO inbound message unit 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 41: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 42: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 43: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 44: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 45: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 46: Unused */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 47: Unused */ + 0x0, /* External 0: */ + 0x0, /* External 1: */ + 0x0, /* External 2: */ + 0x0, /* External 3: */ + 0x0, /* External 4: */ + 0x0, /* External 5: */ + 0x0, /* External 6: */ + 0x0, /* External 7: */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 8: Pixis FPGA */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 9: ULI 8259 INTR Cascade */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 10: Quad ETH PHY */ + 0x0, /* External 11: */ + 0x0, + 0x0, + 0x0, + 0x0, +}; + + +void __init +mpc86xx_hpcn_init_irq(void) +{ + struct mpic *mpic1; + phys_addr_t openpic_paddr; + + /* Determine the Physical Address of the OpenPIC regs */ + openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET; + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic1 = mpic_alloc(openpic_paddr, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250, + mpc86xx_hpcn_openpic_initsenses, + sizeof(mpc86xx_hpcn_openpic_initsenses), + " MPIC "); + BUG_ON(mpic1 == NULL); + + /* 48 Internal Interrupts */ + mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200); + mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400); + mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600); + + /* 16 External interrupts */ + mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL); + i8259_init(0, I8259_OFFSET); +#endif +} + + + +#ifdef CONFIG_PCI +/* + * interrupt routing + */ + +int +mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = { + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 17 -- PCI Slot 1 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 18 -- PCI Slot 2 */ + {0, 0, 0, 0}, /* IDSEL 19 */ + {0, 0, 0, 0}, /* IDSEL 20 */ + {0, 0, 0, 0}, /* IDSEL 21 */ + {0, 0, 0, 0}, /* IDSEL 22 */ + {0, 0, 0, 0}, /* IDSEL 23 */ + {0, 0, 0, 0}, /* IDSEL 24 */ + {0, 0, 0, 0}, /* IDSEL 25 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* IDSEL 26 -- PCI Bridge*/ + {PIRQC, 0, 0, 0}, /* IDSEL 27 -- LAN */ + {PIRQE, PIRQF, PIRQH, PIRQ7}, /* IDSEL 28 -- USB 1.1 */ + {PIRQE, PIRQF, PIRQG, 0}, /* IDSEL 29 -- Audio & Modem */ + {PIRQH, 0, 0, 0}, /* IDSEL 30 -- LPC & PMU*/ + {PIRQD, 0, 0, 0}, /* IDSEL 31 -- ATA */ + }; + + const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET; +} + + +int +mpc86xx_exclude_device(u_char bus, u_char devfn) +{ +#if !defined(CONFIG_PCI) + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; +#endif + + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + + +static void __init +mpc86xx_hpcn_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp; + + fp = (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc86xx_map_irq; + ppc_md.pci_exclude_device = mpc86xx_exclude_device; +#endif + + printk("MPC86xx HPCN board from Freescale Semiconductor\n"); + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif +} + + +void +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + uint memsize = total_memory; + const char *model = ""; + uint svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "Machine\t\t: %s\n", model); + of_node_put(root); + + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc86xx_hpcn_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "mpc86xx")) + return 1; /* Looks good */ + + return 0; +} + + +void +mpc86xx_restart(char *cmd) +{ + void __iomem *rstcr; + + rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100); + + local_irq_disable(); + + /* Assert reset request to Reset Control Register */ + out_be32(rstcr, 0x2); + + /* not reached */ +} + + +long __init +mpc86xx_time_init(void) +{ + unsigned int temp; + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + temp = mfspr(SPRN_HID0); + temp |= HID0_TBEN; + mtspr(SPRN_HID0, temp); + asm volatile("isync"); + + return 0; +} + + +define_machine(mpc86xx_hpcn) { + .name = "MPC86xx HPCN", + .probe = mpc86xx_hpcn_probe, + .setup_arch = mpc86xx_hpcn_setup_arch, + .init_IRQ = mpc86xx_hpcn_init_irq, + .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc86xx_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c new file mode 100644 index 000000000000..944ec4b71416 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -0,0 +1,117 @@ +/* + * Author: Xianghua Xiao + * Zhang Wei + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "mpc86xx.h" + +extern void __secondary_start_mpc86xx(void); +extern unsigned long __secondary_hold_acknowledge; + + +static void __init +smp_86xx_release_core(int nr) +{ + void *mcm_vaddr; + unsigned long vaddr, pcr; + + if (nr < 0 || nr >= NR_CPUS) + return; + + /* + * Startup Core #nr. + */ + mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, + MPC86xx_MCM_SIZE); + vaddr = (unsigned long)mcm_vaddr + MCM_PORT_CONFIG_OFFSET; + pcr = in_be32((volatile unsigned *)vaddr); + pcr |= 1 << (nr + 24); + out_be32((volatile unsigned *)vaddr, pcr); +} + + +static void __init +smp_86xx_kick_cpu(int nr) +{ + unsigned int save_vector; + unsigned long target, flags; + int n = 0; + volatile unsigned int *vector + = (volatile unsigned int *)(KERNELBASE + 0x100); + + if (nr < 0 || nr >= NR_CPUS) + return; + + pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector to call __secondary_start_mpc86xx. */ + target = (unsigned long) __secondary_start_mpc86xx; + create_branch((unsigned long)vector, target, BRANCH_SET_LINK); + + /* Kick that CPU */ + smp_86xx_release_core(nr); + + /* Wait a bit for the CPU to take the exception. */ + while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000)) + mdelay(1); + + /* Restore the exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + + pr_debug("wait CPU #%d for %d msecs.\n", nr, n); +} + + +static void __init +smp_86xx_setup_cpu(int cpu_nr) +{ + mpic_setup_this_cpu(); +} + + +struct smp_ops_t smp_86xx_ops = { + .message_pass = smp_mpic_message_pass, + .probe = smp_mpic_probe, + .kick_cpu = smp_86xx_kick_cpu, + .setup_cpu = smp_86xx_setup_cpu, + .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_generic_give_timebase, +}; + + +void __init +mpc86xx_smp_init(void) +{ + smp_ops = &smp_86xx_ops; +} -- cgit From b809b3e86f39651475b30ceb1caf535071534d4d Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Sat, 17 Jun 2006 17:52:48 -0500 Subject: [POWERPC] Add mpc8641hpcn PCI/PCI-Express platform files. Signed-off-by: Xianghua Xiao Signed-off-by: Wei Zhang Signed-off-by: Haiying Wang Signed-off-by: Jon Loeliger Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/86xx/mpc86xx_pcie.c | 173 +++++++++++++++ arch/powerpc/platforms/86xx/pci.c | 325 +++++++++++++++++++++++++++++ 2 files changed, 498 insertions(+) create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_pcie.c create mode 100644 arch/powerpc/platforms/86xx/pci.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c new file mode 100644 index 000000000000..a2f4f730213e --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c @@ -0,0 +1,173 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (C) 1998 Gabriel Paubert. + * + * 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. + * + * "Temporary" MPC8548 Errata file - + * The standard indirect_pci code should work with future silicon versions. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mpc86xx.h" + +#define PCI_CFG_OUT out_be32 + +/* ERRATA PCI-Ex 14 PCIE Controller timeout */ +#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + + +static int +indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PCIE_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PCIE_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PCIE_FIX; + out_le32(cfg_data, temp); + break; + default: + PCIE_FIX; + out_le32(cfg_data, val); + break; + } + PCIE_FIX; + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops indirect_pcie_ops = { + indirect_read_config_pcie, + indirect_write_config_pcie +}; + +void __init +setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, + void __iomem * cfg_data) +{ + hose->cfg_addr = cfg_addr; + hose->cfg_data = cfg_data; + hose->ops = &indirect_pcie_ops; +} + +void __init +setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + unsigned long base = cfg_addr & PAGE_MASK; + void __iomem *mbase, *addr, *data; + + mbase = ioremap(base, PAGE_SIZE); + addr = mbase + (cfg_addr & ~PAGE_MASK); + if ((cfg_data & PAGE_MASK) != base) + mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); + data = mbase + (cfg_data & ~PAGE_MASK); + setup_indirect_pcie_nomap(hose, addr, data); +} diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c new file mode 100644 index 000000000000..5180df7c75bc --- /dev/null +++ b/arch/powerpc/platforms/86xx/pci.c @@ -0,0 +1,325 @@ +/* + * MPC86XX pci setup code + * + * Recode: ZHANG WEI + * Initial author: Xianghua Xiao + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mpc86xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + +struct pcie_outbound_window_regs { + uint pexotar; /* 0x.0 - PCI Express outbound translation address register */ + uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */ + uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */ + char res1[4]; + uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */ + char res2[12]; +}; + +struct pcie_inbound_window_regs { + uint pexitar; /* 0x.0 - PCI Express inbound translation address register */ + char res1[4]; + uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */ + uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */ + uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */ + char res2[12]; +}; + +static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc) +{ + volatile struct ccsr_pex *pcie; + volatile struct pcie_outbound_window_regs *pcieow; + volatile struct pcie_inbound_window_regs *pcieiw; + int i = 0; + + DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start, + rsrc->end - rsrc->start + 1); + pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); + + /* Disable all windows (except pexowar0 since its ignored) */ + pcie->pexowar1 = 0; + pcie->pexowar2 = 0; + pcie->pexowar3 = 0; + pcie->pexowar4 = 0; + pcie->pexiwar1 = 0; + pcie->pexiwar2 = 0; + pcie->pexiwar3 = 0; + + pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1; + pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1; + + /* Setup outbound MEM window */ + for(i = 0; i < 3; i++) + if (hose->mem_resources[i].flags & IORESOURCE_MEM){ + DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n", + hose->mem_resources[i].start, + hose->mem_resources[i].end + - hose->mem_resources[i].start + 1); + pcieow->pexotar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + /* Enable, Mem R/W */ + pcieow->pexowar = 0x80044000 | + (__ilog2(hose->mem_resources[i].end + - hose->mem_resources[i].start + 1) + - 1); + pcieow++; + } + + /* Setup outbound IO window */ + if (hose->io_resource.flags & IORESOURCE_IO){ + DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n", + hose->io_resource.start, + hose->io_resource.end - hose->io_resource.start + 1, + hose->io_base_phys); + pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff; + /* Enable, IO R/W */ + pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end + - hose->io_resource.start + 1) - 1); + } + + /* Setup 2G inbound Memory Window @ 0 */ + pcieiw->pexitar = 0x00000000; + pcieiw->pexiwbar = 0x00000000; + /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */ + pcieiw->pexiwar = 0xa0f5501e; +} + +static void __init +mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) +{ + volatile struct ccsr_pex *pcie; + u16 cmd; + unsigned int temps; + + DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", + pcie_offset, pcie_size); + + pcie = ioremap(pcie_offset, pcie_size); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY + | PCI_COMMAND_IO; + early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ + early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); + temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); +} + +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int has_address = 0; + int primary = 0; + + DBG("Adding PCIE host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + /* last_busno = 0xfe cause by MPC8641 PCIE bug */ + hose->first_busno = bus_range ? bus_range[0] : 0x0; + hose->last_busno = bus_range ? bus_range[1] : 0xfe; + + setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); + + /* Setup the PCIE host controller. */ + mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); + + if ((rsrc.start & 0xfffff) == 0x8000) + primary = 1; + + printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + /* Setup PEX window registers */ + setup_pcie_atmu(hose, &rsrc); + + return 0; +} + +static void __devinit quirk_ali1575(struct pci_dev *dev) +{ + unsigned short temp; + + /* + * ALI1575 interrupts route table setup: + * + * IRQ pin IRQ# + * PIRQA ---- 3 + * PIRQB ---- 4 + * PIRQC ---- 5 + * PIRQD ---- 6 + * PIRQE ---- 9 + * PIRQF ---- 10 + * PIRQG ---- 11 + * PIRQH ---- 12 + * + * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD + * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA + */ + pci_write_config_dword(dev, 0x48, 0xb9317542); + + /* USB 1.1 OHCI controller 1, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x86, 0x0c); + + /* USB 1.1 OHCI controller 2, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x87, 0x0d); + + /* USB 1.1 OHCI controller 3, interrupt: PIRQH */ + pci_write_config_byte(dev, 0x88, 0x0f); + + /* USB 2.0 controller, interrupt: PIRQ7 */ + pci_write_config_byte(dev, 0x74, 0x06); + + /* Audio controller, interrupt: PIRQE */ + pci_write_config_byte(dev, 0x8a, 0x0c); + + /* Modem controller, interrupt: PIRQF */ + pci_write_config_byte(dev, 0x8b, 0x0d); + + /* HD audio controller, interrupt: PIRQG */ + pci_write_config_byte(dev, 0x8c, 0x0e); + + /* Serial ATA interrupt: PIRQD */ + pci_write_config_byte(dev, 0x8d, 0x0b); + + /* SMB interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8e, 0x0f); + + /* PMU ACPI SCI interrupt: PIRQH */ + pci_write_config_byte(dev, 0x8f, 0x0f); + + /* Primary PATA IDE IRQ: 14 + * Secondary PATA IDE IRQ: 15 + */ + pci_write_config_byte(dev, 0x44, 0x3d); + pci_write_config_byte(dev, 0x75, 0x0f); + + /* Set IRQ14 and IRQ15 to legacy IRQs */ + pci_read_config_word(dev, 0x46, &temp); + temp |= 0xc000; + pci_write_config_word(dev, 0x46, temp); + + /* Set i8259 interrupt trigger + * IRQ 3: Level + * IRQ 4: Level + * IRQ 5: Level + * IRQ 6: Level + * IRQ 7: Level + * IRQ 9: Level + * IRQ 10: Level + * IRQ 11: Level + * IRQ 12: Level + * IRQ 14: Edge + * IRQ 15: Edge + */ + outb(0xfa, 0x4d0); + outb(0x1e, 0x4d1); +} + +static void __devinit quirk_uli5288(struct pci_dev *dev) +{ + unsigned char c; + + pci_read_config_byte(dev,0x83,&c); + c |= 0x80; + pci_write_config_byte(dev, 0x83, c); + + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x0a, 0x06); + + pci_read_config_byte(dev,0x83,&c); + c &= 0x7f; + pci_write_config_byte(dev, 0x83, c); + + pci_read_config_byte(dev,0x84,&c); + c |= 0x01; + pci_write_config_byte(dev, 0x84, c); +} + +static void __devinit quirk_uli5229(struct pci_dev *dev) +{ + unsigned short temp; + pci_write_config_word(dev, 0x04, 0x0405); + pci_read_config_word(dev, 0x4a, &temp); + temp |= 0x1000; + pci_write_config_word(dev, 0x4a, temp); +} + +static void __devinit early_uli5249(struct pci_dev *dev) +{ + unsigned char temp; + pci_write_config_word(dev, 0x04, 0x0007); + pci_read_config_byte(dev, 0x7c, &temp); + pci_write_config_byte(dev, 0x7c, 0x80); + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x7c, temp); + dev->class |= 0x1; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); -- cgit From acf7d76827a577059636e949079021e6af6dd702 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 19 Jun 2006 20:33:16 +0200 Subject: [POWERPC] cell: add RAS support This is a first version of support for the Cell BE "Reliability, Availability and Serviceability" features. It doesn't yet handle some of the RAS interrupts (the ones described in iic_is/iic_irr), I'm still working on a proper way to expose these. They are essentially a cascaded controller by themselves (sic !) though I may just handle them locally to the iic driver. I need also to sync with David Erb on the way he hooked in the performance monitor interrupt. So that's all for 2.6.17 and I'll do more work on that with my rework of the powerpc interrupt layer that I'm hacking on at the moment. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Kconfig | 4 + arch/powerpc/platforms/cell/Makefile | 3 +- arch/powerpc/platforms/cell/cbe_regs.c | 128 +++++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/cbe_regs.h | 129 ++++++++++++++++++++++++++++++++ arch/powerpc/platforms/cell/interrupt.c | 37 +++------ arch/powerpc/platforms/cell/pervasive.c | 104 ++++++------------------- arch/powerpc/platforms/cell/pervasive.h | 37 +-------- arch/powerpc/platforms/cell/ras.c | 112 +++++++++++++++++++++++++++ arch/powerpc/platforms/cell/ras.h | 9 +++ arch/powerpc/platforms/cell/setup.c | 10 ++- 10 files changed, 427 insertions(+), 146 deletions(-) create mode 100644 arch/powerpc/platforms/cell/cbe_regs.c create mode 100644 arch/powerpc/platforms/cell/cbe_regs.h create mode 100644 arch/powerpc/platforms/cell/ras.c create mode 100644 arch/powerpc/platforms/cell/ras.h (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 6a02d51086c8..00b83db2ce73 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -16,4 +16,8 @@ config SPUFS_MMAP select MEMORY_HOTPLUG default y +config CBE_RAS + bool "RAS features for bare metal Cell BE" + default y + endmenu diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index e570bad06394..6b11f6adca08 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,5 +1,6 @@ obj-y += interrupt.o iommu.o setup.o spider-pic.o -obj-y += pervasive.o +obj-y += cbe_regs.o pervasive.o +obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c new file mode 100644 index 000000000000..2dfde61c8412 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -0,0 +1,128 @@ +/* + * cbe_regs.c + * + * Accessor routines for the various MMIO register blocks of the CBE + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + + +#include +#include +#include + +#include +#include +#include +#include + +#include "cbe_regs.h" + +#define MAX_CBE 2 + +/* + * Current implementation uses "cpu" nodes. We build our own mapping + * array of cpu numbers to cpu nodes locally for now to allow interrupt + * time code to have a fast path rather than call of_get_cpu_node(). If + * we implement cpu hotplug, we'll have to install an appropriate norifier + * in order to release references to the cpu going away + */ +static struct cbe_regs_map +{ + struct device_node *cpu_node; + struct cbe_pmd_regs __iomem *pmd_regs; + struct cbe_iic_regs __iomem *iic_regs; +} cbe_regs_maps[MAX_CBE]; +static int cbe_regs_map_count; + +static struct cbe_thread_map +{ + struct device_node *cpu_node; + struct cbe_regs_map *regs; +} cbe_thread_map[NR_CPUS]; + +static struct cbe_regs_map *cbe_find_map(struct device_node *np) +{ + int i; + + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np) + return &cbe_regs_maps[i]; + return NULL; +} + +struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->pmd_regs; +} + +struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->pmd_regs; +} + + +struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->iic_regs; +} +struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->iic_regs; +} + +void __init cbe_regs_init(void) +{ + int i; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_cpu(i) + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; + + /* That hack must die die die ! */ + struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *prop; + + + if (cbe_regs_map_count > MAX_CBE) { + printk(KERN_ERR "cbe_regs: More BE chips than supported" + "!\n"); + cbe_regs_map_count--; + return; + } + map->cpu_node = cpu; + for_each_cpu(i) + if (cbe_thread_map[i].cpu_node == cpu) + cbe_thread_map[i].regs = map; + + prop = (struct address_prop *)get_property(cpu, "pervasive", + NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = (struct address_prop *)get_property(cpu, "iic", + NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + } +} + diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h new file mode 100644 index 000000000000..e76e4a6af5bc --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -0,0 +1,129 @@ +/* + * cbe_regs.h + * + * This file is intended to hold the various register definitions for CBE + * on-chip system devices (memory controller, IO controller, etc...) + * + * (c) 2006 Benjamin Herrenschmidt , IBM Corp. + */ + +#ifndef CBE_REGS_H +#define CBE_REGS_H + +/* + * + * Some HID register definitions + * + */ + +/* CBE specific HID0 bits */ +#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul +#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul +#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul +#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul + + +/* + * + * Pervasive unit register definitions + * + */ + +struct cbe_pmd_regs { + u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ + + /* Thermal Sensor Registers */ + u64 ts_ctsr1; /* 0x0800 */ + u64 ts_ctsr2; /* 0x0808 */ + u64 ts_mtsr1; /* 0x0810 */ + u64 ts_mtsr2; /* 0x0818 */ + u64 ts_itr1; /* 0x0820 */ + u64 ts_itr2; /* 0x0828 */ + u64 ts_gitr; /* 0x0830 */ + u64 ts_isr; /* 0x0838 */ + u64 ts_imr; /* 0x0840 */ + u64 tm_cr1; /* 0x0848 */ + u64 tm_cr2; /* 0x0850 */ + u64 tm_simr; /* 0x0858 */ + u64 tm_tpr; /* 0x0860 */ + u64 tm_str1; /* 0x0868 */ + u64 tm_str2; /* 0x0870 */ + u64 tm_tsr; /* 0x0878 */ + + /* Power Management */ + u64 pm_control; /* 0x0880 */ +#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 + u64 pm_status; /* 0x0888 */ + + /* Time Base Register */ + u64 tbr; /* 0x0890 */ + + u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ + + /* Fault Isolation Registers */ + u64 checkstop_fir; /* 0x0c00 */ + u64 recoverable_fir; + u64 spec_att_mchk_fir; + u64 fir_mode_reg; + u64 fir_enable_mask; + + u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ +}; + +extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); +extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); + +/* + * + * IIC unit register definitions + * + */ + +struct cbe_iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +#define CBE_IIC_IRQ_VALID 0x80 +#define CBE_IIC_IRQ_IPI 0x40 + +struct cbe_iic_thread_regs { + struct cbe_iic_pending_bits pending; + struct cbe_iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct cbe_iic_regs { + u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ + + /* IIC interrupt registers */ + struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ + u64 iic_ir; /* 0x0440 */ + u64 iic_is; /* 0x0448 */ + + u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ + + /* IOC FIR */ + u64 ioc_fir_reset; /* 0x0500 */ + u64 ioc_fir_set; + u64 ioc_checkstop_enable; + u64 ioc_fir_error_mask; + u64 ioc_syserr_enable; + u64 ioc_fir; + + u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ +}; + +extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); +extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); + + +/* Init this module early */ +extern void cbe_regs_init(void); + + +#endif /* CBE_REGS_H */ diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 978be1c30c1b..0a707bcabef6 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -33,29 +33,10 @@ #include #include "interrupt.h" - -struct iic_pending_bits { - u32 data; - u8 flags; - u8 class; - u8 source; - u8 prio; -}; - -enum iic_pending_flags { - IIC_VALID = 0x80, - IIC_IPI = 0x40, -}; - -struct iic_regs { - struct iic_pending_bits pending; - struct iic_pending_bits pending_destr; - u64 generate; - u64 prio; -}; +#include "cbe_regs.h" struct iic { - struct iic_regs __iomem *regs; + struct cbe_iic_thread_regs __iomem *regs; u8 target_id; }; @@ -115,7 +96,7 @@ static struct hw_interrupt_type iic_pic = { .end = iic_end, }; -static int iic_external_get_irq(struct iic_pending_bits pending) +static int iic_external_get_irq(struct cbe_iic_pending_bits pending) { int irq; unsigned char node, unit; @@ -168,15 +149,15 @@ int iic_get_irq(struct pt_regs *regs) { struct iic *iic; int irq; - struct iic_pending_bits pending; + struct cbe_iic_pending_bits pending; iic = &__get_cpu_var(iic); *(unsigned long *) &pending = in_be64((unsigned long __iomem *) &iic->regs->pending_destr); irq = -1; - if (pending.flags & IIC_VALID) { - if (pending.flags & IIC_IPI) { + if (pending.flags & CBE_IIC_IRQ_VALID) { + if (pending.flags & CBE_IIC_IRQ_IPI) { irq = IIC_IPI_OFFSET + (pending.prio >> 4); /* if (irq > 0x80) @@ -226,7 +207,7 @@ static int setup_iic_hardcoded(void) regs += 0x20; printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); - iic->regs = ioremap(regs, sizeof(struct iic_regs)); + iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs)); iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); } @@ -267,12 +248,12 @@ static int setup_iic(void) } iic = &per_cpu(iic, np[0]); - iic->regs = ioremap(regs[0], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); iic = &per_cpu(iic, np[1]); - iic->regs = ioremap(regs[2], sizeof(struct iic_regs)); + iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs)); iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index 7eed8c624517..695ac4e1617e 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c @@ -37,36 +37,28 @@ #include #include "pervasive.h" +#include "cbe_regs.h" static DEFINE_SPINLOCK(cbe_pervasive_lock); -struct cbe_pervasive { - struct pmd_regs __iomem *regs; - unsigned int thread; -}; - -/* can't use per_cpu from setup_arch */ -static struct cbe_pervasive cbe_pervasive[NR_CPUS]; static void __init cbe_enable_pause_zero(void) { unsigned long thread_switch_control; unsigned long temp_register; - struct cbe_pervasive *p; - int thread; + struct cbe_pmd_regs __iomem *pregs; spin_lock_irq(&cbe_pervasive_lock); - p = &cbe_pervasive[smp_processor_id()]; - - if (!cbe_pervasive->regs) + pregs = cbe_get_cpu_pmd_regs(smp_processor_id()); + if (pregs == NULL) goto out; pr_debug("Power Management: CPU %d\n", smp_processor_id()); /* Enable Pause(0) control bit */ - temp_register = in_be64(&p->regs->pm_control); + temp_register = in_be64(&pregs->pm_control); - out_be64(&p->regs->pm_control, - temp_register|PMD_PAUSE_ZERO_CONTROL); + out_be64(&pregs->pm_control, + temp_register | CBE_PMD_PAUSE_ZERO_CONTROL); /* Enable DEC and EE interrupt request */ thread_switch_control = mfspr(SPRN_TSC_CELL); @@ -75,25 +67,16 @@ static void __init cbe_enable_pause_zero(void) switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) { case CTRL_CT0: thread_switch_control |= TSC_CELL_DEC_ENABLE_0; - thread = 0; break; case CTRL_CT1: thread_switch_control |= TSC_CELL_DEC_ENABLE_1; - thread = 1; break; default: printk(KERN_WARNING "%s: unknown configuration\n", __FUNCTION__); - thread = -1; break; } - if (p->thread != thread) - printk(KERN_WARNING "%s: device tree inconsistant, " - "cpu %i: %d/%d\n", __FUNCTION__, - smp_processor_id(), - p->thread, thread); - mtspr(SPRN_TSC_CELL, thread_switch_control); out: @@ -104,6 +87,11 @@ static void cbe_idle(void) { unsigned long ctrl; + /* Why do we do that on every idle ? Couldn't that be done once for + * all or do we lose the state some way ? Also, the pm_control + * register setting, that can't be set once at boot ? We really want + * to move that away in order to implement a simple powersave + */ cbe_enable_pause_zero(); while (1) { @@ -152,8 +140,15 @@ static int cbe_system_reset_exception(struct pt_regs *regs) timer_interrupt(regs); break; case SRR1_WAKEMT: - /* no action required */ break; +#ifdef CONFIG_CBE_RAS + case SRR1_WAKESYSERR: + cbe_system_error_exception(regs); + break; + case SRR1_WAKETHERM: + cbe_thermal_exception(regs); + break; +#endif /* CONFIG_CBE_RAS */ default: /* do system reset */ return 0; @@ -162,68 +157,11 @@ static int cbe_system_reset_exception(struct pt_regs *regs) return 1; } -static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p) -{ - struct device_node *node; - unsigned int *int_servers; - char *addr; - unsigned long real_address; - unsigned int size; - - struct pmd_regs __iomem *pmd_mmio_area; - int hardid, thread; - int proplen; - - pmd_mmio_area = NULL; - hardid = get_hard_smp_processor_id(cpu); - for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) { - int_servers = (void *) get_property(node, - "ibm,ppc-interrupt-server#s", &proplen); - if (!int_servers) { - printk(KERN_WARNING "%s misses " - "ibm,ppc-interrupt-server#s property", - node->full_name); - continue; - } - for (thread = 0; thread < proplen / sizeof (int); thread++) { - if (hardid == int_servers[thread]) { - addr = get_property(node, "pervasive", NULL); - goto found; - } - } - } - - printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu); - return -EINVAL; - -found: - real_address = *(unsigned long*) addr; - addr += sizeof (unsigned long); - size = *(unsigned int*) addr; - - pr_debug("pervasive area for CPU %d at %lx, size %x\n", - cpu, real_address, size); - p->regs = ioremap(real_address, size); - p->thread = thread; - return 0; -} - -void __init cell_pervasive_init(void) +void __init cbe_pervasive_init(void) { - struct cbe_pervasive *p; - int cpu; - int ret; - if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) return; - for_each_possible_cpu(cpu) { - p = &cbe_pervasive[cpu]; - ret = cbe_find_pmd_mmio(cpu, p); - if (ret) - return; - } - ppc_md.idle_loop = cbe_idle; ppc_md.system_reset_exception = cbe_system_reset_exception; } diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h index da1fb85ca3e8..7b50947f8044 100644 --- a/arch/powerpc/platforms/cell/pervasive.h +++ b/arch/powerpc/platforms/cell/pervasive.h @@ -25,38 +25,9 @@ #ifndef PERVASIVE_H #define PERVASIVE_H -struct pmd_regs { - u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ - - /* Thermal Sensor Registers */ - u64 ts_ctsr1; /* 0x0800 */ - u64 ts_ctsr2; /* 0x0808 */ - u64 ts_mtsr1; /* 0x0810 */ - u64 ts_mtsr2; /* 0x0818 */ - u64 ts_itr1; /* 0x0820 */ - u64 ts_itr2; /* 0x0828 */ - u64 ts_gitr; /* 0x0830 */ - u64 ts_isr; /* 0x0838 */ - u64 ts_imr; /* 0x0840 */ - u64 tm_cr1; /* 0x0848 */ - u64 tm_cr2; /* 0x0850 */ - u64 tm_simr; /* 0x0858 */ - u64 tm_tpr; /* 0x0860 */ - u64 tm_str1; /* 0x0868 */ - u64 tm_str2; /* 0x0870 */ - u64 tm_tsr; /* 0x0878 */ - - /* Power Management */ - u64 pm_control; /* 0x0880 */ -#define PMD_PAUSE_ZERO_CONTROL 0x10000 - u64 pm_status; /* 0x0888 */ - - /* Time Base Register */ - u64 tbr; /* 0x0890 */ - - u8 pad_0x0898_0x1000 [0x1000 - 0x0898]; /* 0x0898 */ -}; - -void __init cell_pervasive_init(void); +extern void cbe_pervasive_init(void); +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); #endif diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c new file mode 100644 index 000000000000..033ad6e2827b --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.c @@ -0,0 +1,112 @@ +#define DEBUG + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ras.h" +#include "cbe_regs.h" + + +static void dump_fir(int cpu) +{ + struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu); + struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu); + + if (pregs == NULL) + return; + + /* Todo: do some nicer parsing of bits and based on them go down + * to other sub-units FIRs and not only IIC + */ + printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n", + in_be64(&pregs->spec_att_mchk_fir)); + + if (iregs == NULL) + return; + printk(KERN_ERR "IOC FIR : 0x%016lx\n", + in_be64(&iregs->ioc_fir)); + +} + +void cbe_system_error_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + dump_stack(); +} + +void cbe_maintenance_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the maintenance interrupt at this point + */ + + printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +void cbe_thermal_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the thermal interrupt at this point + */ + + printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +static int cbe_machine_check_handler(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + + /* No recovery from this code now, lets continue */ + return 0; +} + +void __init cbe_ras_init(void) +{ + unsigned long hid0; + + /* + * Enable System Error & thermal interrupts and wakeup conditions + */ + + hid0 = mfspr(SPRN_HID0); + hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP | + HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP; + mtspr(SPRN_HID0, hid0); + mb(); + + /* + * Install machine check handler. Leave setting of precise mode to + * what the firmware did for now + */ + ppc_md.machine_check_exception = cbe_machine_check_handler; + mb(); + + /* + * For now, we assume that IOC_FIR is already set to forward some + * error conditions to the System Error handler. If that is not true + * then it will have to be fixed up here. + */ +} diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h new file mode 100644 index 000000000000..eb7ee54c82a0 --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.h @@ -0,0 +1,9 @@ +#ifndef RAS_H +#define RAS_H + +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); +extern void cbe_ras_init(void); + +#endif /* RAS_H */ diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index fd3e5609e3e0..eb8ab9bbf744 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -52,7 +52,9 @@ #include "interrupt.h" #include "iommu.h" +#include "cbe_regs.h" #include "pervasive.h" +#include "ras.h" #ifdef DEBUG #define DBG(fmt...) udbg_printf(fmt) @@ -82,6 +84,12 @@ static void __init cell_setup_arch(void) ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; + cbe_regs_init(); + +#ifdef CONFIG_CBE_RAS + cbe_ras_init(); +#endif + #ifdef CONFIG_SMP smp_init_cell(); #endif @@ -98,7 +106,7 @@ static void __init cell_setup_arch(void) init_pci_config_tokens(); find_and_init_phbs(); spider_init_IRQ(); - cell_pervasive_init(); + cbe_pervasive_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif -- cgit From b40feec8efbe609a3a38bca1f18d3ba4d590563a Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:17 +0200 Subject: [POWERPC] cell: fix interrupt priority handling Checking the priority field to test for irq validity is completely bogus and breaks with future external interrupt controllers. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/interrupt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 0a707bcabef6..f4e2d8805c9e 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c @@ -117,8 +117,7 @@ static int iic_external_get_irq(struct cbe_iic_pending_bits pending) * One of these units can be connected * to an external interrupt controller. */ - if (pending.prio > 0x3f || - pending.class != 2) + if (pending.class != 2) break; irq = IIC_EXT_OFFSET + spider_get_irq(node) -- cgit From 1d64093f6627a7eef1ed0fe005463f0a5ea25a5f Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 19 Jun 2006 20:33:19 +0200 Subject: [POWERPC] cell: register SPUs as sysdevs SPUs are registered as system devices, exposing attributes through sysfs. Since the sysdev includes a kref, we can remove the one in struct spu (it isn't used at the moment anyway). Currently only the interrupt source and numa node attributes are added. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index ad141fe8d52d..d5877aacc3b6 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -649,6 +649,46 @@ out: return ret; } +struct sysdev_class spu_sysdev_class = { + set_kset_name("spu") +}; + +static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf) +{ + struct spu *spu = container_of(sysdev, struct spu, sysdev); + return sprintf(buf, "%d\n", spu->isrc); + +} +static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL); + +extern int attach_sysdev_to_node(struct sys_device *dev, int nid); + +static int spu_create_sysdev(struct spu *spu) +{ + int ret; + + spu->sysdev.id = spu->number; + spu->sysdev.cls = &spu_sysdev_class; + ret = sysdev_register(&spu->sysdev); + if (ret) { + printk(KERN_ERR "Can't register SPU %d with sysfs\n", + spu->number); + return ret; + } + + sysdev_create_file(&spu->sysdev, &attr_isrc); + sysfs_add_device_to_node(&spu->sysdev, spu->nid); + + return 0; +} + +static void spu_destroy_sysdev(struct spu *spu) +{ + sysdev_remove_file(&spu->sysdev, &attr_isrc); + sysfs_remove_device_from_node(&spu->sysdev, spu->nid); + sysdev_unregister(&spu->sysdev); +} + static int __init create_spu(struct device_node *spe) { struct spu *spu; @@ -695,6 +735,10 @@ static int __init create_spu(struct device_node *spe) if (ret) goto out_unmap; + ret = spu_create_sysdev(spu); + if (ret) + goto out_free_irqs; + list_add(&spu->list, &spu_list); mutex_unlock(&spu_mutex); @@ -703,6 +747,9 @@ static int __init create_spu(struct device_node *spe) spu->problem, spu->priv1, spu->priv2, spu->number); goto out; +out_free_irqs: + spu_free_irqs(spu); + out_unmap: mutex_unlock(&spu_mutex); spu_unmap(spu); @@ -716,6 +763,7 @@ static void destroy_spu(struct spu *spu) { list_del_init(&spu->list); + spu_destroy_sysdev(spu); spu_free_irqs(spu); spu_unmap(spu); kfree(spu); @@ -728,6 +776,7 @@ static void cleanup_spu_base(void) list_for_each_entry_safe(spu, tmp, &spu_list, list) destroy_spu(spu); mutex_unlock(&spu_mutex); + sysdev_class_unregister(&spu_sysdev_class); } module_exit(cleanup_spu_base); @@ -736,6 +785,11 @@ static int __init init_spu_base(void) struct device_node *node; int ret; + /* create sysdev class for spus */ + ret = sysdev_class_register(&spu_sysdev_class); + if (ret) + return ret; + ret = -ENODEV; for (node = of_find_node_by_type(NULL, "spe"); node; node = of_find_node_by_type(node, "spe")) { -- cgit From 91edfa49b97f0b0fafac5c8d5f171fc183782ce6 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:20 +0200 Subject: [POWERPC] cell: always build spu base into the kernel The spu_base module is rather deeply intermixed with the core kernel, so it makes sense to have that built-in. This will let us extend the base in the future without having to export more core symbols just for it. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Makefile | 6 +----- arch/powerpc/platforms/cell/spufs/Makefile | 4 +++- arch/powerpc/platforms/cell/spufs/switch.c | 4 ++++ 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 6b11f6adca08..bfaf40024634 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -3,15 +3,11 @@ obj-y += cbe_regs.o pervasive.o obj-$(CONFIG_CBE_RAS) += ras.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ - -spu-base-y += spu_base.o spu_priv1.o # needed only when building loadable spufs.ko spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o obj-y += $(spufs-modular-m) # always needed in kernel -spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o +spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o spu_base.o spu_priv1.o spufs/ obj-y += $(spufs-builtin-y) $(spufs-builtin-m) - diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index a7cddf40e3d9..7963d520b67b 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,5 +1,7 @@ +obj-y += switch.o + obj-$(CONFIG_SPU_FS) += spufs.o -spufs-y += inode.o file.o context.o switch.o syscalls.o +spufs-y += inode.o file.o context.o syscalls.o spufs-y += sched.o backing_ops.o hw_ops.o run.o # Rules to build switch.o with the help of SPU tool chain diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 1726bfe38ee0..60f8b3616441 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2074,6 +2074,7 @@ int spu_save(struct spu_state *prev, struct spu *spu) } return rc; } +EXPORT_SYMBOL_GPL(spu_save); /** * spu_restore - SPU context restore, with harvest and locking. @@ -2103,6 +2104,7 @@ int spu_restore(struct spu_state *new, struct spu *spu) } return rc; } +EXPORT_SYMBOL_GPL(spu_restore); /** * spu_harvest - SPU harvest (reset) operation @@ -2193,6 +2195,7 @@ void spu_init_csa(struct spu_state *csa) init_priv1(csa); init_priv2(csa); } +EXPORT_SYMBOL_GPL(spu_init_csa); void spu_fini_csa(struct spu_state *csa) { @@ -2203,3 +2206,4 @@ void spu_fini_csa(struct spu_state *csa) vfree(csa->lscsa); } +EXPORT_SYMBOL_GPL(spu_fini_csa); -- cgit From d9379c4bcee7046182edf45eeab349334421416e Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:21 +0200 Subject: [POWERPC] spufs: restore mapping of mssync register A recent change to the way that the mfc file gets mapped made it impossible to map the SPE Multi-Source Synchronization register into user space, but that may be needed by some applications. This restores the missing functionality. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 366185e92667..3bc00913fe18 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -824,6 +824,55 @@ static u64 spufs_signal2_type_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, spufs_signal2_type_set, "%llu"); +#ifdef CONFIG_SPUFS_MMAP +static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma, + unsigned long address, int *type) +{ + return spufs_ps_nopage(vma, address, type, 0x0000); +} + +static struct vm_operations_struct spufs_mss_mmap_vmops = { + .nopage = spufs_mss_mmap_nopage, +}; + +/* + * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. + * Mapping this area requires that the application have CAP_SYS_RAWIO, + * as these registers require special care when read/writing. + */ +static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma) +{ + if (!(vma->vm_flags & VM_SHARED)) + return -EINVAL; + + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + vma->vm_flags |= VM_RESERVED; + vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) + | _PAGE_NO_CACHE); + + vma->vm_ops = &spufs_mss_mmap_vmops; + return 0; +} +#endif + +static int spufs_mss_open(struct inode *inode, struct file *file) +{ + struct spufs_inode_info *i = SPUFS_I(inode); + + file->private_data = i->i_ctx; + return nonseekable_open(inode, file); +} + +static struct file_operations spufs_mss_fops = { + .open = spufs_mss_open, +#ifdef CONFIG_SPUFS_MMAP + .mmap = spufs_mss_mmap, +#endif +}; + + #ifdef CONFIG_SPUFS_MMAP static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, unsigned long address, int *type) @@ -1292,6 +1341,7 @@ struct tree_descr spufs_dir_contents[] = { { "signal2", &spufs_signal2_fops, 0666, }, { "signal1_type", &spufs_signal1_type, 0666, }, { "signal2_type", &spufs_signal2_type, 0666, }, + { "mss", &spufs_mss_fops, 0666, }, { "mfc", &spufs_mfc_fops, 0666, }, { "cntl", &spufs_cntl_fops, 0666, }, { "npc", &spufs_npc_ops, 0666, }, -- cgit From 0309f02d8e1b68811e513bdd06015672d0696af5 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 19 Jun 2006 20:33:22 +0200 Subject: [POWERPC] spufs: fix deadlock in spu_create error path spufs_rmdir tries to acquire the spufs root i_mutex, which is already held by spufs_create_thread. This was tracked as Bug #H9512. Signed-off-by: Michael Ellerman Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/inode.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index d9554199afa7..fed511a2b17f 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -157,20 +157,12 @@ static void spufs_prune_dir(struct dentry *dir) mutex_unlock(&dir->d_inode->i_mutex); } +/* Caller must hold root->i_mutex */ static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry) { - struct spu_context *ctx; - /* remove all entries */ - mutex_lock(&root->i_mutex); spufs_prune_dir(dir_dentry); - mutex_unlock(&root->i_mutex); - /* We have to give up the mm_struct */ - ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx; - spu_forget(ctx); - - /* XXX Do we need to hold i_mutex here ? */ return simple_rmdir(root, dir_dentry); } @@ -199,16 +191,23 @@ out: static int spufs_dir_close(struct inode *inode, struct file *file) { + struct spu_context *ctx; struct inode *dir; struct dentry *dentry; int ret; dentry = file->f_dentry; dir = dentry->d_parent->d_inode; + ctx = SPUFS_I(dentry->d_inode)->i_ctx; + mutex_lock(&dir->i_mutex); ret = spufs_rmdir(dir, dentry); + mutex_unlock(&dir->i_mutex); WARN_ON(ret); + /* We have to give up the mm_struct */ + spu_forget(ctx); + return dcache_dir_close(inode, file); } @@ -324,8 +323,13 @@ long spufs_create_thread(struct nameidata *nd, * in error path of *_open(). */ ret = spufs_context_open(dget(dentry), mntget(nd->mnt)); - if (ret < 0) - spufs_rmdir(nd->dentry->d_inode, dentry); + if (ret < 0) { + WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry)); + mutex_unlock(&nd->dentry->d_inode->i_mutex); + spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); + dput(dentry); + goto out; + } out_dput: dput(dentry); -- cgit From 724bd80e8102ac137868b23fad2b06af65f8e168 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:23 +0200 Subject: [POWERPC] spufs: set up correct SLB entries for 64k pages spufs currently knows only 4k pages and 16M hugetlb pages. Make it use the regular methods for deciding on the SLB bits. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 11 ++++++++--- arch/powerpc/platforms/cell/spufs/switch.c | 14 ++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d5877aacc3b6..fd6ea571dbd3 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -71,7 +71,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) { struct spu_priv2 __iomem *priv2 = spu->priv2; struct mm_struct *mm = spu->mm; - u64 esid, vsid; + u64 esid, vsid, llp; pr_debug("%s\n", __FUNCTION__); @@ -91,9 +91,14 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) } esid = (ea & ESID_MASK) | SLB_ESID_V; - vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER; +#ifdef CONFIG_HUGETLB_PAGE if (in_hugepage_area(mm->context, ea)) - vsid |= SLB_VSID_L; + llp = mmu_psize_defs[mmu_huge_psize].sllp; + else +#endif + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | + SLB_VSID_USER | llp; out_be64(&priv2->slb_index_W, spu->slb_replace); out_be64(&priv2->slb_vsid_RW, vsid); diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 60f8b3616441..97a0e80c7df8 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -718,13 +718,15 @@ static inline void invalidate_slbs(struct spu_state *csa, struct spu *spu) static inline void get_kernel_slb(u64 ea, u64 slb[2]) { - slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL; + u64 llp; + + if (REGION_ID(ea) == KERNEL_REGION_ID) + llp = mmu_psize_defs[mmu_linear_psize].sllp; + else + llp = mmu_psize_defs[mmu_virtual_psize].sllp; + slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | + SLB_VSID_KERNEL | llp; slb[1] = (ea & ESID_MASK) | SLB_ESID_V; - - /* Large pages are used for kernel text/data, but not vmalloc. */ - if (cpu_has_feature(CPU_FTR_16M_PAGE) - && REGION_ID(ea) == KERNEL_REGION_ID) - slb[0] |= SLB_VSID_L; } static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe) -- cgit From 7b1a701480fb17b7f78b95b257bfc90a4f949d04 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:24 +0200 Subject: [POWERPC] spufs: add a phys-id attribute to each SPU context For performance analysis, it is often interesting to know which physical SPE a thread is currently running on, and, more importantly, if it is running at all. This patch adds a simple attribute to each SPU directory with that information. The attribute is read-only and called 'phys-id'. It contains an ascii string with the number of the physical SPU (e.g. "0x5"), or alternatively the string "0xffffffff" (32 bit -1) when it is not running at all at the time that the file is read. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 3bc00913fe18..80c02660e617 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -1328,6 +1328,22 @@ static u64 spufs_srr0_get(void *data) DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set, "%llx\n") +static u64 spufs_id_get(void *data) +{ + struct spu_context *ctx = data; + u64 num; + + spu_acquire(ctx); + if (ctx->state == SPU_STATE_RUNNABLE) + num = ctx->spu->number; + else + num = (unsigned int)-1; + spu_release(ctx); + + return num; +} +DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n") + struct tree_descr spufs_dir_contents[] = { { "mem", &spufs_mem_fops, 0666, }, { "regs", &spufs_regs_fops, 0666, }, @@ -1351,5 +1367,6 @@ struct tree_descr spufs_dir_contents[] = { { "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, }, { "event_mask", &spufs_event_mask_ops, 0666, }, { "srr0", &spufs_srr0_ops, 0666, }, + { "phys-id", &spufs_id_ops, 0666, }, {}, }; -- cgit From 970f1baae78ff99b7536464214d4c78dde4551e2 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:25 +0200 Subject: [POWERPC] spufs: fix initial state of wbox file The wbox channel count of an spu is now initialized to four for the saved context. This makes it possible to write to the mailbox right away without waiting for the SPE to become scheduled first. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/switch.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 97a0e80c7df8..4210ec2cb4ca 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2129,6 +2129,7 @@ static void init_prob(struct spu_state *csa) csa->spu_chnlcnt_RW[28] = 1; csa->spu_chnlcnt_RW[30] = 1; csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP; + csa->prob.mb_stat_R = 0x000400; } static void init_priv1(struct spu_state *csa) -- cgit From ecec21770d87a5035cfd210cfdb22e1935b0c4a6 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Mon, 19 Jun 2006 20:33:26 +0200 Subject: [POWERPC] spufs: use kzalloc in create_spu Clean up create_spu() a little by using kzalloc instead of kmalloc + assignments. Signed-off-by: Jeremy Kerr Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index fd6ea571dbd3..eb367dd89a7d 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -701,7 +701,7 @@ static int __init create_spu(struct device_node *spe) static int number; ret = -ENOMEM; - spu = kmalloc(sizeof (*spu), GFP_KERNEL); + spu = kzalloc(sizeof (*spu), GFP_KERNEL); if (!spu) goto out; @@ -713,28 +713,11 @@ static int __init create_spu(struct device_node *spe) spu->nid = of_node_to_nid(spe); if (spu->nid == -1) spu->nid = 0; - - spu->stop_code = 0; - spu->slb_replace = 0; - spu->mm = NULL; - spu->ctx = NULL; - spu->rq = NULL; - spu->pid = 0; - spu->class_0_pending = 0; - spu->flags = 0UL; - spu->dar = 0UL; - spu->dsisr = 0UL; spin_lock_init(&spu->register_lock); - spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1)); spu_mfc_sr1_set(spu, 0x33); - - spu->ibox_callback = NULL; - spu->wbox_callback = NULL; - spu->stop_callback = NULL; - spu->mfc_callback = NULL; - mutex_lock(&spu_mutex); + spu->number = number++; ret = spu_request_irqs(spu); if (ret) -- cgit From e46a0237fda640f02bc4cb3d9702b6ee91bfd6e4 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:27 +0200 Subject: [POWERPC] spufs: dont try to access SPE channel 1 count The save/restore sequence for SPE contexts currently attempts to save and restore the channel count for SPE channel 1 (the SPU_WriteEventMask channel. But the CBE architecture (section 9.11.2) clearly states that this channel does not have an associated count. Hardware simply ignores the attempt to write this count, but the simulator generates a warning message. WARNING: 279721590: SPE7: Attempt to write channel count for CH 1 with no associated count is ignored. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/switch.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 4210ec2cb4ca..85bea06e798b 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -622,12 +622,17 @@ static inline void save_ppuint_mb(struct spu_state *csa, struct spu *spu) static inline void save_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Save, Step 42: - * Save the following CH: [0,1,3,4,24,25,27] */ + + /* Save CH 1, without channel count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW); + + /* Save the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -1105,13 +1110,18 @@ static inline void clear_spu_status(struct spu_state *csa, struct spu *spu) static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; u64 idx; int i; /* Restore, Step 20: - * Reset the following CH: [0,1,3,4,24,25,27] */ + + /* Reset CH 1 */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, 0UL); + + /* Reset the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); @@ -1572,12 +1582,17 @@ static inline void restore_decr_wrapped(struct spu_state *csa, struct spu *spu) static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu) { struct spu_priv2 __iomem *priv2 = spu->priv2; - u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL }; + u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL }; int i; /* Restore, Step 59: - * Restore the following CH: [0,1,3,4,24,25,27] */ + + /* Restore CH 1 without count */ + out_be64(&priv2->spu_chnlcntptr_RW, 1); + out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]); + + /* Restore the following CH: [0,3,4,24,25,27] */ for (i = 0; i < 7; i++) { idx = ch_indices[i]; out_be64(&priv2->spu_chnlcntptr_RW, idx); -- cgit From c01ea72a3b8abb7baa4291a1876b82599867035a Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:28 +0200 Subject: [POWERPC] spufs: split the Cell BE support into generic and platform dependant parts Creates new config variables PPC_CELL_NATIVE and PPC_IBM_CELL_BLADE. The existing CONFIG_PPC_CELL is now used to denote the generic Cell processor support. PPC_CELL = make descends into platforms/cell PPC_CELL_NATIVE = add bare metal support PPC_IBM_CELL_BLADE = add blade device drivers, etc. Also renames spu_priv1.c to spu_priv1_mmio.c. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/Kconfig | 5 + arch/powerpc/platforms/cell/Makefile | 20 ++-- arch/powerpc/platforms/cell/spu_priv1.c | 133 --------------------------- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 133 +++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 142 deletions(-) delete mode 100644 arch/powerpc/platforms/cell/spu_priv1.c create mode 100644 arch/powerpc/platforms/cell/spu_priv1_mmio.c (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 00b83db2ce73..352bbbacde9a 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig @@ -5,11 +5,16 @@ config SPU_FS tristate "SPU file system" default m depends on PPC_CELL + select SPU_BASE help The SPU file system is used to access Synergistic Processing Units on machines implementing the Broadband Processor Architecture. +config SPU_BASE + bool + default n + config SPUFS_MMAP bool depends on SPU_FS && SPARSEMEM diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index bfaf40024634..c89cdd67383b 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile @@ -1,13 +1,15 @@ -obj-y += interrupt.o iommu.o setup.o spider-pic.o -obj-y += cbe_regs.o pervasive.o -obj-$(CONFIG_CBE_RAS) += ras.o +obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ + cbe_regs.o spider-pic.o pervasive.o +obj-$(CONFIG_CBE_RAS) += ras.o -obj-$(CONFIG_SMP) += smp.o +ifeq ($(CONFIG_SMP),y) +obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o +endif # needed only when building loadable spufs.ko -spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o -obj-y += $(spufs-modular-m) +spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o +spu-priv1-$(CONFIG_PPC_CELL_NATIVE) += spu_priv1_mmio.o -# always needed in kernel -spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o spu_base.o spu_priv1.o spufs/ -obj-y += $(spufs-builtin-y) $(spufs-builtin-m) +obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \ + $(spufs-modular-m) \ + $(spu-priv1-y) spufs/ diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c deleted file mode 100644 index b2656421c7b5..000000000000 --- a/arch/powerpc/platforms/cell/spu_priv1.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * access to SPU privileged registers - */ -#include - -#include -#include - -void spu_int_mask_and(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_and); - -void spu_int_mask_or(struct spu *spu, int class, u64 mask) -{ - u64 old_mask; - - old_mask = in_be64(&spu->priv1->int_mask_RW[class]); - out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_or); - -void spu_int_mask_set(struct spu *spu, int class, u64 mask) -{ - out_be64(&spu->priv1->int_mask_RW[class], mask); -} -EXPORT_SYMBOL_GPL(spu_int_mask_set); - -u64 spu_int_mask_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_mask_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_mask_get); - -void spu_int_stat_clear(struct spu *spu, int class, u64 stat) -{ - out_be64(&spu->priv1->int_stat_RW[class], stat); -} -EXPORT_SYMBOL_GPL(spu_int_stat_clear); - -u64 spu_int_stat_get(struct spu *spu, int class) -{ - return in_be64(&spu->priv1->int_stat_RW[class]); -} -EXPORT_SYMBOL_GPL(spu_int_stat_get); - -void spu_int_route_set(struct spu *spu, u64 route) -{ - out_be64(&spu->priv1->int_route_RW, route); -} -EXPORT_SYMBOL_GPL(spu_int_route_set); - -u64 spu_mfc_dar_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dar_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dar_get); - -u64 spu_mfc_dsisr_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_dsisr_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); - -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) -{ - out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); -} -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); - -void spu_mfc_sdr_set(struct spu *spu, u64 sdr) -{ - out_be64(&spu->priv1->mfc_sdr_RW, sdr); -} -EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); - -void spu_mfc_sr1_set(struct spu *spu, u64 sr1) -{ - out_be64(&spu->priv1->mfc_sr1_RW, sr1); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); - -u64 spu_mfc_sr1_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_sr1_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); - -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) -{ - out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); - -u64 spu_mfc_tclass_id_get(struct spu *spu) -{ - return in_be64(&spu->priv1->mfc_tclass_id_RW); -} -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); - -void spu_tlb_invalidate(struct spu *spu) -{ - out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); -} -EXPORT_SYMBOL_GPL(spu_tlb_invalidate); - -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) -{ - out_be64(&spu->priv1->resource_allocation_groupID_RW, id); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); - -u64 spu_resource_allocation_groupID_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_groupID_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); - -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) -{ - out_be64(&spu->priv1->resource_allocation_enable_RW, enable); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); - -u64 spu_resource_allocation_enable_get(struct spu *spu) -{ - return in_be64(&spu->priv1->resource_allocation_enable_RW); -} -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c new file mode 100644 index 000000000000..b2656421c7b5 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -0,0 +1,133 @@ +/* + * access to SPU privileged registers + */ +#include + +#include +#include + +void spu_int_mask_and(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_and); + +void spu_int_mask_or(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_or); + +void spu_int_mask_set(struct spu *spu, int class, u64 mask) +{ + out_be64(&spu->priv1->int_mask_RW[class], mask); +} +EXPORT_SYMBOL_GPL(spu_int_mask_set); + +u64 spu_int_mask_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_mask_RW[class]); +} +EXPORT_SYMBOL_GPL(spu_int_mask_get); + +void spu_int_stat_clear(struct spu *spu, int class, u64 stat) +{ + out_be64(&spu->priv1->int_stat_RW[class], stat); +} +EXPORT_SYMBOL_GPL(spu_int_stat_clear); + +u64 spu_int_stat_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_stat_RW[class]); +} +EXPORT_SYMBOL_GPL(spu_int_stat_get); + +void spu_int_route_set(struct spu *spu, u64 route) +{ + out_be64(&spu->priv1->int_route_RW, route); +} +EXPORT_SYMBOL_GPL(spu_int_route_set); + +u64 spu_mfc_dar_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dar_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_dar_get); + +u64 spu_mfc_dsisr_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dsisr_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); + +void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) +{ + out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); +} +EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); + +void spu_mfc_sdr_set(struct spu *spu, u64 sdr) +{ + out_be64(&spu->priv1->mfc_sdr_RW, sdr); +} +EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); + +void spu_mfc_sr1_set(struct spu *spu, u64 sr1) +{ + out_be64(&spu->priv1->mfc_sr1_RW, sr1); +} +EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); + +u64 spu_mfc_sr1_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_sr1_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); + +void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +{ + out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); +} +EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); + +u64 spu_mfc_tclass_id_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_tclass_id_RW); +} +EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); + +void spu_tlb_invalidate(struct spu *spu) +{ + out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); +} +EXPORT_SYMBOL_GPL(spu_tlb_invalidate); + +void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) +{ + out_be64(&spu->priv1->resource_allocation_groupID_RW, id); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); + +u64 spu_resource_allocation_groupID_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_groupID_RW); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); + +void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) +{ + out_be64(&spu->priv1->resource_allocation_enable_RW, enable); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); + +u64 spu_resource_allocation_enable_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_enable_RW); +} +EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); -- cgit From 540270d82db943855538cea5d0c790e7e669dda0 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:29 +0200 Subject: [POWERPC] spufs: further abstract priv1 register access To support muti-platform binaries the spu hypervisor accessor routines must have runtime binding. I removed the existing statically linked routines in spu.h and spu_priv1_mmio.c and created new accessor routines in spu_priv1.h that operate indirectly through an ops struct spu_priv1_ops. spu_priv1_mmio.c contains the instance of the accessor routines for running on raw hardware. Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/setup.c | 4 ++ arch/powerpc/platforms/cell/spu_base.c | 5 ++ arch/powerpc/platforms/cell/spu_priv1_mmio.c | 104 ++++++++++++++++----------- arch/powerpc/platforms/cell/spufs/hw_ops.c | 1 + arch/powerpc/platforms/cell/spufs/switch.c | 1 + 5 files changed, 74 insertions(+), 41 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index eb8ab9bbf744..3d1831d331e5 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -49,6 +49,7 @@ #include #include #include +#include #include "interrupt.h" #include "iommu.h" @@ -83,6 +84,9 @@ static void __init cell_setup_arch(void) { ppc_md.init_IRQ = iic_init_IRQ; ppc_md.get_irq = iic_get_irq; +#ifdef CONFIG_SPU_BASE + spu_priv1_ops = &spu_priv1_mmio_ops; +#endif cbe_regs_init(); diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index eb367dd89a7d..c3bb7299c4b5 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -34,10 +34,15 @@ #include #include #include +#include #include #include "interrupt.h" +const struct spu_priv1_ops *spu_priv1_ops; + +EXPORT_SYMBOL_GPL(spu_priv1_ops); + static int __spu_trap_invalid_dma(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index b2656421c7b5..abe8a84925d2 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -1,133 +1,155 @@ /* - * access to SPU privileged registers + * spu hypervisor abstraction for direct hardware access. + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * Copyright 2006 Sony Corp. + * + * 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; version 2 of the License. + * + * 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 #include #include +#include -void spu_int_mask_and(struct spu *spu, int class, u64 mask) +static void int_mask_and(struct spu *spu, int class, u64 mask) { u64 old_mask; old_mask = in_be64(&spu->priv1->int_mask_RW[class]); out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_and); -void spu_int_mask_or(struct spu *spu, int class, u64 mask) +static void int_mask_or(struct spu *spu, int class, u64 mask) { u64 old_mask; old_mask = in_be64(&spu->priv1->int_mask_RW[class]); out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_or); -void spu_int_mask_set(struct spu *spu, int class, u64 mask) +static void int_mask_set(struct spu *spu, int class, u64 mask) { out_be64(&spu->priv1->int_mask_RW[class], mask); } -EXPORT_SYMBOL_GPL(spu_int_mask_set); -u64 spu_int_mask_get(struct spu *spu, int class) +static u64 int_mask_get(struct spu *spu, int class) { return in_be64(&spu->priv1->int_mask_RW[class]); } -EXPORT_SYMBOL_GPL(spu_int_mask_get); -void spu_int_stat_clear(struct spu *spu, int class, u64 stat) +static void int_stat_clear(struct spu *spu, int class, u64 stat) { out_be64(&spu->priv1->int_stat_RW[class], stat); } -EXPORT_SYMBOL_GPL(spu_int_stat_clear); -u64 spu_int_stat_get(struct spu *spu, int class) +static u64 int_stat_get(struct spu *spu, int class) { return in_be64(&spu->priv1->int_stat_RW[class]); } -EXPORT_SYMBOL_GPL(spu_int_stat_get); -void spu_int_route_set(struct spu *spu, u64 route) +static void int_route_set(struct spu *spu, u64 route) { out_be64(&spu->priv1->int_route_RW, route); } -EXPORT_SYMBOL_GPL(spu_int_route_set); -u64 spu_mfc_dar_get(struct spu *spu) +static u64 mfc_dar_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_dar_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_dar_get); -u64 spu_mfc_dsisr_get(struct spu *spu) +static u64 mfc_dsisr_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_dsisr_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get); -void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr) +static void mfc_dsisr_set(struct spu *spu, u64 dsisr) { out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); } -EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set); -void spu_mfc_sdr_set(struct spu *spu, u64 sdr) +static void mfc_sdr_set(struct spu *spu, u64 sdr) { out_be64(&spu->priv1->mfc_sdr_RW, sdr); } -EXPORT_SYMBOL_GPL(spu_mfc_sdr_set); -void spu_mfc_sr1_set(struct spu *spu, u64 sr1) +static void mfc_sr1_set(struct spu *spu, u64 sr1) { out_be64(&spu->priv1->mfc_sr1_RW, sr1); } -EXPORT_SYMBOL_GPL(spu_mfc_sr1_set); -u64 spu_mfc_sr1_get(struct spu *spu) +static u64 mfc_sr1_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_sr1_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_sr1_get); -void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) { out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); } -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set); -u64 spu_mfc_tclass_id_get(struct spu *spu) +static u64 mfc_tclass_id_get(struct spu *spu) { return in_be64(&spu->priv1->mfc_tclass_id_RW); } -EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get); -void spu_tlb_invalidate(struct spu *spu) +static void tlb_invalidate(struct spu *spu) { out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); } -EXPORT_SYMBOL_GPL(spu_tlb_invalidate); -void spu_resource_allocation_groupID_set(struct spu *spu, u64 id) +static void resource_allocation_groupID_set(struct spu *spu, u64 id) { out_be64(&spu->priv1->resource_allocation_groupID_RW, id); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set); -u64 spu_resource_allocation_groupID_get(struct spu *spu) +static u64 resource_allocation_groupID_get(struct spu *spu) { return in_be64(&spu->priv1->resource_allocation_groupID_RW); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get); -void spu_resource_allocation_enable_set(struct spu *spu, u64 enable) +static void resource_allocation_enable_set(struct spu *spu, u64 enable) { out_be64(&spu->priv1->resource_allocation_enable_RW, enable); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set); -u64 spu_resource_allocation_enable_get(struct spu *spu) +static u64 resource_allocation_enable_get(struct spu *spu) { return in_be64(&spu->priv1->resource_allocation_enable_RW); } -EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get); + +const struct spu_priv1_ops spu_priv1_mmio_ops = +{ + .int_mask_and = int_mask_and, + .int_mask_or = int_mask_or, + .int_mask_set = int_mask_set, + .int_mask_get = int_mask_get, + .int_stat_clear = int_stat_clear, + .int_stat_get = int_stat_get, + .int_route_set = int_route_set, + .mfc_dar_get = mfc_dar_get, + .mfc_dsisr_get = mfc_dsisr_get, + .mfc_dsisr_set = mfc_dsisr_set, + .mfc_sdr_set = mfc_sdr_set, + .mfc_sr1_set = mfc_sr1_set, + .mfc_sr1_get = mfc_sr1_get, + .mfc_tclass_id_set = mfc_tclass_id_set, + .mfc_tclass_id_get = mfc_tclass_id_get, + .tlb_invalidate = tlb_invalidate, + .resource_allocation_groupID_set = resource_allocation_groupID_set, + .resource_allocation_groupID_get = resource_allocation_groupID_get, + .resource_allocation_enable_set = resource_allocation_enable_set, + .resource_allocation_enable_get = resource_allocation_enable_get, +}; diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index a13a8b5a014d..ede2cac46b6d 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include "spufs.h" diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 85bea06e798b..2dae062a9aec 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -46,6 +46,7 @@ #include #include +#include #include #include -- cgit From a91942ae7ebd518006dcbeb2a1d7b147253c080e Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Mon, 19 Jun 2006 20:33:30 +0200 Subject: [POWERPC] spufs: fix spu irq affinity setting This changes the hypervisor abstraction of setting cpu affinity to a higher level to avoid platform dependent interrupt controller routines. I replaced spu_priv1_ops:spu_int_route_set() with a new routine spu_priv1_ops:spu_cpu_affinity_set(). As a by-product, this change eliminated what looked like an existing bug in the set affinity code where spu_int_route_set() mistakenly called int_stat_get(). Signed-off-by: Geoff Levand Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 8 -------- arch/powerpc/platforms/cell/spu_priv1_mmio.c | 8 ++++++-- arch/powerpc/platforms/cell/spufs/sched.c | 3 ++- 3 files changed, 8 insertions(+), 11 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index c3bb7299c4b5..8ca22394e4d3 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -522,14 +522,6 @@ int spu_irq_class_1_bottom(struct spu *spu) return ret; } -void spu_irq_setaffinity(struct spu *spu, int cpu) -{ - u64 target = iic_get_target_id(cpu); - u64 route = target << 48 | target << 32 | target << 16; - spu_int_route_set(spu, route); -} -EXPORT_SYMBOL_GPL(spu_irq_setaffinity); - static int __init find_spu_node_id(struct device_node *spe) { unsigned int *id; diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c index abe8a84925d2..71b69f0a1a48 100644 --- a/arch/powerpc/platforms/cell/spu_priv1_mmio.c +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -24,6 +24,8 @@ #include #include +#include "interrupt.h" + static void int_mask_and(struct spu *spu, int class, u64 mask) { u64 old_mask; @@ -60,8 +62,10 @@ static u64 int_stat_get(struct spu *spu, int class) return in_be64(&spu->priv1->int_stat_RW[class]); } -static void int_route_set(struct spu *spu, u64 route) +static void cpu_affinity_set(struct spu *spu, int cpu) { + u64 target = iic_get_target_id(cpu); + u64 route = target << 48 | target << 32 | target << 16; out_be64(&spu->priv1->int_route_RW, route); } @@ -138,7 +142,7 @@ const struct spu_priv1_ops spu_priv1_mmio_ops = .int_mask_get = int_mask_get, .int_stat_clear = int_stat_clear, .int_stat_get = int_stat_get, - .int_route_set = int_route_set, + .cpu_affinity_set = cpu_affinity_set, .mfc_dar_get = mfc_dar_get, .mfc_dsisr_get = mfc_dsisr_get, .mfc_dsisr_set = mfc_dsisr_set, diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index bf652cd77000..3dcc5d8d66b9 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "spufs.h" #define SPU_MIN_TIMESLICE (100 * HZ / 1000) @@ -363,7 +364,7 @@ int spu_activate(struct spu_context *ctx, u64 flags) * We're likely to wait for interrupts on the same * CPU that we are now on, so send them here. */ - spu_irq_setaffinity(spu, raw_smp_processor_id()); + spu_cpu_affinity_set(spu, raw_smp_processor_id()); put_active_spu(spu); return 0; } -- cgit From 2eabbbd33ec39f690005aa186c57476598edc6b3 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:31 +0200 Subject: [POWERPC] spufs: remove stop_code from struct spu This patch remove 'stop_code' -- discarded member of struct spu. It is written at initialize and interrupt, but never read in current implementation. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 2 -- arch/powerpc/platforms/cell/spufs/switch.c | 1 - 2 files changed, 3 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 8ca22394e4d3..249a0af4cc99 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -160,7 +160,6 @@ static int __spu_trap_mailbox(struct spu *spu) static int __spu_trap_stop(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); if (spu->stop_callback) spu->stop_callback(spu); return 0; @@ -169,7 +168,6 @@ static int __spu_trap_stop(struct spu *spu) static int __spu_trap_halt(struct spu *spu) { pr_debug("%s\n", __FUNCTION__); - spu->stop_code = in_be32(&spu->problem->spu_status_R); if (spu->stop_callback) spu->stop_callback(spu); return 0; diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 2dae062a9aec..b30e55dab832 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2109,7 +2109,6 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); - spu->stop_code = 0; spu->dar = 0; spu->dsisr = 0; spu->slb_replace = 0; -- cgit From 6e18b27bd0911d4d2495c6fdeeac0c047d915300 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:32 +0200 Subject: [POWERPC] spufs: fix Makefile for "make clean" added spu_{save,restore}_dump.h to target of 'make clean' Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 7963d520b67b..e3c4482be3be 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -15,6 +15,7 @@ SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2 SPU_LDFLAGS := -N -Ttext=0x0 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h +clean-files := spu_save_dump.h spu_restore_dump.h # Compile SPU files cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $< -- cgit From ba723fe2b2facc8d45b53701fec39aa429596759 Mon Sep 17 00:00:00 2001 From: Masato Noguchi Date: Mon, 19 Jun 2006 20:33:33 +0200 Subject: [POWERPC] spufs: clear class2 interrupt status before wakeup SPU interrupt status must be cleared before handle it. Otherwise, kernel may drop some interrupt packet. Currently, class2 interrupt treated like: 1) call callback to wake up waiting process 2) mask raised mailbox interrupt 3) clear interrupt status I changed like: 1) mask raised mailbox interrupt 2) clear interrupt status 3) call callback to wake up waiting process Clearing status before masking will make spurious interrupt. Thus, it is necessary to hold by steps I described above, I think. Signed-off-by: Masato Noguchi Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_base.c | 78 +++++++++------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 249a0af4cc99..db82f503ba2c 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -140,55 +140,7 @@ static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) spu->dar = ea; spu->dsisr = dsisr; mb(); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_mailbox(struct spu *spu) -{ - if (spu->ibox_callback) - spu->ibox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x1); - spin_unlock(&spu->register_lock); - return 0; -} - -static int __spu_trap_stop(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_halt(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - if (spu->stop_callback) - spu->stop_callback(spu); - return 0; -} - -static int __spu_trap_tag_group(struct spu *spu) -{ - pr_debug("%s\n", __FUNCTION__); - spu->mfc_callback(spu); - return 0; -} - -static int __spu_trap_spubox(struct spu *spu) -{ - if (spu->wbox_callback) - spu->wbox_callback(spu); - - /* atomically disable SPU mailbox interrupts */ - spin_lock(&spu->register_lock); - spu_int_mask_and(spu, 2, ~0x10); - spin_unlock(&spu->register_lock); + spu->stop_callback(spu); return 0; } @@ -199,8 +151,7 @@ spu_irq_class_0(int irq, void *data, struct pt_regs *regs) spu = data; spu->class_0_pending = 1; - if (spu->stop_callback) - spu->stop_callback(spu); + spu->stop_callback(spu); return IRQ_HANDLED; } @@ -278,29 +229,38 @@ spu_irq_class_2(int irq, void *data, struct pt_regs *regs) unsigned long mask; spu = data; + spin_lock(&spu->register_lock); stat = spu_int_stat_get(spu, 2); mask = spu_int_mask_get(spu, 2); + /* ignore interrupts we're not waiting for */ + stat &= mask; + /* + * mailbox interrupts (0x1 and 0x10) are level triggered. + * mask them now before acknowledging. + */ + if (stat & 0x11) + spu_int_mask_and(spu, 2, ~(stat & 0x11)); + /* acknowledge all interrupts before the callbacks */ + spu_int_stat_clear(spu, 2, stat); + spin_unlock(&spu->register_lock); pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask); - stat &= mask; - if (stat & 1) /* PPC core mailbox */ - __spu_trap_mailbox(spu); + spu->ibox_callback(spu); if (stat & 2) /* SPU stop-and-signal */ - __spu_trap_stop(spu); + spu->stop_callback(spu); if (stat & 4) /* SPU halted */ - __spu_trap_halt(spu); + spu->stop_callback(spu); if (stat & 8) /* DMA tag group complete */ - __spu_trap_tag_group(spu); + spu->mfc_callback(spu); if (stat & 0x10) /* SPU mailbox threshold */ - __spu_trap_spubox(spu); + spu->wbox_callback(spu); - spu_int_stat_clear(spu, 2, stat); return stat ? IRQ_HANDLED : IRQ_NONE; } -- cgit From c983294872ebccd4aacf1b8dd694ac2170feadc3 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:34 +0200 Subject: [POWERPC] spufs: fail spu_create with invalid flags At this time, all flags are invalid. Since we are planning to actually add valid flags in the future, we better check if any were passed by the user. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/inode.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index fed511a2b17f..1987697b23a0 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -304,6 +304,10 @@ long spufs_create_thread(struct nameidata *nd, nd->dentry != nd->dentry->d_sb->s_root) goto out; + /* all flags are reserved */ + if (flags) + goto out; + dentry = lookup_create(nd, 1); ret = PTR_ERR(dentry); if (IS_ERR(dentry)) -- cgit From 379507181a1e330d4f5b0fabe61cd43eccf09763 Mon Sep 17 00:00:00 2001 From: "arnd@arndb.de" Date: Mon, 19 Jun 2006 20:33:35 +0200 Subject: [POWERPC] spufs: one more fix for 64k pages The SPU context save/restore code is currently built for a 4k page size and we provide a _shipped version of it since most people don't have the spu toolchain that is needed to rebuild that code. This patch hardcodes the data structures to a 64k page alignment, which also guarantees 4k alignment but unfortunately wastes 60k of memory per SPU context that is created in the running system. We will follow up on this with another patch to reduce that overhead or maybe redo the context save/restore logic to do this part entirely different, but for now it should make experimental systems work with either page size. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/Makefile | 9 +- .../cell/spufs/spu_restore_dump.h_shipped | 1122 ++++++++++++++++---- .../platforms/cell/spufs/spu_save_dump.h_shipped | 922 ++++++++++++---- 3 files changed, 1640 insertions(+), 413 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index e3c4482be3be..bb5dc634272c 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -10,8 +10,10 @@ SPU_CC := $(SPU_CROSS)gcc SPU_AS := $(SPU_CROSS)gcc SPU_LD := $(SPU_CROSS)ld SPU_OBJCOPY := $(SPU_CROSS)objcopy -SPU_CFLAGS := -O2 -Wall -I$(srctree)/include -I$(objtree)/include2 -SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2 +SPU_CFLAGS := -O2 -Wall -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ +SPU_AFLAGS := -c -D__ASSEMBLY__ -I$(srctree)/include \ + -I$(objtree)/include2 -D__KERNEL__ SPU_LDFLAGS := -N -Ttext=0x0 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h @@ -48,7 +50,8 @@ cmd_hexdump = ( \ echo " * Hex-dump auto generated from $*.c." ; \ echo " * Do not edit!" ; \ echo " */" ; \ - echo "static unsigned int $*_code[] __page_aligned = {" ; \ + echo "static unsigned int $*_code[] " \ + "__attribute__((__aligned__(128))) = {" ; \ hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \ echo "};" ; \ ) > $@ diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped index 1b2355ff7036..15183d209b58 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped @@ -3,229 +3,901 @@ * Hex-dump auto generated from spu_restore.c. * Do not edit! */ -static unsigned int spu_restore_code[] __page_aligned = { -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33001180, 0x42030003, 0x33800284, -0x1c010204, 0x40200000, 0x40200000, 0x40200000, -0x34000190, 0x34004191, 0x34008192, 0x3400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85, -0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603, -0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07, -0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b, -0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f, -0x00003ffc, 0x00000000, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204, -0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202, -0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682, -0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f, -0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204, -0x04000203, 0x21a00903, 0x40848002, 0x21a00982, -0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82, -0x21a00083, 0x40800082, 0x21a00b02, 0x10002818, -0x40a80002, 0x32800007, 0x4207000c, 0x18008208, -0x40a0000b, 0x4080020a, 0x40800709, 0x00200000, -0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000, -0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185, -0xb0408584, 0x28830382, 0x1c020387, 0x38828182, -0xb0408405, 0x1802c408, 0x28828182, 0x217ff886, -0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102, -0x04000106, 0x21a00886, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x40800003, 0x04000184, -0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005, -0x34208702, 0x21002282, 0x21a00804, 0x21a00886, -0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102, -0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04, -0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02, -0x34210283, 0x21a00f03, 0x34200284, 0x77400200, -0x3421c282, 0x21a00702, 0x34218283, 0x21a00083, -0x34214282, 0x21a00b02, 0x4200480c, 0x00200000, -0x1c010286, 0x34220284, 0x34220302, 0x0f608203, -0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000, -0x18008185, 0x38808183, 0x3b814182, 0x21004e84, -0x4020007f, 0x35000100, 0x000004e0, 0x000002a0, -0x000002e8, 0x00000428, 0x00000360, 0x000002e8, -0x000004a0, 0x00000468, 0x000003c8, 0x00000360, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085, -0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f, -0x4020007f, 0x20801203, 0x38810602, 0xb0408586, -0x28810602, 0x32004180, 0x34204702, 0x21a00382, -0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203, -0x40800204, 0x3ec40087, 0x40800405, 0x00200000, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x41004003, 0x38810602, -0x4020007f, 0xb0408188, 0x4020007f, 0x28810602, -0x41201002, 0x38814603, 0x10009c09, 0xb060c109, -0x4020007f, 0x28814603, 0x41193f83, 0x38818602, -0x60ffc003, 0xb040818a, 0x28818602, 0x32003080, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x41201008, 0x10009c14, 0x40800405, 0x3ac10609, -0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b, -0x20801203, 0x38810602, 0xb0408409, 0x28810602, -0x38814603, 0xb060c40a, 0x4020007f, 0x28814603, -0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b, -0x28818602, 0x32002380, 0x409ffe02, 0x30801204, -0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607, -0x3ac18608, 0xb0810103, 0x41004002, 0x20801204, -0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107, -0x4020007f, 0x4020007f, 0x28814603, 0x38818602, -0x4020007f, 0x4020007f, 0xb0408588, 0x28818602, -0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e, -0x40800204, 0x30801203, 0x40800405, 0x3ec40087, -0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a, -0xb060c107, 0x20801203, 0x413d8003, 0x38810602, -0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c, -0x40800205, 0x30801204, 0x40800406, 0x3ec40083, -0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002, -0x20801204, 0x38814603, 0x4020007f, 0x327feb80, -0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087, -0x40800405, 0x1000650a, 0x40800606, 0x3ac10608, -0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203, -0x38810602, 0xb0408588, 0x4020007f, 0x327fc980, -0x00400000, 0x40800003, 0x4020007f, 0x35000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_restore_code[] __attribute__((__aligned__(128))) = { +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33001180, +0x42030003, +0x33800284, +0x1c010204, +0x40200000, +0x40200000, +0x40200000, +0x34000190, +0x34004191, +0x34008192, +0x3400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffa85, +0x3080a000, +0x3080a201, +0x3080a402, +0x3080a603, +0x3080a804, +0x3080aa05, +0x3080ac06, +0x3080ae07, +0x3080b008, +0x3080b209, +0x3080b40a, +0x3080b60b, +0x3080b80c, +0x3080ba0d, +0x3080bc0e, +0x3080be0f, +0x00003ffc, +0x00000000, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb0a14103, +0x01a00204, +0x3ec10082, +0x4202800e, +0x04000703, +0xb0a14202, +0x21a00803, +0x3fbf028d, +0x3f20068d, +0x3fbe0682, +0x3fe30102, +0x21a00882, +0x3f82028f, +0x3fe3078f, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x04000203, +0x21a00903, +0x40848002, +0x21a00982, +0x40800003, +0x21a00a03, +0x40802002, +0x21a00a82, +0x21a00083, +0x40800082, +0x21a00b02, +0x10002818, +0x42a00002, +0x32800007, +0x4207000c, +0x18008208, +0x40a0000b, +0x4080020a, +0x40800709, +0x00200000, +0x42070002, +0x3ac30384, +0x1cffc489, +0x00200000, +0x18008383, +0x38830382, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830382, +0x1c020387, +0x38828182, +0xb0408405, +0x1802c408, +0x28828182, +0x217ff886, +0x04000583, +0x21a00803, +0x3fbe0682, +0x3fe30102, +0x04000106, +0x21a00886, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x40800003, +0x04000184, +0x21a00a04, +0x40802202, +0x21a00a82, +0x42028005, +0x34208702, +0x21002282, +0x21a00804, +0x21a00886, +0x3fbf0782, +0x3f200102, +0x3fbe0102, +0x3fe30102, +0x21a00902, +0x40804003, +0x21a00983, +0x21a00a04, +0x40805a02, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x3420c282, +0x21a00e02, +0x34210283, +0x21a00f03, +0x34200284, +0x77400200, +0x3421c282, +0x21a00702, +0x34218283, +0x21a00083, +0x34214282, +0x21a00b02, +0x4200480c, +0x00200000, +0x1c010286, +0x34220284, +0x34220302, +0x0f608203, +0x5c024204, +0x3b81810b, +0x42013c02, +0x00200000, +0x18008185, +0x38808183, +0x3b814182, +0x21004e84, +0x4020007f, +0x35000100, +0x000004e0, +0x000002a0, +0x000002e8, +0x00000428, +0x00000360, +0x000002e8, +0x000004a0, +0x00000468, +0x000003c8, +0x00000360, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40085, +0x10009c09, +0x3ac10606, +0xb060c105, +0x4020007f, +0x4020007f, +0x20801203, +0x38810602, +0xb0408586, +0x28810602, +0x32004180, +0x34204702, +0x21a00382, +0x4020007f, +0x327fdc80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x00200000, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x41004003, +0x38810602, +0x4020007f, +0xb0408188, +0x4020007f, +0x28810602, +0x41201002, +0x38814603, +0x10009c09, +0xb060c109, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818a, +0x28818602, +0x32003080, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x41201008, +0x10009c14, +0x40800405, +0x3ac10609, +0x40800606, +0x3ac1460a, +0xb060c107, +0x3ac1860b, +0x20801203, +0x38810602, +0xb0408409, +0x28810602, +0x38814603, +0xb060c40a, +0x4020007f, +0x28814603, +0x41193f83, +0x38818602, +0x60ffc003, +0xb040818b, +0x28818602, +0x32002380, +0x409ffe02, +0x30801204, +0x40800205, +0x3ec40083, +0x40800406, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x41004002, +0x20801204, +0x4020007f, +0x38814603, +0x10009c0b, +0xb060c107, +0x4020007f, +0x4020007f, +0x28814603, +0x38818602, +0x4020007f, +0x4020007f, +0xb0408588, +0x28818602, +0x4020007f, +0x32001780, +0x409ffe02, +0x1000640e, +0x40800204, +0x30801203, +0x40800405, +0x3ec40087, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x413d8003, +0x38810602, +0x4020007f, +0x327fd780, +0x409ffe02, +0x10007f0c, +0x40800205, +0x30801204, +0x40800406, +0x3ec40083, +0x3ac14607, +0x3ac18608, +0xb0810103, +0x413d8002, +0x20801204, +0x38814603, +0x4020007f, +0x327feb80, +0x409ffe02, +0x30801203, +0x40800204, +0x3ec40087, +0x40800405, +0x1000650a, +0x40800606, +0x3ac10608, +0x3ac14609, +0x3ac1860a, +0xb060c107, +0x20801203, +0x38810602, +0xb0408588, +0x4020007f, +0x327fc980, +0x00400000, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped index 39e54003f1df..b9f81ac8a632 100644 --- a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped +++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped @@ -3,189 +3,741 @@ * Hex-dump auto generated from spu_save.c. * Do not edit! */ -static unsigned int spu_save_code[] __page_aligned = { -0x20805000, 0x20805201, 0x20805402, 0x20805603, -0x20805804, 0x20805a05, 0x20805c06, 0x20805e07, -0x20806008, 0x20806209, 0x2080640a, 0x2080660b, -0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f, -0x4201c003, 0x33800184, 0x1c010204, 0x40200000, -0x24000190, 0x24004191, 0x24008192, 0x2400c193, -0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85, -0x40800000, 0x409ff801, 0x24000080, 0x24fd8081, -0x1cd80081, 0x33000180, 0x00000000, 0x00000000, -0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204, -0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583, -0x34218682, 0x3ed80684, 0xb0408184, 0x24218682, -0x01a00603, 0x00200000, 0x34214682, 0x3ed40684, -0xb0408184, 0x40800003, 0x24214682, 0x21a00083, -0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e, -0x40a80002, 0x32800008, 0x4205c00c, 0x00200000, -0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709, -0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183, -0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404, -0x1cffc489, 0x00200000, 0x18008403, 0x38830402, -0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402, -0x1c020408, 0x38828182, 0xb0408385, 0x1802c387, -0x28828182, 0x217ff886, 0x04000582, 0x32800007, -0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285, -0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903, -0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06, -0x40801202, 0x21a00a82, 0x73000003, 0x24200683, -0x01a00404, 0x00200000, 0x34204682, 0x3ec40683, -0xb0408203, 0x24204682, 0x01a00783, 0x00200000, -0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682, -0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204, -0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002, -0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82, -0x04000683, 0x21a00803, 0x21a00885, 0x21a00904, -0x40848002, 0x21a00982, 0x21a00a06, 0x40801002, -0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000, -0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83, -0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003, -0x4020007f, 0x35000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, -0x00000000, 0x00000000, 0x00000000, 0x00000000, +static unsigned int spu_save_code[] __attribute__((__aligned__(128))) = { +0x20805000, +0x20805201, +0x20805402, +0x20805603, +0x20805804, +0x20805a05, +0x20805c06, +0x20805e07, +0x20806008, +0x20806209, +0x2080640a, +0x2080660b, +0x2080680c, +0x20806a0d, +0x20806c0e, +0x20806e0f, +0x4201c003, +0x33800184, +0x1c010204, +0x40200000, +0x24000190, +0x24004191, +0x24008192, +0x2400c193, +0x141fc205, +0x23fffd84, +0x1c100183, +0x217ffb85, +0x40800000, +0x409ff801, +0x24000080, +0x24fd8081, +0x1cd80081, +0x33000180, +0x00000000, +0x00000000, +0x01a00182, +0x3ec00083, +0xb1c38103, +0x01a00204, +0x3ec10082, +0x4201400d, +0xb1c38202, +0x01a00583, +0x34218682, +0x3ed80684, +0xb0408184, +0x24218682, +0x01a00603, +0x00200000, +0x34214682, +0x3ed40684, +0xb0408184, +0x40800003, +0x24214682, +0x21a00083, +0x40800082, +0x21a00b02, +0x4020007f, +0x1000251e, +0x42a00002, +0x32800008, +0x4205c00c, +0x00200000, +0x40a0000b, +0x3f82070f, +0x4080020a, +0x40800709, +0x3fe3078f, +0x3fbf0783, +0x3f200183, +0x3fbe0183, +0x3fe30187, +0x18008387, +0x4205c002, +0x3ac30404, +0x1cffc489, +0x00200000, +0x18008403, +0x38830402, +0x4cffc486, +0x3ac28185, +0xb0408584, +0x28830402, +0x1c020408, +0x38828182, +0xb0408385, +0x1802c387, +0x28828182, +0x217ff886, +0x04000582, +0x32800007, +0x21a00802, +0x3fbf0705, +0x3f200285, +0x3fbe0285, +0x3fe30285, +0x21a00885, +0x04000603, +0x21a00903, +0x40803c02, +0x21a00982, +0x04000386, +0x21a00a06, +0x40801202, +0x21a00a82, +0x73000003, +0x24200683, +0x01a00404, +0x00200000, +0x34204682, +0x3ec40683, +0xb0408203, +0x24204682, +0x01a00783, +0x00200000, +0x3421c682, +0x3edc0684, +0xb0408184, +0x2421c682, +0x21a00806, +0x21a00885, +0x3fbf0784, +0x3f200204, +0x3fbe0204, +0x3fe30204, +0x21a00904, +0x40804002, +0x21a00982, +0x21a00a06, +0x40805a02, +0x21a00a82, +0x04000683, +0x21a00803, +0x21a00885, +0x21a00904, +0x40848002, +0x21a00982, +0x21a00a06, +0x40801002, +0x21a00a82, +0x21a00a06, +0x40806602, +0x00200000, +0x35800009, +0x21a00a82, +0x40800083, +0x21a00b83, +0x01a00c02, +0x01a00d83, +0x00003ffb, +0x40800003, +0x4020007f, +0x35000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, }; -- cgit From 0aa8d15b01881ccaab5f2fb31eef33ced97ccb5f Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 19 Jun 2006 15:07:40 -0500 Subject: [POWERPC] pseries: Print PCI slot location code on failure The PCI error recovery code will printk diagnostic info when a PCI error event occurs. Change the messages to include the slot location code, which is how most sysadmins will know the device. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_driver.c | 35 ++++++++++++++++++----------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 4d45347afabc..0ec9a5445b95 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -261,16 +261,22 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) struct pci_bus *frozen_bus; int rc = 0; enum pci_ers_result result = PCI_ERS_RESULT_NONE; - const char *pci_str, *drv_str; + const char *location, *pci_str, *drv_str; frozen_dn = find_device_pe(event->dn); frozen_bus = pcibios_find_pci_bus(frozen_dn); if (!frozen_dn) { - printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", - pci_name(event->dev)); + + location = (char *) get_property(event->dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; + printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " + "for location=%s pci addr=%s\n", + location, pci_name(event->dev)); return NULL; } + location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL); + location = location ? location : "unknown"; /* There are two different styles for coming up with the PE. * In the old style, it was the highest EEH-capable device @@ -282,8 +288,9 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); if (!frozen_bus) { - printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", - frozen_dn->full_name); + printk(KERN_ERR "EEH: Cannot find PCI bus " + "for location=%s dn=%s\n", + location, frozen_dn->full_name); return NULL; } @@ -318,8 +325,9 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); printk(KERN_WARNING - "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", - frozen_pdn->eeh_freeze_count, drv_str, pci_str); + "EEH: This PCI device has failed %d times since last reboot: " + "location=%s driver=%s pci addr=%s\n", + frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); /* Walk the various device drivers attached to this slot through * a reset sequence, giving each an opportunity to do what it needs @@ -368,17 +376,18 @@ excess_failures: * due to actual, failed cards. */ printk(KERN_ERR - "EEH: PCI device %s - %s has failed %d times \n" - "and has been permanently disabled. Please try reseating\n" - "this device or replacing it.\n", - drv_str, pci_str, frozen_pdn->eeh_freeze_count); + "EEH: PCI device at location=%s driver=%s pci addr=%s \n" + "has failed %d times and has been permanently disabled. \n" + "Please try reseating this device or replacing it.\n", + location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); goto perm_error; hard_fail: printk(KERN_ERR - "EEH: Unable to recover from failure of PCI device %s - %s\n" + "EEH: Unable to recover from failure of PCI device " + "at location=%s driver=%s pci addr=%s \n" "Please try reseating this device or replacing it.\n", - drv_str, pci_str); + location, drv_str, pci_str); perm_error: eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); -- cgit From 72abd54035a3d71fd8f02596e659257e8bba16ca Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Mon, 19 Jun 2006 22:45:04 +0200 Subject: [POWERPC] Unify ppc syscall tables Avoid duplication of the syscall table for the cell platform. Based on an idea from David Woodhouse. Signed-off-by: Andreas Schwab Acked-by: Arnd Bergmann Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spu_callbacks.c | 314 ++-------------------------- 1 file changed, 13 insertions(+), 301 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index b47fcc5ddb78..47ec3be3edcd 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -34,307 +34,19 @@ */ void *spu_syscall_table[] = { - [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ - [__NR_exit] sys_ni_syscall, /* sys_exit */ - [__NR_fork] sys_ni_syscall, /* ppc_fork */ - [__NR_read] sys_read, - [__NR_write] sys_write, - [__NR_open] sys_open, - [__NR_close] sys_close, - [__NR_waitpid] sys_waitpid, - [__NR_creat] sys_creat, - [__NR_link] sys_link, - [__NR_unlink] sys_unlink, - [__NR_execve] sys_ni_syscall, /* sys_execve */ - [__NR_chdir] sys_chdir, - [__NR_time] sys_time, - [__NR_mknod] sys_mknod, - [__NR_chmod] sys_chmod, - [__NR_lchown] sys_lchown, - [__NR_break] sys_ni_syscall, - [__NR_oldstat] sys_ni_syscall, - [__NR_lseek] sys_lseek, - [__NR_getpid] sys_getpid, - [__NR_mount] sys_ni_syscall, /* sys_mount */ - [__NR_umount] sys_ni_syscall, - [__NR_setuid] sys_setuid, - [__NR_getuid] sys_getuid, - [__NR_stime] sys_stime, - [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ - [__NR_alarm] sys_alarm, - [__NR_oldfstat] sys_ni_syscall, - [__NR_pause] sys_ni_syscall, /* sys_pause */ - [__NR_utime] sys_ni_syscall, /* sys_utime */ - [__NR_stty] sys_ni_syscall, - [__NR_gtty] sys_ni_syscall, - [__NR_access] sys_access, - [__NR_nice] sys_nice, - [__NR_ftime] sys_ni_syscall, - [__NR_sync] sys_sync, - [__NR_kill] sys_kill, - [__NR_rename] sys_rename, - [__NR_mkdir] sys_mkdir, - [__NR_rmdir] sys_rmdir, - [__NR_dup] sys_dup, - [__NR_pipe] sys_pipe, - [__NR_times] sys_times, - [__NR_prof] sys_ni_syscall, - [__NR_brk] sys_brk, - [__NR_setgid] sys_setgid, - [__NR_getgid] sys_getgid, - [__NR_signal] sys_ni_syscall, /* sys_signal */ - [__NR_geteuid] sys_geteuid, - [__NR_getegid] sys_getegid, - [__NR_acct] sys_ni_syscall, /* sys_acct */ - [__NR_umount2] sys_ni_syscall, /* sys_umount */ - [__NR_lock] sys_ni_syscall, - [__NR_ioctl] sys_ioctl, - [__NR_fcntl] sys_fcntl, - [__NR_mpx] sys_ni_syscall, - [__NR_setpgid] sys_setpgid, - [__NR_ulimit] sys_ni_syscall, - [__NR_oldolduname] sys_ni_syscall, - [__NR_umask] sys_umask, - [__NR_chroot] sys_chroot, - [__NR_ustat] sys_ni_syscall, /* sys_ustat */ - [__NR_dup2] sys_dup2, - [__NR_getppid] sys_getppid, - [__NR_getpgrp] sys_getpgrp, - [__NR_setsid] sys_setsid, - [__NR_sigaction] sys_ni_syscall, - [__NR_sgetmask] sys_sgetmask, - [__NR_ssetmask] sys_ssetmask, - [__NR_setreuid] sys_setreuid, - [__NR_setregid] sys_setregid, - [__NR_sigsuspend] sys_ni_syscall, - [__NR_sigpending] sys_ni_syscall, - [__NR_sethostname] sys_sethostname, - [__NR_setrlimit] sys_setrlimit, - [__NR_getrlimit] sys_ni_syscall, - [__NR_getrusage] sys_getrusage, - [__NR_gettimeofday] sys_gettimeofday, - [__NR_settimeofday] sys_settimeofday, - [__NR_getgroups] sys_getgroups, - [__NR_setgroups] sys_setgroups, - [__NR_select] sys_ni_syscall, - [__NR_symlink] sys_symlink, - [__NR_oldlstat] sys_ni_syscall, - [__NR_readlink] sys_readlink, - [__NR_uselib] sys_ni_syscall, /* sys_uselib */ - [__NR_swapon] sys_ni_syscall, /* sys_swapon */ - [__NR_reboot] sys_ni_syscall, /* sys_reboot */ - [__NR_readdir] sys_ni_syscall, - [__NR_mmap] sys_mmap, - [__NR_munmap] sys_munmap, - [__NR_truncate] sys_truncate, - [__NR_ftruncate] sys_ftruncate, - [__NR_fchmod] sys_fchmod, - [__NR_fchown] sys_fchown, - [__NR_getpriority] sys_getpriority, - [__NR_setpriority] sys_setpriority, - [__NR_profil] sys_ni_syscall, - [__NR_statfs] sys_ni_syscall, /* sys_statfs */ - [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ - [__NR_ioperm] sys_ni_syscall, - [__NR_socketcall] sys_socketcall, - [__NR_syslog] sys_syslog, - [__NR_setitimer] sys_setitimer, - [__NR_getitimer] sys_getitimer, - [__NR_stat] sys_newstat, - [__NR_lstat] sys_newlstat, - [__NR_fstat] sys_newfstat, - [__NR_olduname] sys_ni_syscall, - [__NR_iopl] sys_ni_syscall, - [__NR_vhangup] sys_vhangup, - [__NR_idle] sys_ni_syscall, - [__NR_vm86] sys_ni_syscall, - [__NR_wait4] sys_wait4, - [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ - [__NR_sysinfo] sys_sysinfo, - [__NR_ipc] sys_ni_syscall, /* sys_ipc */ - [__NR_fsync] sys_fsync, - [__NR_sigreturn] sys_ni_syscall, - [__NR_clone] sys_ni_syscall, /* ppc_clone */ - [__NR_setdomainname] sys_setdomainname, - [__NR_uname] ppc_newuname, - [__NR_modify_ldt] sys_ni_syscall, - [__NR_adjtimex] sys_adjtimex, - [__NR_mprotect] sys_mprotect, - [__NR_sigprocmask] sys_ni_syscall, - [__NR_create_module] sys_ni_syscall, - [__NR_init_module] sys_ni_syscall, /* sys_init_module */ - [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ - [__NR_get_kernel_syms] sys_ni_syscall, - [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ - [__NR_getpgid] sys_getpgid, - [__NR_fchdir] sys_fchdir, - [__NR_bdflush] sys_bdflush, - [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ - [__NR_personality] ppc64_personality, - [__NR_afs_syscall] sys_ni_syscall, - [__NR_setfsuid] sys_setfsuid, - [__NR_setfsgid] sys_setfsgid, - [__NR__llseek] sys_llseek, - [__NR_getdents] sys_getdents, - [__NR__newselect] sys_select, - [__NR_flock] sys_flock, - [__NR_msync] sys_msync, - [__NR_readv] sys_readv, - [__NR_writev] sys_writev, - [__NR_getsid] sys_getsid, - [__NR_fdatasync] sys_fdatasync, - [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ - [__NR_mlock] sys_mlock, - [__NR_munlock] sys_munlock, - [__NR_mlockall] sys_mlockall, - [__NR_munlockall] sys_munlockall, - [__NR_sched_setparam] sys_sched_setparam, - [__NR_sched_getparam] sys_sched_getparam, - [__NR_sched_setscheduler] sys_sched_setscheduler, - [__NR_sched_getscheduler] sys_sched_getscheduler, - [__NR_sched_yield] sys_sched_yield, - [__NR_sched_get_priority_max] sys_sched_get_priority_max, - [__NR_sched_get_priority_min] sys_sched_get_priority_min, - [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, - [__NR_nanosleep] sys_nanosleep, - [__NR_mremap] sys_mremap, - [__NR_setresuid] sys_setresuid, - [__NR_getresuid] sys_getresuid, - [__NR_query_module] sys_ni_syscall, - [__NR_poll] sys_poll, - [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ - [__NR_setresgid] sys_setresgid, - [__NR_getresgid] sys_getresgid, - [__NR_prctl] sys_prctl, - [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ - [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ - [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ - [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ - [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ - [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ - [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ - [__NR_pread64] sys_pread64, - [__NR_pwrite64] sys_pwrite64, - [__NR_chown] sys_chown, - [__NR_getcwd] sys_getcwd, - [__NR_capget] sys_capget, - [__NR_capset] sys_capset, - [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ - [__NR_sendfile] sys_sendfile64, - [__NR_getpmsg] sys_ni_syscall, - [__NR_putpmsg] sys_ni_syscall, - [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ - [__NR_ugetrlimit] sys_getrlimit, - [__NR_readahead] sys_readahead, - [192] sys_ni_syscall, - [193] sys_ni_syscall, - [194] sys_ni_syscall, - [195] sys_ni_syscall, - [196] sys_ni_syscall, - [197] sys_ni_syscall, - [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ - [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ - [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ - [__NR_multiplexer] sys_ni_syscall, - [__NR_getdents64] sys_getdents64, - [__NR_pivot_root] sys_pivot_root, - [204] sys_ni_syscall, - [__NR_madvise] sys_madvise, - [__NR_mincore] sys_mincore, - [__NR_gettid] sys_gettid, - [__NR_tkill] sys_tkill, - [__NR_setxattr] sys_setxattr, - [__NR_lsetxattr] sys_lsetxattr, - [__NR_fsetxattr] sys_fsetxattr, - [__NR_getxattr] sys_getxattr, - [__NR_lgetxattr] sys_lgetxattr, - [__NR_fgetxattr] sys_fgetxattr, - [__NR_listxattr] sys_listxattr, - [__NR_llistxattr] sys_llistxattr, - [__NR_flistxattr] sys_flistxattr, - [__NR_removexattr] sys_removexattr, - [__NR_lremovexattr] sys_lremovexattr, - [__NR_fremovexattr] sys_fremovexattr, - [__NR_futex] sys_futex, - [__NR_sched_setaffinity] sys_sched_setaffinity, - [__NR_sched_getaffinity] sys_sched_getaffinity, - [224] sys_ni_syscall, - [__NR_tuxcall] sys_ni_syscall, - [226] sys_ni_syscall, - [__NR_io_setup] sys_io_setup, - [__NR_io_destroy] sys_io_destroy, - [__NR_io_getevents] sys_io_getevents, - [__NR_io_submit] sys_io_submit, - [__NR_io_cancel] sys_io_cancel, - [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ - [__NR_fadvise64] sys_fadvise64, - [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ - [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ - [__NR_epoll_create] sys_epoll_create, - [__NR_epoll_ctl] sys_epoll_ctl, - [__NR_epoll_wait] sys_epoll_wait, - [__NR_remap_file_pages] sys_remap_file_pages, - [__NR_timer_create] sys_timer_create, - [__NR_timer_settime] sys_timer_settime, - [__NR_timer_gettime] sys_timer_gettime, - [__NR_timer_getoverrun] sys_timer_getoverrun, - [__NR_timer_delete] sys_timer_delete, - [__NR_clock_settime] sys_clock_settime, - [__NR_clock_gettime] sys_clock_gettime, - [__NR_clock_getres] sys_clock_getres, - [__NR_clock_nanosleep] sys_clock_nanosleep, - [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ - [__NR_tgkill] sys_tgkill, - [__NR_utimes] sys_utimes, - [__NR_statfs64] sys_statfs64, - [__NR_fstatfs64] sys_fstatfs64, - [254] sys_ni_syscall, - [__NR_rtas] ppc_rtas, - [256] sys_ni_syscall, - [257] sys_ni_syscall, - [258] sys_ni_syscall, - [__NR_mbind] sys_ni_syscall, /* sys_mbind */ - [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ - [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ - [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ - [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ - [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ - [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ - [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ - [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ - [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ - [__NR_add_key] sys_ni_syscall, /* sys_add_key */ - [__NR_request_key] sys_ni_syscall, /* sys_request_key */ - [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ - [__NR_waitid] sys_ni_syscall, /* sys_waitid */ - [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ - [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ - [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ - [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ - [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ - [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ - [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ - [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ - [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ - [__NR_unshare] sys_unshare, - [__NR_splice] sys_splice, - [__NR_tee] sys_tee, - [__NR_vmsplice] sys_vmsplice, - [__NR_openat] sys_openat, - [__NR_mkdirat] sys_mkdirat, - [__NR_mknodat] sys_mknodat, - [__NR_fchownat] sys_fchownat, - [__NR_futimesat] sys_futimesat, - [__NR_newfstatat] sys_newfstatat, - [__NR_unlinkat] sys_unlinkat, - [__NR_renameat] sys_renameat, - [__NR_linkat] sys_linkat, - [__NR_symlinkat] sys_symlinkat, - [__NR_readlinkat] sys_readlinkat, - [__NR_fchmodat] sys_fchmodat, - [__NR_faccessat] sys_faccessat, - [__NR_get_robust_list] sys_get_robust_list, - [__NR_set_robust_list] sys_set_robust_list, +#define SYSCALL(func) sys_ni_syscall, +#define COMPAT_SYS(func) sys_ni_syscall, +#define PPC_SYS(func) sys_ni_syscall, +#define OLDSYS(func) sys_ni_syscall, +#define SYS32ONLY(func) sys_ni_syscall, +#define SYSX(f, f3264, f32) sys_ni_syscall, + +#define SYSCALL_SPU(func) sys_##func, +#define COMPAT_SYS_SPU(func) sys_##func, +#define PPC_SYS_SPU(func) ppc_##func, +#define SYSX_SPU(f, f3264, f32) f, + +#include }; long spu_sys_callback(struct spu_syscall_block *s) -- cgit From d3c58fb177dc957af5cdac5ad1638d713fdb8765 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 20 Jun 2006 18:00:30 +1000 Subject: [POWERPC] Dont look for class-code in pci children Looking for class-code in PCI children breaks with direct slots. Lets just count all children. Signed-off-by: Anton Blanchard Acked-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/iommu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2f66dc6503ff..d03a8b078f9d 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -331,13 +331,9 @@ static void iommu_bus_setup_pSeries(struct pci_bus *bus) if (isa_dn_orig) of_node_put(isa_dn_orig); - /* Count number of direct PCI children of the PHB. - * All PCI device nodes have class-code property, so it's - * an easy way to find them. - */ + /* Count number of direct PCI children of the PHB. */ for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) - if (get_property(tmp, "class-code", NULL)) - children++; + children++; DBG("Children: %d\n", children); -- cgit From ccba051c373e342de240ba00d542dac67ae0eb7e Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Tue, 20 Jun 2006 18:01:58 +1000 Subject: [POWERPC] Extra sanity check in EEH code Don't dereference a device node that isn't there. A "shouldn't happen" case, but someone ran into it with a possibly misconfigured device tree. Signed-off-by: Nathan Lynch Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh_cache.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/powerpc/platforms') diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index d4a402c5866c..98c23aec85be 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c @@ -304,6 +304,8 @@ void __init pci_addr_cache_build(void) pci_addr_cache_insert_device(dev); dn = pci_device_to_OF_node(dev); + if (!dn) + continue; pci_dev_get (dev); /* matching put is in eeh_remove_device() */ PCI_DN(dn)->pcidev = dev; } -- cgit