From 99ddef9bfe714c3273e3fce4c6b6a2a99e7d0bf8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 17 Feb 2007 18:17:16 -0700 Subject: [POWERPC] Fix compile error in prom.h In file included from include/asm/pci.h:20, from include/linux/pci.h:751, from arch/powerpc/sysdev/dart_iommu.c:36: include/asm/prom.h: In function `of_irq_to_resource': include/asm/prom.h:341: warning: implicit declaration of function `irq_of_parse_and_map' include/asm/prom.h:345: error: `NO_IRQ' undeclared (first use in this function) include/asm/prom.h:345: error: (Each undeclared identifier is reported only once include/asm/prom.h:345: error: for each function it appears in.) Seems that prom.h has always wanted irq.h. Cc: Mathieu Desnoyers Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- include/asm-powerpc/prom.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 020ed015a94b..1aa15e2e056e 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -18,6 +18,7 @@ #include #include #include +#include #include /* Definitions used by the flattened device tree */ -- cgit v1.2.3-59-g8ed1b From 02567c6cdad4d6254052f25f3b93aa2771f48d25 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 21 Feb 2007 14:53:50 +1100 Subject: [POWERPC] Allocate syscall number for sys_getcpu I forgot to do this when wiring up the syscall. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- include/asm-powerpc/unistd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 0ae954e3d258..bcc21bf56a12 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -324,10 +324,11 @@ #define __NR_get_robust_list 299 #define __NR_set_robust_list 300 #define __NR_move_pages 301 +#define __NR_getcpu 302 #ifdef __KERNEL__ -#define __NR_syscalls 302 +#define __NR_syscalls 303 #define __NR__exit __NR_exit #define NR_syscalls __NR_syscalls -- cgit v1.2.3-59-g8ed1b From dbc11f539df7c9a32424b78afb0314c68d5e7d0b Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Sun, 25 Feb 2007 20:04:18 +0100 Subject: [POWERPC] Include stddef.h in asm-powerpc/current.h to get offsetof On Tue, Oct 31, Hugh Dickins wrote: > +++ linux/include/asm-powerpc/current.h 2006-10-30 19:27:05.000000000 +0000 > +static inline struct task_struct *get_current(void) > +{ > + struct task_struct *task; > + > + __asm__ __volatile__("ld %0,%1(13)" > + : "=r" (task) > + : "i" (offsetof(struct paca_struct, __current))); This breaks compile of 2.6.18.8: CC [M] drivers/media/video/pwc/pwc-uncompress.o In file included from /home/olaf/kernel/linux-2.6.18.8/drivers/media/video/pwc/pwc-uncompress.c:29: include2/asm/current.h: In function 'get_current': include2/asm/current.h:23: warning: implicit declaration of function 'offsetof' include2/asm/current.h:23: error: expected expression before 'struct' make[5]: *** [drivers/media/video/pwc/pwc-uncompress.o] Error 1 Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- include/asm-powerpc/current.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-powerpc/current.h b/include/asm-powerpc/current.h index b8708aedf925..e2c7f06931e7 100644 --- a/include/asm-powerpc/current.h +++ b/include/asm-powerpc/current.h @@ -12,6 +12,7 @@ struct task_struct; #ifdef __powerpc64__ +#include #include static inline struct task_struct *get_current(void) -- cgit v1.2.3-59-g8ed1b From 723ec731de880a76a004a304b62bf8d0f96435d8 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Fri, 2 Mar 2007 13:36:21 -0700 Subject: [POWERPC] EDAC ECC software scrubber Implements the per arch atomic_scrub() that EDAC uses for software ECC scrubbing. It reads memory and then writes back the original value, allowing the hardware to detect and correct memory errors. Signed-off-by: Dave Jiang Signed-off-by: Paul Mackerras --- include/asm-powerpc/edac.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 include/asm-powerpc/edac.h (limited to 'include') diff --git a/include/asm-powerpc/edac.h b/include/asm-powerpc/edac.h new file mode 100644 index 000000000000..6ead88bbfbb8 --- /dev/null +++ b/include/asm-powerpc/edac.h @@ -0,0 +1,40 @@ +/* + * PPC EDAC common defs + * + * Author: Dave Jiang + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef ASM_EDAC_H +#define ASM_EDAC_H +/* + * ECC atomic, DMA, SMP and interrupt safe scrub function. + * Implements the per arch atomic_scrub() that EDAC use for software + * ECC scrubbing. It reads memory and then writes back the original + * value, allowing the hardware to detect and correct memory errors. + */ +static __inline__ void atomic_scrub(void *va, u32 size) +{ + unsigned int *virt_addr = va; + unsigned int temp; + unsigned int i; + + for (i = 0; i < size / sizeof(*virt_addr); i++, virt_addr++) { + /* Very carefully read and write to memory atomically + * so we are interrupt, DMA and SMP safe. + */ + __asm__ __volatile__ ("\n\ + 1: lwarx %0,0,%1\n\ + stwcx. %0,0,%1\n\ + bne- 1b\n\ + isync" + : "=&r"(temp) + : "r"(virt_addr) + : "cr0", "memory"); + } +} + +#endif -- cgit v1.2.3-59-g8ed1b From 9874777016e06ad2df420237963e81389776cb6d Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 4 Mar 2007 16:58:39 +1100 Subject: [POWERPC] Create and use set_pci_dma_ops This will allow us to build without PCI easier. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 5 +++++ arch/powerpc/platforms/cell/iommu.c | 4 ++-- arch/powerpc/platforms/celleb/iommu.c | 2 +- arch/powerpc/platforms/iseries/iommu.c | 2 +- arch/powerpc/platforms/pasemi/iommu.c | 4 ++-- arch/powerpc/platforms/pseries/iommu.c | 4 ++-- arch/powerpc/sysdev/dart_iommu.c | 4 ++-- include/asm-powerpc/pci.h | 6 +++++- 8 files changed, 20 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 7e97d71a5f8f..73d509343d5b 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -70,6 +70,11 @@ int global_phb_number; /* Global phb counter */ struct pci_dev *ppc64_isabridge_dev = NULL; EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); +void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) +{ + pci_dma_ops = dma_ops; +} + static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 67d617b60a23..d0e02ea1d538 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -646,7 +646,7 @@ static int __init cell_iommu_init_disabled(void) unsigned long base = 0, size; /* When no iommu is present, we use direct DMA ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); /* First make sure all IOC translation is turned off */ cell_disable_iommus(); @@ -734,7 +734,7 @@ static int __init cell_iommu_init(void) } /* Setup default PCI iommu ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); bail: /* Register callbacks on OF platform device addition/removal diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index f63b94c65353..fecc4ffd475e 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c @@ -95,7 +95,7 @@ static int __init celleb_init_iommu(void) return -ENODEV; celleb_init_direct_mapping(); - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); bus_register_notifier(&of_platform_bus_type, &celleb_of_bus_notifier); return 0; diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c index d7a756d5135c..7df2902271d0 100644 --- a/arch/powerpc/platforms/iseries/iommu.c +++ b/arch/powerpc/platforms/iseries/iommu.c @@ -194,5 +194,5 @@ void iommu_init_early_iSeries(void) ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free = tce_free_iSeries; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/platforms/pasemi/iommu.c b/arch/powerpc/platforms/pasemi/iommu.c index 459a53b7d24d..4587c1dfeda5 100644 --- a/arch/powerpc/platforms/pasemi/iommu.c +++ b/arch/powerpc/platforms/pasemi/iommu.c @@ -255,7 +255,7 @@ void iommu_init_early_pasemi(void) /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_null; ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_null; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -266,7 +266,7 @@ void iommu_init_early_pasemi(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pasemi; ppc_md.tce_build = iobmap_build; ppc_md.tce_free = iobmap_free; - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } void __init alloc_iobmap_l2(void) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index e6653a868b91..9322f74e1d8b 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -562,7 +562,7 @@ void iommu_init_early_pSeries(void) /* Direct I/O, IOMMU off */ ppc_md.pci_dma_dev_setup = NULL; ppc_md.pci_dma_bus_setup = NULL; - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); return; } @@ -588,6 +588,6 @@ void iommu_init_early_pSeries(void) pSeries_reconfig_notifier_register(&iommu_reconfig_nb); - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); } diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 1488535b0e13..336186dd7f10 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c @@ -333,7 +333,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; /* Setup pci_dma ops */ - pci_dma_ops = &dma_iommu_ops; + set_pci_dma_ops(&dma_iommu_ops); return; } @@ -343,7 +343,7 @@ void iommu_init_early_dart(void) ppc_md.pci_dma_bus_setup = NULL; /* Setup pci_dma ops */ - pci_dma_ops = &dma_direct_ops; + set_pci_dma_ops(&dma_direct_ops); } diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index ac656ee6bb19..ebf31f1c5915 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -70,8 +70,11 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) */ #define PCI_DISABLE_MWI +#ifdef CONFIG_PCI extern struct dma_mapping_ops *pci_dma_ops; +extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops); + /* For DAC DMA, we currently don't support it by default, but * we let 64-bit platforms override this. */ @@ -82,7 +85,6 @@ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) return 0; } -#ifdef CONFIG_PCI static inline void pci_dma_burst_advice(struct pci_dev *pdev, enum pci_dma_burst_strategy *strat, unsigned long *strategy_parameter) @@ -99,6 +101,8 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, *strat = PCI_DMA_BURST_MULTIPLE; *strategy_parameter = cacheline_size; } +#else /* CONFIG_PCI */ +#define set_pci_dma_ops(d) #endif extern int pci_domain_nr(struct pci_bus *bus); -- cgit v1.2.3-59-g8ed1b From 57190708f1f52d732d94fa21a8e576302d384d33 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 4 Mar 2007 17:02:41 +1100 Subject: [POWERPC] Create and use get_pci_dma_ops() This allows us to hide pci_dma_ops. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_64.c | 9 +++++++-- arch/powerpc/platforms/cell/iommu.c | 4 ++-- arch/powerpc/platforms/celleb/iommu.c | 2 +- include/asm-powerpc/pci.h | 10 ++++++---- 4 files changed, 16 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 73d509343d5b..db1d40ef7d60 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -61,8 +61,7 @@ void iSeries_pcibios_init(void); LIST_HEAD(hose_list); -struct dma_mapping_ops *pci_dma_ops; -EXPORT_SYMBOL(pci_dma_ops); +static struct dma_mapping_ops *pci_dma_ops; int global_phb_number; /* Global phb counter */ @@ -75,6 +74,12 @@ void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) pci_dma_ops = dma_ops; } +struct dma_mapping_ops *get_pci_dma_ops(void) +{ + return pci_dma_ops; +} +EXPORT_SYMBOL(get_pci_dma_ops); + static void fixup_broken_pcnet32(struct pci_dev* dev) { if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index d0e02ea1d538..7c953cc022f6 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -496,7 +496,7 @@ static void cell_dma_dev_setup(struct device *dev) struct dev_archdata *archdata = &dev->archdata; /* If we run without iommu, no need to do anything */ - if (pci_dma_ops == &dma_direct_ops) + if (get_pci_dma_ops() == &dma_direct_ops) return; /* Current implementation uses the first window available in that @@ -530,7 +530,7 @@ static int cell_of_bus_notify(struct notifier_block *nb, unsigned long action, return 0; /* We use the PCI DMA ops */ - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); cell_dma_dev_setup(dev); diff --git a/arch/powerpc/platforms/celleb/iommu.c b/arch/powerpc/platforms/celleb/iommu.c index fecc4ffd475e..e94de6a24622 100644 --- a/arch/powerpc/platforms/celleb/iommu.c +++ b/arch/powerpc/platforms/celleb/iommu.c @@ -80,7 +80,7 @@ static int celleb_of_bus_notify(struct notifier_block *nb, if (action != BUS_NOTIFY_ADD_DEVICE) return 0; - dev->archdata.dma_ops = pci_dma_ops; + dev->archdata.dma_ops = get_pci_dma_ops(); return 0; } diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index ebf31f1c5915..ce0f13e8eb14 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -71,17 +71,18 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) #define PCI_DISABLE_MWI #ifdef CONFIG_PCI -extern struct dma_mapping_ops *pci_dma_ops; - extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops); +extern struct dma_mapping_ops *get_pci_dma_ops(void); /* For DAC DMA, we currently don't support it by default, but * we let 64-bit platforms override this. */ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask) { - if (pci_dma_ops && pci_dma_ops->dac_dma_supported) - return pci_dma_ops->dac_dma_supported(&hwdev->dev, mask); + struct dma_mapping_ops *d = get_pci_dma_ops(); + + if (d && d->dac_dma_supported) + return d->dac_dma_supported(&hwdev->dev, mask); return 0; } @@ -103,6 +104,7 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev, } #else /* CONFIG_PCI */ #define set_pci_dma_ops(d) +#define get_pci_dma_ops() NULL #endif extern int pci_domain_nr(struct pci_bus *bus); -- cgit v1.2.3-59-g8ed1b From bed59275810a55500e885cbdc5c2a0507f13c00e Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 4 Mar 2007 17:04:44 +1100 Subject: [POWERPC] Allow pSeries to build without CONFIG_PCI Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig | 5 ++-- arch/powerpc/kernel/Makefile | 4 +-- arch/powerpc/platforms/pseries/Makefile | 5 ++-- arch/powerpc/platforms/pseries/iommu.c | 53 +++++++++++++++++++-------------- arch/powerpc/platforms/pseries/setup.c | 5 ++++ drivers/video/Kconfig | 2 +- include/asm-powerpc/ppc-pci.h | 7 +++++ 7 files changed, 51 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 6dfbd52694ab..e7205273ff37 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -89,7 +89,7 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER config ARCH_MAY_HAVE_PC_FDC bool - default y + default !PPC_PSERIES || PCI config PPC_OF def_bool y @@ -1028,7 +1028,8 @@ config MCA config PCI bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \ - || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3 + || PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \ + || MPC7448HPC2 || PPC_PS3 default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \ && !PPC_85xx && !PPC_86xx default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8120d428ebfd..e0fa80eca366 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -25,8 +25,8 @@ obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o procfs-$(CONFIG_PPC64) := proc_ppc64.o obj-$(CONFIG_PROC_FS) += $(procfs-y) -rtaspci-$(CONFIG_PPC64) := rtas_pci.o -obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y) +rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o +obj-$(CONFIG_PPC_RTAS) += rtas.o rtas-rtc.o $(rtaspci-y-y) obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_RTAS_PROC) += rtas-proc.o obj-$(CONFIG_LPARCFG) += lparcfg.o diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 2dfd05095a25..90235d598751 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,14 +2,15 @@ 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 \ +obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + setup.o iommu.o ras.o rtasd.o \ firmware.o power.o obj-$(CONFIG_SMP) += smp.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 obj-$(CONFIG_KEXEC) += kexec.o +obj-$(CONFIG_PCI) += pci.o pci_dlpar.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 9322f74e1d8b..f9510a5a3e21 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -242,6 +242,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) return tce_ret; } +#ifdef CONFIG_PCI static void iommu_table_setparms(struct pci_controller *phb, struct device_node *dn, struct iommu_table *tbl) @@ -478,29 +479,6 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev) pci_name(dev)); } -static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) -{ - int err = NOTIFY_OK; - struct device_node *np = node; - struct pci_dn *pci = PCI_DN(np); - - switch (action) { - case PSERIES_RECONFIG_REMOVE: - if (pci && pci->iommu_table && - get_property(np, "ibm,dma-window", NULL)) - iommu_free_table(np); - break; - default: - err = NOTIFY_DONE; - break; - } - return err; -} - -static struct notifier_block iommu_reconfig_nb = { - .notifier_call = iommu_reconfig_notifier, -}; - static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) { struct device_node *pdn, *dn; @@ -554,6 +532,35 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) dev->dev.archdata.dma_data = pci->iommu_table; } +#else /* CONFIG_PCI */ +#define pci_dma_bus_setup_pSeries NULL +#define pci_dma_dev_setup_pSeries NULL +#define pci_dma_bus_setup_pSeriesLP NULL +#define pci_dma_dev_setup_pSeriesLP NULL +#endif /* !CONFIG_PCI */ + +static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) +{ + int err = NOTIFY_OK; + struct device_node *np = node; + struct pci_dn *pci = PCI_DN(np); + + switch (action) { + case PSERIES_RECONFIG_REMOVE: + if (pci && pci->iommu_table && + get_property(np, "ibm,dma-window", NULL)) + iommu_free_table(np); + break; + default: + err = NOTIFY_DONE; + break; + } + return err; +} + +static struct notifier_block iommu_reconfig_nb = { + .notifier_call = iommu_reconfig_notifier, +}; /* These are called very early. */ void iommu_init_early_pSeries(void) diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 34aff47b1f55..ff87b1ad8ce9 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -65,6 +65,7 @@ #include #include #include +#include #include "plpar_wrappers.h" #include "pseries.h" @@ -514,6 +515,10 @@ void pSeries_power_off(void) for (;;); } +#ifndef CONFIG_PCI +void pSeries_final_fixup(void) { } +#endif + define_machine(pseries) { .name = "pSeries", .probe = pSeries_probe, diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 7f5a59836818..35d2abd1ed50 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -396,7 +396,7 @@ config FB_ATARI config FB_OF bool "Open Firmware frame buffer device support" - depends on (FB = y) && (PPC64 || PPC_OF) + depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index ab6eddb518c7..4a053404bf6b 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -10,6 +10,8 @@ #define _ASM_POWERPC_PPC_PCI_H #ifdef __KERNEL__ +#ifdef CONFIG_PCI + #include #include @@ -126,5 +128,10 @@ struct device_node * find_device_pe(struct device_node *dn); #endif +#else /* CONFIG_PCI */ +static inline void find_and_init_phbs(void) { } +static inline void init_pci_config_tokens(void) { } +#endif /* !CONFIG_PCI */ + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PPC_PCI_H */ -- cgit v1.2.3-59-g8ed1b From 36241ce695f16193d0f76ea010f212119da37071 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 4 Mar 2007 17:07:38 +1100 Subject: [POWERPC] Make find_and_init_pbs() a void function It always returned 0 and noone checked. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/rtas_pci.c | 4 +--- include/asm-powerpc/ppc-pci.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index ace9f4c86e67..1616a44ac608 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -274,7 +274,7 @@ int __devinit rtas_setup_phb(struct pci_controller *phb) return 0; } -unsigned long __init find_and_init_phbs(void) +void __init find_and_init_phbs(void) { struct device_node *node; struct pci_controller *phb; @@ -319,8 +319,6 @@ unsigned long __init find_and_init_phbs(void) if (prop) pci_assign_all_buses = *prop; } - - return 0; } /* RPA-specific bits for removing PHBs */ diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index 4a053404bf6b..f186720d0739 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -24,7 +24,7 @@ extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary); extern struct list_head hose_list; extern int global_phb_number; -extern unsigned long find_and_init_phbs(void); +extern void find_and_init_phbs(void); extern struct pci_dev *ppc64_isabridge_dev; /* may be NULL if no ISA bus */ -- cgit v1.2.3-59-g8ed1b From a83088003cd53f3cd8d550ab5d7778866568d204 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Fri, 9 Mar 2007 18:56:46 +0100 Subject: [POWERPC] ibmebus: whitespace fixes This fixes a lot of whitespace in ibmebus.[ch] Signed-off-by: Joachim Fenkes Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ibmebus.c | 126 +++++++++++++++++++++--------------------- include/asm-powerpc/ibmebus.h | 42 +++++++------- 2 files changed, 84 insertions(+), 84 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 82bd2f10770f..061df3a066ae 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -3,35 +3,35 @@ * * Copyright (c) 2005 IBM Corporation * Heiko J Schick - * + * * All rights reserved. * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. + * This source code is distributed under a dual license of GPL v2.0 and OpenIB + * BSD. * * OpenIB BSD License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials - * provided with the distribution. + * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @@ -55,7 +55,7 @@ static void *ibmebus_alloc_coherent(struct device *dev, gfp_t flag) { void *mem; - + mem = kmalloc(size, flag); *dma_handle = (dma_addr_t)mem; @@ -63,7 +63,7 @@ static void *ibmebus_alloc_coherent(struct device *dev, } static void ibmebus_free_coherent(struct device *dev, - size_t size, void *vaddr, + size_t size, void *vaddr, dma_addr_t dma_handle) { kfree(vaddr); @@ -79,7 +79,7 @@ static dma_addr_t ibmebus_map_single(struct device *dev, static void ibmebus_unmap_single(struct device *dev, dma_addr_t dma_addr, - size_t size, + size_t size, enum dma_data_direction direction) { return; @@ -90,13 +90,13 @@ static int ibmebus_map_sg(struct device *dev, int nents, enum dma_data_direction direction) { int i; - + for (i = 0; i < nents; i++) { - sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].dma_address = (dma_addr_t)page_address(sg[i].page) + sg[i].offset; sg[i].dma_length = sg[i].length; } - + return nents; } @@ -128,15 +128,15 @@ static int ibmebus_bus_probe(struct device *dev) struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); const struct of_device_id *id; int error = -ENODEV; - + if (!ibmebusdrv->probe) return error; - + id = of_match_device(ibmebusdrv->id_table, &ibmebusdev->ofdev); if (id) { error = ibmebusdrv->probe(ibmebusdev, id); } - + return error; } @@ -144,11 +144,11 @@ static int ibmebus_bus_remove(struct device *dev) { struct ibmebus_dev *ibmebusdev = to_ibmebus_dev(dev); struct ibmebus_driver *ibmebusdrv = to_ibmebus_driver(dev->driver); - + if (ibmebusdrv->remove) { return ibmebusdrv->remove(ibmebusdev); } - + return 0; } @@ -158,12 +158,12 @@ static void __devinit ibmebus_dev_release(struct device *dev) kfree(to_ibmebus_dev(dev)); } -static ssize_t ibmebusdev_show_name(struct device *dev, +static ssize_t ibmebusdev_show_name(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name); } -static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name, +static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name, NULL); static struct ibmebus_dev* __devinit ibmebus_register_device_common( @@ -181,16 +181,16 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( dev->ofdev.dev.archdata.numa_node = of_node_to_nid(dev->ofdev.node); /* An ibmebusdev is based on a of_device. We have to change the - * bus type to use our own DMA mapping operations. - */ + * bus type to use our own DMA mapping operations. + */ if ((err = of_device_register(&dev->ofdev)) != 0) { printk(KERN_ERR "%s: failed to register device (%d).\n", __FUNCTION__, err); return NULL; } - + device_create_file(&dev->ofdev.dev, &dev_attr_name); - + return dev; } @@ -207,7 +207,7 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( __FUNCTION__, dn->name ? dn->name : ""); return NULL; } - + if (strlen(loc_code) == 0) { printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n", __FUNCTION__); @@ -220,10 +220,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( } dev->ofdev.node = of_node_get(dn); - + length = strlen(loc_code); - memcpy(dev->ofdev.dev.bus_id, loc_code - + (length - min(length, BUS_ID_SIZE - 1)), + memcpy(dev->ofdev.dev.bus_id, loc_code + + (length - min(length, BUS_ID_SIZE - 1)), min(length, BUS_ID_SIZE - 1)); /* Register with generic device framework. */ @@ -238,17 +238,17 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( static void ibmebus_probe_of_nodes(char* name) { struct device_node *dn = NULL; - + while ((dn = of_find_node_by_name(dn, name))) { if (ibmebus_register_device_node(dn) == NULL) { of_node_put(dn); - + return; } } - + of_node_put(dn); - + return; } @@ -266,7 +266,7 @@ static int ibmebus_match_helper(struct device *dev, void *data) { if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0) return 1; - + return 0; } @@ -281,17 +281,17 @@ static int ibmebus_unregister_device(struct device *dev) static void ibmebus_remove_devices_by_id(struct of_device_id *idt) { struct device *dev; - + while (strlen(idt->name) > 0) { - while ((dev = bus_find_device(&ibmebus_bus_type, NULL, + while ((dev = bus_find_device(&ibmebus_bus_type, NULL, (void*)idt->name, ibmebus_match_helper))) { ibmebus_unregister_device(dev); } idt++; - + } - + return; } @@ -308,29 +308,29 @@ int ibmebus_register_driver(struct ibmebus_driver *drv) return err; ibmebus_add_devices_by_id(drv->id_table); - + return 0; } EXPORT_SYMBOL(ibmebus_register_driver); void ibmebus_unregister_driver(struct ibmebus_driver *drv) -{ +{ driver_unregister(&drv->driver); ibmebus_remove_devices_by_id(drv->id_table); } EXPORT_SYMBOL(ibmebus_unregister_driver); int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, + u32 ist, irq_handler_t handler, unsigned long irq_flags, const char * devname, void *dev_id) { unsigned int irq = irq_create_mapping(NULL, ist); - + if (irq == NO_IRQ) return -EINVAL; - + return request_irq(irq, handler, irq_flags, devname, dev_id); } @@ -339,25 +339,25 @@ EXPORT_SYMBOL(ibmebus_request_irq); void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { unsigned int irq = irq_find_mapping(NULL, ist); - + free_irq(irq, dev_id); } EXPORT_SYMBOL(ibmebus_free_irq); static int ibmebus_bus_match(struct device *dev, struct device_driver *drv) -{ +{ const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); struct ibmebus_driver *ebus_drv = to_ibmebus_driver(drv); const struct of_device_id *ids = ebus_drv->id_table; const struct of_device_id *found_id; - + if (!ids) return 0; - + found_id = of_match_device(ids, &ebus_dev->ofdev); if (found_id) return 1; - + return 0; } @@ -370,25 +370,25 @@ EXPORT_SYMBOL(ibmebus_bus_type); static int __init ibmebus_bus_init(void) { int err; - + printk(KERN_INFO "IBM eBus Device Driver\n"); - + err = bus_register(&ibmebus_bus_type); if (err) { printk(KERN_ERR ":%s: failed to register IBM eBus.\n", __FUNCTION__); return err; } - + err = device_register(&ibmebus_bus_device.ofdev.dev); if (err) { - printk(KERN_WARNING "%s: device_register returned %i\n", + printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, err); bus_unregister(&ibmebus_bus_type); return err; } - + return 0; } __initcall(ibmebus_bus_init); diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 66112114b8c5..8d3c9e39b90f 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h @@ -3,35 +3,35 @@ * * Copyright (c) 2005 IBM Corporation * Heiko J Schick - * + * * All rights reserved. * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. + * This source code is distributed under a dual license of GPL v2.0 and OpenIB + * BSD. * * OpenIB BSD License * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation * and/or other materials - * provided with the distribution. + * provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ @@ -46,12 +46,12 @@ extern struct bus_type ibmebus_bus_type; -struct ibmebus_dev { +struct ibmebus_dev { const char *name; struct of_device ofdev; }; -struct ibmebus_driver { +struct ibmebus_driver { char *name; struct of_device_id *id_table; int (*probe) (struct ibmebus_dev *dev, const struct of_device_id *id); @@ -63,7 +63,7 @@ int ibmebus_register_driver(struct ibmebus_driver *drv); void ibmebus_unregister_driver(struct ibmebus_driver *drv); int ibmebus_request_irq(struct ibmebus_dev *dev, - u32 ist, + u32 ist, irq_handler_t handler, unsigned long irq_flags, const char * devname, void *dev_id); -- cgit v1.2.3-59-g8ed1b From 6bccf755ff53241d46c01c229b3c2452b9029ec4 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Fri, 9 Mar 2007 19:00:32 +0100 Subject: [POWERPC] ibmebus: dynamic addition/removal of adapters, some code cleanup This adds two sysfs attributes to /sys/bus/ibmebus which can be used to notify the ebus driver of added / removed ebus devices in the OF device tree. Echoing the device's location code (as found in the OFDT "ibm,loc-code" property) into the "probe" attribute will notify ebus of addition of the device and cause the appropriate device driver's probe function to be called on the device. Likewise, echoing the location code into the "remove" attribute will cause the device to be removed from the system. The writes will block until the respective operation has finished and return an error code if the operation failed. In addition, two minor tidbits are fixed: - The fake root device used to provide a common parent for all ebus devices is now based on device instead of of_device - it had no associated devtree node. This saves several checks throughout the ebus driver. - The sysfs attributes are now generated automagically by device_register() instead of by the ibmebus code, which saves a few compiler warnings about unused return codes. Signed-off-by: Joachim Fenkes Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/ibmebus.c | 167 +++++++++++++++++++++++++++++++++--------- include/asm-powerpc/ibmebus.h | 2 +- 2 files changed, 134 insertions(+), 35 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 061df3a066ae..8ed1163c0bd4 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -2,6 +2,7 @@ * IBM PowerPC IBM eBus Infrastructure Support. * * Copyright (c) 2005 IBM Corporation + * Joachim Fenkes * Heiko J Schick * * All rights reserved. @@ -43,12 +44,14 @@ #include #include -static struct ibmebus_dev ibmebus_bus_device = { /* fake "parent" device */ - .name = ibmebus_bus_device.ofdev.dev.bus_id, - .ofdev.dev.bus_id = "ibmebus", - .ofdev.dev.bus = &ibmebus_bus_type, +#define MAX_LOC_CODE_LENGTH 80 + +static struct device ibmebus_bus_device = { /* fake "parent" device */ + .bus_id = "ibmebus", }; +struct bus_type ibmebus_bus_type; + static void *ibmebus_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, @@ -158,21 +161,12 @@ static void __devinit ibmebus_dev_release(struct device *dev) kfree(to_ibmebus_dev(dev)); } -static ssize_t ibmebusdev_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", to_ibmebus_dev(dev)->name); -} -static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name, - NULL); - -static struct ibmebus_dev* __devinit ibmebus_register_device_common( +static int __devinit ibmebus_register_device_common( struct ibmebus_dev *dev, const char *name) { int err = 0; - dev->name = name; - dev->ofdev.dev.parent = &ibmebus_bus_device.ofdev.dev; + dev->ofdev.dev.parent = &ibmebus_bus_device; dev->ofdev.dev.bus = &ibmebus_bus_type; dev->ofdev.dev.release = ibmebus_dev_release; @@ -186,12 +180,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_common( if ((err = of_device_register(&dev->ofdev)) != 0) { printk(KERN_ERR "%s: failed to register device (%d).\n", __FUNCTION__, err); - return NULL; + return -ENODEV; } - device_create_file(&dev->ofdev.dev, &dev_attr_name); - - return dev; + return 0; } static struct ibmebus_dev* __devinit ibmebus_register_device_node( @@ -205,18 +197,18 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( if (!loc_code) { printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n", __FUNCTION__, dn->name ? dn->name : ""); - return NULL; + return ERR_PTR(-EINVAL); } if (strlen(loc_code) == 0) { printk(KERN_WARNING "%s: 'ibm,loc-code' is invalid\n", __FUNCTION__); - return NULL; + return ERR_PTR(-EINVAL); } dev = kzalloc(sizeof(struct ibmebus_dev), GFP_KERNEL); if (!dev) { - return NULL; + return ERR_PTR(-ENOMEM); } dev->ofdev.node = of_node_get(dn); @@ -227,9 +219,9 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node( min(length, BUS_ID_SIZE - 1)); /* Register with generic device framework. */ - if (ibmebus_register_device_common(dev, dn->name) == NULL) { + if (ibmebus_register_device_common(dev, dn->name) != 0) { kfree(dev); - return NULL; + return ERR_PTR(-ENODEV); } return dev; @@ -240,9 +232,8 @@ static void ibmebus_probe_of_nodes(char* name) struct device_node *dn = NULL; while ((dn = of_find_node_by_name(dn, name))) { - if (ibmebus_register_device_node(dn) == NULL) { + if (IS_ERR(ibmebus_register_device_node(dn))) { of_node_put(dn); - return; } } @@ -262,9 +253,15 @@ static void ibmebus_add_devices_by_id(struct of_device_id *idt) return; } -static int ibmebus_match_helper(struct device *dev, void *data) +static int ibmebus_match_helper_name(struct device *dev, void *data) { - if (strcmp((char*)data, to_ibmebus_dev(dev)->name) == 0) + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + char *name; + + name = (char*)get_property( + ebus_dev->ofdev.node, "name", NULL); + + if (name && (strcmp((char*)data, name) == 0)) return 1; return 0; @@ -272,7 +269,6 @@ static int ibmebus_match_helper(struct device *dev, void *data) static int ibmebus_unregister_device(struct device *dev) { - device_remove_file(dev, &dev_attr_name); of_device_unregister(to_of_device(dev)); return 0; @@ -285,11 +281,10 @@ static void ibmebus_remove_devices_by_id(struct of_device_id *idt) while (strlen(idt->name) > 0) { while ((dev = bus_find_device(&ibmebus_bus_type, NULL, (void*)idt->name, - ibmebus_match_helper))) { + ibmebus_match_helper_name))) { ibmebus_unregister_device(dev); } idt++; - } return; @@ -307,6 +302,9 @@ int ibmebus_register_driver(struct ibmebus_driver *drv) if ((err = driver_register(&drv->driver) != 0)) return err; + /* remove all supported devices first, in case someone + * probed them manually before registering the driver */ + ibmebus_remove_devices_by_id(drv->id_table); ibmebus_add_devices_by_id(drv->id_table); return 0; @@ -361,9 +359,110 @@ static int ibmebus_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + char *name = (char*)get_property(ebus_dev->ofdev.node, "name", NULL); + return sprintf(buf, "%s\n", name); +} + +static struct device_attribute ibmebus_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_NULL +}; + +static int ibmebus_match_helper_loc_code(struct device *dev, void *data) +{ + const struct ibmebus_dev *ebus_dev = to_ibmebus_dev(dev); + char *loc_code; + + loc_code = (char*)get_property( + ebus_dev->ofdev.node, "ibm,loc-code", NULL); + + if (loc_code && (strcmp((char*)data, loc_code) == 0)) + return 1; + + return 0; +} + +static ssize_t ibmebus_store_probe(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device_node *dn = NULL; + struct ibmebus_dev *dev; + char *loc_code; + char parm[MAX_LOC_CODE_LENGTH]; + + if (count >= MAX_LOC_CODE_LENGTH) + return -EINVAL; + memcpy(parm, buf, count); + parm[count] = '\0'; + if (parm[count-1] == '\n') + parm[count-1] = '\0'; + + if (bus_find_device(&ibmebus_bus_type, NULL, parm, + ibmebus_match_helper_loc_code)) { + printk(KERN_WARNING "%s: loc_code %s has already been probed\n", + __FUNCTION__, parm); + return -EINVAL; + } + + while ((dn = of_find_all_nodes(dn))) { + loc_code = (char *)get_property(dn, "ibm,loc-code", NULL); + if (loc_code && (strncmp(loc_code, parm, count) == 0)) { + dev = ibmebus_register_device_node(dn); + if (IS_ERR(dev)) { + of_node_put(dn); + return PTR_ERR(dev); + } else + return count; /* success */ + } + } + + /* if we drop out of the loop, the loc code was invalid */ + printk(KERN_WARNING "%s: no device with loc_code %s found\n", + __FUNCTION__, parm); + return -ENODEV; +} + +static ssize_t ibmebus_store_remove(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device *dev; + char parm[MAX_LOC_CODE_LENGTH]; + + if (count >= MAX_LOC_CODE_LENGTH) + return -EINVAL; + memcpy(parm, buf, count); + parm[count] = '\0'; + if (parm[count-1] == '\n') + parm[count-1] = '\0'; + + /* The location code is unique, so we will find one device at most */ + if ((dev = bus_find_device(&ibmebus_bus_type, NULL, parm, + ibmebus_match_helper_loc_code))) { + ibmebus_unregister_device(dev); + } else { + printk(KERN_WARNING "%s: loc_code %s not on the bus\n", + __FUNCTION__, parm); + return -ENODEV; + } + + return count; +} + +static struct bus_attribute ibmebus_bus_attrs[] = { + __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe), + __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove), + __ATTR_NULL +}; + struct bus_type ibmebus_bus_type = { - .name = "ibmebus", - .match = ibmebus_bus_match, + .name = "ibmebus", + .match = ibmebus_bus_match, + .dev_attrs = ibmebus_dev_attrs, + .bus_attrs = ibmebus_bus_attrs }; EXPORT_SYMBOL(ibmebus_bus_type); @@ -380,7 +479,7 @@ static int __init ibmebus_bus_init(void) return err; } - err = device_register(&ibmebus_bus_device.ofdev.dev); + err = device_register(&ibmebus_bus_device); if (err) { printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__, err); diff --git a/include/asm-powerpc/ibmebus.h b/include/asm-powerpc/ibmebus.h index 8d3c9e39b90f..87d396e28db2 100644 --- a/include/asm-powerpc/ibmebus.h +++ b/include/asm-powerpc/ibmebus.h @@ -2,6 +2,7 @@ * IBM PowerPC eBus Infrastructure Support. * * Copyright (c) 2005 IBM Corporation + * Joachim Fenkes * Heiko J Schick * * All rights reserved. @@ -47,7 +48,6 @@ extern struct bus_type ibmebus_bus_type; struct ibmebus_dev { - const char *name; struct of_device ofdev; }; -- cgit v1.2.3-59-g8ed1b From 0e0293c898c424c52e5d4e7f6923a203d06b9c4b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 14 Mar 2007 11:50:40 +1100 Subject: [POWERPC] Update documentation for flat device tree format v17 This patch updates booting-without-of.txt to describe version 17 of the flattened device tree format. Version 17 is a small, backwards compatible change from version 16, adding an extra field giving the size of the device tree's structure block. At this time, the kernel has no use for the extra information, however its presence can make life easier for bootloaders or other software manipulating the tree. In addition this patch adds information on the size_dt_strings field of the device tree header, present since version 3 of the flattened tree format, but omitted from the documentation. It also makes changes to consistently refer to versions 16 and 17 as versions 16 and 17 in decimal, rather than version 0x10 which was occasionally used for version 16 previously. Finally, we also add the new field to the definition of the device tree header structure in prom.h Signed-off-by: David Gibson Acked-by: Jon Loeliger Signed-off-by: Paul Mackerras --- Documentation/powerpc/booting-without-of.txt | 29 ++++++++++++++++++++++------ include/asm-powerpc/prom.h | 2 ++ 2 files changed, 25 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 6d5a5a0fa5e8..a1f83f1c24c9 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -265,6 +265,9 @@ struct boot_param_header { booting on */ /* version 3 fields below */ u32 size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + u32 size_dt_struct; /* size of the DT structure block */ }; Along with the constants: @@ -335,10 +338,13 @@ struct boot_param_header { to reallocate it easily at boot and free up the unused flattened structure after expansion. Version 16 introduces a new more "compact" format for the tree itself that is however not backward - compatible. You should always generate a structure of the highest - version defined at the time of your implementation. Currently - that is version 16, unless you explicitly aim at being backward - compatible. + compatible. Version 17 adds an additional field, size_dt_struct, + allowing it to be reallocated or moved more easily (this is + particularly useful for bootloaders which need to make + adjustments to a device tree based on probed information). You + should always generate a structure of the highest version defined + at the time of your implementation. Currently that is version 17, + unless you explicitly aim at being backward compatible. - last_comp_version @@ -347,7 +353,7 @@ struct boot_param_header { is backward compatible with version 1 (that is, a kernel build for version 1 will be able to boot with a version 2 format). You should put a 1 in this field if you generate a device tree of - version 1 to 3, or 0x10 if you generate a tree of version 0x10 + version 1 to 3, or 16 if you generate a tree of version 16 or 17 using the new unit name format. - boot_cpuid_phys @@ -360,6 +366,17 @@ struct boot_param_header { point (see further chapters for more informations on the required device-tree contents) + - size_dt_strings + + This field only exists on version 3 and later headers. It + gives the size of the "strings" section of the device tree (which + starts at the offset given by off_dt_strings). + + - size_dt_struct + + This field only exists on version 17 and later headers. It gives + the size of the "structure" section of the device tree (which + starts at the offset given by off_dt_struct). So the typical layout of a DT block (though the various parts don't need to be in that order) looks like this (addresses go from top to @@ -417,7 +434,7 @@ root node who has no parent. A node has 2 names. The actual node name is generally contained in a property of type "name" in the node property list whose value is a zero terminated string and is mandatory for version 1 to 3 of the -format definition (as it is in Open Firmware). Version 0x10 makes it +format definition (as it is in Open Firmware). Version 16 makes it optional as it can generate it from the unit name defined below. There is also a "unit name" that is used to differentiate nodes with diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 1aa15e2e056e..994de8ea3308 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -59,6 +59,8 @@ struct boot_param_header u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ /* version 3 fields below */ u32 dt_strings_size; /* size of the DT strings block */ + /* version 17 fields below */ + u32 dt_struct_size; /* size of the DT structure block */ }; -- cgit v1.2.3-59-g8ed1b From e91948fd84086020072e022d5463036033d449c1 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Fri, 16 Mar 2007 17:47:07 +1100 Subject: [POWERPC] Minor paca optimisation Move the slb_shadow_ptr field into the first cache line since it is (like everything there) read-only after boot. It is in fact statically initialised and thereafter only read. Signed-off-by: Stephen Rothwell Acked-by: Michael Neuling Signed-off-by: Paul Mackerras --- include/asm-powerpc/paca.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 0d3adc09c847..4de851d91f96 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -70,6 +70,7 @@ struct paca_struct { s16 hw_cpu_id; /* Physical processor number */ u8 cpu_start; /* At startup, processor spins until */ /* this becomes non-zero. */ + struct slb_shadow *slb_shadow_ptr; /* * Now, starting in cacheline 2, the exception save areas @@ -101,8 +102,6 @@ struct paca_struct { u64 user_time; /* accumulated usermode TB ticks */ u64 system_time; /* accumulated system TB ticks */ u64 startpurr; /* PURR/TB value snapshot */ - - struct slb_shadow *slb_shadow_ptr; }; extern struct paca_struct paca[]; -- cgit v1.2.3-59-g8ed1b From 9c547768e7d9f456f1b145102e75f79e30f7b709 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 19 Mar 2007 14:58:07 -0500 Subject: [POWERPC] EEH: wait for slot status Modify routine that returns PCI slot status to wait for slot status to become available. This is needed, as slots that are in some remote card cage may go offline for extended periods of time. New users for this routine in following patches. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh.c | 110 +++++++++++++++++++---------------- include/asm-powerpc/ppc-pci.h | 3 +- 2 files changed, 61 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index cb8a151bc9e7..c4604f71c962 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -76,6 +76,9 @@ */ #define EEH_MAX_FAILS 2100000 +/* Time to wait for a PCI slot to retport status, in milliseconds */ +#define PCI_BUS_RESET_WAIT_MSEC (60*1000) + /* RTAS tokens */ static int ibm_set_eeh_option; static int ibm_set_slot_reset; @@ -168,6 +171,55 @@ static int read_slot_reset_state(struct pci_dn *pdn, int rets[]) BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid)); } +/** + * eeh_wait_for_slot_status - returns error status of slot + * @pdn pci device node + * @max_wait_msecs maximum number to millisecs to wait + * + * Return negative value if a permanent error, else return + * Partition Endpoint (PE) status value. + * + * If @max_wait_msecs is positive, then this routine will + * sleep until a valid status can be obtained, or until + * the max allowed wait time is exceeded, in which case + * a -2 is returned. + */ +int +eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs) +{ + int rc; + int rets[3]; + int mwait; + + while (1) { + rc = read_slot_reset_state(pdn, rets); + if (rc) return rc; + if (rets[1] == 0) return -1; /* EEH is not supported */ + + if (rets[0] != 5) return rets[0]; /* return actual status */ + + if (rets[2] == 0) return -1; /* permanently unavailable */ + + if (max_wait_msecs <= 0) return -1; + + mwait = rets[2]; + if (mwait <= 0) { + printk (KERN_WARNING + "EEH: Firmware returned bad wait value=%d\n", mwait); + mwait = 1000; + } else if (mwait > 300*1000) { + printk (KERN_WARNING + "EEH: Firmware is taking too long, time=%d\n", mwait); + mwait = 300*1000; + } + max_wait_msecs -= mwait; + msleep (mwait); + } + + printk(KERN_WARNING "EEH: Timed out waiting for slot status\n"); + return -2; +} + /** * eeh_token_to_phys - convert EEH address token to phys address * @token i/o token, should be address in the form 0xA.... @@ -458,38 +510,6 @@ EXPORT_SYMBOL(eeh_check_failure); /* ------------------------------------------------------------- */ /* The code below deals with error recovery */ -/** - * eeh_slot_availability - returns error status of slot - * @pdn pci device node - * - * Return negative value if a permanent error, else return - * a number of milliseconds to wait until the PCI slot is - * ready to be used. - */ -static int -eeh_slot_availability(struct pci_dn *pdn) -{ - int rc; - int rets[3]; - - rc = read_slot_reset_state(pdn, rets); - - if (rc) return rc; - - if (rets[1] == 0) return -1; /* EEH is not supported */ - if (rets[0] == 0) return 0; /* Oll Korrect */ - if (rets[0] == 5) { - if (rets[2] == 0) return -1; /* permanently unavailable */ - return rets[2]; /* number of millisecs to wait */ - } - if (rets[0] == 1) - return 250; - - printk (KERN_ERR "EEH: Slot unavailable: rc=%d, rets=%d %d %d\n", - rc, rets[0], rets[1], rets[2]); - return -2; -} - /** * rtas_pci_enable - enable MMIO or DMA transfers for this slot * @pdn pci device node @@ -596,36 +616,24 @@ int rtas_set_slot_reset(struct pci_dn *pdn) { int i, rc; - __rtas_set_slot_reset(pdn); + /* Take three shots at resetting the bus */ + for (i=0; i<3; i++) { + __rtas_set_slot_reset(pdn); - /* Now double check with the firmware to make sure the device is - * ready to be used; if not, wait for recovery. */ - for (i=0; i<10; i++) { - rc = eeh_slot_availability (pdn); + rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC); if (rc == 0) return 0; - if (rc == -2) { - printk (KERN_ERR "EEH: failed (%d) to reset slot %s\n", - i, pdn->node->full_name); - __rtas_set_slot_reset(pdn); - continue; - } - if (rc < 0) { printk (KERN_ERR "EEH: unrecoverable slot failure %s\n", pdn->node->full_name); return -1; } - - msleep (rc+100); + printk (KERN_ERR "EEH: bus reset %d failed on slot %s\n", + i+1, pdn->node->full_name); } - rc = eeh_slot_availability (pdn); - if (rc) - printk (KERN_ERR "EEH: timeout resetting slot %s\n", pdn->node->full_name); - - return rc; + return -1; } /* ------------------------------------------------------- */ diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h index f186720d0739..d74b2965bb82 100644 --- a/include/asm-powerpc/ppc-pci.h +++ b/include/asm-powerpc/ppc-pci.h @@ -70,7 +70,7 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr); void eeh_slot_error_detail (struct pci_dn *pdn, int severity); /** - * rtas_pci_enableo - enable IO transfers for this slot + * rtas_pci_enable - enable IO transfers for this slot * @pdn: pci device node * @function: either EEH_THAW_MMIO or EEH_THAW_DMA * @@ -91,6 +91,7 @@ int rtas_pci_enable(struct pci_dn *pdn, int function); * Returns a non-zero value if the reset failed. */ int rtas_set_slot_reset (struct pci_dn *); +int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs); /** * eeh_restore_bars - Restore device configuration info. -- cgit v1.2.3-59-g8ed1b From d0ab95ca9854174029cef2f08acf1859441cb547 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Mon, 19 Mar 2007 14:59:10 -0500 Subject: [POWERPC] EEH: rm un-needed data The EEH event notification system passes around data that is not needed or at least, not used properly. Stop passing this data; get it in a more reliable fashion. Signed-off-by: Linas Vepstas Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/pseries/eeh.c | 8 +------- arch/powerpc/platforms/pseries/eeh_driver.c | 16 +++------------- arch/powerpc/platforms/pseries/eeh_event.c | 6 +----- include/asm-powerpc/eeh_event.h | 6 +----- 4 files changed, 6 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index c4604f71c962..1d05c9b55605 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -346,7 +346,6 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) int rets[3]; unsigned long flags; struct pci_dn *pdn; - enum pci_channel_state state; int rc = 0; total_mmio_ffs++; @@ -452,12 +451,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) eeh_mark_slot (dn, EEH_MODE_ISOLATED); spin_unlock_irqrestore(&confirm_error_lock, flags); - state = pci_channel_io_normal; - if ((rets[0] == 1) || (rets[0] == 2) || (rets[0] == 4)) - state = pci_channel_io_frozen; - if (rets[0] == 5) - state = pci_channel_io_perm_failure; - eeh_send_failure_event (dn, dev, state, rets[2]); + eeh_send_failure_event (dn, dev); /* Most EEH events are due to device driver bugs. Having * a stack trace will help the device-driver authors figure diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 5ec6edf19ece..6493f593687f 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -342,13 +342,6 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) return NULL; } -#if 0 - /* We may get "permanent failure" messages on empty slots. - * These are false alarms. Empty slots have no child dn. */ - if ((event->state == pci_channel_io_perm_failure) && (frozen_device == NULL)) - return; -#endif - frozen_pdn = PCI_DN(frozen_dn); frozen_pdn->eeh_freeze_count++; @@ -363,12 +356,9 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event) if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) goto excess_failures; - /* If the reset state is a '5' and the time to reset is 0 (infinity) - * or is more then 15 seconds, then mark this as a permanent failure. - */ - if ((event->state == pci_channel_io_perm_failure) && - ((event->time_unavail <= 0) || - (event->time_unavail > MAX_WAIT_FOR_RECOVERY*1000))) { + /* Get the current PCI slot state. */ + rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000); + if (rc < 0) { printk(KERN_WARNING "EEH: Permanent failure\n"); goto hard_fail; } diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 49037edf7d39..221dec8c16bd 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -118,9 +118,7 @@ static void eeh_thread_launcher(struct work_struct *dummy) * (from a workqueue). */ int eeh_send_failure_event (struct device_node *dn, - struct pci_dev *dev, - enum pci_channel_state state, - int time_unavail) + struct pci_dev *dev) { unsigned long flags; struct eeh_event *event; @@ -144,8 +142,6 @@ int eeh_send_failure_event (struct device_node *dn, event->dn = dn; event->dev = dev; - event->state = state; - event->time_unavail = time_unavail; /* We may or may not be called in an interrupt context */ spin_lock_irqsave(&eeh_eventlist_lock, flags); diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h index dc6bf0ffb796..cc3cb04539ac 100644 --- a/include/asm-powerpc/eeh_event.h +++ b/include/asm-powerpc/eeh_event.h @@ -30,8 +30,6 @@ struct eeh_event { struct list_head list; struct device_node *dn; /* struct device node */ struct pci_dev *dev; /* affected device */ - enum pci_channel_state state; /* PCI bus state for the affected device */ - int time_unavail; /* milliseconds until device might be available */ }; /** @@ -46,9 +44,7 @@ struct eeh_event { * (from a workqueue). */ int eeh_send_failure_event (struct device_node *dn, - struct pci_dev *dev, - enum pci_channel_state state, - int time_unavail); + struct pci_dev *dev); /* Main recovery function */ struct pci_dn * handle_eeh_events (struct eeh_event *); -- cgit v1.2.3-59-g8ed1b From 4002aca771a2aa2848e94a98cf51a2cae4e77ae0 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 20 Mar 2007 10:08:33 -0500 Subject: [POWERPC] Remove last_syscall Remove last_syscall from 32bit powerpc, its been gone in 64bit for years. Signed-off-by: Anton Blanchard Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 1 - arch/powerpc/kernel/entry_32.S | 1 - arch/powerpc/kernel/process.c | 1 - arch/ppc/kernel/asm-offsets.c | 1 - arch/ppc/kernel/entry.S | 1 - include/asm-powerpc/processor.h | 1 - 6 files changed, 6 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 030d300cd71c..9735e828b52d 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -77,7 +77,6 @@ int main(void) DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); #else /* CONFIG_PPC64 */ DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); DEFINE(PT_PTRACED, PT_PTRACED); diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index c03e829fee3c..c29d1652a421 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 972b2acbe713..0df049215503 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -567,7 +567,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, kregs->nip = *((unsigned long *)ret_from_fork); #else kregs->nip = (unsigned long)ret_from_fork; - p->thread.last_syscall = -1; #endif return 0; diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index 1f91eca2f3d7..c5850a272650 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -40,7 +40,6 @@ main(void) DEFINE(PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); DEFINE(PGDIR, offsetof(struct thread_struct, pgdir)); - DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index a9d455369dc6..ab64256110bd 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -191,7 +191,6 @@ stack_ovf: 0: _GLOBAL(DoSyscall) - stw r0,THREAD+LAST_SYSCALL(r2) stw r3,ORIG_GPR3(r1) li r12,0 stw r12,RESULT(r1) diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h index a26c32ee5527..d947b1609491 100644 --- a/include/asm-powerpc/processor.h +++ b/include/asm-powerpc/processor.h @@ -133,7 +133,6 @@ struct thread_struct { mm_segment_t fs; /* for get_fs() validation */ #ifdef CONFIG_PPC32 void *pgdir; /* root of page-table tree */ - signed long last_syscall; #endif #if defined(CONFIG_4xx) || defined (CONFIG_BOOKE) unsigned long dbcr0; /* debug control register values */ -- cgit v1.2.3-59-g8ed1b From 70b52b3869a31aab85241a1f998f9943a3905637 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 19 Mar 2007 11:53:55 +0100 Subject: [POWERPC] powermac: disallow pmu sleep notifiers from aborting sleep Tracing through the code, no current PMU sleep notifier can abort sleep. Since no new PMU sleep notifiers should be added, this patch simplifies the code and removes the ability to abort sleep. Signed-off-by: Johannes Berg Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- drivers/macintosh/adb.c | 42 ++++++++----------------------------- drivers/macintosh/apm_emu.c | 13 ++++-------- drivers/macintosh/via-pmu-led.c | 4 +--- drivers/macintosh/via-pmu.c | 36 ++++++------------------------- include/linux/pmu.h | 12 ++--------- sound/oss/dmasound/dmasound_awacs.c | 5 ++--- 6 files changed, 24 insertions(+), 88 deletions(-) (limited to 'include') diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index f729eebf771f..adfea3c7c62a 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -90,7 +90,7 @@ static int autopoll_devs; int __adb_probe_sync; #ifdef CONFIG_PM -static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); +static void adb_notify_sleep(struct pmu_sleep_notifier *self, int when); static struct pmu_sleep_notifier adb_sleep_notifier = { adb_notify_sleep, SLEEP_LEVEL_ADB, @@ -340,11 +340,9 @@ __initcall(adb_init); /* * notify clients before sleep and reset bus afterwards */ -int +void adb_notify_sleep(struct pmu_sleep_notifier *self, int when) { - int ret; - switch (when) { case PBOOK_SLEEP_REQUEST: adb_got_sleep = 1; @@ -353,22 +351,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) /* Stop autopoll */ if (adb_controller->autopoll) adb_controller->autopoll(0); - ret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_POWERDOWN, NULL); - if (ret & NOTIFY_STOP_MASK) { - up(&adb_probe_mutex); - return PBOOK_SLEEP_REFUSE; - } - break; - case PBOOK_SLEEP_REJECT: - if (adb_got_sleep) { - adb_got_sleep = 0; - up(&adb_probe_mutex); - adb_reset_bus(); - } - break; - - case PBOOK_SLEEP_NOW: + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POWERDOWN, NULL); break; case PBOOK_WAKE: adb_got_sleep = 0; @@ -376,14 +360,13 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) adb_reset_bus(); break; } - return PBOOK_SLEEP_OK; } #endif /* CONFIG_PM */ static int do_adb_reset_bus(void) { - int ret, nret; + int ret; if (adb_controller == NULL) return -ENXIO; @@ -391,13 +374,8 @@ do_adb_reset_bus(void) if (adb_controller->autopoll) adb_controller->autopoll(0); - nret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_PRE_RESET, NULL); - if (nret & NOTIFY_STOP_MASK) { - if (adb_controller->autopoll) - adb_controller->autopoll(autopoll_devs); - return -EBUSY; - } + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_PRE_RESET, NULL); if (sleepy_trackpad) { /* Let the trackpad settle down */ @@ -427,10 +405,8 @@ do_adb_reset_bus(void) } up(&adb_handler_sem); - nret = blocking_notifier_call_chain(&adb_client_list, - ADB_MSG_POST_RESET, NULL); - if (nret & NOTIFY_STOP_MASK) - return -EBUSY; + blocking_notifier_call_chain(&adb_client_list, + ADB_MSG_POST_RESET, NULL); return ret; } diff --git a/drivers/macintosh/apm_emu.c b/drivers/macintosh/apm_emu.c index c5e4d43f97fc..cdb0bead9917 100644 --- a/drivers/macintosh/apm_emu.c +++ b/drivers/macintosh/apm_emu.c @@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); static struct apm_user * user_list; -static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when); +static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when); static struct pmu_sleep_notifier apm_sleep_notifier = { apm_notify_sleep, SLEEP_LEVEL_USERLAND, @@ -352,7 +352,7 @@ static int do_open(struct inode * inode, struct file * filp) * doesn't provide a way to NAK, but this could be added * here. */ -static int wait_all_suspend(void) +static void wait_all_suspend(void) { DECLARE_WAITQUEUE(wait, current); @@ -366,24 +366,19 @@ static int wait_all_suspend(void) remove_wait_queue(&apm_suspend_waitqueue, &wait); DBG("apm_emu: wait_all_suspend() - complete !\n"); - - return 1; } -static int apm_notify_sleep(struct pmu_sleep_notifier *self, int when) +static void apm_notify_sleep(struct pmu_sleep_notifier *self, int when) { switch(when) { case PBOOK_SLEEP_REQUEST: queue_event(APM_SYS_SUSPEND, NULL); - if (!wait_all_suspend()) - return PBOOK_SLEEP_REFUSE; + wait_all_suspend(); break; - case PBOOK_SLEEP_REJECT: case PBOOK_WAKE: queue_event(APM_NORMAL_RESUME, NULL); break; } - return PBOOK_SLEEP_OK; } #define APM_CRITICAL 10 diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c index 179af10105d9..ed8423f4605d 100644 --- a/drivers/macintosh/via-pmu-led.c +++ b/drivers/macintosh/via-pmu-led.c @@ -81,7 +81,7 @@ static struct led_classdev pmu_led = { }; #ifdef CONFIG_PM -static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) +static void pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) { unsigned long flags; @@ -99,8 +99,6 @@ static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) break; } spin_unlock_irqrestore(&pmu_blink_lock, flags); - - return PBOOK_SLEEP_OK; } static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index b6073bdb50c3..ca3c4aba5a22 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -1769,35 +1769,21 @@ EXPORT_SYMBOL(pmu_unregister_sleep_notifier); #if defined(CONFIG_PM) && defined(CONFIG_PPC32) /* Sleep is broadcast last-to-first */ -static int -broadcast_sleep(int when, int fallback) +static void broadcast_sleep(int when) { - int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier; for (list = sleep_notifiers.prev; list != &sleep_notifiers; list = list->prev) { notifier = list_entry(list, struct pmu_sleep_notifier, list); - ret = notifier->notifier_call(notifier, when); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n", - when, notifier, notifier->notifier_call); - for (; list != &sleep_notifiers; list = list->next) { - notifier = list_entry(list, struct pmu_sleep_notifier, list); - notifier->notifier_call(notifier, fallback); - } - return ret; - } + notifier->notifier_call(notifier, when); } - return ret; } /* Wake is broadcast first-to-last */ -static int -broadcast_wake(void) +static void broadcast_wake(void) { - int ret = PBOOK_SLEEP_OK; struct list_head *list; struct pmu_sleep_notifier *notifier; @@ -1806,7 +1792,6 @@ broadcast_wake(void) notifier = list_entry(list, struct pmu_sleep_notifier, list); notifier->notifier_call(notifier, PBOOK_WAKE); } - return ret; } /* @@ -2013,12 +1998,8 @@ pmac_suspend_devices(void) pm_prepare_console(); - /* Notify old-style device drivers & userland */ - ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_ERR "Sleep rejected by drivers\n"); - return -EBUSY; - } + /* Notify old-style device drivers */ + broadcast_sleep(PBOOK_SLEEP_REQUEST); /* Sync the disks. */ /* XXX It would be nice to have some way to ensure that @@ -2028,12 +2009,7 @@ pmac_suspend_devices(void) */ sys_sync(); - /* Sleep can fail now. May not be very robust but useful for debugging */ - ret = broadcast_sleep(PBOOK_SLEEP_NOW, PBOOK_WAKE); - if (ret != PBOOK_SLEEP_OK) { - printk(KERN_ERR "Driver sleep failed\n"); - return -EBUSY; - } + broadcast_sleep(PBOOK_SLEEP_NOW); /* Send suspend call to devices, hold the device core's dpm_sem */ ret = device_suspend(PMSG_SUSPEND); diff --git a/include/linux/pmu.h b/include/linux/pmu.h index 783177387ac6..b0952e532ed5 100644 --- a/include/linux/pmu.h +++ b/include/linux/pmu.h @@ -168,24 +168,16 @@ extern int pmu_get_model(void); struct pmu_sleep_notifier { - int (*notifier_call)(struct pmu_sleep_notifier *self, int when); + void (*notifier_call)(struct pmu_sleep_notifier *self, int when); int priority; struct list_head list; }; /* Code values for calling sleep/wakeup handlers - * - * Note: If a sleep request got cancelled, all drivers will get - * the PBOOK_SLEEP_REJECT, even those who didn't get the PBOOK_SLEEP_REQUEST. */ #define PBOOK_SLEEP_REQUEST 1 #define PBOOK_SLEEP_NOW 2 -#define PBOOK_SLEEP_REJECT 3 -#define PBOOK_WAKE 4 - -/* Result codes returned by the notifiers */ -#define PBOOK_SLEEP_OK 0 -#define PBOOK_SLEEP_REFUSE -1 +#define PBOOK_WAKE 3 /* priority levels in notifiers */ #define SLEEP_LEVEL_VIDEO 100 /* Video driver (first wake) */ diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 37773b1deea5..f8a49bd17a13 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -257,7 +257,7 @@ static volatile struct dbdma_cmd *emergency_dbdma_cmd; /* * Stuff for restoring after a sleep. */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); +static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when); struct pmu_sleep_notifier awacs_sleep_notifier = { awacs_sleep_notify, SLEEP_LEVEL_SOUND, }; @@ -1419,7 +1419,7 @@ load_awacs(void) * Save state when going to sleep, restore it afterwards. */ /* FIXME: sort out disabling/re-enabling of read stuff as well */ -static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) +static void awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) { unsigned long flags; @@ -1548,7 +1548,6 @@ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) spin_unlock_irqrestore(&dmasound.lock, flags); UNLOCK(); } - return PBOOK_SLEEP_OK; } #endif /* CONFIG_PM */ -- cgit v1.2.3-59-g8ed1b From 9eb90a0c3b333e27db74412833a36da3f27da6a3 Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Fri, 9 Mar 2007 13:27:28 +0800 Subject: [POWERPC] 86xx/85xx: Unify Freescale PCI Express memory map registers structure Unify PCI Express memory map registers structure define to arch/pwoerpc/sysdev/fsl_pcie.h for Freescale 85xx/86xx processor family. Signed-off-by: Roy Zang Signed-off-by: Kumar Gala --- arch/powerpc/platforms/86xx/pci.c | 2 +- arch/powerpc/sysdev/fsl_pcie.h | 94 +++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/immap_86xx.h | 75 ------------------------------- 3 files changed, 95 insertions(+), 76 deletions(-) create mode 100644 arch/powerpc/sysdev/fsl_pcie.h (limited to 'include') diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 481e18ed5be9..ba86c48f446b 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c @@ -22,9 +22,9 @@ #include #include #include -#include #include #include +#include #include "mpc86xx.h" diff --git a/arch/powerpc/sysdev/fsl_pcie.h b/arch/powerpc/sysdev/fsl_pcie.h new file mode 100644 index 000000000000..8d9779c84bea --- /dev/null +++ b/arch/powerpc/sysdev/fsl_pcie.h @@ -0,0 +1,94 @@ +/* + * MPC85xx/86xx PCI Express structure define + * + * Copyright 2007 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. + * + */ + +#ifdef __KERNEL__ +#ifndef __POWERPC_FSL_PCIE_H +#define __POWERPC_FSL_PCIE_H + +/* PCIE Express IO block registers in 85xx/86xx */ + +struct ccsr_pex { + __be32 __iomem pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ + __be32 __iomem pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ + u8 __iomem res1[4]; + __be32 __iomem pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ + __be32 __iomem pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ + u8 __iomem res2[12]; + __be32 __iomem pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ + __be32 __iomem pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ + __be32 __iomem pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ + __be32 __iomem pex_pmcr; /* 0x.02c - PCI Express power management command register */ + u8 __iomem res3[3024]; + __be32 __iomem pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ + __be32 __iomem pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ + u8 __iomem res4[8]; + __be32 __iomem pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ + u8 __iomem res5[12]; + __be32 __iomem pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ + __be32 __iomem pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ + __be32 __iomem pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ + u8 __iomem res6[4]; + __be32 __iomem pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ + u8 __iomem res7[12]; + __be32 __iomem pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ + __be32 __iomem pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ + __be32 __iomem pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ + u8 __iomem res8[4]; + __be32 __iomem pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ + u8 __iomem res9[12]; + __be32 __iomem pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ + __be32 __iomem pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ + __be32 __iomem pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ + u8 __iomem res10[4]; + __be32 __iomem pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ + u8 __iomem res11[12]; + __be32 __iomem pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ + __be32 __iomem pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ + __be32 __iomem pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ + u8 __iomem res12[4]; + __be32 __iomem pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ + u8 __iomem res13[12]; + u8 __iomem res14[256]; + __be32 __iomem pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ + u8 __iomem res15[4]; + __be32 __iomem pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ + __be32 __iomem pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ + __be32 __iomem pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ + u8 __iomem res16[12]; + __be32 __iomem pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ + u8 __iomem res17[4]; + __be32 __iomem pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res18[12]; + __be32 __iomem pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ + u8 __iomem res19[4]; + __be32 __iomem pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ + __be32 __iomem pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ + __be32 __iomem pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ + u8 __iomem res20[12]; + __be32 __iomem pex_err_dr; /* 0x.e00 - PCI Express error detect register */ + u8 __iomem res21[4]; + __be32 __iomem pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ + u8 __iomem res22[4]; + __be32 __iomem pex_err_disr; /* 0x.e10 - PCI Express error disable register */ + u8 __iomem res23[12]; + __be32 __iomem pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ + u8 __iomem res24[4]; + __be32 __iomem pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ + __be32 __iomem pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ +}; + +#endif /* __POWERPC_FSL_PCIE_H */ +#endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h index d905b6622268..59b9e07b8e99 100644 --- a/include/asm-powerpc/immap_86xx.h +++ b/include/asm-powerpc/immap_86xx.h @@ -85,81 +85,6 @@ typedef struct ccsr_pci { char res19[472]; } ccsr_pci_t; -/* PCI Express Registers */ -typedef struct ccsr_pex { - uint pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ - uint pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ - char res1[4]; - uint pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ - uint pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ - char res2[12]; - uint pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ - uint pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ - uint pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ - uint pex_pmcr; /* 0x.02c - PCI Express power management command register */ - char res3[3024]; - uint pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ - uint pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ - char res4[8]; - uint pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ - char res5[12]; - uint pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ - uint pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ - uint pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ - char res6[4]; - uint pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ - char res7[12]; - uint pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ - uint pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ - uint pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ - char res8[4]; - uint pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ - char res9[12]; - uint pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ - uint pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ - uint pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ - char res10[4]; - uint pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ - char res11[12]; - uint pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ - uint pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ - uint pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ - char res12[4]; - uint pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ - char res13[12]; - char res14[256]; - uint pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ - char res15[4]; - uint pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ - uint pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ - uint pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ - char res16[12]; - uint pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ - char res17[4]; - uint pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ - uint pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ - uint pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ - char res18[12]; - uint pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ - char res19[4]; - uint pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ - uint pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ - uint pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ - char res20[12]; - uint pex_err_dr; /* 0x.e00 - PCI Express error detect register */ - char res21[4]; - uint pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ - char res22[4]; - uint pex_err_disr; /* 0x.e10 - PCI Express error disable register */ - char res23[12]; - uint pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ - char res24[4]; - uint pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ - uint pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ - uint pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ - uint pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ -} ccsr_pex_t; - /* Global Utility Registers */ typedef struct ccsr_guts { uint porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ -- cgit v1.2.3-59-g8ed1b From eb0cb8a07e320ed3237789cc4f29858338d14d8e Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 12 Feb 2007 23:13:25 +0100 Subject: [POWERPC] Add a unified uevent handler for bus based on of_device This common uevent handler allow the several bus types based on of_device to generate the uevent properly and avoiding code duplication. This handlers take a struct device as argument and can therefore be used as the uevent call directly if no special treatment is needed for the bus. Signed-off-by: Sylvain Munaut Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/of_device.c | 112 ++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/of_device.h | 3 ++ 2 files changed, 115 insertions(+) (limited to 'include') diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index e921514e655b..e8aa1f3675b7 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -120,6 +120,117 @@ void of_device_unregister(struct of_device *ofdev) } +static ssize_t of_device_get_modalias(struct of_device *ofdev, + char *str, ssize_t len) +{ + const char *compat; + int cplen, i; + ssize_t tsize, csize, repend; + + /* Name & Type */ + csize = snprintf(str, len, "of:N%sT%s", + ofdev->node->name, ofdev->node->type); + + /* Get compatible property if any */ + compat = get_property(ofdev->node, "compatible", &cplen); + if (!compat) + return csize; + + /* Find true end (we tolerate multiple \0 at the end */ + for (i=(cplen-1); i>=0 && !compat[i]; i--) + cplen--; + if (!cplen) + return csize; + cplen++; + + /* Check space (need cplen+1 chars including final \0) */ + tsize = csize + cplen; + repend = tsize; + + if (csize>=len) /* @ the limit, all is already filled */ + return tsize; + + if (tsize>=len) { /* limit compat list */ + cplen = len-csize-1; + repend = len; + } + + /* Copy and do char replacement */ + memcpy(&str[csize+1], compat, cplen); + for (i=csize; inode->name)) + return -ENOMEM; + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_TYPE=%s", ofdev->node->type)) + return -ENOMEM; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = get_property(ofdev->node, "compatible", &cplen); + while (compat && *compat && cplen > 0) { + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_%d=%s", seen, compat)) + return -ENOMEM; + + sl = strlen (compat) + 1; + compat += sl; + cplen -= sl; + seen++; + } + + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "OF_COMPATIBLE_N=%d", seen)) + return -ENOMEM; + + /* modalias is trickier, we add it in 2 steps */ + if (add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, + "MODALIAS=")) + return -ENOMEM; + + sl = of_device_get_modalias(ofdev, &buffer[length-1], + buffer_size-length); + if (sl >= (buffer_size-length)) + return -ENOMEM; + + length += sl; + + envp[i] = NULL; + + return 0; +} + + EXPORT_SYMBOL(of_match_node); EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_device_register); @@ -127,3 +238,4 @@ EXPORT_SYMBOL(of_device_unregister); EXPORT_SYMBOL(of_dev_get); EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_release_dev); +EXPORT_SYMBOL(of_device_uevent); diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index a889b2005bf5..4f1aabe0ce73 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -32,5 +32,8 @@ extern int of_device_register(struct of_device *ofdev); extern void of_device_unregister(struct of_device *ofdev); extern void of_release_dev(struct device *dev); +extern int of_device_uevent(struct device *dev, + char **envp, int num_envp, char *buffer, int buffer_size); + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_OF_DEVICE_H */ -- cgit v1.2.3-59-g8ed1b From 3467bfd340f9ad48f3732415533a2e9c18240b62 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Thu, 22 Mar 2007 09:34:13 -0500 Subject: [POWERPC] Use mtocrf instruction in asm when CONFIG_POWER4_ONLY=y mtocrf is a faster single-field mtcrf (move to condition register fields) instruction available in POWER4 and later processors. It can make quite a difference in performance on some implementations, so use it for CONFIG_POWER4_ONLY builds. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/lib/copyuser_64.S | 6 +++--- arch/powerpc/lib/mem_64.S | 6 +++--- arch/powerpc/lib/memcpy_64.S | 6 +++--- include/asm-powerpc/asm-compat.h | 10 ++++++++++ 4 files changed, 19 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index a6b54cb97c49..25ec5378afa4 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S @@ -24,7 +24,7 @@ _GLOBAL(__copy_tofrom_user) dcbt 0,r4 beq .Lcopy_page_4K andi. r6,r6,7 - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 blt cr1,.Lshort_copy bne .Ldst_unaligned .Ldst_aligned: @@ -135,7 +135,7 @@ _GLOBAL(__copy_tofrom_user) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */ + PPC_MTOCRF 0x01,r6 /* put #bytes to 8B bdry into cr7 */ subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -150,7 +150,7 @@ _GLOBAL(__copy_tofrom_user) 2: bf cr7*4+1,3f 37: lwzx r0,r7,r4 83: stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/arch/powerpc/lib/mem_64.S b/arch/powerpc/lib/mem_64.S index 68df20283ff5..11ce045e21fd 100644 --- a/arch/powerpc/lib/mem_64.S +++ b/arch/powerpc/lib/mem_64.S @@ -19,7 +19,7 @@ _GLOBAL(memset) rlwimi r4,r4,16,0,15 cmplw cr1,r5,r0 /* do we get that far? */ rldimi r4,r4,32,0 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 mr r6,r3 blt cr1,8f beq+ 3f /* if already 8-byte aligned */ @@ -49,7 +49,7 @@ _GLOBAL(memset) bdnz 4b 5: srwi. r0,r5,3 clrlwi r5,r5,29 - mtcrf 1,r0 + PPC_MTOCRF 1,r0 beq 8f bf 29,6f std r4,0(r6) @@ -65,7 +65,7 @@ _GLOBAL(memset) std r4,0(r6) addi r6,r6,8 8: cmpwi r5,0 - mtcrf 1,r5 + PPC_MTOCRF 1,r5 beqlr+ bf 29,9f stw r4,0(r6) diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 7173ba98f427..3f131129d1c1 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S @@ -12,7 +12,7 @@ .align 7 _GLOBAL(memcpy) std r3,48(r1) /* save destination pointer for return value */ - mtcrf 0x01,r5 + PPC_MTOCRF 0x01,r5 cmpldi cr1,r5,16 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry andi. r6,r6,7 @@ -128,7 +128,7 @@ _GLOBAL(memcpy) b .Ldo_tail .Ldst_unaligned: - mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7 + PPC_MTOCRF 0x01,r6 # put #bytes to 8B bdry into cr7 subf r5,r6,r5 li r7,0 cmpldi r1,r5,16 @@ -143,7 +143,7 @@ _GLOBAL(memcpy) 2: bf cr7*4+1,3f lwzx r0,r7,r4 stwx r0,r7,r3 -3: mtcrf 0x01,r5 +3: PPC_MTOCRF 0x01,r5 add r4,r6,r4 add r3,r6,r3 b .Ldst_aligned diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h index c89bd58ee283..c19e7367fce6 100644 --- a/include/asm-powerpc/asm-compat.h +++ b/include/asm-powerpc/asm-compat.h @@ -78,6 +78,15 @@ #define PPC_STLCX stringify_in_c(stdcx.) #define PPC_CNTLZL stringify_in_c(cntlzd) +/* Move to CR, single-entry optimized version. Only available + * on POWER4 and later. + */ +#ifdef CONFIG_POWER4_ONLY +#define PPC_MTOCRF stringify_in_c(mtocrf) +#else +#define PPC_MTOCRF stringify_in_c(mtcrf) +#endif + #else /* 32-bit */ /* operations for longs and pointers */ @@ -89,6 +98,7 @@ #define PPC_LLARX stringify_in_c(lwarx) #define PPC_STLCX stringify_in_c(stwcx.) #define PPC_CNTLZL stringify_in_c(cntlzw) +#define PPC_MTOCRF stringify_in_c(mtcrf) #endif -- cgit v1.2.3-59-g8ed1b From 0e56efc7dcd1eb5004363e52bdbe801783245638 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 10:54:01 +1000 Subject: [POWERPC] Rename get_property to of_get_property This is more consistent and gets us closer to the Sparc code. We add a get_property define for compatibility during the change over. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 24 ++++++++++++------------ include/asm-powerpc/prom.h | 3 ++- include/asm-ppc/prom.h | 3 ++- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index ef6bfb70b24a..622472818723 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -400,8 +400,8 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, } if (allnextpp) { *prev_pp = NULL; - np->name = get_property(np, "name", NULL); - np->type = get_property(np, "device_type", NULL); + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); if (!np->name) np->name = ""; @@ -1048,7 +1048,7 @@ prom_n_addr_cells(struct device_node* np) do { if (np->parent) np = np->parent; - ip = get_property(np, "#address-cells", NULL); + ip = of_get_property(np, "#address-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); @@ -1064,7 +1064,7 @@ prom_n_size_cells(struct device_node* np) do { if (np->parent) np = np->parent; - ip = get_property(np, "#size-cells", NULL); + ip = of_get_property(np, "#size-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); @@ -1136,7 +1136,7 @@ int device_is_compatible(const struct device_node *device, const char *compat) const char* cp; int cplen, l; - cp = get_property(device, "compatible", &cplen); + cp = of_get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { @@ -1547,8 +1547,8 @@ static int of_finish_dynamic_node(struct device_node *node) int err = 0; const phandle *ibm_phandle; - node->name = get_property(node, "name", NULL); - node->type = get_property(node, "device_type", NULL); + node->name = of_get_property(node, "name", NULL); + node->type = of_get_property(node, "device_type", NULL); if (!parent) { err = -ENODEV; @@ -1562,7 +1562,7 @@ static int of_finish_dynamic_node(struct device_node *node) return -ENODEV; /* fix up new node's linux_phandle field */ - if ((ibm_phandle = get_property(node, "ibm,phandle", NULL))) + if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) node->linux_phandle = *ibm_phandle; out: @@ -1625,13 +1625,13 @@ EXPORT_SYMBOL(of_find_property); * Find a property with a given name for a given node * and return the value. */ -const void *get_property(const struct device_node *np, const char *name, +const void *of_get_property(const struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; } -EXPORT_SYMBOL(get_property); +EXPORT_SYMBOL(of_get_property); /* * Add a property to a node @@ -1762,10 +1762,10 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist * fallback to "reg" property and assume no threads */ - intserv = get_property(np, "ibm,ppc-interrupt-server#s", + intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &plen); if (intserv == NULL) { - const u32 *reg = get_property(np, "reg", NULL); + const u32 *reg = of_get_property(np, "reg", NULL); if (reg == NULL) continue; if (*reg == hardid) { diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 994de8ea3308..448c5ce76fbe 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -165,9 +165,10 @@ extern void early_init_devtree(void *); extern int device_is_compatible(const struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); -extern const void *get_property(const struct device_node *node, +extern const void *of_get_property(const struct device_node *node, const char *name, int *lenp); +#define get_property(a, b, c) of_get_property((a), (b), (c)) extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index adc5ae784924..901f7fa8b2d7 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -34,7 +34,8 @@ extern unsigned long sub_reloc_offset(unsigned long); */ #define machine_is_compatible(x) 0 #define of_find_compatible_node(f, t, c) NULL -#define get_property(p, n, l) NULL +#define of_get_property(p, n, l) NULL +#define get_property(a, b, c) of_get_property((a), (b), (c)) #endif /* _PPC_PROM_H */ #endif /* __KERNEL__ */ -- cgit v1.2.3-59-g8ed1b From 7a92f74f98bde8498c98aad6cac5da5a87dd0bf4 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 10:55:39 +1000 Subject: [POWERPC] Rename device_is_compatible to of_device_is_compatible This is more consistent and gets us closer to the Sparc code. We add a device_is_compatible define for compatibility during the change over. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 11 ++++++----- include/asm-powerpc/prom.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 622472818723..d2840b66c8c1 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1131,7 +1131,8 @@ EXPORT_SYMBOL(find_all_nodes); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int device_is_compatible(const struct device_node *device, const char *compat) +int of_device_is_compatible(const struct device_node *device, + const char *compat) { const char* cp; int cplen, l; @@ -1149,7 +1150,7 @@ int device_is_compatible(const struct device_node *device, const char *compat) return 0; } -EXPORT_SYMBOL(device_is_compatible); +EXPORT_SYMBOL(of_device_is_compatible); /** @@ -1163,7 +1164,7 @@ int machine_is_compatible(const char *compat) root = of_find_node_by_path("/"); if (root) { - rc = device_is_compatible(root, compat); + rc = of_device_is_compatible(root, compat); of_node_put(root); } return rc; @@ -1184,7 +1185,7 @@ struct device_node *find_compatible_devices(const char *type, if (type != NULL && !(np->type != 0 && strcasecmp(np->type, type) == 0)) continue; - if (device_is_compatible(np, compat)) { + if (of_device_is_compatible(np, compat)) { *prevp = np; prevp = &np->next; } @@ -1300,7 +1301,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, if (type != NULL && !(np->type != 0 && strcasecmp(np->type, type) == 0)) continue; - if (device_is_compatible(np, compatible) && of_node_get(np)) + if (of_device_is_compatible(np, compatible) && of_node_get(np)) break; } of_node_put(from); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 448c5ce76fbe..fcacc88b7706 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -162,8 +162,9 @@ extern void of_detach_node(const struct device_node *); extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); -extern int device_is_compatible(const struct device_node *device, +extern int of_device_is_compatible(const struct device_node *device, const char *); +#define device_is_compatible(d, c) of_device_is_compatible((d), (c)) extern int machine_is_compatible(const char *compat); extern const void *of_get_property(const struct device_node *node, const char *name, -- cgit v1.2.3-59-g8ed1b From a8bda5dd4f99d6469f3c0dc362db3cce8a4d6416 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 10:56:50 +1000 Subject: [POWERPC] Rename prom_n_addr_cells to of_n_addr_cells This is more consistent and gets us closer to the Sparc code. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/pci_32.c | 2 +- arch/powerpc/kernel/pci_64.c | 2 +- arch/powerpc/kernel/prom.c | 5 ++--- arch/powerpc/kernel/prom_parse.c | 4 ++-- arch/powerpc/kernel/setup-common.c | 2 +- arch/powerpc/mm/numa.c | 2 +- arch/powerpc/platforms/chrp/setup.c | 4 ++-- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/pasemi/setup.c | 2 +- arch/powerpc/platforms/pseries/setup.c | 4 ++-- arch/powerpc/platforms/pseries/xics.c | 2 +- drivers/char/tpm/tpm_atmel.h | 2 +- include/asm-powerpc/prom.h | 2 +- 13 files changed, 17 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index d8ef2e100505..ecc765819305 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -895,7 +895,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0, orig_rlen; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); np = na + 5; /* First we try to merge ranges to fix a problem with some pmacs diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index db1d40ef7d60..84b4f66e98b6 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -957,7 +957,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, int rlen = 0; int memno = 0; struct resource *res; - int np, na = prom_n_addr_cells(dev); + int np, na = of_n_addr_cells(dev); unsigned long pci_addr, cpu_phys_addr; np = na + 5; diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d2840b66c8c1..08d619756d33 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1041,8 +1041,7 @@ void __init early_init_devtree(void *params) #undef printk -int -prom_n_addr_cells(struct device_node* np) +int of_n_addr_cells(struct device_node* np) { const int *ip; do { @@ -1055,7 +1054,7 @@ prom_n_addr_cells(struct device_node* np) /* No #address-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_addr_cells); +EXPORT_SYMBOL(of_n_addr_cells); int prom_n_size_cells(struct device_node* np) diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 91b443c9a488..e3d036fa6059 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -68,7 +68,7 @@ static void of_bus_default_count_cells(struct device_node *dev, int *addrc, int *sizec) { if (addrc) - *addrc = prom_n_addr_cells(dev); + *addrc = of_n_addr_cells(dev); if (sizec) *sizec = prom_n_size_cells(dev); } @@ -654,7 +654,7 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, if (!prop) prop = get_property(dn, "#address-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); *phys = of_read_number(dma_window, cells); dma_window += cells; diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index d44db58e8a81..f7ef5a97c0ea 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -379,7 +379,7 @@ void __init smp_setup_cpu_maps(void) int num_addr_cell, num_size_cell, maxcpus; const unsigned int *ireg; - num_addr_cell = prom_n_addr_cells(dn); + num_addr_cell = of_n_addr_cells(dn); num_size_cell = prom_n_size_cells(dn); ireg = get_property(dn, "ibm,lrdr-capacity", NULL); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index e86c37c82cfd..119cef99a2b0 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -201,7 +201,7 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells) if (!memory) panic("numa.c: No memory nodes found!"); - *n_addr_cells = prom_n_addr_cells(memory); + *n_addr_cells = of_n_addr_cells(memory); *n_size_cells = prom_n_size_cells(memory); of_node_put(memory); } diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 7bdfa6269aaf..044ad3f1e04a 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -361,7 +361,7 @@ static void __init chrp_find_openpic(void) root = of_find_node_by_path("/"); if (root) { opprop = get_property(root, "platform-open-pic", &oplen); - na = prom_n_addr_cells(root); + na = of_n_addr_cells(root); } if (opprop && oplen >= na * sizeof(unsigned int)) { opaddr = opprop[na-1]; /* assume 32-bit */ @@ -468,7 +468,7 @@ static void __init chrp_find_8259(void) if (addrp == NULL) continue; - chrp_int_ack = addrp[prom_n_addr_cells(np)-1]; + chrp_int_ack = addrp[of_n_addr_cells(np)-1]; break; } if (np == NULL) diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 9389d29cd0be..f21add0e4786 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -248,7 +248,7 @@ static void __init maple_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); + naddr = of_n_addr_cells(root); opprop = get_property(root, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 449cf1a08291..d4fd61328c8b 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -136,7 +136,7 @@ static __init void pas_init_IRQ(void) /* Find address list in /platform-open-pic */ root = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(root); + naddr = of_n_addr_cells(root); opprop = get_property(root, "platform-open-pic", &opplen); if (!opprop) { printk(KERN_ERR "No platform-open-pic property.\n"); diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index ff87b1ad8ce9..54e93eb8a8ee 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -139,7 +139,7 @@ static void __init pseries_mpic_init_IRQ(void) struct mpic *mpic; np = of_find_node_by_path("/"); - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); opprop = get_property(np, "platform-open-pic", &opplen); if (opprop != 0) { openpic_addr = of_read_number(opprop, naddr); @@ -193,7 +193,7 @@ static void __init pseries_mpic_init_IRQ(void) NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 81d172d65038..f0795faada91 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -643,7 +643,7 @@ static void __init xics_setup_8259_cascade(void) addrp = get_property(np, "8259-interrupt-acknowledge", NULL); if (addrp == NULL) continue; - naddr = prom_n_addr_cells(np); + naddr = of_n_addr_cells(np); intack = addrp[naddr-1]; if (naddr > 1) intack |= ((unsigned long)addrp[naddr-2]) << 32; diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index aefd683c60b7..3501c0369d38 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h @@ -53,7 +53,7 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) } reg = get_property(dn, "reg", ®len); - naddrc = prom_n_addr_cells(dn); + naddrc = of_n_addr_cells(dn); nsizec = prom_n_size_cells(dn); of_node_put(dn); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index fcacc88b7706..e0c92bf2019b 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -171,7 +171,7 @@ extern const void *of_get_property(const struct device_node *node, int *lenp); #define get_property(a, b, c) of_get_property((a), (b), (c)) extern void print_properties(struct device_node *node); -extern int prom_n_addr_cells(struct device_node* np); +extern int of_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -- cgit v1.2.3-59-g8ed1b From 9213feea6e197f8507ec855337798cc3388f5570 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 10:57:48 +1000 Subject: [POWERPC] Rename prom_n_size_cells to of_n_size_cells This is more consistent and gets us closer to the Sparc code. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 5 ++--- arch/powerpc/kernel/prom_parse.c | 4 ++-- arch/powerpc/kernel/setup-common.c | 2 +- arch/powerpc/mm/numa.c | 2 +- drivers/char/tpm/tpm_atmel.h | 2 +- include/asm-powerpc/prom.h | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 08d619756d33..2890ce3d6641 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1056,8 +1056,7 @@ int of_n_addr_cells(struct device_node* np) } EXPORT_SYMBOL(of_n_addr_cells); -int -prom_n_size_cells(struct device_node* np) +int of_n_size_cells(struct device_node* np) { const int* ip; do { @@ -1070,7 +1069,7 @@ prom_n_size_cells(struct device_node* np) /* No #size-cells property for the root node, default to 1 */ return 1; } -EXPORT_SYMBOL(prom_n_size_cells); +EXPORT_SYMBOL(of_n_size_cells); /** * Construct and return a list of the device_nodes with a given name. diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index e3d036fa6059..ba9c7c1e4108 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -70,7 +70,7 @@ static void of_bus_default_count_cells(struct device_node *dev, if (addrc) *addrc = of_n_addr_cells(dev); if (sizec) - *sizec = prom_n_size_cells(dev); + *sizec = of_n_size_cells(dev); } static u64 of_bus_default_map(u32 *addr, const u32 *range, @@ -660,7 +660,7 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, dma_window += cells; prop = get_property(dn, "ibm,#dma-size-cells", NULL); - cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); *size = of_read_number(dma_window, cells); } diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index f7ef5a97c0ea..640ff0d8f83c 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -380,7 +380,7 @@ void __init smp_setup_cpu_maps(void) const unsigned int *ireg; num_addr_cell = of_n_addr_cells(dn); - num_size_cell = prom_n_size_cells(dn); + num_size_cell = of_n_size_cells(dn); ireg = get_property(dn, "ibm,lrdr-capacity", NULL); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 119cef99a2b0..683839b2b06b 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -202,7 +202,7 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells) panic("numa.c: No memory nodes found!"); *n_addr_cells = of_n_addr_cells(memory); - *n_size_cells = prom_n_size_cells(memory); + *n_size_cells = of_n_size_cells(memory); of_node_put(memory); } diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index 3501c0369d38..3c852009196e 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h @@ -54,7 +54,7 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) reg = get_property(dn, "reg", ®len); naddrc = of_n_addr_cells(dn); - nsizec = prom_n_size_cells(dn); + nsizec = of_n_size_cells(dn); of_node_put(dn); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index e0c92bf2019b..fb068f2eca4a 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -172,7 +172,7 @@ extern const void *of_get_property(const struct device_node *node, #define get_property(a, b, c) of_get_property((a), (b), (c)) extern void print_properties(struct device_node *node); extern int of_n_addr_cells(struct device_node* np); -extern int prom_n_size_cells(struct device_node* np); +extern int of_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern int prom_add_property(struct device_node* np, struct property* prop); -- cgit v1.2.3-59-g8ed1b From 1a38147ed0737a9c01dbf5f2ca47fd2a0aa5cb55 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 10:58:52 +1000 Subject: [POWERPC] Make struct property's value a void * Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/machine_kexec_64.c | 10 +++++----- arch/powerpc/kernel/pci_32.c | 2 +- arch/powerpc/kernel/prom.c | 5 +++-- arch/powerpc/platforms/maple/pci.c | 2 +- arch/powerpc/platforms/powermac/pci.c | 2 +- arch/powerpc/platforms/powermac/pfunc_core.c | 3 +-- drivers/macintosh/smu.c | 2 +- fs/proc/proc_devtree.c | 2 +- include/asm-powerpc/prom.h | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index a24b09c27718..b975b5b0e3d5 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -294,19 +294,19 @@ static unsigned long htab_base, kernel_end; static struct property htab_base_prop = { .name = "linux,htab-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_base, + .value = &htab_base, }; static struct property htab_size_prop = { .name = "linux,htab-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&htab_size_bytes, + .value = &htab_size_bytes, }; static struct property kernel_end_prop = { .name = "linux,kernel-end", .length = sizeof(unsigned long), - .value = (unsigned char *)&kernel_end, + .value = &kernel_end, }; static void __init export_htab_values(void) @@ -335,7 +335,7 @@ static void __init export_htab_values(void) static struct property crashk_base_prop = { .name = "linux,crashkernel-base", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_res.start, + .value = &crashk_res.start, }; static unsigned long crashk_size; @@ -343,7 +343,7 @@ static unsigned long crashk_size; static struct property crashk_size_prop = { .name = "linux,crashkernel-size", .length = sizeof(unsigned long), - .value = (unsigned char *)&crashk_size, + .value = &crashk_size, }; static void __init export_crashk_values(void) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index ecc765819305..e99ffe2140bf 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -1012,7 +1012,7 @@ pci_create_OF_bus_map(void) memset(of_prop, -1, sizeof(struct property) + 256); of_prop->name = "pci-OF-bus-map"; of_prop->length = 256; - of_prop->value = (unsigned char *)&of_prop[1]; + of_prop->value = &of_prop[1]; prom_add_property(find_path_device("/"), of_prop); } } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 2890ce3d6641..ec6921c54a07 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -390,12 +390,13 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, if (allnextpp) { pp->name = "name"; pp->length = sz; - pp->value = (unsigned char *)(pp + 1); + pp->value = pp + 1; *prev_pp = pp; prev_pp = &pp->next; memcpy(pp->value, ps, sz - 1); ((char *)pp->value)[sz - 1] = 0; - DBG("fixed up name for %s -> %s\n", pathp, pp->value); + DBG("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); } } if (allnextpp) { diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index 73c59904697f..ab5a6f12e1f0 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -77,7 +77,7 @@ static void __init fixup_bus_range(struct device_node *bridge) bridge->full_name); return; } - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 6fbac308ded6..431a685a15dd 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -100,7 +100,7 @@ static void __init fixup_bus_range(struct device_node *bridge) if (prop == NULL || prop->length < 2 * sizeof(int)) return; - bus_range = (int *)prop->value; + bus_range = prop->value; bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); } diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index 7651f278615a..a128553b8413 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c @@ -692,8 +692,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata) name = pp->name + plen; if (strlen(name) && pp->length >= 12) count += pmf_add_function_prop(dev, driverdata, name, - (u32 *)pp->value, - pp->length); + pp->value, pp->length); } return count; } diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 3096836d8bd3..45bb3c1dfeb1 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -952,7 +952,7 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) prop->name = ((char *)prop) + tlen - 18; sprintf(prop->name, "sdb-partition-%02x", id); prop->length = len; - prop->value = (unsigned char *)hdr; + prop->value = hdr; prop->next = NULL; /* Read the datablock */ diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index abdf068bc27f..eca471bc8512 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -38,7 +38,7 @@ static int property_read_proc(char *page, char **start, off_t off, n = count; else *eof = 1; - memcpy(page, pp->value + off, n); + memcpy(page, (char *)pp->value + off, n); *start = page; return n; } diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index fb068f2eca4a..e73a2b482a15 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -71,7 +71,7 @@ typedef u32 ihandle; struct property { char *name; int length; - unsigned char *value; + void *value; struct property *next; }; -- cgit v1.2.3-59-g8ed1b From 721151d004dcf01a71b12bb6b893f9160284cf6e Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 3 Apr 2007 21:24:02 +1000 Subject: [POWERPC] Allow drivers to map individual 4k pages to userspace Some drivers have resources that they want to be able to map into userspace that are 4k in size. On a kernel configured with 64k pages we currently end up mapping the 4k we want plus another 60k of physical address space, which could contain anything. This can introduce security problems, for example in the case of an infiniband adaptor where the other 60k could contain registers that some other program is using for its communications. This patch adds a new function, remap_4k_pfn, which drivers can use to map a single 4k page to userspace regardless of whether the kernel is using a 4k or a 64k page size. Like remap_pfn_range, it would typically be called in a driver's mmap function. It only maps a single 4k page, which on a 64k page kernel appears replicated 16 times throughout a 64k page. On a 4k page kernel it reduces to a call to remap_pfn_range. The way this works on a 64k kernel is that a new bit, _PAGE_4K_PFN, gets set on the linux PTE. This alters the way that __hash_page_4K computes the real address to put in the HPTE. The RPN field of the linux PTE becomes the 4k RPN directly rather than being interpreted as a 64k RPN. Since the RPN field is 32 bits, this means that physical addresses being mapped with remap_4k_pfn have to be below 2^44, i.e. 0x100000000000. The patch also factors out the code in arch/powerpc/mm/hash_utils_64.c that deals with demoting a process to use 4k pages into one function that gets called in the various different places where we need to do that. There were some discrepancies between exactly what was done in the various places, such as a call to spu_flush_all_slbs in one case but not in others. Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_low_64.S | 5 ++++- arch/powerpc/mm/hash_utils_64.c | 43 +++++++++++++++++++++++++++------------ include/asm-powerpc/pgtable-4k.h | 3 +++ include/asm-powerpc/pgtable-64k.h | 5 +++++ 4 files changed, 42 insertions(+), 14 deletions(-) (limited to 'include') diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S index 9bc0a9c2b9bc..e64ce3eec36e 100644 --- a/arch/powerpc/mm/hash_low_64.S +++ b/arch/powerpc/mm/hash_low_64.S @@ -445,9 +445,12 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE) htab_insert_pte: /* real page number in r5, PTE RPN value + index */ - rldicl r5,r31,64-PTE_RPN_SHIFT,PTE_RPN_SHIFT + andis. r0,r31,_PAGE_4K_PFN@h + srdi r5,r31,PTE_RPN_SHIFT + bne- htab_special_pfn sldi r5,r5,PAGE_SHIFT-HW_PAGE_SHIFT add r5,r5,r25 +htab_special_pfn: sldi r5,r5,HW_PAGE_SHIFT /* Calculate primary group hash */ diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3c7fe2c65b5a..aae085317018 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -573,6 +573,27 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) return pp; } +/* + * Demote a segment to using 4k pages. + * For now this makes the whole process use 4k pages. + */ +void demote_segment_4k(struct mm_struct *mm, unsigned long addr) +{ +#ifdef CONFIG_PPC_64K_PAGES + if (mm->context.user_psize == MMU_PAGE_4K) + return; + mm->context.user_psize = MMU_PAGE_4K; + mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; + get_paca()->context = mm->context; + slb_flush_and_rebolt(); +#ifdef CONFIG_SPE_BASE + spu_flush_all_slbs(mm); +#endif +#endif +} + +EXPORT_SYMBOL_GPL(demote_segment_4k); + /* Result code is: * 0 - handled * 1 - normal page fault @@ -665,15 +686,19 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) #ifndef CONFIG_PPC_64K_PAGES rc = __hash_page_4K(ea, access, vsid, ptep, trap, local); #else + /* If _PAGE_4K_PFN is set, make sure this is a 4k segment */ + if (pte_val(*ptep) & _PAGE_4K_PFN) { + demote_segment_4k(mm, ea); + psize = MMU_PAGE_4K; + } + if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (psize == MMU_PAGE_64K && (pte_val(*ptep) & _PAGE_NO_CACHE)) { if (user_region) { + demote_segment_4k(mm, ea); psize = MMU_PAGE_4K; - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; } else if (ea < VMALLOC_END) { /* * some driver did a non-cacheable mapping @@ -756,16 +781,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, if (mmu_ci_restrictions) { /* If this PTE is non-cacheable, switch to 4k */ if (mm->context.user_psize == MMU_PAGE_64K && - (pte_val(*ptep) & _PAGE_NO_CACHE)) { - mm->context.user_psize = MMU_PAGE_4K; - mm->context.sllp = SLB_VSID_USER | - mmu_psize_defs[MMU_PAGE_4K].sllp; - get_paca()->context = mm->context; - slb_flush_and_rebolt(); -#ifdef CONFIG_SPE_BASE - spu_flush_all_slbs(mm); -#endif - } + (pte_val(*ptep) & _PAGE_NO_CACHE)) + demote_segment_4k(mm, ea); } if (mm->context.user_psize == MMU_PAGE_64K) __hash_page_64K(ea, access, vsid, ptep, trap, local); diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h index 345d9b07b3e2..a28fa8bc01da 100644 --- a/include/asm-powerpc/pgtable-4k.h +++ b/include/asm-powerpc/pgtable-4k.h @@ -97,3 +97,6 @@ #define pud_ERROR(e) \ printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) + +#define remap_4k_pfn(vma, addr, pfn, prot) \ + remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot)) diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h index 4b7126c53f37..5e84f070eaf7 100644 --- a/include/asm-powerpc/pgtable-64k.h +++ b/include/asm-powerpc/pgtable-64k.h @@ -35,6 +35,7 @@ #define _PAGE_HPTE_SUB 0x0ffff000 /* combo only: sub pages HPTE bits */ #define _PAGE_HPTE_SUB0 0x08000000 /* combo only: first sub page */ #define _PAGE_COMBO 0x10000000 /* this is a combo 4k page */ +#define _PAGE_4K_PFN 0x20000000 /* PFN is for a single 4k page */ #define _PAGE_F_SECOND 0x00008000 /* full page: hidx bits */ #define _PAGE_F_GIX 0x00007000 /* full page: hidx bits */ @@ -93,6 +94,10 @@ #define pte_pagesize_index(pte) \ (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) +#define remap_4k_pfn(vma, addr, pfn, prot) \ + remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ + __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_PGTABLE_64K_H */ -- cgit v1.2.3-59-g8ed1b From ceef87782a9452eeeca774e65d7f4e06455780a3 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Apr 2007 22:24:06 +1000 Subject: [POWERPC] Rename get_property to of_get_property: include Signed-off-by: Stephen Rothwell Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/parport.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/asm-powerpc/parport.h b/include/asm-powerpc/parport.h index 3fca21ddf546..b37b81e37278 100644 --- a/include/asm-powerpc/parport.h +++ b/include/asm-powerpc/parport.h @@ -20,18 +20,18 @@ extern struct parport *parport_pc_probe_port (unsigned long int base, static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) { struct device_node *np; - u32 *prop; + const u32 *prop; u32 io1, io2; int propsize; int count = 0; for (np = NULL; (np = of_find_compatible_node(np, "parallel", "pnpPNP,400")) != NULL;) { - prop = (u32 *)get_property(np, "reg", &propsize); + prop = of_get_property(np, "reg", &propsize); if (!prop || propsize > 6*sizeof(u32)) continue; io1 = prop[1]; io2 = prop[2]; - prop = (u32 *)get_property(np, "interrupts", NULL); + prop = of_get_property(np, "interrupts", NULL); if (!prop) continue; if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL) -- cgit v1.2.3-59-g8ed1b From e68c825bb016703eda94aac99be96de73b482d61 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 11 Apr 2007 16:13:19 +1000 Subject: [POWERPC] Add inatomic versions of __get_user and __put_user Those are needed by things like alignment exception fixup handlers since those can now be triggered by copy_tofrom_user_inatomic. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- include/asm-powerpc/uaccess.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'include') diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index adbf16b8cfbb..8e798e3758bc 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -110,12 +110,18 @@ struct exception_table_entry { __get_user_nocheck((x), (ptr), sizeof(*(ptr))) #define __put_user(x, ptr) \ __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + #ifndef __powerpc64__ #define __get_user64(x, ptr) \ __get_user64_nocheck((x), (ptr), sizeof(*(ptr))) #define __put_user64(x, ptr) __put_user(x, ptr) #endif +#define __get_user_inatomic(x, ptr) \ + __get_user_nosleep((x), (ptr), sizeof(*(ptr))) +#define __put_user_inatomic(x, ptr) \ + __put_user_nosleep((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + #define __get_user_unaligned __get_user #define __put_user_unaligned __put_user @@ -198,6 +204,16 @@ do { \ __pu_err; \ }) +#define __put_user_nosleep(x, ptr, size) \ +({ \ + long __pu_err; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __chk_user_ptr(ptr); \ + __put_user_size((x), __pu_addr, (size), __pu_err); \ + __pu_err; \ +}) + + extern long __get_user_bad(void); #define __get_user_asm(x, addr, err, op) \ @@ -297,6 +313,18 @@ do { \ __gu_err; \ }) +#define __get_user_nosleep(x, ptr, size) \ +({ \ + long __gu_err; \ + unsigned long __gu_val; \ + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __chk_user_ptr(ptr); \ + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + + /* more complex routines */ extern unsigned long __copy_tofrom_user(void __user *to, -- cgit v1.2.3-59-g8ed1b From a741e67969577163a4cfc78d7fd2753219087ef1 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 10 Apr 2007 17:09:37 +1000 Subject: [POWERPC] Make tlb flush batch use lazy MMU mode The current tlb flush code on powerpc 64 bits has a subtle race since we lost the page table lock due to the possible faulting in of new PTEs after a previous one has been removed but before the corresponding hash entry has been evicted, which can leads to all sort of fatal problems. This patch reworks the batch code completely. It doesn't use the mmu_gather stuff anymore. Instead, we use the lazy mmu hooks that were added by the paravirt code. They have the nice property that the enter/leave lazy mmu mode pair is always fully contained by the PTE lock for a given range of PTEs. Thus we can guarantee that all batches are flushed on a given CPU before it drops that lock. We also generalize batching for any PTE update that require a flush. Batching is now enabled on a CPU by arch_enter_lazy_mmu_mode() and disabled by arch_leave_lazy_mmu_mode(). The code epects that this is always contained within a PTE lock section so no preemption can happen and no PTE insertion in that range from another CPU. When batching is enabled on a CPU, every PTE updates that need a hash flush will use the batch for that flush. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 4 +-- arch/powerpc/kernel/smp.c | 4 --- arch/powerpc/mm/hugetlbpage.c | 16 ++++------ arch/powerpc/mm/tlb_64.c | 68 ++++++++++++++++++++++++++---------------- include/asm-powerpc/pgtable.h | 50 ++++++++++--------------------- include/asm-powerpc/tlb.h | 1 - include/asm-powerpc/tlbflush.h | 39 +++++++++++++++--------- 7 files changed, 90 insertions(+), 92 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 949092dccf44..e509aae2feb3 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -305,9 +305,7 @@ struct task_struct *__switch_to(struct task_struct *prev, set_dabr(new->thread.dabr); __get_cpu_var(current_dabr) = new->thread.dabr; } - - flush_tlb_pending(); -#endif +#endif /* CONFIG_PPC64 */ new_thread = &new->thread; old_thread = ¤t->thread; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 924d692bc8f9..d8e503b2e1af 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -428,10 +428,6 @@ void generic_mach_cpu_die(void) smp_wmb(); while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE) cpu_relax(); - -#ifdef CONFIG_PPC64 - flush_tlb_pending(); -#endif cpu_set(cpu, cpu_online_map); local_irq_enable(); } diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index f6ffaaa7a5bf..8508f973d9cc 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c @@ -316,12 +316,11 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, { if (pte_present(*ptep)) { /* We open-code pte_clear because we need to pass the right - * argument to hpte_update (huge / !huge) + * argument to hpte_need_flush (huge / !huge). Might not be + * necessary anymore if we make hpte_need_flush() get the + * page size from the slices */ - unsigned long old = pte_update(ptep, ~0UL); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - flush_tlb_pending(); + pte_update(mm, addr & HPAGE_MASK, ptep, ~0UL, 1); } *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); } @@ -329,12 +328,7 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr & HPAGE_MASK, ptep, old, 1); - *ptep = __pte(0); - + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 1); return __pte(old); } diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index b58baa65c4a7..fd8d08c325eb 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c @@ -120,17 +120,20 @@ void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf) } /* - * Update the MMU hash table to correspond with a change to - * a Linux PTE. If wrprot is true, it is permissible to - * change the existing HPTE to read-only rather than removing it - * (if we remove it we should clear the _PTE_HPTEFLAGS bits). + * A linux PTE was changed and the corresponding hash table entry + * neesd to be flushed. This function will either perform the flush + * immediately or will batch it up if the current CPU has an active + * batch on it. + * + * Must be called from within some kind of spinlock/non-preempt region... */ -void hpte_update(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, unsigned long pte, int huge) +void hpte_need_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge) { struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); - unsigned long vsid; + unsigned long vsid, vaddr; unsigned int psize; + real_pte_t rpte; int i; i = batch->index; @@ -151,6 +154,26 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, } else psize = pte_pagesize_index(pte); + /* Build full vaddr */ + if (!is_kernel_addr(addr)) { + vsid = get_vsid(mm->context.id, addr); + WARN_ON(vsid == 0); + } else + vsid = get_kernel_vsid(addr); + vaddr = (vsid << 28 ) | (addr & 0x0fffffff); + rpte = __real_pte(__pte(pte), ptep); + + /* + * Check if we have an active batch on this CPU. If not, just + * flush now and return. For now, we don global invalidates + * in that case, might be worth testing the mm cpu mask though + * and decide to use local invalidates instead... + */ + if (!batch->active) { + flush_hash_page(vaddr, rpte, psize, 0); + return; + } + /* * This can happen when we are in the middle of a TLB batch and * we encounter memory pressure (eg copy_page_range when it tries @@ -162,47 +185,42 @@ void hpte_update(struct mm_struct *mm, unsigned long addr, * batch */ if (i != 0 && (mm != batch->mm || batch->psize != psize)) { - flush_tlb_pending(); + __flush_tlb_pending(batch); i = 0; } if (i == 0) { batch->mm = mm; batch->psize = psize; } - if (!is_kernel_addr(addr)) { - vsid = get_vsid(mm->context.id, addr); - WARN_ON(vsid == 0); - } else - vsid = get_kernel_vsid(addr); - batch->vaddr[i] = (vsid << 28 ) | (addr & 0x0fffffff); - batch->pte[i] = __real_pte(__pte(pte), ptep); + batch->pte[i] = rpte; + batch->vaddr[i] = vaddr; batch->index = ++i; if (i >= PPC64_TLB_BATCH_NR) - flush_tlb_pending(); + __flush_tlb_pending(batch); } +/* + * This function is called when terminating an mmu batch or when a batch + * is full. It will perform the flush of all the entries currently stored + * in a batch. + * + * Must be called from within some kind of spinlock/non-preempt region... + */ void __flush_tlb_pending(struct ppc64_tlb_batch *batch) { - int i; - int cpu; cpumask_t tmp; - int local = 0; + int i, local = 0; - BUG_ON(in_interrupt()); - - cpu = get_cpu(); i = batch->index; - tmp = cpumask_of_cpu(cpu); + tmp = cpumask_of_cpu(smp_processor_id()); if (cpus_equal(batch->mm->cpu_vm_mask, tmp)) local = 1; - if (i == 1) flush_hash_page(batch->vaddr[0], batch->pte[0], batch->psize, local); else flush_hash_range(i, local); batch->index = 0; - put_cpu(); } void pte_free_finish(void) diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index 10f52743f4ff..c7142c7e0e05 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -272,7 +272,10 @@ static inline pte_t pte_mkhuge(pte_t pte) { return pte; } /* Atomic PTE updates */ -static inline unsigned long pte_update(pte_t *p, unsigned long clr) +static inline unsigned long pte_update(struct mm_struct *mm, + unsigned long addr, + pte_t *ptep, unsigned long clr, + int huge) { unsigned long old, tmp; @@ -283,20 +286,15 @@ static inline unsigned long pte_update(pte_t *p, unsigned long clr) andc %1,%0,%4 \n\ stdcx. %1,0,%3 \n\ bne- 1b" - : "=&r" (old), "=&r" (tmp), "=m" (*p) - : "r" (p), "r" (clr), "m" (*p), "i" (_PAGE_BUSY) + : "=&r" (old), "=&r" (tmp), "=m" (*ptep) + : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY) : "cc" ); + + if (old & _PAGE_HASHPTE) + hpte_need_flush(mm, addr, ptep, old, huge); return old; } -/* PTE updating functions, this function puts the PTE in the - * batch, doesn't actually triggers the hash flush immediately, - * you need to call flush_tlb_pending() to do that. - * Pass -1 for "normal" size (4K or 64K) - */ -extern void hpte_update(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, unsigned long pte, int huge); - static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { @@ -304,11 +302,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) return 0; - old = pte_update(ptep, _PAGE_ACCESSED); - if (old & _PAGE_HASHPTE) { - hpte_update(mm, addr, ptep, old, 0); - flush_tlb_pending(); - } + old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0); return (old & _PAGE_ACCESSED) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG @@ -331,9 +325,7 @@ static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, if ((pte_val(*ptep) & _PAGE_DIRTY) == 0) return 0; - old = pte_update(ptep, _PAGE_DIRTY); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + old = pte_update(mm, addr, ptep, _PAGE_DIRTY, 0); return (old & _PAGE_DIRTY) != 0; } #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY @@ -352,9 +344,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, if ((pte_val(*ptep) & _PAGE_RW) == 0) return; - old = pte_update(ptep, _PAGE_RW); - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + old = pte_update(mm, addr, ptep, _PAGE_RW, 0); } /* @@ -378,7 +368,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, ({ \ int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \ __ptep); \ - flush_tlb_page(__vma, __address); \ __dirty; \ }) @@ -386,20 +375,14 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0); return __pte(old); } static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep) { - unsigned long old = pte_update(ptep, ~0UL); - - if (old & _PAGE_HASHPTE) - hpte_update(mm, addr, ptep, old, 0); + pte_update(mm, addr, ptep, ~0UL, 0); } /* @@ -408,10 +391,8 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte) { - if (pte_present(*ptep)) { + if (pte_present(*ptep)) pte_clear(mm, addr, ptep); - flush_tlb_pending(); - } pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); *ptep = pte; } @@ -522,6 +503,7 @@ void pgtable_cache_init(void); return pt; } + #include #endif /* __ASSEMBLY__ */ diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h index 4e2a834683fb..0a17682663d8 100644 --- a/include/asm-powerpc/tlb.h +++ b/include/asm-powerpc/tlb.h @@ -38,7 +38,6 @@ extern void pte_free_finish(void); static inline void tlb_flush(struct mmu_gather *tlb) { - flush_tlb_pending(); pte_free_finish(); } diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index 93c7d0c7230f..0bc5a5e506be 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -28,25 +28,41 @@ struct mm_struct; #define PPC64_TLB_BATCH_NR 192 struct ppc64_tlb_batch { - unsigned long index; - struct mm_struct *mm; - real_pte_t pte[PPC64_TLB_BATCH_NR]; - unsigned long vaddr[PPC64_TLB_BATCH_NR]; - unsigned int psize; + int active; + unsigned long index; + struct mm_struct *mm; + real_pte_t pte[PPC64_TLB_BATCH_NR]; + unsigned long vaddr[PPC64_TLB_BATCH_NR]; + unsigned int psize; }; DECLARE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); extern void __flush_tlb_pending(struct ppc64_tlb_batch *batch); -static inline void flush_tlb_pending(void) +extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, + pte_t *ptep, unsigned long pte, int huge); + +#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE + +static inline void arch_enter_lazy_mmu_mode(void) +{ + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); + + batch->active = 1; +} + +static inline void arch_leave_lazy_mmu_mode(void) { - struct ppc64_tlb_batch *batch = &get_cpu_var(ppc64_tlb_batch); + struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch); if (batch->index) __flush_tlb_pending(batch); - put_cpu_var(ppc64_tlb_batch); + batch->active = 0; } +#define arch_flush_lazy_mmu_mode() do {} while (0) + + extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local); extern void flush_hash_range(unsigned long number, int local); @@ -88,15 +104,12 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); static inline void flush_tlb_mm(struct mm_struct *mm) { - flush_tlb_pending(); } static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) { -#ifdef CONFIG_PPC64 - flush_tlb_pending(); -#else +#ifndef CONFIG_PPC64 _tlbie(vmaddr); #endif } @@ -112,13 +125,11 @@ static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, static inline void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - flush_tlb_pending(); } static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - flush_tlb_pending(); } #else /* 6xx, 7xx, 7xxx cpus */ -- cgit v1.2.3-59-g8ed1b From 88df6e90fa9782dbf44d936e44649afe271e4790 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 12 Apr 2007 15:30:22 +1000 Subject: [POWERPC] DEBUG_PAGEALLOC for 32-bit Here's an implementation of DEBUG_PAGEALLOC for ppc32. It disables BAT mapping and is only tested with Hash table based processor though it shouldn't be too hard to adapt it to others. Signed-off-by: Benjamin Herrenschmidt arch/powerpc/Kconfig.debug | 9 ++++++ arch/powerpc/mm/init_32.c | 4 +++ arch/powerpc/mm/pgtable_32.c | 52 +++++++++++++++++++++++++++++++++++++++ arch/powerpc/mm/ppc_mmu_32.c | 4 ++- include/asm-powerpc/cacheflush.h | 6 ++++ 5 files changed, 74 insertions(+), 1 deletion(-) Signed-off-by: Paul Mackerras --- arch/powerpc/Kconfig.debug | 9 +++++++ arch/powerpc/mm/init_32.c | 4 ++++ arch/powerpc/mm/pgtable_32.c | 52 ++++++++++++++++++++++++++++++++++++++++ arch/powerpc/mm/ppc_mmu_32.c | 4 +++- include/asm-powerpc/cacheflush.h | 6 +++++ 5 files changed, 74 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 50f48f0c5630..0f8bb86995b4 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -18,6 +18,15 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config DEBUG_PAGEALLOC + bool "Debug page memory allocations" + depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND && PPC32 + help + Unmap pages from the kernel linear mapping after free_pages(). + This results in a large slowdown, but helps to find certain types + of memory corruptions. + + config HCALL_STATS bool "Hypervisor call instrumentation" depends on PPC_PSERIES && DEBUG_FS diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 0e53ca8f02fb..5fce6ccecb8d 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c @@ -115,6 +115,10 @@ void MMU_setup(void) if (strstr(cmd_line, "noltlbs")) { __map_without_ltlbs = 1; } +#ifdef CONFIG_DEBUG_PAGEALLOC + __map_without_bats = 1; + __map_without_ltlbs = 1; +#endif } /* diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f75f2fc7bc7e..8a2fc16ee0a7 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -451,3 +451,55 @@ exit: return ret; } +#ifdef CONFIG_DEBUG_PAGEALLOC + +static int __change_page_attr(struct page *page, pgprot_t prot) +{ + pte_t *kpte; + pmd_t *kpmd; + unsigned long address; + + BUG_ON(PageHighMem(page)); + address = (unsigned long)page_address(page); + + if (v_mapped_by_bats(address) || v_mapped_by_tlbcam(address)) + return 0; + if (!get_pteptr(&init_mm, address, &kpte, &kpmd)) + return -EINVAL; + set_pte_at(&init_mm, address, kpte, mk_pte(page, prot)); + wmb(); + flush_HPTE(0, address, pmd_val(*kpmd)); + pte_unmap(kpte); + + return 0; +} + +/* + * Change the page attributes of an page in the linear mapping. + * + * THIS CONFLICTS WITH BAT MAPPINGS, DEBUG USE ONLY + */ +static int change_page_attr(struct page *page, int numpages, pgprot_t prot) +{ + int i, err = 0; + unsigned long flags; + + local_irq_save(flags); + for (i = 0; i < numpages; i++, page++) { + err = __change_page_attr(page, prot); + if (err) + break; + } + local_irq_restore(flags); + return err; +} + + +void kernel_map_pages(struct page *page, int numpages, int enable) +{ + if (PageHighMem(page)) + return; + + change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0)); +} +#endif /* CONFIG_DEBUG_PAGEALLOC */ diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 7cceb2c44cb9..05066674a7a0 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c @@ -85,8 +85,10 @@ unsigned long __init mmu_mapin_ram(void) unsigned long max_size = (256<<20); unsigned long align; - if (__map_without_bats) + if (__map_without_bats) { + printk(KERN_DEBUG "RAM mapped without BATs\n"); return 0; + } /* Set up BAT2 and if necessary BAT3 to cover RAM. */ diff --git a/include/asm-powerpc/cacheflush.h b/include/asm-powerpc/cacheflush.h index 08e93e789219..ba667a383b8c 100644 --- a/include/asm-powerpc/cacheflush.h +++ b/include/asm-powerpc/cacheflush.h @@ -64,6 +64,12 @@ extern void flush_dcache_phys_range(unsigned long start, unsigned long stop); memcpy(dst, src, len) + +#ifdef CONFIG_DEBUG_PAGEALLOC +/* internal debugging function */ +void kernel_map_pages(struct page *page, int numpages, int enable); +#endif + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_CACHEFLUSH_H */ -- cgit v1.2.3-59-g8ed1b From 57dace2391ba10135e38457904121e7ef34d0c83 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 23 Apr 2007 21:08:15 +0200 Subject: [POWERPC] spufs: make spu page faults not block scheduling Until now, we have always entered the spu page fault handler with a mutex for the spu context held. This has multiple bad side-effects: - it becomes impossible to suspend the context during page faults - if an spu program attempts to access its own mmio areas through DMA, we get an immediate livelock when the nopage function tries to acquire the same mutex This patch makes the page fault logic operate on a struct spu_context instead of a struct spu, and moves it from spu_base.c to a new file fault.c inside of spufs. We now also need to copy the dar and dsisr contents of the last fault into the saved context to have it accessible in case we schedule out the context before activating the page fault handler. Signed-off-by: Arnd Bergmann --- arch/powerpc/platforms/cell/spu_base.c | 103 ------------- arch/powerpc/platforms/cell/spufs/Makefile | 2 +- arch/powerpc/platforms/cell/spufs/backing_ops.c | 6 + arch/powerpc/platforms/cell/spufs/fault.c | 193 ++++++++++++++++++++++++ arch/powerpc/platforms/cell/spufs/hw_ops.c | 9 ++ arch/powerpc/platforms/cell/spufs/run.c | 28 +--- arch/powerpc/platforms/cell/spufs/spufs.h | 4 + arch/powerpc/platforms/cell/spufs/switch.c | 8 +- include/asm-powerpc/mmu.h | 1 + include/asm-powerpc/spu_csa.h | 1 + 10 files changed, 225 insertions(+), 130 deletions(-) create mode 100644 arch/powerpc/platforms/cell/spufs/fault.c (limited to 'include') diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index 6242f3c19f68..31fa55f33415 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c @@ -290,7 +290,6 @@ spu_irq_class_1(int irq, void *data) return stat ? IRQ_HANDLED : IRQ_NONE; } -EXPORT_SYMBOL_GPL(spu_irq_class_1_bottom); static irqreturn_t spu_irq_class_2(int irq, void *data) @@ -462,108 +461,6 @@ void spu_free(struct spu *spu) } EXPORT_SYMBOL_GPL(spu_free); -static int spu_handle_mm_fault(struct spu *spu) -{ - struct mm_struct *mm = spu->mm; - struct vm_area_struct *vma; - u64 ea, dsisr, is_write; - int ret; - - ea = spu->dar; - dsisr = spu->dsisr; -#if 0 - if (!IS_VALID_EA(ea)) { - return -EFAULT; - } -#endif /* XXX */ - if (mm == NULL) { - return -EFAULT; - } - if (mm->pgd == NULL) { - return -EFAULT; - } - - down_read(&mm->mmap_sem); - vma = find_vma(mm, ea); - if (!vma) - goto bad_area; - if (vma->vm_start <= ea) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; -#if 0 - if (expand_stack(vma, ea)) - goto bad_area; -#endif /* XXX */ -good_area: - is_write = dsisr & MFC_DSISR_ACCESS_PUT; - if (is_write) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (dsisr & MFC_DSISR_ACCESS_DENIED) - goto bad_area; - if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; - } - ret = 0; - switch (handle_mm_fault(mm, vma, ea, is_write)) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - ret = -EFAULT; - goto bad_area; - case VM_FAULT_OOM: - ret = -ENOMEM; - goto bad_area; - default: - BUG(); - } - up_read(&mm->mmap_sem); - return ret; - -bad_area: - up_read(&mm->mmap_sem); - return -EFAULT; -} - -int spu_irq_class_1_bottom(struct spu *spu) -{ - u64 ea, dsisr, access, error = 0UL; - int ret = 0; - - ea = spu->dar; - dsisr = spu->dsisr; - if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { - u64 flags; - - access = (_PAGE_PRESENT | _PAGE_USER); - access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; - local_irq_save(flags); - if (hash_page(ea, access, 0x300) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - local_irq_restore(flags); - } - if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { - if ((ret = spu_handle_mm_fault(spu)) != 0) - error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; - else - error &= ~CLASS1_ENABLE_STORAGE_FAULT_INTR; - } - spu->dar = 0UL; - spu->dsisr = 0UL; - if (!error) { - spu_restart_dma(spu); - } else { - spu->dma_callback(spu, SPE_EVENT_SPE_DATA_STORAGE); - } - return ret; -} - struct sysdev_class spu_sysdev_class = { set_kset_name("spu") }; diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile index 472217d19faf..2cd89c11af5a 100644 --- a/arch/powerpc/platforms/cell/spufs/Makefile +++ b/arch/powerpc/platforms/cell/spufs/Makefile @@ -1,4 +1,4 @@ -obj-y += switch.o +obj-y += switch.o fault.o obj-$(CONFIG_SPU_FS) += spufs.o spufs-y += inode.o file.o context.o syscalls.o coredump.o diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index 1898f0d3a8b8..3322528fa6eb 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c @@ -350,6 +350,11 @@ static int spu_backing_send_mfc_command(struct spu_context *ctx, return ret; } +static void spu_backing_restart_dma(struct spu_context *ctx) +{ + /* nothing to do here */ +} + struct spu_context_ops spu_backing_ops = { .mbox_read = spu_backing_mbox_read, .mbox_stat_read = spu_backing_mbox_stat_read, @@ -376,4 +381,5 @@ struct spu_context_ops spu_backing_ops = { .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, .get_mfc_free_elements = spu_backing_get_mfc_free_elements, .send_mfc_command = spu_backing_send_mfc_command, + .restart_dma = spu_backing_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c new file mode 100644 index 000000000000..182dc914cbc9 --- /dev/null +++ b/arch/powerpc/platforms/cell/spufs/fault.c @@ -0,0 +1,193 @@ +/* + * Low-level SPU handling + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * + * Author: Arnd Bergmann + * + * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +#include +#include + +#include "spufs.h" + +/* + * This ought to be kept in sync with the powerpc specific do_page_fault + * function. Currently, there are a few corner cases that we haven't had + * to handle fortunately. + */ +static int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, unsigned long dsisr) +{ + struct vm_area_struct *vma; + unsigned long is_write; + int ret; + +#if 0 + if (!IS_VALID_EA(ea)) { + return -EFAULT; + } +#endif /* XXX */ + if (mm == NULL) { + return -EFAULT; + } + if (mm->pgd == NULL) { + return -EFAULT; + } + + down_read(&mm->mmap_sem); + vma = find_vma(mm, ea); + if (!vma) + goto bad_area; + if (vma->vm_start <= ea) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, ea)) + goto bad_area; +good_area: + is_write = dsisr & MFC_DSISR_ACCESS_PUT; + if (is_write) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (dsisr & MFC_DSISR_ACCESS_DENIED) + goto bad_area; + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto bad_area; + } + ret = 0; + switch (handle_mm_fault(mm, vma, ea, is_write)) { + case VM_FAULT_MINOR: + current->min_flt++; + break; + case VM_FAULT_MAJOR: + current->maj_flt++; + break; + case VM_FAULT_SIGBUS: + ret = -EFAULT; + goto bad_area; + case VM_FAULT_OOM: + ret = -ENOMEM; + goto bad_area; + default: + BUG(); + } + up_read(&mm->mmap_sem); + return ret; + +bad_area: + up_read(&mm->mmap_sem); + return -EFAULT; +} + +static void spufs_handle_dma_error(struct spu_context *ctx, int type) +{ + if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { + ctx->event_return |= type; + wake_up_all(&ctx->stop_wq); + } else { + switch (type) { + case SPE_EVENT_DMA_ALIGNMENT: + case SPE_EVENT_SPE_DATA_STORAGE: + case SPE_EVENT_INVALID_DMA: + force_sig(SIGBUS, /* info, */ current); + break; + case SPE_EVENT_SPE_ERROR: + force_sig(SIGILL, /* info */ current); + break; + } + } +} + +void spufs_dma_callback(struct spu *spu, int type) +{ + spufs_handle_dma_error(spu->ctx, type); +} +EXPORT_SYMBOL_GPL(spufs_dma_callback); + +/* + * bottom half handler for page faults, we can't do this from + * interrupt context, since we might need to sleep. + * we also need to give up the mutex so we can get scheduled + * out while waiting for the backing store. + * + * TODO: try calling hash_page from the interrupt handler first + * in order to speed up the easy case. + */ +int spufs_handle_class1(struct spu_context *ctx) +{ + u64 ea, dsisr, access; + unsigned long flags; + int ret; + + /* + * dar and dsisr get passed from the registers + * to the spu_context, to this function, but not + * back to the spu if it gets scheduled again. + * + * if we don't handle the fault for a saved context + * in time, we can still expect to get the same fault + * the immediately after the context restore. + */ + if (ctx->state == SPU_STATE_RUNNABLE) { + ea = ctx->spu->dar; + dsisr = ctx->spu->dsisr; + ctx->spu->dar= ctx->spu->dsisr = 0; + } else { + ea = ctx->csa.priv1.mfc_dar_RW; + dsisr = ctx->csa.priv1.mfc_dsisr_RW; + ctx->csa.priv1.mfc_dar_RW = 0; + ctx->csa.priv1.mfc_dsisr_RW = 0; + } + + if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) + return 0; + + pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, + dsisr, ctx->state); + + /* we must not hold the lock when entering spu_handle_mm_fault */ + spu_release(ctx); + + access = (_PAGE_PRESENT | _PAGE_USER); + access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; + local_irq_save(flags); + ret = hash_page(ea, access, 0x300); + local_irq_restore(flags); + + /* hashing failed, so try the actual fault handler */ + if (ret) + ret = spu_handle_mm_fault(current->mm, ea, dsisr); + + spu_acquire(ctx); + /* + * If we handled the fault successfully and are in runnable + * state, restart the DMA. + * In case of unhandled error report the problem to user space. + */ + if (!ret) { + if (ctx->spu) + ctx->ops->restart_dma(ctx); + } else + spufs_handle_dma_error(ctx, SPE_EVENT_SPE_DATA_STORAGE); + + return ret; +} +EXPORT_SYMBOL_GPL(spufs_handle_class1); diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index ae42e03b8c86..428875c5e4ec 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -296,6 +296,14 @@ static int spu_hw_send_mfc_command(struct spu_context *ctx, } } +static void spu_hw_restart_dma(struct spu_context *ctx) +{ + struct spu_priv2 __iomem *priv2 = ctx->spu->priv2; + + if (!test_bit(SPU_CONTEXT_SWITCH_PENDING, &ctx->spu->flags)) + out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESTART_DMA_COMMAND); +} + struct spu_context_ops spu_hw_ops = { .mbox_read = spu_hw_mbox_read, .mbox_stat_read = spu_hw_mbox_stat_read, @@ -320,4 +328,5 @@ struct spu_context_ops spu_hw_ops = { .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, .get_mfc_free_elements = spu_hw_get_mfc_free_elements, .send_mfc_command = spu_hw_send_mfc_command, + .restart_dma = spu_hw_restart_dma, }; diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 7df5202c9a90..1a8195bf75d5 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c @@ -18,27 +18,6 @@ void spufs_stop_callback(struct spu *spu) wake_up_all(&ctx->stop_wq); } -void spufs_dma_callback(struct spu *spu, int type) -{ - struct spu_context *ctx = spu->ctx; - - if (ctx->flags & SPU_CREATE_EVENTS_ENABLED) { - ctx->event_return |= type; - wake_up_all(&ctx->stop_wq); - } else { - switch (type) { - case SPE_EVENT_DMA_ALIGNMENT: - case SPE_EVENT_SPE_DATA_STORAGE: - case SPE_EVENT_INVALID_DMA: - force_sig(SIGBUS, /* info, */ current); - break; - case SPE_EVENT_SPE_ERROR: - force_sig(SIGILL, /* info */ current); - break; - } - } -} - static inline int spu_stopped(struct spu_context *ctx, u32 * stat) { struct spu *spu; @@ -294,11 +273,8 @@ int spu_process_callback(struct spu_context *ctx) static inline int spu_process_events(struct spu_context *ctx) { struct spu *spu = ctx->spu; - u64 pte_fault = MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED; int ret = 0; - if (spu->dsisr & pte_fault) - ret = spu_irq_class_1_bottom(spu); if (spu->class_0_pending) ret = spu_irq_class_0_bottom(spu); if (!ret && signal_pending(current)) @@ -332,6 +308,10 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, break; status &= ~SPU_STATUS_STOPPED_BY_STOP; } + ret = spufs_handle_class1(ctx); + if (ret) + break; + if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { ret = spu_reacquire_runnable(ctx, npc, &status); if (ret) { diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index cae2ad435b0a..9993c9b3cffc 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h @@ -141,6 +141,7 @@ struct spu_context_ops { struct spu_dma_info * info); void (*proxydma_info_read) (struct spu_context * ctx, struct spu_proxydma_info * info); + void (*restart_dma)(struct spu_context *ctx); }; extern struct spu_context_ops spu_hw_ops; @@ -172,6 +173,9 @@ int put_spu_gang(struct spu_gang *gang); void spu_gang_remove_ctx(struct spu_gang *gang, struct spu_context *ctx); void spu_gang_add_ctx(struct spu_gang *gang, struct spu_context *ctx); +/* fault handling */ +int spufs_handle_class1(struct spu_context *ctx); + /* context management */ static inline void spu_acquire(struct spu_context *ctx) { diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index fd91c73de34e..8347c4a3f894 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c @@ -2084,6 +2084,10 @@ int spu_save(struct spu_state *prev, struct spu *spu) int rc; acquire_spu_lock(spu); /* Step 1. */ + prev->dar = spu->dar; + prev->dsisr = spu->dsisr; + spu->dar = 0; + spu->dsisr = 0; rc = __do_spu_save(prev, spu); /* Steps 2-53. */ release_spu_lock(spu); if (rc != 0 && rc != 2 && rc != 6) { @@ -2109,9 +2113,9 @@ int spu_restore(struct spu_state *new, struct spu *spu) acquire_spu_lock(spu); harvest(NULL, spu); - spu->dar = 0; - spu->dsisr = 0; spu->slb_replace = 0; + new->dar = 0; + new->dsisr = 0; spu->class_0_pending = 0; rc = __do_spu_restore(new, spu); release_spu_lock(spu); diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index 200055a4b82b..e22fd8811505 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -234,6 +234,7 @@ extern int __hash_page_64K(unsigned long ea, unsigned long access, unsigned long vsid, pte_t *ptep, unsigned long trap, unsigned int local); struct mm_struct; +extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); extern int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long ea, unsigned long vsid, int local, unsigned long trap); diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h index 8aad0619eb8e..02e56a6685a2 100644 --- a/include/asm-powerpc/spu_csa.h +++ b/include/asm-powerpc/spu_csa.h @@ -242,6 +242,7 @@ struct spu_state { u64 spu_chnldata_RW[32]; u32 spu_mailbox_data[4]; u32 pu_mailbox_data[1]; + u64 dar, dsisr; unsigned long suspend_time; spinlock_t register_lock; }; -- cgit v1.2.3-59-g8ed1b From 91a69c9646a5b709381d99a171890e77377b1b9c Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Mon, 23 Apr 2007 21:35:39 +0200 Subject: [POWERPC] cell: add cbe_node_to_cpu function This patch adds code to deal with conversion of logical cpu to cbe nodes. It removes code that assummed there were two logical CPUs per CBE. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann --- arch/powerpc/oprofile/op_model_cell.c | 1 + arch/powerpc/platforms/cell/cbe_regs.c | 53 +++++++++++++++++++++++++--------- arch/powerpc/platforms/cell/cbe_regs.h | 5 ++++ include/asm-powerpc/cell-pmu.h | 5 ---- 4 files changed, 45 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/arch/powerpc/oprofile/op_model_cell.c b/arch/powerpc/oprofile/op_model_cell.c index e08e1d7b3dc5..fb999e3e9f21 100644 --- a/arch/powerpc/oprofile/op_model_cell.c +++ b/arch/powerpc/oprofile/op_model_cell.c @@ -37,6 +37,7 @@ #include #include "../platforms/cell/interrupt.h" +#include "../platforms/cell/cbe_regs.h" #define PPU_CYCLES_EVENT_NUM 1 /* event number for CYCLES */ #define PPU_CYCLES_GRP_NUM 1 /* special group number for identifying diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c index 7c94af4ac439..dca39c0af7ea 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.c +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -38,8 +38,13 @@ static struct cbe_thread_map { struct device_node *cpu_node; struct cbe_regs_map *regs; + unsigned int thread_id; + unsigned int cbe_id; } cbe_thread_map[NR_CPUS]; +static cpumask_t cbe_local_mask[MAX_CBE] = { [0 ... MAX_CBE-1] = CPU_MASK_NONE }; +static cpumask_t cbe_first_online_cpu = CPU_MASK_NONE; + static struct cbe_regs_map *cbe_find_map(struct device_node *np) { int i; @@ -130,31 +135,40 @@ struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu) } EXPORT_SYMBOL_GPL(cbe_get_cpu_mic_tm_regs); -/* FIXME - * This is little more than a stub at the moment. It should be - * fleshed out so that it works for both SMT and non-SMT, no - * matter if the passed cpu is odd or even. - * For SMT enabled, returns 0 for even-numbered cpu; otherwise 1. - * For SMT disabled, returns 0 for all cpus. - */ u32 cbe_get_hw_thread_id(int cpu) { - return (cpu & 1); + return cbe_thread_map[cpu].thread_id; } EXPORT_SYMBOL_GPL(cbe_get_hw_thread_id); +u32 cbe_cpu_to_node(int cpu) +{ + return cbe_thread_map[cpu].cbe_id; +} +EXPORT_SYMBOL_GPL(cbe_cpu_to_node); + +u32 cbe_node_to_cpu(int node) +{ + return find_first_bit( (unsigned long *) &cbe_local_mask[node], sizeof(cpumask_t)); +} +EXPORT_SYMBOL_GPL(cbe_node_to_cpu); + void __init cbe_regs_init(void) { int i; + unsigned int thread_id; struct device_node *cpu; /* Build local fast map of CPUs */ - for_each_possible_cpu(i) - cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); + for_each_possible_cpu(i) { + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, &thread_id); + cbe_thread_map[i].thread_id = thread_id; + } /* 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++]; + struct cbe_regs_map *map; + unsigned int cbe_id; /* That hack must die die die ! */ const struct address_prop { @@ -162,6 +176,8 @@ void __init cbe_regs_init(void) unsigned int len; } __attribute__((packed)) *prop; + cbe_id = cbe_regs_map_count++; + map = &cbe_regs_maps[cbe_id]; if (cbe_regs_map_count > MAX_CBE) { printk(KERN_ERR "cbe_regs: More BE chips than supported" @@ -170,9 +186,18 @@ void __init cbe_regs_init(void) return; } map->cpu_node = cpu; - for_each_possible_cpu(i) - if (cbe_thread_map[i].cpu_node == cpu) - cbe_thread_map[i].regs = map; + + for_each_possible_cpu(i) { + struct cbe_thread_map *thread = &cbe_thread_map[i]; + + if (thread->cpu_node == cpu) { + thread->regs = map; + thread->cbe_id = cbe_id; + cpu_set(i, cbe_local_mask[cbe_id]); + if(thread->thread_id == 0) + cpu_set(i, cbe_first_online_cpu); + } + } prop = of_get_property(cpu, "pervasive", NULL); if (prop != NULL) diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h index 440a7ecc66ea..17d597144877 100644 --- a/arch/powerpc/platforms/cell/cbe_regs.h +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -255,6 +255,11 @@ struct cbe_mic_tm_regs { extern struct cbe_mic_tm_regs __iomem *cbe_get_mic_tm_regs(struct device_node *np); extern struct cbe_mic_tm_regs __iomem *cbe_get_cpu_mic_tm_regs(int cpu); +/* some utility functions to deal with SMT */ +extern u32 cbe_get_hw_thread_id(int cpu); +extern u32 cbe_cpu_to_node(int cpu); +extern u32 cbe_node_to_cpu(int node); + /* Init this module early */ extern void cbe_regs_init(void); diff --git a/include/asm-powerpc/cell-pmu.h b/include/asm-powerpc/cell-pmu.h index 35b95773746c..8066eede3a0c 100644 --- a/include/asm-powerpc/cell-pmu.h +++ b/include/asm-powerpc/cell-pmu.h @@ -97,11 +97,6 @@ extern void cbe_disable_pm_interrupts(u32 cpu); extern u32 cbe_get_and_clear_pm_interrupts(u32 cpu); extern void cbe_sync_irq(int node); -/* Utility functions, macros */ -extern u32 cbe_get_hw_thread_id(int cpu); - -#define cbe_cpu_to_node(cpu) ((cpu) >> 1) - #define CBE_COUNT_SUPERVISOR_MODE 0 #define CBE_COUNT_HYPERVISOR_MODE 1 #define CBE_COUNT_PROBLEM_MODE 2 -- cgit v1.2.3-59-g8ed1b From 6bf05fd776e38a0a9c17e17c2345b59b1b9aa2cb Mon Sep 17 00:00:00 2001 From: Christian Krafft Date: Mon, 23 Apr 2007 21:35:45 +0200 Subject: [POWERPC] add of_iomap function The of_iomap function maps memory for a given device_node and returns a pointer to that memory. This is used at some places, so it makes sense to a seperate function. Signed-off-by: Christian Krafft Signed-off-by: Arnd Bergmann --- arch/powerpc/sysdev/pmi.c | 19 ++----------------- include/asm-powerpc/prom.h | 11 +++++++++++ 2 files changed, 13 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 05db1f9f82d3..85a7c99c1003 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c @@ -33,7 +33,7 @@ #include #include #include - +#include struct pmi_data { struct list_head handler; @@ -49,21 +49,6 @@ struct pmi_data { }; - -static void __iomem *of_iomap(struct device_node *np) -{ - struct resource res; - - if (of_address_to_resource(np, 0, &res)) - return NULL; - - pr_debug("Resource start: 0x%lx\n", res.start); - pr_debug("Resource end: 0x%lx\n", res.end); - - return ioremap(res.start, 1 + res.end - res.start); -} - - static int pmi_irq_handler(int irq, void *dev_id) { struct pmi_data *data; @@ -154,7 +139,7 @@ static int pmi_of_probe(struct of_device *dev, goto out; } - data->pmi_reg = of_iomap(np); + data->pmi_reg = of_iomap(np, 0); if (!data->pmi_reg) { printk(KERN_ERR "pmi: invalid register address.\n"); rc = -EFAULT; diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index e73a2b482a15..f31af713e6a4 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -20,6 +20,7 @@ #include #include #include +#include /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* marker */ @@ -355,6 +356,16 @@ static inline int of_irq_to_resource(struct device_node *dev, int index, struct return irq; } +static inline void __iomem *of_iomap(struct device_node *np, int index) +{ + struct resource res; + + if (of_address_to_resource(np, index, &res)) + return NULL; + + return ioremap(res.start, 1 + res.end - res.start); +} + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ -- cgit v1.2.3-59-g8ed1b From a14c4508f4bb1bb7772b1976a82646be8d8b515a Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Fri, 13 Apr 2007 04:33:25 +1000 Subject: [POWERPC] Fix PowerPC 750CL and 750GX CPU features PowerPC 750CL has high BATs. The patch below adds a CPU_FTRS_750CL that includes that. Without it, the original firmware mappings in the high BATs aren't cleared which continue to override the linux translations. It also adds CPU_FTR_COMMON to CPU_FTRS_750GX for completeness. Signed-off-by: Josh Boyer Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 4 ++-- include/asm-powerpc/cputable.h | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 6b59e40214d2..ad74fecae507 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -562,12 +562,12 @@ static struct cpu_spec cpu_specs[] = { .pvr_mask = 0xfffff0f0, .pvr_value = 0x00087010, .cpu_name = "750CL", - .cpu_features = CPU_FTRS_750, + .cpu_features = CPU_FTRS_750CL, .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750cx, + .cpu_setup = __setup_cpu_750, .platform = "ppc750", }, { /* 745/755 */ diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index e870b5393175..4f7c25518641 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -223,6 +223,10 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_PPC_LE) +#define CPU_FTRS_750CL (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_750FX1 (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ @@ -235,9 +239,9 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start, CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) -#define CPU_FTRS_750GX (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \ - CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ +#define CPU_FTRS_750GX (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ + CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ + CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \ CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE) #define CPU_FTRS_7400_NOTAU (CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \ CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \ -- cgit v1.2.3-59-g8ed1b From 25fc530eed1ca9ccde2a1e96d0b2060867f76bb2 Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Wed, 18 Apr 2007 16:38:21 +1000 Subject: [POWERPC] pasemi: PA6T oprofile support Oprofile support for PA6T, kernel side. Also rename the PA6T_SPRN.* defines to SPRN_PA6T.*. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 2 + arch/powerpc/kernel/sysfs.c | 12 +- arch/powerpc/oprofile/Makefile | 2 +- arch/powerpc/oprofile/common.c | 3 + arch/powerpc/oprofile/op_model_pa6t.c | 234 ++++++++++++++++++++++++++++++++++ include/asm-powerpc/cputable.h | 1 + include/asm-powerpc/oprofile_impl.h | 2 + include/asm-powerpc/pmc.h | 1 + include/asm-powerpc/reg.h | 68 +++++++++- 9 files changed, 312 insertions(+), 13 deletions(-) create mode 100644 arch/powerpc/oprofile/op_model_pa6t.c (limited to 'include') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index ad74fecae507..9cb24d20f0f9 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -389,6 +389,8 @@ static struct cpu_spec cpu_specs[] = { .pmc_type = PPC_PMC_PA6T, .cpu_setup = __setup_cpu_pa6t, .cpu_restore = __restore_cpu_pa6t, + .oprofile_cpu_type = "ppc64/pa6t", + .oprofile_type = PPC_OPROFILE_PA6T, .platform = "pa6t", }, { /* default match */ diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 476f1d546056..6fc27e771b5a 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -189,12 +189,12 @@ SYSFS_PMCSETUP(purr, SPRN_PURR); SYSFS_PMCSETUP(spurr, SPRN_SPURR); SYSFS_PMCSETUP(dscr, SPRN_DSCR); -SYSFS_PMCSETUP(pa6t_pmc0, PA6T_SPRN_PMC0); -SYSFS_PMCSETUP(pa6t_pmc1, PA6T_SPRN_PMC1); -SYSFS_PMCSETUP(pa6t_pmc2, PA6T_SPRN_PMC2); -SYSFS_PMCSETUP(pa6t_pmc3, PA6T_SPRN_PMC3); -SYSFS_PMCSETUP(pa6t_pmc4, PA6T_SPRN_PMC4); -SYSFS_PMCSETUP(pa6t_pmc5, PA6T_SPRN_PMC5); +SYSFS_PMCSETUP(pa6t_pmc0, SPRN_PA6T_PMC0); +SYSFS_PMCSETUP(pa6t_pmc1, SPRN_PA6T_PMC1); +SYSFS_PMCSETUP(pa6t_pmc2, SPRN_PA6T_PMC2); +SYSFS_PMCSETUP(pa6t_pmc3, SPRN_PA6T_PMC3); +SYSFS_PMCSETUP(pa6t_pmc4, SPRN_PA6T_PMC4); +SYSFS_PMCSETUP(pa6t_pmc5, SPRN_PA6T_PMC5); static SYSDEV_ATTR(mmcra, 0600, show_mmcra, store_mmcra); diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 4ccef2d5530c..4b5f9528218c 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile @@ -12,6 +12,6 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o oprofile-$(CONFIG_PPC_CELL_NATIVE) += op_model_cell.o -oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o +oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o oprofile-$(CONFIG_6xx) += op_model_7450.o diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index fbd62eacfdf4..1a7ef7e246d2 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c @@ -160,6 +160,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case PPC_OPROFILE_POWER4: model = &op_model_power4; break; + case PPC_OPROFILE_PA6T: + model = &op_model_pa6t; + break; #endif #ifdef CONFIG_6xx case PPC_OPROFILE_G4: diff --git a/arch/powerpc/oprofile/op_model_pa6t.c b/arch/powerpc/oprofile/op_model_pa6t.c new file mode 100644 index 000000000000..e8a56b0adadc --- /dev/null +++ b/arch/powerpc/oprofile/op_model_pa6t.c @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Author: Shashi Rao, PA Semi + * + * Maintained by: Olof Johansson + * + * Based on arch/powerpc/oprofile/op_model_power4.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +static unsigned char oprofile_running; + +/* mmcr values are set in pa6t_reg_setup, used in pa6t_cpu_setup */ +static u64 mmcr0_val; +static u64 mmcr1_val; + +/* inited in pa6t_reg_setup */ +static u64 reset_value[OP_MAX_COUNTER]; + +static inline u64 ctr_read(unsigned int i) +{ + switch (i) { + case 0: + return mfspr(SPRN_PA6T_PMC0); + case 1: + return mfspr(SPRN_PA6T_PMC1); + case 2: + return mfspr(SPRN_PA6T_PMC2); + case 3: + return mfspr(SPRN_PA6T_PMC3); + case 4: + return mfspr(SPRN_PA6T_PMC4); + case 5: + return mfspr(SPRN_PA6T_PMC5); + default: + printk(KERN_ERR "ctr_read called with bad arg %u\n", i); + return 0; + } +} + +static inline void ctr_write(unsigned int i, u64 val) +{ + switch (i) { + case 0: + mtspr(SPRN_PA6T_PMC0, val); + break; + case 1: + mtspr(SPRN_PA6T_PMC1, val); + break; + case 2: + mtspr(SPRN_PA6T_PMC2, val); + break; + case 3: + mtspr(SPRN_PA6T_PMC3, val); + break; + case 4: + mtspr(SPRN_PA6T_PMC4, val); + break; + case 5: + mtspr(SPRN_PA6T_PMC5, val); + break; + default: + printk(KERN_ERR "ctr_write called with bad arg %u\n", i); + break; + } +} + + +/* precompute the values to stuff in the hardware registers */ +static void pa6t_reg_setup(struct op_counter_config *ctr, + struct op_system_config *sys, + int num_ctrs) +{ + int pmc; + + /* + * adjust the mmcr0.en[0-5] and mmcr0.inten[0-5] values obtained from the + * event_mappings file by turning off the counters that the user doesn't + * care about + * + * setup user and kernel profiling + */ + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) + if (!ctr[pmc].enabled) { + sys->mmcr0 &= ~(0x1UL << pmc); + sys->mmcr0 &= ~(0x1UL << (pmc+12)); + pr_debug("turned off counter %u\n", pmc); + } + + if (sys->enable_kernel) + sys->mmcr0 |= PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN; + else + sys->mmcr0 &= ~(PA6T_MMCR0_SUPEN | PA6T_MMCR0_HYPEN); + + if (sys->enable_user) + sys->mmcr0 |= PA6T_MMCR0_PREN; + else + sys->mmcr0 &= ~PA6T_MMCR0_PREN; + + /* + * The performance counter event settings are given in the mmcr0 and + * mmcr1 values passed from the user in the op_system_config + * structure (sys variable). + */ + mmcr0_val = sys->mmcr0; + mmcr1_val = sys->mmcr1; + pr_debug("mmcr0_val inited to %016lx\n", sys->mmcr0); + pr_debug("mmcr1_val inited to %016lx\n", sys->mmcr1); + + for (pmc = 0; pmc < cur_cpu_spec->num_pmcs; pmc++) { + /* counters are 40 bit. Move to cputable at some point? */ + reset_value[pmc] = (0x1UL << 39) - ctr[pmc].count; + pr_debug("reset_value for pmc%u inited to 0x%lx\n", + pmc, reset_value[pmc]); + } +} + +/* configure registers on this cpu */ +static void pa6t_cpu_setup(struct op_counter_config *ctr) +{ + u64 mmcr0 = mmcr0_val; + u64 mmcr1 = mmcr1_val; + + /* Default is all PMCs off */ + mmcr0 &= ~(0x3FUL); + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + /* program selected programmable events in */ + mtspr(SPRN_PA6T_MMCR1, mmcr1); + + pr_debug("setup on cpu %d, mmcr0 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR0)); + pr_debug("setup on cpu %d, mmcr1 %016lx\n", smp_processor_id(), + mfspr(SPRN_PA6T_MMCR1)); +} + +static void pa6t_start(struct op_counter_config *ctr) +{ + int i; + + /* Hold off event counting until rfid */ + u64 mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) + if (ctr[i].enabled) + ctr_write(i, reset_value[i]); + else + ctr_write(i, 0UL); + + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 1; + + pr_debug("start on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +static void pa6t_stop(void) +{ + u64 mmcr0; + + /* freeze counters */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mmcr0 |= PA6T_MMCR0_FCM0; + mtspr(SPRN_PA6T_MMCR0, mmcr0); + + oprofile_running = 0; + + pr_debug("stop on cpu %d, mmcr0 %lx\n", smp_processor_id(), mmcr0); +} + +/* handle the perfmon overflow vector */ +static void pa6t_handle_interrupt(struct pt_regs *regs, + struct op_counter_config *ctr) +{ + unsigned long pc = mfspr(SPRN_PA6T_SIAR); + int is_kernel = is_kernel_addr(pc); + u64 val; + int i; + u64 mmcr0; + + /* disable perfmon counting until rfid */ + mmcr0 = mfspr(SPRN_PA6T_MMCR0); + mtspr(SPRN_PA6T_MMCR0, mmcr0 | PA6T_MMCR0_HANDDIS); + + /* Record samples. We've got one global bit for whether a sample + * was taken, so add it for any counter that triggered overflow. + */ + for (i = 0; i < cur_cpu_spec->num_pmcs; i++) { + val = ctr_read(i); + if (val & (0x1UL << 39)) { /* Overflow bit set */ + if (oprofile_running && ctr[i].enabled) { + if (mmcr0 & PA6T_MMCR0_SIARLOG) + oprofile_add_ext_sample(pc, regs, i, is_kernel); + ctr_write(i, reset_value[i]); + } else { + ctr_write(i, 0UL); + } + } + } + + /* Restore mmcr0 to a good known value since the PMI changes it */ + mmcr0 = mmcr0_val | PA6T_MMCR0_HANDDIS; + mtspr(SPRN_PA6T_MMCR0, mmcr0); +} + +struct op_powerpc_model op_model_pa6t = { + .reg_setup = pa6t_reg_setup, + .cpu_setup = pa6t_cpu_setup, + .start = pa6t_start, + .stop = pa6t_stop, + .handle_interrupt = pa6t_handle_interrupt, +}; diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h index 4f7c25518641..434524931ef3 100644 --- a/include/asm-powerpc/cputable.h +++ b/include/asm-powerpc/cputable.h @@ -48,6 +48,7 @@ enum powerpc_oprofile_type { PPC_OPROFILE_G4 = 3, PPC_OPROFILE_BOOKE = 4, PPC_OPROFILE_CELL = 5, + PPC_OPROFILE_PA6T = 6, }; enum powerpc_pmc_type { diff --git a/include/asm-powerpc/oprofile_impl.h b/include/asm-powerpc/oprofile_impl.h index 94c0ad2bff96..8d6b47f7b300 100644 --- a/include/asm-powerpc/oprofile_impl.h +++ b/include/asm-powerpc/oprofile_impl.h @@ -57,6 +57,8 @@ extern struct op_powerpc_model op_model_rs64; extern struct op_powerpc_model op_model_power4; extern struct op_powerpc_model op_model_7450; extern struct op_powerpc_model op_model_cell; +extern struct op_powerpc_model op_model_pa6t; + /* All the classic PPC parts use these */ static inline unsigned int classic_ctr_read(unsigned int i) diff --git a/include/asm-powerpc/pmc.h b/include/asm-powerpc/pmc.h index 8588be68e0ad..d6a616a1b3ea 100644 --- a/include/asm-powerpc/pmc.h +++ b/include/asm-powerpc/pmc.h @@ -30,6 +30,7 @@ void release_pmc_hardware(void); #ifdef CONFIG_PPC64 void power4_enable_pmcs(void); +void pasemi_enable_pmcs(void); #endif #endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h index 0d7f0164ed81..749c7f953b58 100644 --- a/include/asm-powerpc/reg.h +++ b/include/asm-powerpc/reg.h @@ -469,12 +469,68 @@ #define SPRN_SIAR 780 #define SPRN_SDAR 781 -#define PA6T_SPRN_PMC0 787 -#define PA6T_SPRN_PMC1 788 -#define PA6T_SPRN_PMC2 789 -#define PA6T_SPRN_PMC3 790 -#define PA6T_SPRN_PMC4 791 -#define PA6T_SPRN_PMC5 792 +#define SPRN_PA6T_MMCR0 795 +#define PA6T_MMCR0_EN0 0x0000000000000001UL +#define PA6T_MMCR0_EN1 0x0000000000000002UL +#define PA6T_MMCR0_EN2 0x0000000000000004UL +#define PA6T_MMCR0_EN3 0x0000000000000008UL +#define PA6T_MMCR0_EN4 0x0000000000000010UL +#define PA6T_MMCR0_EN5 0x0000000000000020UL +#define PA6T_MMCR0_SUPEN 0x0000000000000040UL +#define PA6T_MMCR0_PREN 0x0000000000000080UL +#define PA6T_MMCR0_HYPEN 0x0000000000000100UL +#define PA6T_MMCR0_FCM0 0x0000000000000200UL +#define PA6T_MMCR0_FCM1 0x0000000000000400UL +#define PA6T_MMCR0_INTGEN 0x0000000000000800UL +#define PA6T_MMCR0_INTEN0 0x0000000000001000UL +#define PA6T_MMCR0_INTEN1 0x0000000000002000UL +#define PA6T_MMCR0_INTEN2 0x0000000000004000UL +#define PA6T_MMCR0_INTEN3 0x0000000000008000UL +#define PA6T_MMCR0_INTEN4 0x0000000000010000UL +#define PA6T_MMCR0_INTEN5 0x0000000000020000UL +#define PA6T_MMCR0_DISCNT 0x0000000000040000UL +#define PA6T_MMCR0_UOP 0x0000000000080000UL +#define PA6T_MMCR0_TRG 0x0000000000100000UL +#define PA6T_MMCR0_TRGEN 0x0000000000200000UL +#define PA6T_MMCR0_TRGREG 0x0000000001600000UL +#define PA6T_MMCR0_SIARLOG 0x0000000002000000UL +#define PA6T_MMCR0_SDARLOG 0x0000000004000000UL +#define PA6T_MMCR0_PROEN 0x0000000008000000UL +#define PA6T_MMCR0_PROLOG 0x0000000010000000UL +#define PA6T_MMCR0_DAMEN2 0x0000000020000000UL +#define PA6T_MMCR0_DAMEN3 0x0000000040000000UL +#define PA6T_MMCR0_DAMEN4 0x0000000080000000UL +#define PA6T_MMCR0_DAMEN5 0x0000000100000000UL +#define PA6T_MMCR0_DAMSEL2 0x0000000200000000UL +#define PA6T_MMCR0_DAMSEL3 0x0000000400000000UL +#define PA6T_MMCR0_DAMSEL4 0x0000000800000000UL +#define PA6T_MMCR0_DAMSEL5 0x0000001000000000UL +#define PA6T_MMCR0_HANDDIS 0x0000002000000000UL +#define PA6T_MMCR0_PCTEN 0x0000004000000000UL +#define PA6T_MMCR0_SOCEN 0x0000008000000000UL +#define PA6T_MMCR0_SOCMOD 0x0000010000000000UL + +#define SPRN_PA6T_MMCR1 798 +#define PA6T_MMCR1_ES2 0x00000000000000ffUL +#define PA6T_MMCR1_ES3 0x000000000000ff00UL +#define PA6T_MMCR1_ES4 0x0000000000ff0000UL +#define PA6T_MMCR1_ES5 0x00000000ff000000UL + +#define SPRN_PA6T_SIAR 780 +#define SPRN_PA6T_UPMC0 771 +#define SPRN_PA6T_UPMC1 772 +#define SPRN_PA6T_UPMC2 773 +#define SPRN_PA6T_UPMC3 774 +#define SPRN_PA6T_UPMC4 775 +#define SPRN_PA6T_UPMC5 776 +#define SPRN_PA6T_UMMCR0 779 +#define SPRN_PA6T_UMMCR1 782 +#define SPRN_PA6T_PMC0 787 +#define SPRN_PA6T_PMC1 788 +#define SPRN_PA6T_PMC2 789 +#define SPRN_PA6T_PMC3 790 +#define SPRN_PA6T_PMC4 791 +#define SPRN_PA6T_PMC5 792 #else /* 32-bit */ #define SPRN_MMCR0 952 /* Monitor Mode Control Register 0 */ -- cgit v1.2.3-59-g8ed1b From e6349a958b3577da6e5c5eacda85c07f9a364cb5 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Wed, 18 Apr 2007 15:57:51 +1000 Subject: [POWERPC] kprobes: Eliminate sstep exception if instruction can be emulated For cases when probes are placed on instructions that can be emulated, don't take the single-step exception. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/kprobes.c | 36 +++++++++++++++++++++++++++++++++++- include/asm-powerpc/kprobes.h | 5 +++++ 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index dd2886f97e98..ef647e7a9dc3 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -59,12 +59,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) } if (!ret) { - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); + memcpy(p->ainsn.insn, p->addr, + MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); p->opcode = *p->addr; flush_icache_range((unsigned long)p->ainsn.insn, (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t)); } + p->ainsn.boostable = 0; return ret; } @@ -232,6 +234,38 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) return 1; ss_probe: + if (p->ainsn.boostable >= 0) { + unsigned int insn = *p->ainsn.insn; + + /* regs->nip is also adjusted if emulate_step returns 1 */ + ret = emulate_step(regs, insn); + if (ret > 0) { + /* + * Once this instruction has been boosted + * successfully, set the boostable flag + */ + if (unlikely(p->ainsn.boostable == 0)) + p->ainsn.boostable = 1; + + if (p->post_handler) + p->post_handler(p, regs, 0); + + kcb->kprobe_status = KPROBE_HIT_SSDONE; + reset_current_kprobe(); + preempt_enable_no_resched(); + return 1; + } else if (ret < 0) { + /* + * We don't allow kprobes on mtmsr(d)/rfi(d), etc. + * So, we should never get here... but, its still + * good to catch them, just in case... + */ + printk("Can't step on instruction %x\n", insn); + BUG(); + } else if (ret == 0) + /* This instruction can't be boosted */ + p->ainsn.boostable = -1; + } prepare_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; return 1; diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h index 3a5dd492588f..f850ca7020ed 100644 --- a/include/asm-powerpc/kprobes.h +++ b/include/asm-powerpc/kprobes.h @@ -87,6 +87,11 @@ extern void arch_remove_kprobe(struct kprobe *p); struct arch_specific_insn { /* copy of original instruction */ kprobe_opcode_t *insn; + /* + * Set in kprobes code, initially to 0. If the instruction can be + * eumulated, this is set to 1, if not, to -1. + */ + int boostable; }; struct prev_kprobe { -- cgit v1.2.3-59-g8ed1b From e58923ed14370e0facc5eb2c3923216adc3bf260 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 18 Apr 2007 16:36:26 +1000 Subject: [POWERPC] Add arch/powerpc driver for UIC, PPC4xx interrupt controller This patch adds a driver to arch/powerpc/sysdev for the UIC, the on-chip interrupt controller from IBM/AMCC 4xx chips. It uses the new irq host mapping infrastructure. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- arch/powerpc/sysdev/Makefile | 1 + arch/powerpc/sysdev/uic.c | 342 +++++++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/uic.h | 23 +++ 3 files changed, 366 insertions(+) create mode 100644 arch/powerpc/sysdev/uic.c create mode 100644 include/asm-powerpc/uic.h (limited to 'include') diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 83fbbfc779a1..e96ca9618dbb 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_PM) += timer.o ifeq ($(CONFIG_PPC_MERGE),y) obj-$(CONFIG_PPC_I8259) += i8259.o obj-$(CONFIG_PPC_83xx) += ipic.o +obj-$(CONFIG_4xx) += uic.o endif # Temporary hack until we have migrated to asm-powerpc diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c new file mode 100644 index 000000000000..cdbe68437afe --- /dev/null +++ b/arch/powerpc/sysdev/uic.c @@ -0,0 +1,342 @@ +/* + * arch/powerpc/sysdev/uic.c + * + * IBM PowerPC 4xx Universal Interrupt Controller + * + * Copyright 2007 David Gibson , 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NR_UIC_INTS 32 + +#define UIC_SR 0x0 +#define UIC_ER 0x2 +#define UIC_CR 0x3 +#define UIC_PR 0x4 +#define UIC_TR 0x5 +#define UIC_MSR 0x6 +#define UIC_VR 0x7 +#define UIC_VCR 0x8 + +#define uic_irq_to_hw(virq) (irq_map[virq].hwirq) + +struct uic *primary_uic; + +struct uic { + int index; + int dcrbase; + + spinlock_t lock; + + /* The remapper for this UIC */ + struct irq_host *irqhost; + + /* For secondary UICs, the cascade interrupt's irqaction */ + struct irqaction cascade; + + /* The device node of the interrupt controller */ + struct device_node *of_node; +}; + +static void uic_unmask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er |= 1 << (31 - src); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_mask_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + u32 er; + + spin_lock_irqsave(&uic->lock, flags); + er = mfdcr(uic->dcrbase + UIC_ER); + er &= ~(1 << (31 - src)); + mtdcr(uic->dcrbase + UIC_ER, er); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static void uic_ack_irq(unsigned int virq) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + unsigned long flags; + + spin_lock_irqsave(&uic->lock, flags); + mtdcr(uic->dcrbase + UIC_SR, 1 << (31-src)); + spin_unlock_irqrestore(&uic->lock, flags); +} + +static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) +{ + struct uic *uic = get_irq_chip_data(virq); + unsigned int src = uic_irq_to_hw(virq); + struct irq_desc *desc = get_irq_desc(virq); + unsigned long flags; + int trigger, polarity; + u32 tr, pr, mask; + + switch (flow_type & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_NONE: + uic_mask_irq(virq); + return 0; + + case IRQ_TYPE_EDGE_RISING: + trigger = 1; polarity = 1; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger = 1; polarity = 0; + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger = 0; polarity = 1; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger = 0; polarity = 0; + break; + default: + return -EINVAL; + } + + mask = ~(1 << (31 - src)); + + spin_lock_irqsave(&uic->lock, flags); + tr = mfdcr(uic->dcrbase + UIC_TR); + pr = mfdcr(uic->dcrbase + UIC_PR); + tr = (tr & mask) | (trigger << (31-src)); + pr = (pr & mask) | (polarity << (31-src)); + + mtdcr(uic->dcrbase + UIC_PR, pr); + mtdcr(uic->dcrbase + UIC_TR, tr); + + desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); + desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; + if (trigger) + desc->status |= IRQ_LEVEL; + + spin_unlock_irqrestore(&uic->lock, flags); + + return 0; +} + +static struct irq_chip uic_irq_chip = { + .typename = " UIC ", + .unmask = uic_unmask_irq, + .mask = uic_mask_irq, +/* .mask_ack = uic_mask_irq_and_ack, */ + .ack = uic_ack_irq, + .set_type = uic_set_irq_type, +}; + +static int uic_host_match(struct irq_host *h, struct device_node *node) +{ + struct uic *uic = h->host_data; + return uic->of_node == node; +} + +static int uic_host_map(struct irq_host *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct uic *uic = h->host_data; + + set_irq_chip_data(virq, uic); + /* Despite the name, handle_level_irq() works for both level + * and edge irqs on UIC. FIXME: check this is correct */ + set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq); + + /* Set default irq type */ + set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; +} + +static int uic_host_xlate(struct irq_host *h, struct device_node *ct, + u32 *intspec, unsigned int intsize, + irq_hw_number_t *out_hwirq, unsigned int *out_type) + +{ + /* UIC intspecs must have 2 cells */ + BUG_ON(intsize != 2); + *out_hwirq = intspec[0]; + *out_type = intspec[1]; + return 0; +} + +static struct irq_host_ops uic_host_ops = { + .match = uic_host_match, + .map = uic_host_map, + .xlate = uic_host_xlate, +}; + +irqreturn_t uic_cascade(int virq, void *data) +{ + struct uic *uic = data; + u32 msr; + int src; + int subvirq; + + msr = mfdcr(uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + subvirq = irq_linear_revmap(uic->irqhost, src); + generic_handle_irq(subvirq); + + return IRQ_HANDLED; +} + +static struct uic * __init uic_init_one(struct device_node *node) +{ + struct uic *uic; + const u32 *indexp, *dcrreg; + int len; + + BUG_ON(! device_is_compatible(node, "ibm,uic")); + + uic = alloc_bootmem(sizeof(*uic)); + if (! uic) + return NULL; /* FIXME: panic? */ + + memset(uic, 0, sizeof(*uic)); + spin_lock_init(&uic->lock); + uic->of_node = of_node_get(node); + indexp = get_property(node, "cell-index", &len); + if (!indexp || (len != sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "cell-index property\n", node->full_name); + return NULL; + } + uic->index = *indexp; + + dcrreg = get_property(node, "dcr-reg", &len); + if (!dcrreg || (len != 2*sizeof(u32))) { + printk(KERN_ERR "uic: Device node %s has missing or invalid " + "dcr-reg property\n", node->full_name); + return NULL; + } + uic->dcrbase = *dcrreg; + + uic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, NR_UIC_INTS, + &uic_host_ops, -1); + if (! uic->irqhost) { + of_node_put(node); + return NULL; /* FIXME: panic? */ + } + + uic->irqhost->host_data = uic; + + /* Start with all interrupts disabled, level and non-critical */ + mtdcr(uic->dcrbase + UIC_ER, 0); + mtdcr(uic->dcrbase + UIC_CR, 0); + mtdcr(uic->dcrbase + UIC_TR, 0); + /* Clear any pending interrupts, in case the firmware left some */ + mtdcr(uic->dcrbase + UIC_SR, 0xffffffff); + + printk ("UIC%d (%d IRQ sources) at DCR 0x%x\n", uic->index, + NR_UIC_INTS, uic->dcrbase); + + return uic; +} + +void __init uic_init_tree(void) +{ + struct device_node *np; + struct uic *uic; + const u32 *interrupts; + + /* First locate and initialize the top-level UIC */ + + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = get_property(np, "interrupts", NULL); + if (! interrupts) + break; + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } + + BUG_ON(!np); /* uic_init_tree() assumes there's a UIC as the + * top-level interrupt controller */ + primary_uic = uic_init_one(np); + if (! primary_uic) + panic("Unable to initialize primary UIC %s\n", np->full_name); + + irq_set_default_host(primary_uic->irqhost); + of_node_put(np); + + /* The scan again for cascaded UICs */ + np = of_find_compatible_node(NULL, NULL, "ibm,uic"); + while (np) { + interrupts = get_property(np, "interrupts", NULL); + if (interrupts) { + /* Secondary UIC */ + int cascade_virq; + int ret; + + uic = uic_init_one(np); + if (! uic) + panic("Unable to initialize a secondary UIC %s\n", + np->full_name); + + cascade_virq = irq_of_parse_and_map(np, 0); + + uic->cascade.handler = uic_cascade; + uic->cascade.name = "UIC cascade"; + uic->cascade.dev_id = uic; + + ret = setup_irq(cascade_virq, &uic->cascade); + if (ret) + printk(KERN_ERR "Failed to setup_irq(%d) for " + "UIC%d cascade\n", cascade_virq, + uic->index); + + /* FIXME: setup critical cascade?? */ + } + + np = of_find_compatible_node(np, NULL, "ibm,uic"); + } +} + +/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ +unsigned int uic_get_irq(void) +{ + u32 msr; + int src; + + BUG_ON(! primary_uic); + + msr = mfdcr(primary_uic->dcrbase + UIC_MSR); + src = 32 - ffs(msr); + + return irq_linear_revmap(primary_uic->irqhost, src); +} diff --git a/include/asm-powerpc/uic.h b/include/asm-powerpc/uic.h new file mode 100644 index 000000000000..970eb7e2186a --- /dev/null +++ b/include/asm-powerpc/uic.h @@ -0,0 +1,23 @@ +/* + * include/asm-powerpc/uic.h + * + * IBM PPC4xx UIC external definitions and structure. + * + * Maintainer: David Gibson + * Copyright 2007 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. + */ +#ifndef _ASM_POWERPC_UIC_H +#define _ASM_POWERPC_UIC_H + +#ifdef __KERNEL__ + +extern void __init uic_init_tree(void); +extern unsigned int uic_get_irq(void); + +#endif /* __KERNEL__ */ +#endif /* _ASM_POWERPC_UIC_H */ -- cgit v1.2.3-59-g8ed1b From 6cfef5b27e49e826125f12637ee0d7210a896044 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Mon, 23 Apr 2007 18:47:08 +1000 Subject: [POWERPC] Rename MPIC_BROKEN_U3 to MPIC_U3_HT_IRQS Rename MPIC_BROKEN_U3 to something a little more descriptive. Its effect is to enable support for HT irqs behind the PCI-X/HT bridge on U3/U4 (aka. CPC9x5) parts. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/configs/g5_defconfig | 2 +- arch/powerpc/configs/maple_defconfig | 2 +- arch/powerpc/configs/ppc64_defconfig | 2 +- arch/powerpc/platforms/Kconfig | 2 +- arch/powerpc/platforms/maple/Kconfig | 2 +- arch/powerpc/platforms/maple/setup.c | 2 +- arch/powerpc/platforms/powermac/Kconfig | 2 +- arch/powerpc/platforms/powermac/pic.c | 2 +- arch/powerpc/sysdev/mpic.c | 24 ++++++++++++------------ include/asm-powerpc/mpic.h | 12 ++++++------ 10 files changed, 26 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 7724847f702a..3ccf19d8da38 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -143,7 +143,7 @@ CONFIG_PPC_NATIVE=y CONFIG_U3_DART=y # CONFIG_PPC_RTAS is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index de97f2f0ae96..15366f0e489f 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -146,7 +146,7 @@ CONFIG_PPC_RTAS=y CONFIG_RTAS_PROC=y # CONFIG_RTAS_FLASH is not set # CONFIG_MMIO_NVRAM is not set -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y # CONFIG_PPC_MPC106 is not set CONFIG_PPC_970_NAP=y # CONFIG_PPC_INDIRECT_IO is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index a8da0aea3b87..126b9f87df25 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -152,7 +152,7 @@ CONFIG_RTAS_ERROR_LOGGING=y CONFIG_RTAS_PROC=y CONFIG_RTAS_FLASH=m CONFIG_MMIO_NVRAM=y -CONFIG_MPIC_BROKEN_U3=y +CONFIG_MPIC_U3_HT_IRQS=y CONFIG_IBMVIO=y # CONFIG_IBMEBUS is not set # CONFIG_PPC_MPC106 is not set diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 86be82a4b9ef..ac62fa08f5e6 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -115,7 +115,7 @@ config MMIO_NVRAM bool default n -config MPIC_BROKEN_U3 +config MPIC_U3_HT_IRQS bool depends on PPC_MAPLE default y diff --git a/arch/powerpc/platforms/maple/Kconfig b/arch/powerpc/platforms/maple/Kconfig index 5f364b8e5c0f..f7c95eb5d8ba 100644 --- a/arch/powerpc/platforms/maple/Kconfig +++ b/arch/powerpc/platforms/maple/Kconfig @@ -3,7 +3,7 @@ config PPC_MAPLE bool "Maple 970FX Evaluation Board" select MPIC select U3_DART - select MPIC_BROKEN_U3 + select MPIC_U3_HT_IRQS select GENERIC_TBSYNC select PPC_UDBG_16550 select PPC_970_NAP diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 120cd048e0cc..2a30c5b2532e 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -264,7 +264,7 @@ static void __init maple_init_IRQ(void) flags |= MPIC_BIG_ENDIAN; /* XXX Maple specific bits */ - flags |= MPIC_BROKEN_U3 | MPIC_WANTS_RESET; + flags |= MPIC_U3_HT_IRQS | MPIC_WANTS_RESET; /* All U3/U4 are big-endian, older SLOF firmware doesn't encode this */ flags |= MPIC_BIG_ENDIAN; diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 02d9c7dba876..5b7afe50039a 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig @@ -12,7 +12,7 @@ config PPC_PMAC64 depends on PPC_PMAC && POWER4 select MPIC select U3_DART - select MPIC_BROKEN_U3 + select MPIC_U3_HT_IRQS select GENERIC_TBSYNC select PPC_970_NAP default y diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index f59d311e25da..ae5097ac0378 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c @@ -489,7 +489,7 @@ static struct mpic * __init pmac_setup_one_mpic(struct device_node *np, * but works until I find a better way */ if (master && (flags & MPIC_BIG_ENDIAN)) - flags |= MPIC_BROKEN_U3; + flags |= MPIC_U3_HT_IRQS; mpic = mpic_alloc(np, r.start, flags, 0, 0, name); if (mpic == NULL) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 27e6f78739eb..0b84b7c775d8 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -304,7 +304,7 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) } } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Test if an interrupt is sourced from HyperTransport (used on broken U3s) * to force the edge setting on the MPIC and do the ack workaround. @@ -476,7 +476,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) } } -#else /* CONFIG_MPIC_BROKEN_U3 */ +#else /* CONFIG_MPIC_U3_HT_IRQS */ static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source) { @@ -487,7 +487,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic) { } -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) @@ -615,7 +615,7 @@ static void mpic_end_irq(unsigned int irq) mpic_eoi(mpic); } -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static void mpic_unmask_ht_irq(unsigned int irq) { @@ -665,7 +665,7 @@ static void mpic_end_ht_irq(unsigned int irq) mpic_ht_end_irq(mpic, src); mpic_eoi(mpic); } -#endif /* !CONFIG_MPIC_BROKEN_U3 */ +#endif /* !CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP @@ -788,7 +788,7 @@ static struct irq_chip mpic_ipi_chip = { }; #endif /* CONFIG_SMP */ -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS static struct irq_chip mpic_irq_ht_chip = { .startup = mpic_startup_ht_irq, .shutdown = mpic_shutdown_ht_irq, @@ -797,7 +797,7 @@ static struct irq_chip mpic_irq_ht_chip = { .eoi = mpic_end_ht_irq, .set_type = mpic_set_irq_type, }; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ static int mpic_host_match(struct irq_host *h, struct device_node *node) @@ -837,11 +837,11 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, /* Default chip */ chip = &mpic->hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Check for HT interrupts, override vecpri */ if (mpic_is_ht_interrupt(mpic, hw)) chip = &mpic->hc_ht_irq; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ DBG("mpic: mapping to irq chip @%p\n", chip); @@ -937,12 +937,12 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->hc_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_irq.set_affinity = mpic_set_affinity; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS mpic->hc_ht_irq = mpic_irq_ht_chip; mpic->hc_ht_irq.typename = name; if (flags & MPIC_PRIMARY) mpic->hc_ht_irq.set_affinity = mpic_set_affinity; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ #ifdef CONFIG_SMP mpic->hc_ipi = mpic_ipi_chip; @@ -1142,7 +1142,7 @@ void __init mpic_init(struct mpic *mpic) /* Do the HT PIC fixups on U3 broken mpic */ DBG("MPIC flags: %x\n", mpic->flags); - if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY)) + if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) mpic_scan_ht_pics(mpic); for (i = 0; i < mpic->num_sources; i++) { diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index cb204a71e912..e4d5fc5362a0 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -199,7 +199,7 @@ enum { }; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* Fixup table entry */ struct mpic_irq_fixup { @@ -208,7 +208,7 @@ struct mpic_irq_fixup u32 data; unsigned int index; }; -#endif /* CONFIG_MPIC_BROKEN_U3 */ +#endif /* CONFIG_MPIC_U3_HT_IRQS */ enum mpic_reg_type { @@ -239,7 +239,7 @@ struct mpic /* The "linux" controller struct */ struct irq_chip hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS struct irq_chip hc_ht_irq; #endif #ifdef CONFIG_SMP @@ -268,7 +268,7 @@ struct mpic /* Spurious vector to program into unused sources */ unsigned int spurious_vec; -#ifdef CONFIG_MPIC_BROKEN_U3 +#ifdef CONFIG_MPIC_U3_HT_IRQS /* The fixup table */ struct mpic_irq_fixup *fixups; spinlock_t fixup_lock; @@ -313,7 +313,7 @@ struct mpic /* Set this for a big-endian MPIC */ #define MPIC_BIG_ENDIAN 0x00000002 /* Broken U3 MPIC */ -#define MPIC_BROKEN_U3 0x00000004 +#define MPIC_U3_HT_IRQS 0x00000004 /* Broken IPI registers (autodetected) */ #define MPIC_BROKEN_IPI 0x00000008 /* MPIC wants a reset */ @@ -352,7 +352,7 @@ struct mpic * @senses_num: number of entries in the array * * Note about the sense array. If none is passed, all interrupts are - * setup to be level negative unless MPIC_BROKEN_U3 is set in which + * setup to be level negative unless MPIC_U3_HT_IRQS is set in which * case they are edge positive (and the array is ignored anyway). * The values in the array start at the first source of the MPIC, * that is senses[0] correspond to linux irq "irq_offset". -- cgit v1.2.3-59-g8ed1b From 687304014f7ca8e2fbb3feaefef356b4a0da65ad Mon Sep 17 00:00:00 2001 From: Olof Johansson Date: Tue, 24 Apr 2007 01:11:55 +1000 Subject: [POWERPC] Save trap number in bad_stack Save the trap number in the case of getting a bad stack in an exception handler. It is sometimes useful to know what exception it was that caused this to happen. Without this, no trap number is reported. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/head_64.S | 10 ++++++++-- include/asm-powerpc/paca.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 9735e828b52d..0c5150c69175 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -139,6 +139,7 @@ int main(void) DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr)); DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset)); + DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); DEFINE(SLBSHADOW_STACKVSID, offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid)); diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index aff5398a5f63..1111fcec7673 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -278,8 +278,12 @@ exception_marker: beq- 1f; \ ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ - bge- cr1,bad_stack; /* abort if it is */ \ - std r9,_CCR(r1); /* save CR in stackframe */ \ + bge- cr1,2f; /* abort if it is */ \ + b 3f; \ +2: li r1,(n); /* will be reloaded later */ \ + sth r1,PACA_TRAP_SAVE(r13); \ + b bad_stack; \ +3: std r9,_CCR(r1); /* save CR in stackframe */ \ std r11,_NIP(r1); /* save SRR0 in stackframe */ \ std r12,_MSR(r1); /* save SRR1 in stackframe */ \ std r10,0(r1); /* make stack chain pointer */ \ @@ -940,6 +944,8 @@ bad_stack: SAVE_2GPRS(7,r1) SAVE_10GPRS(12,r1) SAVE_10GPRS(22,r1) + lhz r12,PACA_TRAP_SAVE(r13) + std r12,_TRAP(r1) addi r11,r1,INT_FRAME_SIZE std r11,0(r1) li r12,0 diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index 4de851d91f96..cf95274f735e 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h @@ -94,6 +94,7 @@ struct paca_struct { u64 stab_rr; /* stab/slb round-robin counter */ u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ + u16 trap_save; /* Used when bad stack is encountered */ u8 soft_enabled; /* irq soft-enable flag */ u8 hard_enabled; /* set if irqs are enabled in MSR */ u8 io_sync; /* writel() needs spin_unlock sync */ -- cgit v1.2.3-59-g8ed1b From 621023072524fc0155ed16490255e1ea3aa11585 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 24 Apr 2007 13:09:12 +1000 Subject: [POWERPC] Cleanup and fix breakage in tlbflush.h BenH's commit a741e67969577163a4cfc78d7fd2753219087ef1 in powerpc.git, although (AFAICT) only intended to affect ppc64, also has side-effects which break 44x. I think 40x, 8xx and Freescale Book E are also affected, though I haven't tested them. The problem lies in unconditionally removing flush_tlb_pending() from the versions of flush_tlb_mm(), flush_tlb_range() and flush_tlb_kernel_range() used on ppc64 - which are also used the embedded platforms mentioned above. The patch below cleans up the convoluted #ifdef logic in tlbflush.h, in the process restoring the necessary flushes for the software TLB platforms. There are three sets of definitions for the flushing hooks: the software TLB versions (revised to avoid using names which appear to related to TLB batching), the 32-bit hash based versions (external functions) amd the 64-bit hash based versions (which implement batching). It also moves the declaration of update_mmu_cache() to always be in tlbflush.h (previously it was in tlbflush.h except for PPC64, where it was in pgtable.h). Booted on Ebony (440GP) and compiled for 64-bit and 32-bit multiplatform. Signed-off-by: David Gibson Acked-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/mm/mmu_decl.h | 1 + include/asm-powerpc/pgtable.h | 10 --- include/asm-powerpc/tlbflush.h | 135 ++++++++++++++++++++++++----------------- 3 files changed, 81 insertions(+), 65 deletions(-) (limited to 'include') diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index ee55e0bb28bc..9c4538bb04b0 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h @@ -19,6 +19,7 @@ * 2 of the License, or (at your option) any later version. * */ +#include #include #include diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h index c7142c7e0e05..19edb6982b81 100644 --- a/include/asm-powerpc/pgtable.h +++ b/include/asm-powerpc/pgtable.h @@ -448,16 +448,6 @@ extern pgd_t swapper_pg_dir[]; extern void paging_init(void); -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to put a corresponding HPTE into the hash table - * ahead of time, instead of waiting for the inevitable extra - * hash-table miss exception. - */ -struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); - /* Encode and de-code a swap entry */ #define __swp_type(entry) (((entry).val >> 1) & 0x3f) #define __swp_offset(entry) ((entry).val >> 8) diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h index 0bc5a5e506be..86e6266a028b 100644 --- a/include/asm-powerpc/tlbflush.h +++ b/include/asm-powerpc/tlbflush.h @@ -17,10 +17,73 @@ */ #ifdef __KERNEL__ - struct mm_struct; +struct vm_area_struct; + +#if defined(CONFIG_4xx) || defined(CONFIG_8xx) || defined(CONFIG_FSL_BOOKE) +/* + * TLB flushing for software loaded TLB chips + * + * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range & + * flush_tlb_kernel_range are best implemented as tlbia vs + * specific tlbie's + */ + +extern void _tlbie(unsigned long address); + +#if defined(CONFIG_40x) || defined(CONFIG_8xx) +#define _tlbia() asm volatile ("tlbia; sync" : : : "memory") +#else /* CONFIG_44x || CONFIG_FSL_BOOKE */ +extern void _tlbia(void); +#endif -#ifdef CONFIG_PPC64 +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + _tlbia(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ + _tlbie(vmaddr); +} + +static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, + unsigned long vmaddr) +{ + _tlbie(vmaddr); +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + _tlbia(); +} + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ + _tlbia(); +} + +#elif defined(CONFIG_PPC32) +/* + * TLB flushing for "classic" hash-MMMU 32-bit CPUs, 6xx, 7xx, 7xxx + */ +extern void _tlbie(unsigned long address); +extern void _tlbia(void); + +extern void flush_tlb_mm(struct mm_struct *mm); +extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); +extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); +extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); + +#else +/* + * TLB flushing for 64-bit has-MMU CPUs + */ #include #include @@ -67,89 +130,51 @@ extern void flush_hash_page(unsigned long va, real_pte_t pte, int psize, int local); extern void flush_hash_range(unsigned long number, int local); -#else /* CONFIG_PPC64 */ - -#include - -extern void _tlbie(unsigned long address); -extern void _tlbia(void); - -/* - * TODO: (CONFIG_FSL_BOOKE) determine if flush_tlb_range & - * flush_tlb_kernel_range are best implemented as tlbia vs - * specific tlbie's - */ - -#if (defined(CONFIG_4xx) && !defined(CONFIG_44x)) || defined(CONFIG_8xx) -#define flush_tlb_pending() asm volatile ("tlbia; sync" : : : "memory") -#elif defined(CONFIG_4xx) || defined(CONFIG_FSL_BOOKE) -#define flush_tlb_pending() _tlbia() -#endif - -/* - * This gets called at the end of handling a page fault, when - * the kernel has put a new PTE into the page table for the process. - * We use it to ensure coherency between the i-cache and d-cache - * for the page which has just been mapped in. - * On machines which use an MMU hash table, we use this to put a - * corresponding HPTE into the hash table ahead of time, instead of - * waiting for the inevitable extra hash-table miss exception. - */ -extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); - -#endif /* CONFIG_PPC64 */ - -#if defined(CONFIG_PPC64) || defined(CONFIG_4xx) || \ - defined(CONFIG_FSL_BOOKE) || defined(CONFIG_8xx) static inline void flush_tlb_mm(struct mm_struct *mm) { } static inline void flush_tlb_page(struct vm_area_struct *vma, - unsigned long vmaddr) + unsigned long vmaddr) { -#ifndef CONFIG_PPC64 - _tlbie(vmaddr); -#endif } static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long vmaddr) { -#ifndef CONFIG_PPC64 - _tlbie(vmaddr); -#endif } static inline void flush_tlb_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { } static inline void flush_tlb_kernel_range(unsigned long start, - unsigned long end) + unsigned long end) { } -#else /* 6xx, 7xx, 7xxx cpus */ - -extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr); -extern void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr); -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); - #endif +/* + * This gets called at the end of handling a page fault, when + * the kernel has put a new PTE into the page table for the process. + * We use it to ensure coherency between the i-cache and d-cache + * for the page which has just been mapped in. + * On machines which use an MMU hash table, we use this to put a + * corresponding HPTE into the hash table ahead of time, instead of + * waiting for the inevitable extra hash-table miss exception. + */ +extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); + /* * This is called in munmap when we have freed up some page-table * pages. We don't need to do anything here, there's nothing special * about our page-table pages. -- paulus */ static inline void flush_tlb_pgtables(struct mm_struct *mm, - unsigned long start, unsigned long end) + unsigned long start, unsigned long end) { } -- cgit v1.2.3-59-g8ed1b From 4bf56e1725a298fb430977cf143ad3a36c91b46a Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 24 Apr 2007 13:48:41 +1000 Subject: [POWERPC] Remove find_compatible_devices This is an old interface and is replaced by of_find_compatible_node. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 24 ------------------------ arch/powerpc/platforms/chrp/time.c | 13 +++++++++---- drivers/macintosh/macio-adb.c | 16 +++++++++++++--- include/asm-powerpc/prom.h | 2 -- 4 files changed, 22 insertions(+), 33 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index ec6921c54a07..2f7e6ec215f8 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1170,30 +1170,6 @@ int machine_is_compatible(const char *compat) } EXPORT_SYMBOL(machine_is_compatible); -/** - * Construct and return a list of the device_nodes with a given type - * and compatible property. - */ -struct device_node *find_compatible_devices(const char *type, - const char *compat) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcasecmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compat)) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_compatible_devices); - /** * Find the device_node with a given full_name. */ diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 7d7889026936..96d1e4b3c493 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -39,12 +39,17 @@ long __init chrp_time_init(void) struct resource r; int base; - rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); + rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); if (rtcs == NULL) - rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) + rtcs = of_find_compatible_node(NULL, "rtc", "ds1385-rtc"); + if (rtcs == NULL) + return 0; + if (of_address_to_resource(rtcs, 0, &r)) { + of_node_put(rtcs); return 0; - + } + of_node_put(rtcs); + base = r.start; nvram_as1 = 0; nvram_as0 = base; diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index 026b67f4f659..79119f56e82d 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c @@ -82,7 +82,14 @@ struct adb_driver macio_adb_driver = { int macio_probe(void) { - return find_compatible_devices("adb", "chrp,adb0")? 0: -ENODEV; + struct device_node *np; + + np = of_find_compatible_node(NULL, "adb", "chrp,adb0"); + if (np) { + of_node_put(np); + return 0; + } + return -ENODEV; } int macio_init(void) @@ -91,12 +98,14 @@ int macio_init(void) struct resource r; unsigned int irq; - adbs = find_compatible_devices("adb", "chrp,adb0"); + adbs = of_find_compatible_node(NULL, "adb", "chrp,adb0"); if (adbs == 0) return -ENXIO; - if (of_address_to_resource(adbs, 0, &r)) + if (of_address_to_resource(adbs, 0, &r)) { + of_node_put(adbs); return -ENXIO; + } adb = ioremap(r.start, sizeof(struct adb_regs)); out_8(&adb->ctrl.r, 0); @@ -107,6 +116,7 @@ int macio_init(void) out_8(&adb->autopoll.r, APE); irq = irq_of_parse_and_map(adbs, 0); + of_node_put(adbs); if (request_irq(irq, macio_adb_interrupt, 0, "ADB", (void *)0)) { printk(KERN_ERR "ADB: can't get irq %d\n", irq); return -EAGAIN; diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index f31af713e6a4..58eabb2fa24e 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -116,8 +116,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e extern struct device_node *find_devices(const char *name); extern struct device_node *find_type_devices(const char *type); extern struct device_node *find_path_device(const char *path); -extern struct device_node *find_compatible_devices(const char *type, - const char *compat); extern struct device_node *find_all_nodes(void); /* New style node lookup */ -- cgit v1.2.3-59-g8ed1b From 112466b4d0036b3244509d01dbbf3c8caec52a23 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 24 Apr 2007 13:49:47 +1000 Subject: [POWERPC] Remove find_all_nodes This old interface has no more users. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 17 ----------------- include/asm-powerpc/prom.h | 1 - 2 files changed, 18 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 2f7e6ec215f8..911ec77a42d2 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1110,23 +1110,6 @@ struct device_node *find_type_devices(const char *type) } EXPORT_SYMBOL(find_type_devices); -/** - * Returns all nodes linked together - */ -struct device_node *find_all_nodes(void) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - *prevp = np; - prevp = &np->next; - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_all_nodes); - /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 58eabb2fa24e..a9acdd8b3bb6 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -116,7 +116,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e extern struct device_node *find_devices(const char *name); extern struct device_node *find_type_devices(const char *type); extern struct device_node *find_path_device(const char *path); -extern struct device_node *find_all_nodes(void); /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, -- cgit v1.2.3-59-g8ed1b From 8c8dc322486d5394dc981bef9276dd0ce6c8d1ce Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 24 Apr 2007 13:50:55 +1000 Subject: [POWERPC] Remove old interface find_path_device Replaced by of_find_node_by_path. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/lparcfg.c | 6 ++++-- arch/powerpc/kernel/pci_32.c | 17 +++++++++++----- arch/powerpc/kernel/prom.c | 14 ------------- arch/powerpc/kernel/rtas.c | 3 ++- arch/powerpc/kernel/sysfs.c | 3 ++- arch/powerpc/platforms/chrp/pci.c | 7 ++++--- arch/powerpc/platforms/chrp/setup.c | 9 +++++--- arch/powerpc/platforms/powermac/feature.c | 34 +++++++++++++++++++++---------- drivers/char/briq_panel.c | 7 +++++-- drivers/scsi/ibmvscsi/ibmvstgt.c | 3 ++- drivers/scsi/ibmvscsi/rpa_vscsi.c | 3 ++- include/asm-powerpc/prom.h | 1 - 12 files changed, 62 insertions(+), 45 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index b8dc1eeb0169..fc1f7a949b2b 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -321,7 +321,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) struct device_node *rtas_node; const int *lrdrp = NULL; - rtas_node = find_path_device("/rtas"); + rtas_node = of_find_node_by_path("/rtas"); if (rtas_node) lrdrp = of_get_property(rtas_node, "ibm,lrdr-capacity", NULL); @@ -330,6 +330,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) } else { partition_potential_processors = *(lrdrp + 4); } + of_node_put(rtas_node); partition_active_processors = lparcfg_count_active_processors(); @@ -537,7 +538,7 @@ static int lparcfg_data(struct seq_file *m, void *v) seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS); - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (rootdn) { tmp = of_get_property(rootdn, "model", NULL); if (tmp) { @@ -557,6 +558,7 @@ static int lparcfg_data(struct seq_file *m, void *v) NULL); if (lp_index_ptr) lp_index = *lp_index_ptr; + of_node_put(rootdn); } seq_printf(m, "serial_number=%s\n", system_id); seq_printf(m, "system_type=%s\n", model); diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index ae04f9418363..5b05a09a6bdf 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -669,6 +669,7 @@ pcibios_make_OF_bus_map(void) int i; struct pci_controller* hose; struct property *map_prop; + struct device_node *dn; pci_to_OF_bus_map = kmalloc(pci_bus_count, GFP_KERNEL); if (!pci_to_OF_bus_map) { @@ -690,12 +691,13 @@ pcibios_make_OF_bus_map(void) continue; make_one_node_map(node, hose->first_busno); } - map_prop = of_find_property(find_path_device("/"), - "pci-OF-bus-map", NULL); + dn = of_find_node_by_path("/"); + map_prop = of_find_property(dn, "pci-OF-bus-map", NULL); if (map_prop) { BUG_ON(pci_bus_count > map_prop->length); memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count); } + of_node_put(dn); #ifdef DEBUG printk("PCI->OF bus map:\n"); for (i=0; iname = "pci-OF-bus-map"; of_prop->length = 256; of_prop->value = &of_prop[1]; - prom_add_property(find_path_device("/"), of_prop); + prom_add_property(dn, of_prop); + of_node_put(dn); } } diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 911ec77a42d2..17c41fefecf2 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1153,20 +1153,6 @@ int machine_is_compatible(const char *compat) } EXPORT_SYMBOL(machine_is_compatible); -/** - * Find the device_node with a given full_name. - */ -struct device_node *find_path_device(const char *path) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) - return np; - return NULL; -} -EXPORT_SYMBOL(find_path_device); - /******* * * New implementation of the OF "find" APIs, return a refcounted diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 702fecc93204..214780798289 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -192,7 +192,7 @@ void rtas_progress(char *s, unsigned short hex) if (display_width == 0) { display_width = 0x10; - if ((root = find_path_device("/rtas"))) { + if ((root = of_find_node_by_path("/rtas"))) { if ((p = of_get_property(root, "ibm,display-line-length", NULL))) display_width = *p; @@ -204,6 +204,7 @@ void rtas_progress(char *s, unsigned short hex) display_lines = *p; row_width = of_get_property(root, "ibm,display-truncation-length", NULL); + of_node_put(root); } display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 6fc27e771b5a..933e214c33e8 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -66,7 +66,7 @@ static int __init smt_setup(void) if (!cpu_has_feature(CPU_FTR_SMT)) return -ENODEV; - options = find_path_device("/options"); + options = of_find_node_by_path("/options"); if (!options) return -ENODEV; @@ -76,6 +76,7 @@ static int __init smt_setup(void) per_cpu(smt_snooze_delay, cpu) = *val; } + of_node_put(options); return 0; } __initcall(smt_setup); diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index b23e39796a0b..de776e3889e3 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -185,10 +185,9 @@ setup_python(struct pci_controller *hose, struct device_node *dev) /* Marvell Discovery II based Pegasos 2 */ static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev) { - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct device_node *rtas; - of_node_get(root); rtas = of_find_node_by_name (root, "rtas"); if (rtas) { hose->ops = &rtas_pci_ops; @@ -198,6 +197,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d " your firmware\n"); } pci_assign_all_buses = 1; + /* keep the reference to the root node */ } void __init @@ -210,7 +210,7 @@ chrp_find_bridges(void) const unsigned int *dma; const char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); struct resource r; /* * The PCI host bridge nodes on some machines don't have @@ -309,6 +309,7 @@ chrp_find_bridges(void) printk("pci_dram_offset = %lx\n", pci_dram_offset); } } + of_node_put(root); } /* SL82C105 IDE Control/Status Register */ diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 05d1bc0c8918..e46c4d4a5804 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -110,7 +110,7 @@ void chrp_show_cpuinfo(struct seq_file *m) struct device_node *root; const char *model = ""; - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) model = of_get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); @@ -160,6 +160,7 @@ void chrp_show_cpuinfo(struct seq_file *m) gg2_cachetypes[(t>>2) & 3], gg2_cachemodes[t & 3]); } + of_node_put(root); } /* @@ -204,7 +205,7 @@ static void __init sio_init(void) { struct device_node *root; - if ((root = find_path_device("/")) && + if ((root = of_find_node_by_path("/")) && !strncmp(of_get_property(root, "model", NULL), "IBM,LongTrail", 13)) { /* logical device 0 (KBC/Keyboard) */ @@ -212,6 +213,7 @@ static void __init sio_init(void) /* select logical device 1 (KBC/Mouse) */ sio_fixup_irq("mouse", 1, 12, 2); } + of_node_put(root); } @@ -250,7 +252,7 @@ static void briq_restart(char *cmd) void __init chrp_setup_arch(void) { - struct device_node *root = find_path_device ("/"); + struct device_node *root = of_find_node_by_path("/"); const char *machine = NULL; /* init to some ~sane value until calibrate_delay() runs */ @@ -273,6 +275,7 @@ void __init chrp_setup_arch(void) /* Let's assume it is an IBM chrp if all else fails */ _chrp_type = _CHRP_IBM; } + of_node_put(root); printk("chrp type = %x [%s]\n", _chrp_type, chrp_names[_chrp_type]); rtas_initialize(); diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 103fcc4c5605..44f85507db3c 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -1044,6 +1044,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, KL_GPIO_RESET_CPU1, KL_GPIO_RESET_CPU2, @@ -1053,10 +1054,10 @@ core99_reset_cpu(struct device_node *node, long param, long value) if (macio->type != macio_keylargo) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { + for (np = cpus->child; np != NULL; np = np->sibling) { const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) @@ -1066,6 +1067,7 @@ core99_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) reset_io = dflt_reset_lines[param]; @@ -1497,15 +1499,16 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) unsigned long flags; struct macio_chip *macio; struct device_node *np; + struct device_node *cpus; macio = &macio_chips[0]; if (macio->type != macio_keylargo2 && macio->type != macio_shasta) return -ENODEV; - np = find_path_device("/cpus"); - if (np == NULL) + cpus = of_find_node_by_path("/cpus"); + if (cpus == NULL) return -ENODEV; - for (np = np->child; np != NULL; np = np->sibling) { + for (np = cpus->child; np != NULL; np = np->sibling) { const u32 *num = of_get_property(np, "reg", NULL); const u32 *rst = of_get_property(np, "soft-reset", NULL); if (num == NULL || rst == NULL) @@ -1515,6 +1518,7 @@ static long g5_reset_cpu(struct device_node *node, long param, long value) break; } } + of_node_put(cpus); if (np == NULL || reset_io == 0) return -ENODEV; @@ -2499,18 +2503,26 @@ found: * that all Apple OF revs did it properly, I do it the paranoid way. */ while (uninorth_base && uninorth_rev > 3) { - struct device_node *np = find_path_device("/cpus"); - if (!np || !np->child) { + struct device_node *cpus = of_find_node_by_path("/cpus"); + struct device_node *np; + + if (!cpus || !cpus->child) { printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); + of_node_put(cpus); break; } - np = np->child; + np = cpus->child; /* Nap mode not supported on SMP */ - if (np->sibling) + if (np->sibling) { + of_node_put(cpus); break; + } /* Nap mode not supported if flush-on-lock property is present */ - if (of_get_property(np, "flush-on-lock", NULL)) + if (of_get_property(np, "flush-on-lock", NULL)) { + of_node_put(cpus); break; + } + of_node_put(cpus); powersave_nap = 1; printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n"); break; diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 669965a461f9..ed53f541d9e8 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -202,13 +202,16 @@ static struct miscdevice briq_panel_miscdev = { static int __init briq_panel_init(void) { - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); const char *machine; int i; machine = of_get_property(root, "model", NULL); - if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) + if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { + of_node_put(root); return -ENODEV; + } + of_node_put(root); printk(KERN_INFO "briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 3fe831cdb74e..140dd9700ff6 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -899,7 +899,7 @@ static int get_system_info(void) const char *id, *model, *name; const unsigned int *num; - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (!rootdn) return -ENOENT; @@ -916,6 +916,7 @@ static int get_system_info(void) if (num) partition_number = *num; + of_node_put(rootdn); return 0; } diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 9bbb69ca73ee..d8700aaa6114 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -157,7 +157,7 @@ static void gather_partition_info(void) const unsigned int *p_number_ptr; /* Retrieve information about this partition */ - rootdn = find_path_device("/"); + rootdn = of_find_node_by_path("/"); if (!rootdn) { return; } @@ -169,6 +169,7 @@ static void gather_partition_info(void) p_number_ptr = of_get_property(rootdn, "ibm,partition-no", NULL); if (p_number_ptr) partition_number = *p_number_ptr; + of_node_put(rootdn); } static void set_adapter_info(struct ibmvscsi_host_data *hostdata) diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index a9acdd8b3bb6..a070defc4438 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -115,7 +115,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e /* OBSOLETE: Old style node lookup */ extern struct device_node *find_devices(const char *name); extern struct device_node *find_type_devices(const char *type); -extern struct device_node *find_path_device(const char *path); /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, -- cgit v1.2.3-59-g8ed1b From 1658ab66781d918f604c6069c5cf9a94b6f52f84 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 24 Apr 2007 13:51:59 +1000 Subject: [POWERPC] Remove old interface find_type_devices Replaced by of_find_node_by_type. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 19 ------------------- arch/powerpc/platforms/chrp/setup.c | 6 ++++-- arch/powerpc/platforms/powermac/cpufreq_32.c | 3 ++- arch/powerpc/platforms/powermac/setup.c | 5 +++-- drivers/macintosh/via-pmu.c | 5 ++++- include/asm-powerpc/prom.h | 1 - 6 files changed, 13 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 17c41fefecf2..860c88b2f6d1 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1091,25 +1091,6 @@ struct device_node *find_devices(const char *name) } EXPORT_SYMBOL(find_devices); -/** - * Construct and return a list of the device_nodes with a given type. - */ -struct device_node *find_type_devices(const char *type) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->type != 0 && strcasecmp(np->type, type) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_type_devices); - /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e46c4d4a5804..9c1b231b1ff9 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -226,12 +226,12 @@ static void __init pegasos_set_l2cr(void) return; /* Enable L2 cache if needed */ - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != NULL) { const unsigned int *l2cr = of_get_property(np, "l2cr", NULL); if (l2cr == NULL) { printk ("Pegasos l2cr : no cpu l2cr property found\n"); - return; + goto out; } if (!((*l2cr) & 0x80000000)) { printk ("Pegasos l2cr : L2 cache was not active, " @@ -240,6 +240,8 @@ static void __init pegasos_set_l2cr(void) _set_L2CR((*l2cr) | 0x80000000); } } +out: + of_node_put(np); } static void briq_restart(char *cmd) diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 76eda9fcd1aa..8943a9456bb7 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c @@ -658,7 +658,7 @@ static int __init pmac_cpufreq_setup(void) return 0; /* Assume only one CPU */ - cpunode = find_type_devices("cpu"); + cpunode = of_find_node_by_type(NULL, "cpu"); if (!cpunode) goto out; @@ -708,6 +708,7 @@ static int __init pmac_cpufreq_setup(void) else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) pmac_cpufreq_init_750FX(cpunode); out: + of_node_put(cpunode); if (set_speed_proc == NULL) return -ENODEV; diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 8c96f2461e9a..ae37d3e23783 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -250,9 +250,9 @@ static void __init l2cr_init(void) { /* Checks "l2cr-value" property in the registry */ if (cpu_has_feature(CPU_FTR_L2CR)) { - struct device_node *np = find_devices("cpus"); + struct device_node *np = of_find_node_by_name(NULL, "cpus"); if (np == 0) - np = find_type_devices("cpu"); + np = of_find_node_by_type(NULL, "cpu"); if (np != 0) { const unsigned int *l2cr = of_get_property(np, "l2cr-value", NULL); @@ -262,6 +262,7 @@ static void __init l2cr_init(void) _set_L2CR(0); _set_L2CR(ppc_override_l2cr_value); } + of_node_put(np); } } diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 75623fd18792..7b7db5db50dc 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -319,10 +319,13 @@ int __init find_via_pmu(void) else if (device_is_compatible(vias->parent, "Keylargo") || device_is_compatible(vias->parent, "K2-Keylargo")) { struct device_node *gpiop; + struct device_node *adbp; u64 gaddr = OF_BAD_ADDR; pmu_kind = PMU_KEYLARGO_BASED; - pmu_has_adb = (find_type_devices("adb") != NULL); + adbp = of_find_node_by_type(NULL, "adb"); + pmu_has_adb = (adbp != NULL); + of_node_put(adbp); pmu_intr_mask = PMU_INT_PCEJECT | PMU_INT_SNDBRT | PMU_INT_ADB | diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index a070defc4438..990489cac9b9 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -114,7 +114,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e /* OBSOLETE: Old style node lookup */ extern struct device_node *find_devices(const char *name); -extern struct device_node *find_type_devices(const char *type); /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, -- cgit v1.2.3-59-g8ed1b From 30686ba6d56858657829d3eb524ed73e5dc98d2b Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 24 Apr 2007 13:53:04 +1000 Subject: [POWERPC] Remove old interface find_devices Replace uses with of_find_node_by_name and for_each_node_by_name. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 19 ------ arch/powerpc/kernel/vio.c | 3 +- arch/powerpc/platforms/chrp/pci.c | 6 +- arch/powerpc/platforms/chrp/setup.c | 9 ++- arch/powerpc/platforms/powermac/backlight.c | 7 ++- arch/powerpc/platforms/powermac/feature.c | 45 ++++++++------- arch/powerpc/platforms/powermac/pci.c | 23 ++++---- arch/powerpc/platforms/powermac/setup.c | 25 ++++++-- arch/powerpc/platforms/powermac/smp.c | 5 +- drivers/macintosh/ans-lcd.c | 9 +-- drivers/macintosh/via-pmu.c | 4 +- drivers/media/video/planb.c | 5 +- drivers/serial/pmac_zilog.c | 4 +- drivers/video/controlfb.c | 16 +++-- include/asm-powerpc/prom.h | 3 - sound/oss/dmasound/dmasound_awacs.c | 90 +++++++++++++++++++---------- sound/oss/dmasound/tas_common.c | 5 +- sound/ppc/pmac.c | 27 +++++---- sound/ppc/tumbler.c | 35 +++++++---- 19 files changed, 206 insertions(+), 134 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 860c88b2f6d1..caef555f2dc0 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1072,25 +1072,6 @@ int of_n_size_cells(struct device_node* np) } EXPORT_SYMBOL(of_n_size_cells); -/** - * Construct and return a list of the device_nodes with a given name. - */ -struct device_node *find_devices(const char *name) -{ - struct device_node *head, **prevp, *np; - - prevp = &head; - for (np = allnodes; np != 0; np = np->allnext) { - if (np->name != 0 && strcasecmp(np->name, name) == 0) { - *prevp = np; - prevp = &np->next; - } - } - *prevp = NULL; - return head; -} -EXPORT_SYMBOL(find_devices); - /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index a09277a8639f..9eaefac5053f 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -308,7 +308,7 @@ static int __init vio_bus_init(void) return err; } - node_vroot = find_devices("vdevice"); + node_vroot = of_find_node_by_name(NULL, "vdevice"); if (node_vroot) { struct device_node *of_node; @@ -322,6 +322,7 @@ static int __init vio_bus_init(void) __FUNCTION__, of_node); vio_register_device_node(of_node); } + of_node_put(node_vroot); } return 0; diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index de776e3889e3..1469d6478f67 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -136,9 +136,11 @@ hydra_init(void) struct device_node *np; struct resource r; - np = find_devices("mac-io"); - if (np == NULL || of_address_to_resource(np, 0, &r)) + np = of_find_node_by_name(NULL, "mac-io"); + if (np == NULL || of_address_to_resource(np, 0, &r)) { + of_node_put(np); return 0; + } Hydra = ioremap(r.start, r.end-r.start); printk("Hydra Mac I/O at %llx\n", (unsigned long long)r.start); printk("Hydra Feature_Control was %x", diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 9c1b231b1ff9..1870038a8e0a 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -468,7 +468,7 @@ static void __init chrp_find_8259(void) * Also, Pegasos-type platforms don't have a proper node to start * from anyway */ - for (np = find_devices("pci"); np != NULL; np = np->next) { + for_each_node_by_name(np, "pci") { const unsigned int *addrp = of_get_property(np, "8259-interrupt-acknowledge", NULL); @@ -477,6 +477,7 @@ static void __init chrp_find_8259(void) chrp_int_ack = addrp[of_n_addr_cells(np)-1]; break; } + of_node_put(np); if (np == NULL) printk(KERN_WARNING "Cannot find PCI interrupt acknowledge" " address, polling\n"); @@ -518,10 +519,11 @@ void __init chrp_init_IRQ(void) #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) /* see if there is a keyboard in the device tree with a parent of type "adb" */ - for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) + for_each_node_by_name(kbd, "keyboard") if (kbd->parent && kbd->parent->type && strcmp(kbd->parent->type, "adb") == 0) break; + of_node_put(kbd); if (kbd) setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction); #endif @@ -547,7 +549,7 @@ chrp_init2(void) /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ - device = find_devices("rtas"); + device = of_find_node_by_name(NULL, "rtas"); if (device) p = of_get_property(device, "rtas-event-scan-rate", NULL); if (p && *p) { @@ -576,6 +578,7 @@ chrp_init2(void) printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", *p, interval); } + of_node_put(device); if (ppc_md.progress) ppc_md.progress(" Have fun! ", 0x7777); diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c index 0dc8a45c408a..d679964ae2ab 100644 --- a/arch/powerpc/platforms/powermac/backlight.c +++ b/arch/powerpc/platforms/powermac/backlight.c @@ -56,13 +56,16 @@ struct backlight_device *pmac_backlight; int pmac_has_backlight_type(const char *type) { - struct device_node* bk_node = find_devices("backlight"); + struct device_node* bk_node = of_find_node_by_name(NULL, "backlight"); if (bk_node) { const char *prop = of_get_property(bk_node, "backlight-control", NULL); - if (prop && strncmp(prop, type, strlen(type)) == 0) + if (prop && strncmp(prop, type, strlen(type)) == 0) { + of_node_put(bk_node); return 1; + } + of_node_put(bk_node); } return 0; diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 44f85507db3c..52cfdd86c928 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -2408,12 +2408,13 @@ static int __init probe_motherboard(void) struct macio_chip *macio = &macio_chips[0]; const char *model = NULL; struct device_node *dt; + int ret = 0; /* Lookup known motherboard type in device-tree. First try an * exact match on the "model" property, then try a "compatible" * match is none is found. */ - dt = find_devices("device-tree"); + dt = of_find_node_by_name(NULL, "device-tree"); if (dt != NULL) model = of_get_property(dt, "model", NULL); for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { @@ -2478,15 +2479,18 @@ static int __init probe_motherboard(void) break; #endif /* CONFIG_POWER4 */ default: - return -ENODEV; + ret = -ENODEV; + goto done; } found: #ifndef CONFIG_POWER4 /* Fixup Hooper vs. Comet */ if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); - if (!mach_id_ptr) - return -ENODEV; + if (!mach_id_ptr) { + ret = -ENODEV; + goto done; + } /* Here, I used to disable the media-bay on comet. It * appears this is wrong, the floppy connector is actually * a kind of media-bay and works with the current driver. @@ -2544,7 +2548,9 @@ found: printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); - return 0; +done: + of_node_put(dt); + return ret; } /* Initialize the Core99 UniNorth host bridge and memory controller @@ -2747,12 +2753,14 @@ set_initial_features(void) * differenciate them all and since that hack was there for a long * time, I'll keep it around */ - if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { - struct macio_chip *macio = &macio_chips[0]; - MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); - } else if (macio_chips[0].type == macio_ohare) { + if (macio_chips[0].type == macio_ohare) { struct macio_chip *macio = &macio_chips[0]; - MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); + else + MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); + of_node_put(np); } else if (macio_chips[1].type == macio_ohare) { struct macio_chip *macio = &macio_chips[1]; MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); @@ -2845,14 +2853,13 @@ set_initial_features(void) } /* Switch airport off */ - np = find_devices("radio"); - while(np) { + for_each_node_by_name(np, "radio") { if (np && np->parent == macio_chips[0].of_node) { macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; core99_airport_enable(np, 0, 0); } - np = np->next; } + of_node_put(np); } /* On all machines that support sound PM, switch sound off */ @@ -2872,16 +2879,12 @@ set_initial_features(void) #endif /* CONFIG_POWER4 */ /* On all machines, switch modem & serial ports off */ - np = find_devices("ch-a"); - while(np) { + for_each_node_by_name(np, "ch-a") initial_serial_shutdown(np); - np = np->next; - } - np = find_devices("ch-b"); - while(np) { + of_node_put(np); + for_each_node_by_name(np, "ch-b") initial_serial_shutdown(np); - np = np->next; - } + of_node_put(np); } void __init diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 092cef4160a1..22c4ae4c6934 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c @@ -622,13 +622,14 @@ static void __init init_p2pbridge(void) /* XXX it would be better here to identify the specific PCI-PCI bridge chip we have. */ - if ((p2pbridge = find_devices("pci-bridge")) == 0 + p2pbridge = of_find_node_by_name(NULL, "pci-bridge"); + if (p2pbridge == NULL || p2pbridge->parent == NULL || strcmp(p2pbridge->parent->name, "pci") != 0) - return; + goto done; if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { DBG("Can't find PCI infos for PCI<->PCI bridge\n"); - return; + goto done; } /* Warning: At this point, we have not yet renumbered all busses. * So we must use OF walking to find out hose @@ -636,16 +637,18 @@ static void __init init_p2pbridge(void) hose = pci_find_hose_for_OF_device(p2pbridge); if (!hose) { DBG("Can't find hose for PCI<->PCI bridge\n"); - return; + goto done; } if (early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { printk(KERN_ERR "init_p2pbridge: couldn't read bridge" " control\n"); - return; + goto done; } val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); +done: + of_node_put(p2pbridge); } static void __init init_second_ohare(void) @@ -1199,8 +1202,7 @@ void __init pmac_pcibios_after_init(void) } #endif /* CONFIG_BLK_DEV_IDE */ - nd = find_devices("firewire"); - while (nd) { + for_each_node_by_name(nd, "firewire") { if (nd->parent && (device_is_compatible(nd, "pci106b,18") || device_is_compatible(nd, "pci106b,30") || device_is_compatible(nd, "pci11c1,5811")) @@ -1208,15 +1210,14 @@ void __init pmac_pcibios_after_init(void) pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); } - nd = nd->next; } - nd = find_devices("ethernet"); - while (nd) { + of_node_put(nd); + for_each_node_by_name(nd, "ethernet") { if (nd->parent && device_is_compatible(nd, "gmac") && device_is_compatible(nd->parent, "uni-north")) pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); - nd = nd->next; } + of_node_put(nd); } #ifdef CONFIG_PPC32 diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index ae37d3e23783..0444e07e8d7a 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -193,8 +193,11 @@ static void pmac_show_cpuinfo(struct seq_file *m) #ifndef CONFIG_ADB_CUDA int find_via_cuda(void) { - if (!find_devices("via-cuda")) + struct device_node *dn = of_find_node_by_name(NULL, "via-cuda"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is CUDA-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); return 0; @@ -204,8 +207,11 @@ int find_via_cuda(void) #ifndef CONFIG_ADB_PMU int find_via_pmu(void) { - if (!find_devices("via-pmu")) + struct device_node *dn = of_find_node_by_name(NULL, "via-pmu"); + + if (!dn) return 0; + of_node_put(dn); printk("WARNING ! Your machine is PMU-based but your kernel\n"); printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); return 0; @@ -225,6 +231,8 @@ static volatile u32 *sysctrl_regs; static void __init ohare_init(void) { + struct device_node *dn; + /* this area has the CPU identification register and some registers used by smp boards */ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); @@ -234,7 +242,9 @@ static void __init ohare_init(void) * We assume that we have a PSX memory controller iff * we have an ohare I/O controller. */ - if (find_devices("ohare") != NULL) { + dn = of_find_node_by_name(NULL, "ohare"); + if (dn) { + of_node_put(dn); if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { if (sysctrl_regs[4] & 0x10) sysctrl_regs[4] |= 0x04000020; @@ -343,8 +353,15 @@ static void __init pmac_setup_arch(void) #ifdef CONFIG_SMP /* Check for Core99 */ - if (find_devices("uni-n") || find_devices("u3") || find_devices("u4")) + ic = of_find_node_by_name(NULL, "uni-n"); + if (!ic) + ic = of_find_node_by_name(NULL, "u3"); + if (!ic) + ic = of_find_node_by_name(NULL, "u4"); + if (ic) { + of_node_put(ic); smp_ops = &core99_smp_ops; + } #ifdef CONFIG_PPC32 else smp_ops = &psurge_smp_ops; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 20f328678fd1..6f32c4eca6e5 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -264,6 +264,7 @@ static void __init psurge_quad_init(void) static int __init smp_psurge_probe(void) { int i, ncpus; + struct device_node *dn; /* We don't do SMP on the PPC601 -- paulus */ if (PVR_VER(mfspr(SPRN_PVR)) == 1) @@ -279,8 +280,10 @@ static int __init smp_psurge_probe(void) * in the hammerhead memory controller in the case of the * dual-cpu powersurge board. -- paulus. */ - if (find_devices("hammerhead") == NULL) + dn = of_find_node_by_name(NULL, "hammerhead"); + if (dn == NULL) return 1; + of_node_put(dn); hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c index cdd5a0f72e3c..e54c4d9f6365 100644 --- a/drivers/macintosh/ans-lcd.c +++ b/drivers/macintosh/ans-lcd.c @@ -145,11 +145,12 @@ anslcd_init(void) int retval; struct device_node* node; - node = find_devices("lcd"); - if (!node || !node->parent) - return -ENODEV; - if (strcmp(node->parent->name, "gc")) + node = of_find_node_by_name(NULL, "lcd"); + if (!node || !node->parent || strcmp(node->parent->name, "gc")) { + of_node_put(node); return -ENODEV; + } + of_node_put(node); anslcd_ptr = ioremap(ANSLCD_ADDR, 0x20); diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 7b7db5db50dc..e31cb1e7a47b 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -487,7 +487,8 @@ static int __init via_pmu_dev_init(void) pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } else { - struct device_node* prim = find_devices("power-mgt"); + struct device_node* prim = + of_find_node_by_name(NULL, "power-mgt"); const u32 *prim_info = NULL; if (prim) prim_info = of_get_property(prim, "prim-info", NULL); @@ -498,6 +499,7 @@ static int __init via_pmu_dev_init(void) if (pmu_battery_count > 1) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } + of_node_put(prim); } #endif /* CONFIG_PPC32 */ diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c index 86d2884e16c6..e6e61df0d071 100644 --- a/drivers/media/video/planb.c +++ b/drivers/media/video/planb.c @@ -2160,7 +2160,7 @@ static int find_planb(void) if (!machine_is(powermac)) return 0; - planb_devices = find_devices("planb"); + planb_devices = of_find_node_by_name(NULL, "planb"); if (planb_devices == 0) { planb_num=0; printk(KERN_WARNING "PlanB: no device found!\n"); @@ -2175,12 +2175,14 @@ static int find_planb(void) if (planb_devices->n_addrs != 1) { printk (KERN_WARNING "PlanB: expecting 1 address for planb " "(got %d)", planb_devices->n_addrs); + of_node_put(planb_devices); return 0; } if (planb_devices->n_intrs == 0) { printk(KERN_WARNING "PlanB: no intrs for device %s\n", planb_devices->full_name); + of_node_put(planb_devices); return 0; } else { irq = planb_devices->intrs[0].line; @@ -2202,6 +2204,7 @@ static int find_planb(void) confreg = planb_devices->addrs[0].space & 0xff; old_base = planb_devices->addrs[0].address; new_base = 0xf1000000; + of_node_put(planb_devices); DEBUG("PlanB: Found on bus %d, dev %d, func %d, " "membase 0x%x (base reg. 0x%x)\n", diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 2b163c532e0d..cd92a3966b0c 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -1467,7 +1467,8 @@ no_dma: if (ZS_IS_IRDA(uap)) uap->port_type = PMAC_SCC_IRDA; if (ZS_IS_INTMODEM(uap)) { - struct device_node* i2c_modem = find_devices("i2c-modem"); + struct device_node* i2c_modem = + of_find_node_by_name(NULL, "i2c-modem"); if (i2c_modem) { const char* mid = of_get_property(i2c_modem, "modem-id", NULL); @@ -1482,6 +1483,7 @@ no_dma: } printk(KERN_INFO "pmac_zilog: i2c-modem detected, id: %d\n", mid ? (*mid) : 0); + of_node_put(i2c_modem); } else { printk(KERN_INFO "pmac_zilog: serial modem detected\n"); } diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index fd60dba294da..8b762739b1e0 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -179,12 +179,14 @@ MODULE_LICENSE("GPL"); int init_module(void) { struct device_node *dp; + int ret = -ENXIO; - dp = find_devices("control"); + dp = of_find_node_by_name(NULL, "control"); if (dp != 0 && !control_of_init(dp)) - return 0; + ret = 0; + of_node_put(dp); - return -ENXIO; + return ret; } void cleanup_module(void) @@ -589,16 +591,18 @@ static int __init control_init(void) { struct device_node *dp; char *option = NULL; + int ret = -ENXIO; if (fb_get_options("controlfb", &option)) return -ENODEV; control_setup(option); - dp = find_devices("control"); + dp = of_find_node_by_name(NULL, "control"); if (dp != 0 && !control_of_init(dp)) - return 0; + ret = 0; + of_node_put(dp); - return -ENXIO; + return ret; } module_init(control_init); diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 990489cac9b9..ec400f608e16 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -112,9 +112,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e } -/* OBSOLETE: Old style node lookup */ -extern struct device_node *find_devices(const char *name); - /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 977b91cea603..730fa1d001a5 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c @@ -346,14 +346,16 @@ int gpio_headphone_irq; int setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol) { + struct device_node *gpiop; struct device_node *np; const u32* pp; + int ret = -ENODEV; - np = find_devices("gpio"); - if (!np) - return -ENODEV; + gpiop = of_find_node_by_name(NULL, "gpio"); + if (!gpiop) + goto done; - np = np->child; + np = of_get_next_child(gpiop, NULL); while(np != 0) { if (name) { const char *property = @@ -362,20 +364,24 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* break; } else if (compatible && device_is_compatible(np, compatible)) break; - np = np->sibling; + np = of_get_next_child(gpiop, np); } if (!np) - return -ENODEV; + goto done; pp = of_get_property(np, "AAPL,address", NULL); if (!pp) - return -ENODEV; + goto done; *gpio_addr = (*pp) & 0x0000ffff; pp = of_get_property(np, "audio-gpio-active-state", NULL); if (pp) *gpio_pol = *pp; else *gpio_pol = 1; - return irq_of_parse_and_map(np, 0); + ret = irq_of_parse_and_map(np, 0); +done: + of_node_put(np); + of_node_put(gpiop); + return ret; } static inline void @@ -2552,32 +2558,33 @@ set_model(void) static struct device_node* __init get_snd_io_node(void) { - struct device_node *np = NULL; + struct device_node *np; /* set up awacs_node for early OF which doesn't have a full set of * properties on davbus - */ - - awacs_node = find_devices("awacs"); + */ + awacs_node = of_find_node_by_name(NULL, "awacs"); if (awacs_node) awacs_revision = AWACS_AWACS; /* powermac models after 9500 (other than those which use DACA or * Tumbler) have a node called "davbus". */ - np = find_devices("davbus"); + np = of_find_node_by_name(NULL, "davbus"); /* * if we didn't find a davbus device, try 'i2s-a' since * this seems to be what iBooks (& Tumbler) have. */ - if (np == NULL) - np = i2s_node = find_devices("i2s-a"); + if (np == NULL) { + i2s_node = of_find_node_by_name(NULL, "i2s-a"); + np = of_node_get(i2s_node); + } /* if we didn't find this - perhaps we are on an early model * which _only_ has an 'awacs' node */ if (np == NULL && awacs_node) - np = awacs_node ; + np = of_node_get(awacs_node); /* if we failed all these return null - this will cause the * driver to give up... @@ -2596,9 +2603,9 @@ get_snd_info_node(struct device_node *io) { struct device_node *info; - info = find_devices("sound"); - while (info && info->parent != io) - info = info->next; + for_each_node_by_name(info, "sound") + if (info->parent == io) + break; return info; } @@ -2634,11 +2641,17 @@ get_codec_type(struct device_node *info) static void __init get_expansion_type(void) { - if (find_devices("perch") != NULL) + struct device_node *dn; + + dn = of_find_node_by_name(NULL, "perch"); + if (dn != NULL) has_perch = 1; + of_node_put(dn); - if (find_devices("pb-ziva-pc") != NULL) + dn = of_find_node_by_name(NULL, "pb-ziva-pc"); + if (dn != NULL) has_ziva = 1; + of_node_put(dn); /* need to work out how we deal with iMac SRS module */ } @@ -2827,7 +2840,7 @@ int __init dmasound_awacs_init(void) #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find sound io OF node\n"); #endif - return -ENODEV ; + goto no_device; } /* find the OF node that tells us about the sound sub-system @@ -2839,7 +2852,7 @@ printk("dmasound_pmac: couldn't find sound io OF node\n"); #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find 'sound' OF node\n"); #endif - return -ENODEV ; + goto no_device; } } @@ -2848,7 +2861,7 @@ printk("dmasound_pmac: couldn't find 'sound' OF node\n"); #ifdef DEBUG_DMASOUND printk("dmasound_pmac: couldn't find a Codec we can handle\n"); #endif - return -ENODEV ; /* we don't know this type of h/w */ + goto no_device; /* we don't know this type of h/w */ } /* set up perch, ziva, SRS or whatever else we have as sound @@ -2866,11 +2879,12 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); * machines). */ if (awacs_node) { - io = awacs_node ; + of_node_put(io); + io = of_node_get(awacs_node); if (of_get_address(io, 2, NULL, NULL) == NULL) { printk("dmasound_pmac: can't use %s\n", io->full_name); - return -ENODEV; + goto no_device; } } else printk("dmasound_pmac: can't use %s\n", io->full_name); @@ -2881,7 +2895,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); awacs_rsrc[0].end - awacs_rsrc[0].start + 1, " (IO)") == NULL) { printk(KERN_ERR "dmasound: can't request IO resource !\n"); - return -ENODEV; + goto no_device; } if (of_address_to_resource(io, 1, &awacs_rsrc[1]) || request_mem_region(awacs_rsrc[1].start, @@ -2890,7 +2904,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[0].start, awacs_rsrc[0].end - awacs_rsrc[0].start + 1); printk(KERN_ERR "dmasound: can't request Tx DMA resource !\n"); - return -ENODEV; + goto no_device; } if (of_address_to_resource(io, 2, &awacs_rsrc[2]) || request_mem_region(awacs_rsrc[2].start, @@ -2901,7 +2915,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[1].start, awacs_rsrc[1].end - awacs_rsrc[1].start + 1); printk(KERN_ERR "dmasound: can't request Rx DMA resource !\n"); - return -ENODEV; + goto no_device; } awacs_beep_dev = input_allocate_device(); @@ -2913,7 +2927,7 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); release_mem_region(awacs_rsrc[2].start, awacs_rsrc[2].end - awacs_rsrc[2].start + 1); printk(KERN_ERR "dmasound: can't allocate input device !\n"); - return -ENOMEM; + goto no_device; } awacs_beep_dev->name = "dmasound beeper"; @@ -2941,7 +2955,8 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); awacs_rx_irq = irq_of_parse_and_map(io, 2); /* Hack for legacy crap that will be killed someday */ - awacs_node = io; + of_node_put(awacs_node); + awacs_node = of_node_get(io); /* if we have an awacs or screamer - probe the chip to make * sure we have the right revision. @@ -2990,6 +3005,8 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); /* if it's there use it to set up frame rates */ init_frame_rates(prop, l) ; + of_node_put(info); + info = NULL; } if (awacs) @@ -3159,7 +3176,16 @@ printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev); */ input_register_device(awacs_beep_dev); + of_node_put(io); + return dmasound_init(); + +no_device: + of_node_put(info); + of_node_put(awacs_node); + of_node_put(i2s_node); + of_node_put(io); + return -ENODEV ; } static void __exit dmasound_awacs_cleanup(void) @@ -3178,6 +3204,8 @@ static void __exit dmasound_awacs_cleanup(void) } dmasound_deinit(); + of_node_put(awacs_node); + of_node_put(i2s_node); } MODULE_DESCRIPTION("PowerMac built-in audio driver."); diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c index 11257600d6d0..b295ef682192 100644 --- a/sound/oss/dmasound/tas_common.c +++ b/sound/oss/dmasound/tas_common.c @@ -41,7 +41,6 @@ static u8 tas_i2c_address = 0x34; static struct i2c_client *tas_client; -static struct device_node* tas_node; static int tas_attach_adapter(struct i2c_adapter *); static int tas_detach_client(struct i2c_client *); @@ -191,13 +190,14 @@ int __init tas_init(int driver_id, const char *driver_name) { const u32* paddr; + struct device_node *tas_node; printk(KERN_INFO "tas driver [%s])\n", driver_name); #ifndef CONFIG_I2C_POWERMAC request_module("i2c-powermac"); #endif - tas_node = find_devices("deq"); + tas_node = of_find_node_by_name("deq"); if (tas_node == NULL) return -ENODEV; paddr = of_get_property(tas_node, "i2c-address", NULL); @@ -208,6 +208,7 @@ tas_init(int driver_id, const char *driver_name) } else printk(KERN_INFO "using i2c address: 0x%x (default)\n", tas_i2c_address); + of_node_put(tas_node); return i2c_add_driver(&tas_driver); } diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 5e829683d1ad..2bae9c1a2b54 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -816,6 +816,7 @@ static int snd_pmac_free(struct snd_pmac *chip) if (chip->pdev) pci_dev_put(chip->pdev); + of_node_put(chip->node); kfree(chip); return 0; } @@ -863,7 +864,8 @@ static void __init detect_byte_swap(struct snd_pmac *chip) */ static int __init snd_pmac_detect(struct snd_pmac *chip) { - struct device_node *sound = NULL; + struct device_node *sound; + struct device_node *dn; const unsigned int *prop; unsigned int l; struct macio_chip* macio; @@ -891,22 +893,21 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) else if (machine_is_compatible("PowerBook1,1") || machine_is_compatible("AAPL,PowerBook1998")) chip->is_pbook_G3 = 1; - chip->node = find_devices("awacs"); - if (chip->node) - sound = chip->node; + chip->node = of_find_node_by_name(NULL, "awacs"); + sound = of_node_get(chip->node); /* * powermac G3 models have a node called "davbus" * with a child called "sound". */ if (!chip->node) - chip->node = find_devices("davbus"); + chip->node = of_find_node_by_name(NULL, "davbus"); /* * if we didn't find a davbus device, try 'i2s-a' since * this seems to be what iBooks have */ if (! chip->node) { - chip->node = find_devices("i2s-a"); + chip->node = of_find_node_by_name(NULL, "i2s-a"); if (chip->node && chip->node->parent && chip->node->parent->parent) { if (device_is_compatible(chip->node->parent->parent, @@ -918,12 +919,14 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) return -ENODEV; if (!sound) { - sound = find_devices("sound"); + sound = of_find_node_by_name(NULL, "sound"); while (sound && sound->parent != chip->node) - sound = sound->next; + sound = of_find_node_by_name(sound, "sound"); } - if (! sound) + if (! sound) { + of_node_put(chip->node); return -ENODEV; + } prop = of_get_property(sound, "sub-frame", NULL); if (prop && *prop < 16) chip->subframe = *prop; @@ -934,6 +937,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) printk(KERN_INFO "snd-powermac no longer handles any " "machines with a layout-id property " "in the device-tree, use snd-aoa.\n"); + of_node_put(chip->node); return -ENODEV; } /* This should be verified on older screamers */ @@ -971,7 +975,9 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) prop = of_get_property(sound, "device-id", NULL); if (prop) chip->device_id = *prop; - chip->has_iic = (find_devices("perch") != NULL); + dn = of_find_node_by_name(NULL, "perch"); + chip->has_iic = (dn != NULL); + of_node_put(dn); /* We need the PCI device for DMA allocations, let's use a crude method * for now ... @@ -1021,6 +1027,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) chip->freqs_ok = 1; } + of_node_put(sound); return 0; } diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index 8e01b558131d..54e333fbb1d0 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -1031,32 +1031,40 @@ static irqreturn_t headphone_intr(int irq, void *devid) /* look for audio-gpio device */ static struct device_node *find_audio_device(const char *name) { + struct device_node *gpiop; struct device_node *np; - if (! (np = find_devices("gpio"))) + gpiop = of_find_node_by_name(NULL, "gpio"); + if (! gpiop) return NULL; - for (np = np->child; np; np = np->sibling) { + for (np = of_get_next_child(gpiop, NULL); np; + np = of_get_next_child(gpiop, np)) { const char *property = of_get_property(np, "audio-gpio", NULL); if (property && strcmp(property, name) == 0) - return np; + break; } - return NULL; + of_node_put(gpiop); + return np; } /* look for audio-gpio device */ static struct device_node *find_compatible_audio_device(const char *name) { + struct device_node *gpiop; struct device_node *np; - if (! (np = find_devices("gpio"))) + gpiop = of_find_node_by_name(NULL, "gpio"); + if (!gpiop) return NULL; - for (np = np->child; np; np = np->sibling) { + for (np = of_get_next_child(gpiop, NULL); np; + np = of_get_next_child(gpiop, np)) { if (device_is_compatible(np, name)) - return np; + break; } - return NULL; + of_node_put(gpiop); + return np; } /* find an audio device and get its address */ @@ -1066,6 +1074,7 @@ static long tumbler_find_device(const char *device, const char *platform, struct device_node *node; const u32 *base; u32 addr; + long ret; if (is_compatible) node = find_compatible_audio_device(device); @@ -1083,6 +1092,7 @@ static long tumbler_find_device(const char *device, const char *platform, if (!base) { DBG("(E) cannot find address for device %s !\n", device); snd_printd("cannot find address for device %s\n", device); + of_node_put(node); return -ENODEV; } addr = *base; @@ -1124,7 +1134,9 @@ static long tumbler_find_device(const char *device, const char *platform, DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", device, gp->addr, gp->active_state); - return irq_of_parse_and_map(node, 0); + ret = irq_of_parse_and_map(node, 0); + of_node_put(node); + return ret; } /* reset audio */ @@ -1342,9 +1354,9 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) return err; /* set up TAS */ - tas_node = find_devices("deq"); + tas_node = of_find_node_by_name(NULL, "deq"); if (tas_node == NULL) - tas_node = find_devices("codec"); + tas_node = of_find_node_by_name(NULL, "codec"); if (tas_node == NULL) return -ENODEV; @@ -1355,6 +1367,7 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) mix->i2c.addr = (*paddr) >> 1; else mix->i2c.addr = TAS_I2C_ADDR; + of_node_put(tas_node); DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); -- cgit v1.2.3-59-g8ed1b From 8d2169e8d6b8a91413df33bc402e0f602ceaabcc Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 27 Apr 2007 11:53:52 +1000 Subject: [POWERPC] Prepare for splitting up mmu.h by MMU type Currently asm-powerpc/mmu.h has definitions for the 64-bit hash based MMU. If CONFIG_PPC64 is not set, it instead includes asm-ppc/mmu.h which contains a particularly horrible mess of #ifdefs giving the definitions for all the various 32-bit MMUs. It would be nice to have the low level definitions for each MMU type neatly in their own separate files. It would also be good to wean arch/powerpc off dependence on the old asm-ppc/mmu.h. This patch makes a start on such a cleanup by moving the definitions for the 64-bit hash MMU to their own file, asm-powerpc/mmu_hash64.h. Definitions for the other MMUs still all come from asm-ppc/mmu.h, however each MMU type can now be one-by-one moved over to their own file, in the process cleaning them up stripping them of cruft no longer necessary in arch/powerpc. Signed-off-by: David Gibson Signed-off-by: Paul Mackerras --- include/asm-powerpc/mmu-hash64.h | 400 ++++++++++++++++++++++++++++++++++++++ include/asm-powerpc/mmu.h | 406 +-------------------------------------- 2 files changed, 406 insertions(+), 400 deletions(-) create mode 100644 include/asm-powerpc/mmu-hash64.h (limited to 'include') diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h new file mode 100644 index 000000000000..6739457d8bc0 --- /dev/null +++ b/include/asm-powerpc/mmu-hash64.h @@ -0,0 +1,400 @@ +#ifndef _ASM_POWERPC_MMU_HASH64_H_ +#define _ASM_POWERPC_MMU_HASH64_H_ +/* + * PowerPC64 memory management structures + * + * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> + * PPC64 rework. + * + * 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 + +/* + * Segment table + */ + +#define STE_ESID_V 0x80 +#define STE_ESID_KS 0x20 +#define STE_ESID_KP 0x10 +#define STE_ESID_N 0x08 + +#define STE_VSID_SHIFT 12 + +/* Location of cpu0's segment table */ +#define STAB0_PAGE 0x6 +#define STAB0_OFFSET (STAB0_PAGE << 12) +#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) + +#ifndef __ASSEMBLY__ +extern char initial_stab[]; +#endif /* ! __ASSEMBLY */ + +/* + * SLB + */ + +#define SLB_NUM_BOLTED 3 +#define SLB_CACHE_ENTRIES 8 + +/* Bits in the SLB ESID word */ +#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ + +/* Bits in the SLB VSID word */ +#define SLB_VSID_SHIFT 12 +#define SLB_VSID_B ASM_CONST(0xc000000000000000) +#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) +#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) +#define SLB_VSID_KS ASM_CONST(0x0000000000000800) +#define SLB_VSID_KP ASM_CONST(0x0000000000000400) +#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ +#define SLB_VSID_L ASM_CONST(0x0000000000000100) +#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ +#define SLB_VSID_LP ASM_CONST(0x0000000000000030) +#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) +#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) +#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) +#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) +#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) + +#define SLB_VSID_KERNEL (SLB_VSID_KP) +#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) + +#define SLBIE_C (0x08000000) + +/* + * Hash table + */ + +#define HPTES_PER_GROUP 8 + +#define HPTE_V_AVPN_SHIFT 7 +#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) +#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) +#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) +#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) +#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) +#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) +#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) +#define HPTE_V_VALID ASM_CONST(0x0000000000000001) + +#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) +#define HPTE_R_TS ASM_CONST(0x4000000000000000) +#define HPTE_R_RPN_SHIFT 12 +#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) +#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) +#define HPTE_R_PP ASM_CONST(0x0000000000000003) +#define HPTE_R_N ASM_CONST(0x0000000000000004) +#define HPTE_R_C ASM_CONST(0x0000000000000080) +#define HPTE_R_R ASM_CONST(0x0000000000000100) + +/* Values for PP (assumes Ks=0, Kp=1) */ +/* pp0 will always be 0 for linux */ +#define PP_RWXX 0 /* Supervisor read/write, User none */ +#define PP_RWRX 1 /* Supervisor read/write, User read */ +#define PP_RWRW 2 /* Supervisor read/write, User read/write */ +#define PP_RXRX 3 /* Supervisor read, User read */ + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned long v; + unsigned long r; +} hpte_t; + +extern hpte_t *htab_address; +extern unsigned long htab_size_bytes; +extern unsigned long htab_hash_mask; + +/* + * Page size definition + * + * shift : is the "PAGE_SHIFT" value for that page size + * sllp : is a bit mask with the value of SLB L || LP to be or'ed + * directly to a slbmte "vsid" value + * penc : is the HPTE encoding mask for the "LP" field: + * + */ +struct mmu_psize_def +{ + unsigned int shift; /* number of bits */ + unsigned int penc; /* HPTE encoding */ + unsigned int tlbiel; /* tlbiel supported for that page size */ + unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ + unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ +}; + +#endif /* __ASSEMBLY__ */ + +/* + * The kernel use the constants below to index in the page sizes array. + * The use of fixed constants for this purpose is better for performances + * of the low level hash refill handlers. + * + * A non supported page size has a "shift" field set to 0 + * + * Any new page size being implemented can get a new entry in here. Whether + * the kernel will use it or not is a different matter though. The actual page + * size used by hugetlbfs is not defined here and may be made variable + */ + +#define MMU_PAGE_4K 0 /* 4K */ +#define MMU_PAGE_64K 1 /* 64K */ +#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ +#define MMU_PAGE_1M 3 /* 1M */ +#define MMU_PAGE_16M 4 /* 16M */ +#define MMU_PAGE_16G 5 /* 16G */ +#define MMU_PAGE_COUNT 6 + +#ifndef __ASSEMBLY__ + +/* + * The current system page sizes + */ +extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; +extern int mmu_linear_psize; +extern int mmu_virtual_psize; +extern int mmu_vmalloc_psize; +extern int mmu_io_psize; + +/* + * If the processor supports 64k normal pages but not 64k cache + * inhibited pages, we have to be prepared to switch processes + * to use 4k pages when they create cache-inhibited mappings. + * If this is the case, mmu_ci_restrictions will be set to 1. + */ +extern int mmu_ci_restrictions; + +#ifdef CONFIG_HUGETLB_PAGE +/* + * The page size index of the huge pages for use by hugetlbfs + */ +extern int mmu_huge_psize; + +#endif /* CONFIG_HUGETLB_PAGE */ + +/* + * This function sets the AVPN and L fields of the HPTE appropriately + * for the page size + */ +static inline unsigned long hpte_encode_v(unsigned long va, int psize) +{ + unsigned long v = + v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); + v <<= HPTE_V_AVPN_SHIFT; + if (psize != MMU_PAGE_4K) + v |= HPTE_V_LARGE; + return v; +} + +/* + * This function sets the ARPN, and LP fields of the HPTE appropriately + * for the page size. We assume the pa is already "clean" that is properly + * aligned for the requested page size + */ +static inline unsigned long hpte_encode_r(unsigned long pa, int psize) +{ + unsigned long r; + + /* A 4K page needs no special encoding */ + if (psize == MMU_PAGE_4K) + return pa & HPTE_R_RPN; + else { + unsigned int penc = mmu_psize_defs[psize].penc; + unsigned int shift = mmu_psize_defs[psize].shift; + return (pa & ~((1ul << shift) - 1)) | (penc << 12); + } + return r; +} + +/* + * This hashes a virtual address for a 256Mb segment only for now + */ + +static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) +{ + return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); +} + +extern int __hash_page_4K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +extern int __hash_page_64K(unsigned long ea, unsigned long access, + unsigned long vsid, pte_t *ptep, unsigned long trap, + unsigned int local); +struct mm_struct; +extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); +extern int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local, + unsigned long trap); + +extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + unsigned long pstart, unsigned long mode, + int psize); + +extern void htab_initialize(void); +extern void htab_initialize_secondary(void); +extern void hpte_init_native(void); +extern void hpte_init_lpar(void); +extern void hpte_init_iSeries(void); +extern void hpte_init_beat(void); + +extern void stabs_alloc(void); +extern void slb_initialize(void); +extern void slb_flush_and_rebolt(void); +extern void stab_initialize(unsigned long stab); + +#endif /* __ASSEMBLY__ */ + +/* + * VSID allocation + * + * We first generate a 36-bit "proto-VSID". For kernel addresses this + * is equal to the ESID, for user addresses it is: + * (context << 15) | (esid & 0x7fff) + * + * The two forms are distinguishable because the top bit is 0 for user + * addresses, whereas the top two bits are 1 for kernel addresses. + * Proto-VSIDs with the top two bits equal to 0b10 are reserved for + * now. + * + * The proto-VSIDs are then scrambled into real VSIDs with the + * multiplicative hash: + * + * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS + * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 + * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF + * + * This scramble is only well defined for proto-VSIDs below + * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are + * reserved. VSID_MULTIPLIER is prime, so in particular it is + * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. + * Because the modulus is 2^n-1 we can compute it efficiently without + * a divide or extra multiply (see below). + * + * This scheme has several advantages over older methods: + * + * - We have VSIDs allocated for every kernel address + * (i.e. everything above 0xC000000000000000), except the very top + * segment, which simplifies several things. + * + * - We allow for 15 significant bits of ESID and 20 bits of + * context for user addresses. i.e. 8T (43 bits) of address space for + * up to 1M contexts (although the page table structure and context + * allocation will need changes to take advantage of this). + * + * - The scramble function gives robust scattering in the hash + * table (at least based on some initial results). The previous + * method was more susceptible to pathological cases giving excessive + * hash collisions. + */ +/* + * WARNING - If you change these you must make sure the asm + * implementations in slb_allocate (slb_low.S), do_stab_bolted + * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly. + * + * You'll also need to change the precomputed VSID values in head.S + * which are used by the iSeries firmware. + */ + +#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ +#define VSID_BITS 36 +#define VSID_MODULUS ((1UL<= \ + * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ + * the bit clear, r3 already has the answer we want, if it \ + * doesn't, the answer is the low 36 bits of r3+1. So in all \ + * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ + addi rx,rt,1; \ + srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ + add rt,rt,rx + + +#ifndef __ASSEMBLY__ + +typedef unsigned long mm_context_id_t; + +typedef struct { + mm_context_id_t id; + u16 user_psize; /* page size index */ + u16 sllp; /* SLB entry page size encoding */ +#ifdef CONFIG_HUGETLB_PAGE + u16 low_htlb_areas, high_htlb_areas; +#endif + unsigned long vdso_base; +} mm_context_t; + + +static inline unsigned long vsid_scramble(unsigned long protovsid) +{ +#if 0 + /* The code below is equivalent to this function for arguments + * < 2^VSID_BITS, which is all this should ever be called + * with. However gcc is not clever enough to compute the + * modulus (2^n-1) without a second multiply. */ + return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); +#else /* 1 */ + unsigned long x; + + x = protovsid * VSID_MULTIPLIER; + x = (x >> VSID_BITS) + (x & VSID_MODULUS); + return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; +#endif /* 1 */ +} + +/* This is only valid for addresses >= KERNELBASE */ +static inline unsigned long get_kernel_vsid(unsigned long ea) +{ + return vsid_scramble(ea >> SID_SHIFT); +} + +/* This is only valid for user addresses (which are below 2^41) */ +static inline unsigned long get_vsid(unsigned long context, unsigned long ea) +{ + return vsid_scramble((context << USER_ESID_BITS) + | (ea >> SID_SHIFT)); +} + +#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS) +#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea)) + +/* Physical address used by some IO functions */ +typedef unsigned long phys_addr_t; + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_MMU_HASH64_H_ */ diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h index e22fd8811505..06b3e6d336cb 100644 --- a/include/asm-powerpc/mmu.h +++ b/include/asm-powerpc/mmu.h @@ -2,408 +2,14 @@ #define _ASM_POWERPC_MMU_H_ #ifdef __KERNEL__ -#ifndef CONFIG_PPC64 -#include +#ifdef CONFIG_PPC64 +/* 64-bit classic hash table MMU */ +# include #else - -/* - * PowerPC memory management structures - * - * Dave Engebretsen & Mike Corrigan <{engebret|mikejc}@us.ibm.com> - * PPC64 rework. - * - * 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 - -/* - * Segment table - */ - -#define STE_ESID_V 0x80 -#define STE_ESID_KS 0x20 -#define STE_ESID_KP 0x10 -#define STE_ESID_N 0x08 - -#define STE_VSID_SHIFT 12 - -/* Location of cpu0's segment table */ -#define STAB0_PAGE 0x6 -#define STAB0_OFFSET (STAB0_PAGE << 12) -#define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) - -#ifndef __ASSEMBLY__ -extern char initial_stab[]; -#endif /* ! __ASSEMBLY */ - -/* - * SLB - */ - -#define SLB_NUM_BOLTED 3 -#define SLB_CACHE_ENTRIES 8 - -/* Bits in the SLB ESID word */ -#define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ - -/* Bits in the SLB VSID word */ -#define SLB_VSID_SHIFT 12 -#define SLB_VSID_B ASM_CONST(0xc000000000000000) -#define SLB_VSID_B_256M ASM_CONST(0x0000000000000000) -#define SLB_VSID_B_1T ASM_CONST(0x4000000000000000) -#define SLB_VSID_KS ASM_CONST(0x0000000000000800) -#define SLB_VSID_KP ASM_CONST(0x0000000000000400) -#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ -#define SLB_VSID_L ASM_CONST(0x0000000000000100) -#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ -#define SLB_VSID_LP ASM_CONST(0x0000000000000030) -#define SLB_VSID_LP_00 ASM_CONST(0x0000000000000000) -#define SLB_VSID_LP_01 ASM_CONST(0x0000000000000010) -#define SLB_VSID_LP_10 ASM_CONST(0x0000000000000020) -#define SLB_VSID_LP_11 ASM_CONST(0x0000000000000030) -#define SLB_VSID_LLP (SLB_VSID_L|SLB_VSID_LP) - -#define SLB_VSID_KERNEL (SLB_VSID_KP) -#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS|SLB_VSID_C) - -#define SLBIE_C (0x08000000) - -/* - * Hash table - */ - -#define HPTES_PER_GROUP 8 - -#define HPTE_V_AVPN_SHIFT 7 -#define HPTE_V_AVPN ASM_CONST(0xffffffffffffff80) -#define HPTE_V_AVPN_VAL(x) (((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT) -#define HPTE_V_COMPARE(x,y) (!(((x) ^ (y)) & HPTE_V_AVPN)) -#define HPTE_V_BOLTED ASM_CONST(0x0000000000000010) -#define HPTE_V_LOCK ASM_CONST(0x0000000000000008) -#define HPTE_V_LARGE ASM_CONST(0x0000000000000004) -#define HPTE_V_SECONDARY ASM_CONST(0x0000000000000002) -#define HPTE_V_VALID ASM_CONST(0x0000000000000001) - -#define HPTE_R_PP0 ASM_CONST(0x8000000000000000) -#define HPTE_R_TS ASM_CONST(0x4000000000000000) -#define HPTE_R_RPN_SHIFT 12 -#define HPTE_R_RPN ASM_CONST(0x3ffffffffffff000) -#define HPTE_R_FLAGS ASM_CONST(0x00000000000003ff) -#define HPTE_R_PP ASM_CONST(0x0000000000000003) -#define HPTE_R_N ASM_CONST(0x0000000000000004) -#define HPTE_R_C ASM_CONST(0x0000000000000080) -#define HPTE_R_R ASM_CONST(0x0000000000000100) - -/* Values for PP (assumes Ks=0, Kp=1) */ -/* pp0 will always be 0 for linux */ -#define PP_RWXX 0 /* Supervisor read/write, User none */ -#define PP_RWRX 1 /* Supervisor read/write, User read */ -#define PP_RWRW 2 /* Supervisor read/write, User read/write */ -#define PP_RXRX 3 /* Supervisor read, User read */ - -#ifndef __ASSEMBLY__ - -typedef struct { - unsigned long v; - unsigned long r; -} hpte_t; - -extern hpte_t *htab_address; -extern unsigned long htab_size_bytes; -extern unsigned long htab_hash_mask; - -/* - * Page size definition - * - * shift : is the "PAGE_SHIFT" value for that page size - * sllp : is a bit mask with the value of SLB L || LP to be or'ed - * directly to a slbmte "vsid" value - * penc : is the HPTE encoding mask for the "LP" field: - * - */ -struct mmu_psize_def -{ - unsigned int shift; /* number of bits */ - unsigned int penc; /* HPTE encoding */ - unsigned int tlbiel; /* tlbiel supported for that page size */ - unsigned long avpnm; /* bits to mask out in AVPN in the HPTE */ - unsigned long sllp; /* SLB L||LP (exact mask to use in slbmte) */ -}; - -#endif /* __ASSEMBLY__ */ - -/* - * The kernel use the constants below to index in the page sizes array. - * The use of fixed constants for this purpose is better for performances - * of the low level hash refill handlers. - * - * A non supported page size has a "shift" field set to 0 - * - * Any new page size being implemented can get a new entry in here. Whether - * the kernel will use it or not is a different matter though. The actual page - * size used by hugetlbfs is not defined here and may be made variable - */ - -#define MMU_PAGE_4K 0 /* 4K */ -#define MMU_PAGE_64K 1 /* 64K */ -#define MMU_PAGE_64K_AP 2 /* 64K Admixed (in a 4K segment) */ -#define MMU_PAGE_1M 3 /* 1M */ -#define MMU_PAGE_16M 4 /* 16M */ -#define MMU_PAGE_16G 5 /* 16G */ -#define MMU_PAGE_COUNT 6 - -#ifndef __ASSEMBLY__ - -/* - * The current system page sizes - */ -extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; -extern int mmu_linear_psize; -extern int mmu_virtual_psize; -extern int mmu_vmalloc_psize; -extern int mmu_io_psize; - -/* - * If the processor supports 64k normal pages but not 64k cache - * inhibited pages, we have to be prepared to switch processes - * to use 4k pages when they create cache-inhibited mappings. - * If this is the case, mmu_ci_restrictions will be set to 1. - */ -extern int mmu_ci_restrictions; - -#ifdef CONFIG_HUGETLB_PAGE -/* - * The page size index of the huge pages for use by hugetlbfs - */ -extern int mmu_huge_psize; - -#endif /* CONFIG_HUGETLB_PAGE */ - -/* - * This function sets the AVPN and L fields of the HPTE appropriately - * for the page size - */ -static inline unsigned long hpte_encode_v(unsigned long va, int psize) -{ - unsigned long v = - v = (va >> 23) & ~(mmu_psize_defs[psize].avpnm); - v <<= HPTE_V_AVPN_SHIFT; - if (psize != MMU_PAGE_4K) - v |= HPTE_V_LARGE; - return v; -} - -/* - * This function sets the ARPN, and LP fields of the HPTE appropriately - * for the page size. We assume the pa is already "clean" that is properly - * aligned for the requested page size - */ -static inline unsigned long hpte_encode_r(unsigned long pa, int psize) -{ - unsigned long r; - - /* A 4K page needs no special encoding */ - if (psize == MMU_PAGE_4K) - return pa & HPTE_R_RPN; - else { - unsigned int penc = mmu_psize_defs[psize].penc; - unsigned int shift = mmu_psize_defs[psize].shift; - return (pa & ~((1ul << shift) - 1)) | (penc << 12); - } - return r; -} - -/* - * This hashes a virtual address for a 256Mb segment only for now - */ - -static inline unsigned long hpt_hash(unsigned long va, unsigned int shift) -{ - return ((va >> 28) & 0x7fffffffffUL) ^ ((va & 0x0fffffffUL) >> shift); -} - -extern int __hash_page_4K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned int local); -extern int __hash_page_64K(unsigned long ea, unsigned long access, - unsigned long vsid, pte_t *ptep, unsigned long trap, - unsigned int local); -struct mm_struct; -extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); -extern int hash_huge_page(struct mm_struct *mm, unsigned long access, - unsigned long ea, unsigned long vsid, int local, - unsigned long trap); - -extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, - unsigned long pstart, unsigned long mode, - int psize); - -extern void htab_initialize(void); -extern void htab_initialize_secondary(void); -extern void hpte_init_native(void); -extern void hpte_init_lpar(void); -extern void hpte_init_iSeries(void); -extern void hpte_init_beat(void); - -extern void stabs_alloc(void); -extern void slb_initialize(void); -extern void slb_flush_and_rebolt(void); -extern void stab_initialize(unsigned long stab); - -#endif /* __ASSEMBLY__ */ - -/* - * VSID allocation - * - * We first generate a 36-bit "proto-VSID". For kernel addresses this - * is equal to the ESID, for user addresses it is: - * (context << 15) | (esid & 0x7fff) - * - * The two forms are distinguishable because the top bit is 0 for user - * addresses, whereas the top two bits are 1 for kernel addresses. - * Proto-VSIDs with the top two bits equal to 0b10 are reserved for - * now. - * - * The proto-VSIDs are then scrambled into real VSIDs with the - * multiplicative hash: - * - * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS - * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 - * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF - * - * This scramble is only well defined for proto-VSIDs below - * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are - * reserved. VSID_MULTIPLIER is prime, so in particular it is - * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. - * Because the modulus is 2^n-1 we can compute it efficiently without - * a divide or extra multiply (see below). - * - * This scheme has several advantages over older methods: - * - * - We have VSIDs allocated for every kernel address - * (i.e. everything above 0xC000000000000000), except the very top - * segment, which simplifies several things. - * - * - We allow for 15 significant bits of ESID and 20 bits of - * context for user addresses. i.e. 8T (43 bits) of address space for - * up to 1M contexts (although the page table structure and context - * allocation will need changes to take advantage of this). - * - * - The scramble function gives robust scattering in the hash - * table (at least based on some initial results). The previous - * method was more susceptible to pathological cases giving excessive - * hash collisions. - */ -/* - * WARNING - If you change these you must make sure the asm - * implementations in slb_allocate (slb_low.S), do_stab_bolted - * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly. - * - * You'll also need to change the precomputed VSID values in head.S - * which are used by the iSeries firmware. - */ - -#define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ -#define VSID_BITS 36 -#define VSID_MODULUS ((1UL<= \ - * 2^36-1, then r3+1 has the 2^36 bit set. So, if r3+1 has \ - * the bit clear, r3 already has the answer we want, if it \ - * doesn't, the answer is the low 36 bits of r3+1. So in all \ - * cases the answer is the low 36 bits of (r3 + ((r3+1) >> 36))*/\ - addi rx,rt,1; \ - srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ - add rt,rt,rx - - -#ifndef __ASSEMBLY__ - -typedef unsigned long mm_context_id_t; - -typedef struct { - mm_context_id_t id; - u16 user_psize; /* page size index */ - u16 sllp; /* SLB entry page size encoding */ -#ifdef CONFIG_HUGETLB_PAGE - u16 low_htlb_areas, high_htlb_areas; +/* 32-bit. FIXME: split up the 32-bit MMU types, and revise for + * arch/powerpc */ +# include #endif - unsigned long vdso_base; -} mm_context_t; - - -static inline unsigned long vsid_scramble(unsigned long protovsid) -{ -#if 0 - /* The code below is equivalent to this function for arguments - * < 2^VSID_BITS, which is all this should ever be called - * with. However gcc is not clever enough to compute the - * modulus (2^n-1) without a second multiply. */ - return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); -#else /* 1 */ - unsigned long x; - - x = protovsid * VSID_MULTIPLIER; - x = (x >> VSID_BITS) + (x & VSID_MODULUS); - return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; -#endif /* 1 */ -} - -/* This is only valid for addresses >= KERNELBASE */ -static inline unsigned long get_kernel_vsid(unsigned long ea) -{ - return vsid_scramble(ea >> SID_SHIFT); -} - -/* This is only valid for user addresses (which are below 2^41) */ -static inline unsigned long get_vsid(unsigned long context, unsigned long ea) -{ - return vsid_scramble((context << USER_ESID_BITS) - | (ea >> SID_SHIFT)); -} - -#define VSID_SCRAMBLE(pvsid) (((pvsid) * VSID_MULTIPLIER) % VSID_MODULUS) -#define KERNEL_VSID(ea) VSID_SCRAMBLE(GET_ESID(ea)) - -/* Physical address used by some IO functions */ -typedef unsigned long phys_addr_t; - - -#endif /* __ASSEMBLY */ -#endif /* CONFIG_PPC64 */ #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MMU_H_ */ -- cgit v1.2.3-59-g8ed1b From 8d8a0241eb019ce9648a77b55f9f76a834207cbb Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 26 Apr 2007 06:36:56 +1000 Subject: [POWERPC] Generic check_legacy_ioport check_legacy_ioport makes only sense on PREP, CHRP and pSeries. They may have an isa node with PS/2, parport, floppy and serial ports. Remove the check_legacy_ioport call from ppc_md, it's not needed anymore. Hardware capabilities come from the device-tree. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 34 ++++++++++++++++++++++++++++++--- arch/powerpc/platforms/cell/setup.c | 10 ---------- arch/powerpc/platforms/celleb/setup.c | 10 ---------- arch/powerpc/platforms/iseries/setup.c | 10 ---------- arch/powerpc/platforms/pasemi/setup.c | 7 ------- arch/powerpc/platforms/powermac/setup.c | 10 ---------- arch/powerpc/platforms/pseries/setup.c | 27 -------------------------- include/asm-powerpc/io.h | 7 ++++++- include/asm-powerpc/machdep.h | 3 --- 9 files changed, 37 insertions(+), 81 deletions(-) (limited to 'include') diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 3c8847b647fa..370803722e47 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -478,11 +478,39 @@ void probe_machine(void) printk(KERN_INFO "Using %s machine description\n", ppc_md.name); } +/* Match a class of boards, not a specific device configuration. */ int check_legacy_ioport(unsigned long base_port) { - if (ppc_md.check_legacy_ioport == NULL) - return 0; - return ppc_md.check_legacy_ioport(base_port); + struct device_node *parent, *np = NULL; + int ret = -ENODEV; + + switch(base_port) { + case I8042_DATA_REG: + np = of_find_node_by_type(NULL, "8042"); + break; + case FDC_BASE: /* FDC1 */ + np = of_find_node_by_type(NULL, "fdc"); + break; +#ifdef CONFIG_PPC_PREP + case _PIDXR: + case _PNPWRP: + case PNPBIOS_BASE: + /* implement me */ +#endif + default: + /* ipmi is supposed to fail here */ + break; + } + if (!np) + return ret; + parent = of_get_parent(np); + if (parent) { + if (strcmp(parent->type, "isa") == 0) + ret = 0; + of_node_put(parent); + } + of_node_put(np); + return ret; } EXPORT_SYMBOL(check_legacy_ioport); diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index 5c5fa34e59ee..54b96183cb64 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c @@ -190,15 +190,6 @@ static int __init cell_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int cell_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - define_machine(cell) { .name = "Cell", .probe = cell_probe, @@ -211,7 +202,6 @@ define_machine(cell) { .get_rtc_time = rtas_get_rtc_time, .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = cell_check_legacy_ioport, .progress = cell_progress, .init_IRQ = cell_init_irq, .pci_setup_phb = rtas_setup_phb, diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c index ab1db9dd1aa1..596ab2a788d4 100644 --- a/arch/powerpc/platforms/celleb/setup.c +++ b/arch/powerpc/platforms/celleb/setup.c @@ -128,15 +128,6 @@ static int __init celleb_probe(void) return 1; } -/* - * Cell has no legacy IO; anything calling this function has to - * fail or bad things will happen - */ -static int celleb_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - #ifdef CONFIG_KEXEC static void celleb_kexec_cpu_down(int crash, int secondary) { @@ -173,7 +164,6 @@ define_machine(celleb) { .get_rtc_time = beat_get_rtc_time, .set_rtc_time = beat_set_rtc_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = celleb_check_legacy_ioport, .progress = celleb_progress, .power_save = beat_power_save, .nvram_size = beat_nvram_get_size, diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index cce7e309340c..7f5dcee814d4 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -628,15 +628,6 @@ static void iseries_iounmap(volatile void __iomem *token) { } -/* - * iSeries has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int iseries_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init iseries_probe(void) { unsigned long root = of_get_flat_dt_root(); @@ -667,7 +658,6 @@ define_machine(iseries) { .calibrate_decr = generic_calibrate_decr, .progress = iSeries_progress, .probe = iseries_probe, - .check_legacy_ioport = iseries_check_legacy_ioport, .ioremap = iseries_ioremap, .iounmap = iseries_iounmap, /* XXX Implement enable_pmcs for iSeries */ diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index a7bf88e94c64..f88f0ec4c8cb 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c @@ -102,12 +102,6 @@ void __init pas_setup_arch(void) pasemi_idle_init(); } -/* No legacy IO on our parts */ -static int pas_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static __init void pas_init_IRQ(void) { struct device_node *np; @@ -252,7 +246,6 @@ define_machine(pas) { .restart = pas_restart, .get_boot_time = pas_get_boot_time, .calibrate_decr = generic_calibrate_decr, - .check_legacy_ioport = pas_check_legacy_ioport, .progress = pas_progress, .machine_check_exception = pas_machine_check_handler, .pci_irq_fixup = pas_pci_irq_fixup, diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 0444e07e8d7a..b820cabac697 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -635,15 +635,6 @@ static void __init pmac_init_early(void) #endif } -/* - * pmac has no legacy IO, anything calling this function has to - * fail or bad things will happen - */ -static int pmac_check_legacy_ioport(unsigned int baseport) -{ - return -ENODEV; -} - static int __init pmac_declare_of_platform_devices(void) { struct device_node *np; @@ -755,7 +746,6 @@ define_machine(powermac) { .get_rtc_time = pmac_get_rtc_time, .calibrate_decr = pmac_calibrate_decr, .feature_call = pmac_do_feature_call, - .check_legacy_ioport = pmac_check_legacy_ioport, .progress = udbg_progress, #ifdef CONFIG_PPC64 .pci_probe_mode = pmac_pci_probe_mode, diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index e2fcd2307e67..33eec2822c66 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -335,32 +335,6 @@ static void __init pSeries_init_early(void) DBG(" <- pSeries_init_early()\n"); } - -static int pSeries_check_legacy_ioport(unsigned int baseport) -{ - struct device_node *np; - -#define I8042_DATA_REG 0x60 -#define FDC_BASE 0x3f0 - - - switch(baseport) { - case I8042_DATA_REG: - np = of_find_node_by_type(NULL, "8042"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - case FDC_BASE: - np = of_find_node_by_type(NULL, "fdc"); - if (np == NULL) - return -ENODEV; - of_node_put(np); - break; - } - return 0; -} - /* * Called very early, MMU is off, device-tree isn't unflattened */ @@ -537,7 +511,6 @@ define_machine(pseries) { .set_rtc_time = rtas_set_rtc_time, .calibrate_decr = generic_calibrate_decr, .progress = rtas_progress, - .check_legacy_ioport = pSeries_check_legacy_ioport, .system_reset_exception = pSeries_system_reset_exception, .machine_check_exception = pSeries_machine_check_exception, }; diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h index 301c9bb308b1..350c9bdb31dc 100644 --- a/include/asm-powerpc/io.h +++ b/include/asm-powerpc/io.h @@ -11,7 +11,12 @@ /* Check of existence of legacy devices */ extern int check_legacy_ioport(unsigned long base_port); -#define PNPBIOS_BASE 0xf000 /* only relevant for PReP */ +#define I8042_DATA_REG 0x60 +#define FDC_BASE 0x3f0 +/* only relevant for PReP */ +#define _PIDXR 0x279 +#define _PNPWRP 0xa79 +#define PNPBIOS_BASE 0xf000 #include #include diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 1b04e5723548..b204926ce913 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -153,9 +153,6 @@ struct machdep_calls { */ long (*feature_call)(unsigned int feature, ...); - /* Check availability of legacy devices like i8042 */ - int (*check_legacy_ioport)(unsigned int baseport); - /* Get legacy PCI/IDE interrupt mapping */ int (*pci_get_legacy_ide_irq)(struct pci_dev *dev, int channel); -- cgit v1.2.3-59-g8ed1b From 5ff084f21da25ffcc5e0cb0293a0ea588cb46272 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 28 Apr 2007 05:50:00 +1000 Subject: [POWERPC] Merge common virtex header files The header files for the ml403 and ml300 are virtually identical, merge them into a single file. Signed-off-by: Grant Likely Signed-off-by: Paul Mackerras --- arch/ppc/platforms/4xx/virtex.h | 40 ++++++++++++++++++++-------- arch/ppc/platforms/4xx/xilinx_ml300.c | 1 + arch/ppc/platforms/4xx/xilinx_ml300.h | 45 -------------------------------- arch/ppc/platforms/4xx/xilinx_ml403.c | 1 + arch/ppc/platforms/4xx/xilinx_ml403.h | 49 ----------------------------------- include/asm-ppc/ibm4xx.h | 8 ++---- 6 files changed, 33 insertions(+), 111 deletions(-) delete mode 100644 arch/ppc/platforms/4xx/xilinx_ml300.h delete mode 100644 arch/ppc/platforms/4xx/xilinx_ml403.h (limited to 'include') diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h index c14325dfd7b1..e9f58a784314 100644 --- a/arch/ppc/platforms/4xx/virtex.h +++ b/arch/ppc/platforms/4xx/virtex.h @@ -1,22 +1,18 @@ /* - * arch/ppc/platforms/4xx/virtex.h + * Basic Virtex platform defines, included by * - * Include file that defines the Xilinx Virtex-II Pro processor + * 2005-2007 (c) Secret Lab Technologies Ltd. + * 2002-2004 (c) MontaVista Software, Inc. * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. */ #ifdef __KERNEL__ #ifndef __ASM_VIRTEX_H__ #define __ASM_VIRTEX_H__ -/* serial defines */ - #include /* Ugly, ugly, ugly! BASE_BAUD defined here to keep 8250.c happy. */ @@ -29,7 +25,29 @@ enum ppc_sys_devices { VIRTEX_UART, NUM_PPC_SYS_DEVS, }; -#endif +typedef struct board_info { + unsigned int bi_memsize; /* DRAM installed, in bytes */ + unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ + unsigned int bi_intfreq; /* Processor speed, in Hz */ + unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ + unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ +} bd_t; + +/* Some 4xx parts use a different timebase frequency from the internal clock. + * the Virtex 405 does not, so just use a macro to make tbfreq match intfreq +*/ +#define bi_tbfreq bi_intfreq + +extern const char* virtex_machine_name; +#define PPC4xx_MACHINE_NAME (virtex_machine_name) + +#endif /* !__ASSEMBLY__ */ + +/* We don't need anything mapped. Size of zero will accomplish that. */ +#define PPC4xx_ONB_IO_PADDR 0u +#define PPC4xx_ONB_IO_VADDR 0u +#define PPC4xx_ONB_IO_SIZE 0u + #endif /* __ASM_VIRTEX_H__ */ #endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index fb5f0b5e13d1..4e4aca43c890 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -68,6 +68,7 @@ struct ppc_sys_spec ppc_sys_specs[] = { }, }, }; +const char* virtex_machine_name = "ML300 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h deleted file mode 100644 index 3d57332ba820..000000000000 --- a/arch/ppc/platforms/4xx/xilinx_ml300.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Include file that defines the Xilinx ML300 evaluation board - * - * Author: MontaVista Software, Inc. - * source@mvista.com - * - * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the - * terms of the GNU General Public License version 2. This program is licensed - * "as is" without any warranty of any kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML300_H__ -#define __ASM_XILINX_ML300_H__ - -/* ML300 has a Xilinx Virtex-II Pro processor */ -#include - -#ifndef __ASSEMBLY__ - -#include - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML300 Reference System" - -#endif /* __ASM_XILINX_ML300_H__ */ -#endif /* __KERNEL__ */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c index cb3bf7a2bcbe..c98e40a8799f 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml403.c +++ b/arch/ppc/platforms/4xx/xilinx_ml403.c @@ -72,6 +72,7 @@ struct ppc_sys_spec ppc_sys_specs[] = { }, }, }; +const char* virtex_machine_name = "ML403 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.h b/arch/ppc/platforms/4xx/xilinx_ml403.h deleted file mode 100644 index 473596959902..000000000000 --- a/arch/ppc/platforms/4xx/xilinx_ml403.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * arch/ppc/platforms/4xx/xilinx_ml403.h - * - * Include file that defines the Xilinx ML403 reference design - * - * Author: Grant Likely - * - * 2005 (c) Secret Lab Technologies Ltd. - * 2002-2004 (c) MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_XILINX_ML403_H__ -#define __ASM_XILINX_ML403_H__ - -/* ML403 has a Xilinx Virtex-4 FPGA with a PPC405 hard core */ -#include - -#ifndef __ASSEMBLY__ - -#include - -typedef struct board_info { - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -/* We don't need anything mapped. Size of zero will accomplish that. */ -#define PPC4xx_ONB_IO_PADDR 0u -#define PPC4xx_ONB_IO_VADDR 0u -#define PPC4xx_ONB_IO_SIZE 0u - -#define PPC4xx_MACHINE_NAME "Xilinx ML403 Reference Design" - -#endif /* __ASM_XILINX_ML403_H__ */ -#endif /* __KERNEL__ */ diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h index 92fd02d7b177..ed6891af05d3 100644 --- a/include/asm-ppc/ibm4xx.h +++ b/include/asm-ppc/ibm4xx.h @@ -47,12 +47,8 @@ #include #endif -#if defined(CONFIG_XILINX_ML300) -#include -#endif - -#if defined(CONFIG_XILINX_ML403) -#include +#if defined(CONFIG_XILINX_VIRTEX) +#include #endif #ifndef __ASSEMBLY__ -- cgit v1.2.3-59-g8ed1b From 8c38fc2b7429b26105fe244890c8d5ab3043f099 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Sat, 28 Apr 2007 05:50:02 +1000 Subject: [POWERPC] Stop using ppc_sys for Xilinx Virtex boards The arch/ppc/syslib/ppc_sys.c infrastructure does not work well for the virtex ports. Move the ml300 and ml403 board ports over to use the new virtex_devices infrastructure. Signed-off-by: Grant Likely Acked-by: Peter Korsgaard Signed-off-by: Paul Mackerras --- arch/ppc/platforms/4xx/Makefile | 1 - arch/ppc/platforms/4xx/virtex.c | 56 ------------------------------ arch/ppc/platforms/4xx/virtex.h | 7 +--- arch/ppc/platforms/4xx/xilinx_ml300.c | 64 +++------------------------------- arch/ppc/platforms/4xx/xilinx_ml403.c | 65 +++-------------------------------- arch/ppc/syslib/Makefile | 3 +- include/asm-ppc/ppc_sys.h | 2 -- 7 files changed, 11 insertions(+), 187 deletions(-) delete mode 100644 arch/ppc/platforms/4xx/virtex.c (limited to 'include') diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile index fa6610bccaf9..723ad7985cc6 100644 --- a/arch/ppc/platforms/4xx/Makefile +++ b/arch/ppc/platforms/4xx/Makefile @@ -28,5 +28,4 @@ obj-$(CONFIG_440SP) += ibm440sp.o obj-$(CONFIG_440SPE) += ppc440spe.o obj-$(CONFIG_405EP) += ibm405ep.o obj-$(CONFIG_405GPR) += ibm405gpr.o -obj-$(CONFIG_XILINX_VIRTEX) += virtex.o diff --git a/arch/ppc/platforms/4xx/virtex.c b/arch/ppc/platforms/4xx/virtex.c deleted file mode 100644 index 133a83147199..000000000000 --- a/arch/ppc/platforms/4xx/virtex.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Virtex-II Pro & Virtex-4 FX common infrastructure - * - * Maintainer: Grant Likely - * - * Copyright 2005 Secret Lab Technologies Ltd. - * Copyright 2005 General Dynamics Canada Ltd. - * 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 - -#define XPAR_UART(num) { \ - .mapbase = XPAR_UARTNS550_##num##_BASEADDR + 3, \ - .irq = XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ - .iotype = UPIO_MEM, \ - .uartclk = XPAR_UARTNS550_##num##_CLOCK_FREQ_HZ, \ - .flags = UPF_BOOT_AUTOCONF, \ - .regshift = 2, \ - } - -struct plat_serial8250_port serial_platform_data[] = { -#ifdef XPAR_UARTNS550_0_BASEADDR - XPAR_UART(0), -#endif -#ifdef XPAR_UARTNS550_1_BASEADDR - XPAR_UART(1), -#endif -#ifdef XPAR_UARTNS550_2_BASEADDR - XPAR_UART(2), -#endif -#ifdef XPAR_UARTNS550_3_BASEADDR - XPAR_UART(3), -#endif - { }, /* terminated by empty record */ -}; - -struct platform_device ppc_sys_platform_devices[] = { - [VIRTEX_UART] = { - .name = "serial8250", - .id = 0, - .dev.platform_data = serial_platform_data, - }, -}; - diff --git a/arch/ppc/platforms/4xx/virtex.h b/arch/ppc/platforms/4xx/virtex.h index e9f58a784314..4fc76da2a4ba 100644 --- a/arch/ppc/platforms/4xx/virtex.h +++ b/arch/ppc/platforms/4xx/virtex.h @@ -19,13 +19,8 @@ #if !defined(BASE_BAUD) #define BASE_BAUD (0) /* dummy value; not used */ #endif - -/* Device type enumeration for platform bus definitions */ + #ifndef __ASSEMBLY__ -enum ppc_sys_devices { - VIRTEX_UART, NUM_PPC_SYS_DEVS, -}; - typedef struct board_info { unsigned int bi_memsize; /* DRAM installed, in bytes */ unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c index 4e4aca43c890..6e522fefc26f 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml300.c +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c @@ -18,9 +18,9 @@ #include #include #include -#include #include +#include #include /* @@ -53,25 +53,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML300 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; const char* virtex_machine_name = "ML300 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -96,52 +80,14 @@ ml300_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml300_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml300_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml300_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml300_setup_arch(void) { - ml300_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ - printk(KERN_INFO "Xilinx Virtex-II Pro port\n"); - printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); + printk(KERN_INFO "Xilinx ML300 Reference System (Virtex-II Pro)\n"); } /* Called after board_setup_irq from ppc4xx_init_IRQ(). */ @@ -157,8 +103,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml300_setup_arch; ppc_md.setup_io_mappings = ml300_map_io; ppc_md.init_IRQ = ml300_init_irq; @@ -168,7 +112,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml300_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/platforms/4xx/xilinx_ml403.c b/arch/ppc/platforms/4xx/xilinx_ml403.c index c98e40a8799f..bc3ace3762e7 100644 --- a/arch/ppc/platforms/4xx/xilinx_ml403.c +++ b/arch/ppc/platforms/4xx/xilinx_ml403.c @@ -1,11 +1,9 @@ /* - * arch/ppc/platforms/4xx/xilinx_ml403.c - * * Xilinx ML403 evaluation board initialization * * Author: Grant Likely * - * 2005 (c) Secret Lab Technologies Ltd. + * 2005-2007 (c) Secret Lab Technologies Ltd. * 2002-2004 (c) MontaVista Software, Inc. * * This file is licensed under the terms of the GNU General Public License @@ -22,9 +20,9 @@ #include #include #include -#include #include +#include #include /* @@ -57,25 +55,9 @@ * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c */ -/* Board specifications structures */ -struct ppc_sys_spec *cur_ppc_sys_spec; -struct ppc_sys_spec ppc_sys_specs[] = { - { - /* Only one entry, always assume the same design */ - .ppc_sys_name = "Xilinx ML403 Reference Design", - .mask = 0x00000000, - .value = 0x00000000, - .num_devices = 1, - .device_list = (enum ppc_sys_devices[]) - { - VIRTEX_UART, - }, - }, -}; const char* virtex_machine_name = "ML403 Reference Design"; #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) - static volatile unsigned *powerdown_base = (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; @@ -100,47 +82,10 @@ ml403_map_io(void) #endif } -/* Early serial support functions */ -static void __init -ml403_early_serial_init(int num, struct plat_serial8250_port *pdata) -{ -#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) - struct uart_port serial_req; - - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.mapbase = pdata->mapbase; - serial_req.membase = pdata->membase; - serial_req.irq = pdata->irq; - serial_req.uartclk = pdata->uartclk; - serial_req.regshift = pdata->regshift; - serial_req.iotype = pdata->iotype; - serial_req.flags = pdata->flags; - gen550_init(num, &serial_req); -#endif -} - -void __init -ml403_early_serial_map(void) -{ -#ifdef CONFIG_SERIAL_8250 - struct plat_serial8250_port *pdata; - int i = 0; - - pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(VIRTEX_UART); - while(pdata && pdata->flags) - { - pdata->membase = ioremap(pdata->mapbase, 0x100); - ml403_early_serial_init(i, pdata); - pdata++; - i++; - } -#endif /* CONFIG_SERIAL_8250 */ -} - void __init ml403_setup_arch(void) { - ml403_early_serial_map(); + virtex_early_serial_map(); ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ /* Identify the system */ @@ -160,8 +105,6 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { ppc4xx_init(r3, r4, r5, r6, r7); - identify_ppc_sys_by_id(mfspr(SPRN_PVR)); - ppc_md.setup_arch = ml403_setup_arch; ppc_md.setup_io_mappings = ml403_map_io; ppc_md.init_IRQ = ml403_init_irq; @@ -171,7 +114,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif #ifdef CONFIG_KGDB - ppc_md.early_serial_map = ml403_early_serial_map; + ppc_md.early_serial_map = virtex_early_serial_map; #endif } diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 09911118c675..95694159b226 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile @@ -18,7 +18,8 @@ obj-$(CONFIG_440SP) += ibm440gx_common.o ibm440sp_common.o obj-$(CONFIG_440SPE) += ibm440gx_common.o ibm440sp_common.o ppc440spe_pcie.o ifeq ($(CONFIG_4xx),y) ifeq ($(CONFIG_XILINX_VIRTEX),y) -obj-$(CONFIG_40x) += xilinx_pic.o ppc_sys.o +obj-$(CONFIG_40x) += xilinx_pic.o +obj-y += virtex_devices.o else ifeq ($(CONFIG_403),y) obj-$(CONFIG_40x) += ppc403_pic.o diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 40f197af6508..de99e92d627b 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h @@ -33,8 +33,6 @@ #include #elif defined(CONFIG_MPC10X_BRIDGE) #include -#elif defined(CONFIG_XILINX_VIRTEX) -#include #else #error "need definition of ppc_sys_devices" #endif -- cgit v1.2.3-59-g8ed1b From d169d140944a67edd6f88f78b65b3117059f4380 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 28 Apr 2007 08:00:03 +1000 Subject: [POWERPC] Declare enable_kernel_spe in a header This patch puts enable_kernel_spe into along with enable_kernel_altivec etc. Signed-off-by: Johannes Berg Signed-off-by: Paul Mackerras --- include/asm-powerpc/system.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h index f7b1227d6454..d3e0906ff2bc 100644 --- a/include/asm-powerpc/system.h +++ b/include/asm-powerpc/system.h @@ -131,6 +131,7 @@ extern void enable_kernel_altivec(void); extern void giveup_altivec(struct task_struct *); extern void load_up_altivec(struct task_struct *); extern int emulate_altivec(struct pt_regs *); +extern void enable_kernel_spe(void); extern void giveup_spe(struct task_struct *); extern void load_up_spe(struct task_struct *); extern int fix_alignment(struct pt_regs *); -- cgit v1.2.3-59-g8ed1b