Merge branch 'linux-2.6' into next
authorPaul Mackerras <paulus@samba.org>
Thu, 18 Dec 2008 00:06:12 +0000 (11:06 +1100)
committerPaul Mackerras <paulus@samba.org>
Thu, 18 Dec 2008 00:06:12 +0000 (11:06 +1100)
169 files changed:
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/Makefile
arch/powerpc/boot/dts/bamboo.dts
arch/powerpc/boot/dts/canyonlands.dts
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/boot/dts/kuroboxHD.dts
arch/powerpc/boot/dts/kuroboxHG.dts
arch/powerpc/boot/dts/lite5200.dts
arch/powerpc/boot/dts/lite5200b.dts
arch/powerpc/boot/dts/motionpro.dts
arch/powerpc/boot/dts/mpc8315erdb.dts
arch/powerpc/boot/dts/mpc8349emitx.dts
arch/powerpc/boot/dts/mpc8349emitxgp.dts
arch/powerpc/boot/dts/mpc8377_rdb.dts
arch/powerpc/boot/dts/mpc8378_rdb.dts
arch/powerpc/boot/dts/mpc8379_rdb.dts
arch/powerpc/boot/dts/mpc8572ds.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts [new file with mode: 0644]
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts [new file with mode: 0644]
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/boot/dts/tqm5200.dts
arch/powerpc/boot/libfdt-wrapper.c
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/byteorder.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/dma-mapping.h
arch/powerpc/include/asm/eeh.h
arch/powerpc/include/asm/highmem.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/local.h
arch/powerpc/include/asm/lppaca.h
arch/powerpc/include/asm/mmu-fsl-booke.h
arch/powerpc/include/asm/mmu_context.h
arch/powerpc/include/asm/mutex.h
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/pgalloc-32.h
arch/powerpc/include/asm/pgalloc-64.h
arch/powerpc/include/asm/pgalloc.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/ps3.h
arch/powerpc/include/asm/ps3av.h
arch/powerpc/include/asm/rtas.h
arch/powerpc/include/asm/sfp-machine.h
arch/powerpc/include/asm/smp.h
arch/powerpc/include/asm/spinlock.h
arch/powerpc/include/asm/synch.h
arch/powerpc/include/asm/system.h
arch/powerpc/include/asm/time.h
arch/powerpc/include/asm/tlbflush.h
arch/powerpc/include/asm/vdso_datapage.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/of_device.c
arch/powerpc/kernel/paca.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_32.c
arch/powerpc/kernel/pci_64.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_parse.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/rtas_pci.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/smp-tbsync.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kernel/vdso32/gettimeofday.S
arch/powerpc/kernel/vdso64/gettimeofday.S
arch/powerpc/kernel/vio.c
arch/powerpc/lib/copyuser_64.S
arch/powerpc/lib/dma-noncoherent.c
arch/powerpc/lib/memcpy_64.S
arch/powerpc/math-emu/Makefile
arch/powerpc/math-emu/fadd.c
arch/powerpc/math-emu/fcmpo.c
arch/powerpc/math-emu/fdiv.c
arch/powerpc/math-emu/fdivs.c
arch/powerpc/math-emu/fmadd.c
arch/powerpc/math-emu/fmadds.c
arch/powerpc/math-emu/fmsub.c
arch/powerpc/math-emu/fmsubs.c
arch/powerpc/math-emu/fmul.c
arch/powerpc/math-emu/fmuls.c
arch/powerpc/math-emu/fnmadd.c
arch/powerpc/math-emu/fnmadds.c
arch/powerpc/math-emu/fnmsub.c
arch/powerpc/math-emu/fnmsubs.c
arch/powerpc/math-emu/fsqrt.c
arch/powerpc/math-emu/fsqrts.c
arch/powerpc/math-emu/fsub.c
arch/powerpc/math-emu/fsubs.c
arch/powerpc/math-emu/math_efp.c [new file with mode: 0644]
arch/powerpc/mm/Makefile
arch/powerpc/mm/fault.c
arch/powerpc/mm/hash_low_32.S
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mmu_decl.h
arch/powerpc/mm/pgtable.c [new file with mode: 0644]
arch/powerpc/mm/pgtable_32.c
arch/powerpc/mm/tlb_hash32.c [moved from arch/powerpc/mm/tlb_32.c with 100% similarity]
arch/powerpc/mm/tlb_hash64.c [moved from arch/powerpc/mm/tlb_64.c with 75% similarity]
arch/powerpc/platforms/40x/ep405.c
arch/powerpc/platforms/40x/kilauea.c
arch/powerpc/platforms/40x/ppc40x_simple.c
arch/powerpc/platforms/44x/ebony.c
arch/powerpc/platforms/44x/ppc44x_simple.c
arch/powerpc/platforms/44x/sam440ep.c
arch/powerpc/platforms/52xx/mpc52xx_pci.c
arch/powerpc/platforms/82xx/pq2.c
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/smp.c [new file with mode: 0644]
arch/powerpc/platforms/86xx/Kconfig
arch/powerpc/platforms/86xx/Makefile
arch/powerpc/platforms/86xx/gef_gpio.c [new file with mode: 0644]
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/powermac/pci.c
arch/powerpc/platforms/powermac/setup.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/device-init.c
arch/powerpc/platforms/ps3/mm.c
arch/powerpc/platforms/ps3/setup.c
arch/powerpc/platforms/ps3/system-bus.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/pci_dlpar.c
arch/powerpc/platforms/pseries/xics.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/grackle.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_pci.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/qe_lib/ucc.c
arch/sparc/include/asm/device.h
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/bsr.c
drivers/char/hvc_console.c
drivers/char/hvc_console.h
drivers/char/hvc_iseries.c
drivers/char/hvc_udbg.c [new file with mode: 0644]
drivers/char/hvc_vio.c
drivers/char/hvcs.c
drivers/char/hvsi.c
drivers/macintosh/windfarm_smu_sat.c
drivers/of/base.c
drivers/of/gpio.c
drivers/of/of_i2c.c
drivers/pci/hotplug/rpadlpar_core.c
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
drivers/rapidio/rio-scan.c
drivers/serial/pmac_zilog.c
drivers/video/ps3fb.c
fs/proc/proc_devtree.c
include/linux/of.h
include/linux/of_gpio.h
include/linux/rio_drv.h

index 525c13a..be4f99b 100644 (file)
@@ -285,6 +285,10 @@ config IOMMU_VMERGE
 config IOMMU_HELPER
        def_bool PPC64
 
+config PPC_NEED_DMA_SYNC_OPS
+       def_bool y
+       depends on NOT_COHERENT_CACHE
+
 config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
        depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
index 15eb278..08f7cc0 100644 (file)
@@ -2,6 +2,15 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
+config PRINT_STACK_DEPTH
+       int "Stack depth to print" if DEBUG_KERNEL
+       default 64
+       help
+         This option allows you to set the stack depth that the kernel
+         prints in stack traces. This can be useful if your display is
+         too small and stack traces cause important information to
+         scroll off the screen.
+
 config DEBUG_STACKOVERFLOW
        bool "Check for stack overflows"
        depends on DEBUG_KERNEL
index 1f06670..72d17f5 100644 (file)
@@ -107,7 +107,6 @@ KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
 # (We use all available options to help semi-broken compilers)
 KBUILD_CFLAGS += $(call cc-option,-mno-spe)
 KBUILD_CFLAGS += $(call cc-option,-mspe=no)
-KBUILD_CFLAGS += $(call cc-option,-mabi=no-spe)
 
 # Enable unit-at-a-time mode when possible. It shrinks the
 # kernel considerably.
index 6ce0cc2..aa68911 100644 (file)
                         * later cannot be changed. Chip supports a second
                         * IO range but we don't use it for now
                         */
-                       ranges = <0x02000000 0x00000000 0xa0000000 0x00000000 0xa0000000 0x00000000 0x20000000
+                       ranges = <0x02000000 0x00000000 0xa0000000 0x00000000 0xa0000000 0x00000000 0x40000000
+                                 0x02000000 0x00000000 0x00000000 0x00000000 0xe0000000 0x00000000 0x00100000
                                  0x01000000 0x00000000 0x00000000 0x00000000 0xe8000000 0x00000000 0x00010000>;
 
                        /* Inbound 2GB range starting at 0 */
index 79fe412..8b5ba82 100644 (file)
@@ -40,6 +40,7 @@
                        d-cache-size = <32768>;
                        dcr-controller;
                        dcr-access-method = "native";
+                       next-level-cache = <&L2C0>;
                };
        };
 
                dcr-reg = <0x00c 0x002>;
        };
 
+       L2C0: l2c {
+               compatible = "ibm,l2-cache-460ex", "ibm,l2-cache";
+               dcr-reg = <0x020 0x008          /* Internal SRAM DCR's */
+                          0x030 0x008>;        /* L2 cache DCR's */
+               cache-line-size = <32>;         /* 32 bytes */
+               cache-size = <262144>;          /* L2, 256K */
+               interrupt-parent = <&UIC1>;
+               interrupts = <11 1>;
+       };
+
        plb {
                compatible = "ibm,plb-460ex", "ibm,plb4";
                #address-cells = <2>;
                         * later cannot be changed
                         */
                        ranges = <0x02000000 0x00000000 0x80000000 0x0000000d 0x80000000 0x00000000 0x80000000
+                                 0x02000000 0x00000000 0x00000000 0x0000000c 0x0ee00000 0x00000000 0x00100000
                                  0x01000000 0x00000000 0x00000000 0x0000000c 0x08000000 0x00000000 0x00010000>;
 
                        /* Inbound 2GB range starting at 0 */
                         * later cannot be changed
                         */
                        ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x00000000 0x00000000 0x80000000
+                                 0x02000000 0x00000000 0x00000000 0x0000000f 0x00000000 0x00000000 0x00100000
                                  0x01000000 0x00000000 0x00000000 0x0000000f 0x80000000 0x00000000 0x00010000>;
 
                        /* Inbound 2GB range starting at 0 */
                         * later cannot be changed
                         */
                        ranges = <0x02000000 0x00000000 0x80000000 0x0000000e 0x80000000 0x00000000 0x80000000
+                                 0x02000000 0x00000000 0x00000000 0x0000000f 0x00100000 0x00000000 0x00100000
                                  0x01000000 0x00000000 0x00000000 0x0000000f 0x80010000 0x00000000 0x00010000>;
 
                        /* Inbound 2GB range starting at 0 */
index e48cfa7..9708b34 100644 (file)
                        interrupt-parent = <&mpic>;
 
                };
+               gef_gpio: gpio@7,14000 {
+                       #gpio-cells = <2>;
+                       compatible = "gef,sbc610-gpio";
+                       reg = <0x7 0x14000 0x24>;
+                       gpio-controller;
+               };
        };
 
        soc@fef00000 {
                        interrupt-parent = <&mpic>;
                        dfsrr;
 
+                       rtc@51 {
+                               compatible = "epson,rx8581";
+                               reg = <0x00000051>;
+                       };
+
                        eti@6b {
                                compatible = "dallas,ds1682";
                                reg = <0x6b>;
index 2e5a1a1..8d725d1 100644 (file)
@@ -76,7 +76,6 @@ XXXX add flash parts, rtc, ??
                        interrupt-parent = <&mpic>;
 
                        rtc@32 {
-                               device_type = "rtc";
                                compatible = "ricoh,rs5c372a";
                                reg = <0x32>;
                        };
index e4916e6..b13a11e 100644 (file)
@@ -76,7 +76,6 @@ XXXX add flash parts, rtc, ??
                        interrupt-parent = <&mpic>;
 
                        rtc@32 {
-                               device_type = "rtc";
                                compatible = "ricoh,rs5c372a";
                                reg = <0x32>;
                        };
index 2cf9a87..3f7a5dc 100644 (file)
 
                rtc@800 {       // Real time clock
                        compatible = "fsl,mpc5200-rtc";
-                       device_type = "rtc";
                        reg = <0x800 0x100>;
                        interrupts = <1 5 0 1 6 0>;
                        interrupt-parent = <&mpc5200_pic>;
index 7bd5b9c..63e3bb4 100644 (file)
 
                rtc@800 {       // Real time clock
                        compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-                       device_type = "rtc";
                        reg = <0x800 0x100>;
                        interrupts = <1 5 0 1 6 0>;
                        interrupt-parent = <&mpc5200_pic>;
index 9e3c921..52ba6f9 100644 (file)
                        fsl5200-clocking;
 
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                        };
index 6b85067..d3d3097 100644 (file)
                        interrupt-parent = <&ipic>;
                        dfsrr;
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                        };
index 4bdbaf4..5ba5c66 100644 (file)
@@ -85,7 +85,6 @@
                        dfsrr;
 
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                                interrupts = <18 0x8>;
index fa40647..fd4bbc4 100644 (file)
@@ -83,7 +83,6 @@
                        dfsrr;
 
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                                interrupts = <18 0x8>;
index 435ef3d..9fe8e4c 100644 (file)
                        interrupt-parent = <&ipic>;
                        dfsrr;
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                        };
index b11e68f..3a6d528 100644 (file)
                        interrupt-parent = <&ipic>;
                        dfsrr;
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                        };
index 337af6e..ee64def 100644 (file)
                        interrupt-parent = <&ipic>;
                        dfsrr;
                        rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1339";
                                reg = <0x68>;
                        };
index 5c69b2f..a10506e 100644 (file)
                device_type = "memory";
        };
 
+       localbus@ffe05000 {
+               #address-cells = <2>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc8572-elbc", "fsl,elbc", "simple-bus";
+               reg = <0 0xffe05000 0 0x1000>;
+               interrupts = <19 2>;
+               interrupt-parent = <&mpic>;
+
+               ranges = <0x0 0x0 0x0 0xe8000000 0x08000000
+                         0x1 0x0 0x0 0xe0000000 0x08000000
+                         0x2 0x0 0x0 0xffa00000 0x00040000
+                         0x3 0x0 0x0 0xffdf0000 0x00008000
+                         0x4 0x0 0x0 0xffa40000 0x00040000
+                         0x5 0x0 0x0 0xffa80000 0x00040000
+                         0x6 0x0 0x0 0xffac0000 0x00040000>;
+
+               nor@0,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "cfi-flash";
+                       reg = <0x0 0x0 0x8000000>;
+                       bank-width = <2>;
+                       device-width = <1>;
+
+                       ramdisk@0 {
+                               reg = <0x0 0x03000000>;
+                               readl-only;
+                       };
+
+                       diagnostic@3000000 {
+                               reg = <0x03000000 0x00e00000>;
+                               read-only;
+                       };
+
+                       dink@3e00000 {
+                               reg = <0x03e00000 0x00200000>;
+                               read-only;
+                       };
+
+                       kernel@4000000 {
+                               reg = <0x04000000 0x00400000>;
+                               read-only;
+                       };
+
+                       jffs2@4400000 {
+                               reg = <0x04400000 0x03b00000>;
+                       };
+
+                       dtb@7f00000 {
+                               reg = <0x07f00000 0x00080000>;
+                               read-only;
+                       };
+
+                       u-boot@7f80000 {
+                               reg = <0x07f80000 0x00080000>;
+                               read-only;
+                       };
+               };
+
+               nand@2,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,mpc8572-fcm-nand",
+                                    "fsl,elbc-fcm-nand";
+                       reg = <0x2 0x0 0x40000>;
+
+                       u-boot@0 {
+                               reg = <0x0 0x02000000>;
+                               read-only;
+                       };
+
+                       jffs2@2000000 {
+                               reg = <0x02000000 0x10000000>;
+                       };
+
+                       ramdisk@12000000 {
+                               reg = <0x12000000 0x08000000>;
+                               read-only;
+                       };
+
+                       kernel@1a000000 {
+                               reg = <0x1a000000 0x04000000>;
+                       };
+
+                       dtb@1e000000 {
+                               reg = <0x1e000000 0x01000000>;
+                               read-only;
+                       };
+
+                       empty@1f000000 {
+                               reg = <0x1f000000 0x21000000>;
+                       };
+               };
+
+               nand@4,0 {
+                       compatible = "fsl,mpc8572-fcm-nand",
+                                    "fsl,elbc-fcm-nand";
+                       reg = <0x4 0x0 0x40000>;
+               };
+
+               nand@5,0 {
+                       compatible = "fsl,mpc8572-fcm-nand",
+                                    "fsl,elbc-fcm-nand";
+                       reg = <0x5 0x0 0x40000>;
+               };
+
+               nand@6,0 {
+                       compatible = "fsl,mpc8572-fcm-nand",
+                                    "fsl,elbc-fcm-nand";
+                       reg = <0x6 0x0 0x40000>;
+               };
+       };
+
        soc8572@ffe00000 {
                #address-cells = <1>;
                #size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
new file mode 100644 (file)
index 0000000..c114c4e
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * MPC8572 DS Core0 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts file allows core0 to have memory, l2, i2c, dma1, global-util, eth0,
+ * eth1, crypto, pci0, pci1.
+ *
+ * Copyright 2007, 2008 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.
+ */
+
+/dts-v1/;
+/ {
+       model = "fsl,MPC8572DS";
+       compatible = "fsl,MPC8572DS", "fsl,MPC8572DS-CAMP";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+               serial0 = &serial0;
+               pci0 = &pci0;
+               pci1 = &pci1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8572@0 {
+                       device_type = "cpu";
+                       reg = <0x0>;
+                       d-cache-line-size = <32>;       // 32 bytes
+                       i-cache-line-size = <32>;       // 32 bytes
+                       d-cache-size = <0x8000>;                // L1, 32K
+                       i-cache-size = <0x8000>;                // L1, 32K
+                       timebase-frequency = <0>;
+                       bus-frequency = <0>;
+                       clock-frequency = <0>;
+                       next-level-cache = <&L2>;
+               };
+
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x0>;        // Filled by U-Boot
+       };
+
+       soc8572@ffe00000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "simple-bus";
+               ranges = <0x0 0xffe00000 0x100000>;
+               reg = <0xffe00000 0x1000>;      // CCSRBAR & soc regs, remove once parse code for immrbase fixed
+               bus-frequency = <0>;            // Filled out by uboot.
+
+               memory-controller@2000 {
+                       compatible = "fsl,mpc8572-memory-controller";
+                       reg = <0x2000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <18 2>;
+               };
+
+               memory-controller@6000 {
+                       compatible = "fsl,mpc8572-memory-controller";
+                       reg = <0x6000 0x1000>;
+                       interrupt-parent = <&mpic>;
+                       interrupts = <18 2>;
+               };
+
+               L2: l2-cache-controller@20000 {
+                       compatible = "fsl,mpc8572-l2-cache-controller";
+                       reg = <0x20000 0x1000>;
+                       cache-line-size = <32>; // 32 bytes
+                       cache-size = <0x80000>; // L2, 512K
+                       interrupt-parent = <&mpic>;
+                       interrupts = <16 2>;
+               };
+
+               i2c@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <0>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3000 0x100>;
+                       interrupts = <43 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
+               i2c@3100 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       cell-index = <1>;
+                       compatible = "fsl-i2c";
+                       reg = <0x3100 0x100>;
+                       interrupts = <43 2>;
+                       interrupt-parent = <&mpic>;
+                       dfsrr;
+               };
+
+               dma@21300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+                       reg = <0x21300 0x4>;
+                       ranges = <0x0 0x21100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <20 2>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <21 2>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <22 2>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <23 2>;
+                       };
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <0x24520 0x20>;
+
+                       phy0: ethernet-phy@0 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <10 1>;
+                               reg = <0x0>;
+                       };
+                       phy1: ethernet-phy@1 {
+                               interrupt-parent = <&mpic>;
+                               interrupts = <10 1>;
+                               reg = <0x1>;
+                       };
+               };
+
+               enet0: ethernet@24000 {
+                       cell-index = <0>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x24000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <29 2 30 2 34 2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy0>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               enet1: ethernet@25000 {
+                       cell-index = <1>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x25000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <35 2 36 2 40 2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy1>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               serial0: serial@4500 {
+                       cell-index = <0>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4500 0x100>;
+                       clock-frequency = <0>;
+               };
+
+               global-utilities@e0000 {        //global utilities block
+                       compatible = "fsl,mpc8572-guts";
+                       reg = <0xe0000 0x1000>;
+                       fsl,has-rstcr;
+               };
+
+               crypto@30000 {
+                       compatible = "fsl,sec3.0", "fsl,sec2.4", "fsl,sec2.2",
+                                    "fsl,sec2.1", "fsl,sec2.0";
+                       reg = <0x30000 0x10000>;
+                       interrupts = <45 2 58 2>;
+                       interrupt-parent = <&mpic>;
+                       fsl,num-channels = <4>;
+                       fsl,channel-fifo-len = <24>;
+                       fsl,exec-units-mask = <0x9fe>;
+                       fsl,descriptor-types-mask = <0x3ab0ebf>;
+               };
+
+               mpic: pic@40000 {
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                       protected-sources = <
+                       31 32 33 37 38 39       /* enet2 enet3 */
+                       76 77 78 79 27 42       /* dma2 pci2 serial*/
+                       0xe0 0xe1 0xe2 0xe3     /* msi */
+                       0xe4 0xe5 0xe6 0xe7
+                       >;
+               };
+       };
+
+       pci0: pcie@ffe08000 {
+               cell-index = <0>;
+               compatible = "fsl,mpc8548-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xffe08000 0x1000>;
+               bus-range = <0 255>;
+               ranges = <0x2000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x0 0xffc00000 0x0 0x10000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <24 2>;
+               interrupt-map-mask = <0xff00 0x0 0x0 0x7>;
+               interrupt-map = <
+                       /* IDSEL 0x11 func 0 - PCI slot 1 */
+                       0x8800 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8800 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8800 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8800 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 1 - PCI slot 1 */
+                       0x8900 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8900 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8900 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8900 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 2 - PCI slot 1 */
+                       0x8a00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8a00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8a00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8a00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 3 - PCI slot 1 */
+                       0x8b00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8b00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8b00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8b00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 4 - PCI slot 1 */
+                       0x8c00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8c00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8c00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8c00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 5 - PCI slot 1 */
+                       0x8d00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8d00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8d00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8d00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 6 - PCI slot 1 */
+                       0x8e00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8e00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8e00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8e00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x11 func 7 - PCI slot 1 */
+                       0x8f00 0x0 0x0 0x1 &mpic 0x2 0x1
+                       0x8f00 0x0 0x0 0x2 &mpic 0x3 0x1
+                       0x8f00 0x0 0x0 0x3 &mpic 0x4 0x1
+                       0x8f00 0x0 0x0 0x4 &mpic 0x1 0x1
+
+                       /* IDSEL 0x12 func 0 - PCI slot 2 */
+                       0x9000 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9000 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9000 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9000 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 1 - PCI slot 2 */
+                       0x9100 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9100 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9100 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9100 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 2 - PCI slot 2 */
+                       0x9200 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9200 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9200 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9200 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 3 - PCI slot 2 */
+                       0x9300 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9300 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9300 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9300 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 4 - PCI slot 2 */
+                       0x9400 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9400 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9400 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9400 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 5 - PCI slot 2 */
+                       0x9500 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9500 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9500 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9500 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 6 - PCI slot 2 */
+                       0x9600 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9600 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9600 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9600 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       /* IDSEL 0x12 func 7 - PCI slot 2 */
+                       0x9700 0x0 0x0 0x1 &mpic 0x3 0x1
+                       0x9700 0x0 0x0 0x2 &mpic 0x4 0x1
+                       0x9700 0x0 0x0 0x3 &mpic 0x1 0x1
+                       0x9700 0x0 0x0 0x4 &mpic 0x2 0x1
+
+                       // IDSEL 0x1c  USB
+                       0xe000 0x0 0x0 0x1 &i8259 0xc 0x2
+                       0xe100 0x0 0x0 0x2 &i8259 0x9 0x2
+                       0xe200 0x0 0x0 0x3 &i8259 0xa 0x2
+                       0xe300 0x0 0x0 0x4 &i8259 0xb 0x2
+
+                       // IDSEL 0x1d  Audio
+                       0xe800 0x0 0x0 0x1 &i8259 0x6 0x2
+
+                       // IDSEL 0x1e Legacy
+                       0xf000 0x0 0x0 0x1 &i8259 0x7 0x2
+                       0xf100 0x0 0x0 0x1 &i8259 0x7 0x2
+
+                       // IDSEL 0x1f IDE/SATA
+                       0xf800 0x0 0x0 0x1 &i8259 0xe 0x2
+                       0xf900 0x0 0x0 0x1 &i8259 0x5 0x2
+
+                       >;
+
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x2000000 0x0 0x80000000
+                                 0x2000000 0x0 0x80000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+                       uli1575@0 {
+                               reg = <0x0 0x0 0x0 0x0 0x0>;
+                               #size-cells = <2>;
+                               #address-cells = <3>;
+                               ranges = <0x2000000 0x0 0x80000000
+                                         0x2000000 0x0 0x80000000
+                                         0x0 0x20000000
+
+                                         0x1000000 0x0 0x0
+                                         0x1000000 0x0 0x0
+                                         0x0 0x100000>;
+                               isa@1e {
+                                       device_type = "isa";
+                                       #interrupt-cells = <2>;
+                                       #size-cells = <1>;
+                                       #address-cells = <2>;
+                                       reg = <0xf000 0x0 0x0 0x0 0x0>;
+                                       ranges = <0x1 0x0 0x1000000 0x0 0x0
+                                                 0x1000>;
+                                       interrupt-parent = <&i8259>;
+
+                                       i8259: interrupt-controller@20 {
+                                               reg = <0x1 0x20 0x2
+                                                      0x1 0xa0 0x2
+                                                      0x1 0x4d0 0x2>;
+                                               interrupt-controller;
+                                               device_type = "interrupt-controller";
+                                               #address-cells = <0>;
+                                               #interrupt-cells = <2>;
+                                               compatible = "chrp,iic";
+                                               interrupts = <9 2>;
+                                               interrupt-parent = <&mpic>;
+                                       };
+
+                                       i8042@60 {
+                                               #size-cells = <0>;
+                                               #address-cells = <1>;
+                                               reg = <0x1 0x60 0x1 0x1 0x64 0x1>;
+                                               interrupts = <1 3 12 3>;
+                                               interrupt-parent =
+                                                       <&i8259>;
+
+                                               keyboard@0 {
+                                                       reg = <0x0>;
+                                                       compatible = "pnpPNP,303";
+                                               };
+
+                                               mouse@1 {
+                                                       reg = <0x1>;
+                                                       compatible = "pnpPNP,f03";
+                                               };
+                                       };
+
+                                       rtc@70 {
+                                               compatible = "pnpPNP,b00";
+                                               reg = <0x1 0x70 0x2>;
+                                       };
+
+                                       gpio@400 {
+                                               reg = <0x1 0x400 0x80>;
+                                       };
+                               };
+                       };
+               };
+
+       };
+
+       pci1: pcie@ffe09000 {
+               cell-index = <1>;
+               compatible = "fsl,mpc8548-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xffe09000 0x1000>;
+               bus-range = <0 255>;
+               ranges = <0x2000000 0x0 0xa0000000 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x0 0xffc10000 0x0 0x10000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <26 2>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0x0 0x0 0x1 &mpic 0x4 0x1
+                       0000 0x0 0x0 0x2 &mpic 0x5 0x1
+                       0000 0x0 0x0 0x3 &mpic 0x6 0x1
+                       0000 0x0 0x0 0x4 &mpic 0x7 0x1
+                       >;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x2000000 0x0 0xa0000000
+                                 0x2000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
diff --git a/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts b/arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
new file mode 100644 (file)
index 0000000..04ecda1
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * MPC8572 DS Core1 Device Tree Source in CAMP mode.
+ *
+ * In CAMP mode, each core needs to have its own dts. Only mpic and L2 cache
+ * can be shared, all the other devices must be assigned to one core only.
+ * This dts allows core1 to have l2, dma2, eth2, eth3, pci2, msi.
+ *
+ * Please note to add "-b 1" for core1's dts compiling.
+ *
+ * Copyright 2007, 2008 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.
+ */
+
+/dts-v1/;
+/ {
+       model = "fsl,MPC8572DS";
+       compatible = "fsl,MPC8572DS", "fsl,MPC8572DS-CAMP";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet2 = &enet2;
+               ethernet3 = &enet3;
+               serial0 = &serial0;
+               pci2 = &pci2;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,8572@1 {
+                       device_type = "cpu";
+                       reg = <0x1>;
+                       d-cache-line-size = <32>;       // 32 bytes
+                       i-cache-line-size = <32>;       // 32 bytes
+                       d-cache-size = <0x8000>;                // L1, 32K
+                       i-cache-size = <0x8000>;                // L1, 32K
+                       timebase-frequency = <0>;
+                       bus-frequency = <0>;
+                       clock-frequency = <0>;
+                       next-level-cache = <&L2>;
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x0 0x0>;        // Filled by U-Boot
+       };
+
+       soc8572@ffe00000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               device_type = "soc";
+               compatible = "simple-bus";
+               ranges = <0x0 0xffe00000 0x100000>;
+               reg = <0xffe00000 0x1000>;      // CCSRBAR & soc regs, remove once parse code for immrbase fixed
+               bus-frequency = <0>;            // Filled out by uboot.
+
+               L2: l2-cache-controller@20000 {
+                       compatible = "fsl,mpc8572-l2-cache-controller";
+                       reg = <0x20000 0x1000>;
+                       cache-line-size = <32>; // 32 bytes
+                       cache-size = <0x80000>; // L2, 512K
+                       interrupt-parent = <&mpic>;
+               };
+
+               dma@c300 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,mpc8572-dma", "fsl,eloplus-dma";
+                       reg = <0xc300 0x4>;
+                       ranges = <0x0 0xc100 0x200>;
+                       cell-index = <0>;
+                       dma-channel@0 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x0 0x80>;
+                               cell-index = <0>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <76 2>;
+                       };
+                       dma-channel@80 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x80 0x80>;
+                               cell-index = <1>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <77 2>;
+                       };
+                       dma-channel@100 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x100 0x80>;
+                               cell-index = <2>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <78 2>;
+                       };
+                       dma-channel@180 {
+                               compatible = "fsl,mpc8572-dma-channel",
+                                               "fsl,eloplus-dma-channel";
+                               reg = <0x180 0x80>;
+                               cell-index = <3>;
+                               interrupt-parent = <&mpic>;
+                               interrupts = <79 2>;
+                       };
+               };
+
+               mdio@24520 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,gianfar-mdio";
+                       reg = <0x24520 0x20>;
+
+                       phy2: ethernet-phy@2 {
+                               interrupt-parent = <&mpic>;
+                               reg = <0x2>;
+                       };
+                       phy3: ethernet-phy@3 {
+                               interrupt-parent = <&mpic>;
+                               reg = <0x3>;
+                       };
+               };
+
+               enet2: ethernet@26000 {
+                       cell-index = <2>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x26000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <31 2 32 2 33 2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy2>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               enet3: ethernet@27000 {
+                       cell-index = <3>;
+                       device_type = "network";
+                       model = "eTSEC";
+                       compatible = "gianfar";
+                       reg = <0x27000 0x1000>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <37 2 38 2 39 2>;
+                       interrupt-parent = <&mpic>;
+                       phy-handle = <&phy3>;
+                       phy-connection-type = "rgmii-id";
+               };
+
+               msi@41600 {
+                       compatible = "fsl,mpc8572-msi", "fsl,mpic-msi";
+                       reg = <0x41600 0x80>;
+                       msi-available-ranges = <0 0x100>;
+                       interrupts = <
+                               0xe0 0
+                               0xe1 0
+                               0xe2 0
+                               0xe3 0
+                               0xe4 0
+                               0xe5 0
+                               0xe6 0
+                               0xe7 0>;
+                       interrupt-parent = <&mpic>;
+               };
+
+               serial0: serial@4600 {
+                       cell-index = <1>;
+                       device_type = "serial";
+                       compatible = "ns16550";
+                       reg = <0x4600 0x100>;
+                       clock-frequency = <0>;
+               };
+
+               mpic: pic@40000 {
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <2>;
+                       reg = <0x40000 0x40000>;
+                       compatible = "chrp,open-pic";
+                       device_type = "open-pic";
+                       protected-sources = <
+                       18 16 10 42 45 58       /* MEM L2 mdio serial crypto */
+                       29 30 34 35 36 40       /* enet0 enet1 */
+                       24 26 20 21 22 23       /* pcie0 pcie1 dma1 */
+                       43                      /* i2c */
+                       0x1 0x2 0x3 0x4         /* pci slot */
+                       0x9 0xa 0xb 0xc         /* usb */
+                       0x6 0x7 0xe 0x5         /* Audio elgacy SATA */
+                       >;
+               };
+       };
+
+       pci2: pcie@ffe0a000 {
+               cell-index = <2>;
+               compatible = "fsl,mpc8548-pcie";
+               device_type = "pci";
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               reg = <0xffe0a000 0x1000>;
+               bus-range = <0 255>;
+               ranges = <0x2000000 0x0 0xc0000000 0xc0000000 0x0 0x20000000
+                         0x1000000 0x0 0x0 0xffc20000 0x0 0x10000>;
+               clock-frequency = <33333333>;
+               interrupt-parent = <&mpic>;
+               interrupts = <27 2>;
+               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+               interrupt-map = <
+                       /* IDSEL 0x0 */
+                       0000 0x0 0x0 0x1 &mpic 0x0 0x1
+                       0000 0x0 0x0 0x2 &mpic 0x1 0x1
+                       0000 0x0 0x0 0x3 &mpic 0x2 0x1
+                       0000 0x0 0x0 0x4 &mpic 0x3 0x1
+                       >;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       #size-cells = <2>;
+                       #address-cells = <3>;
+                       device_type = "pci";
+                       ranges = <0x2000000 0x0 0xc0000000
+                                 0x2000000 0x0 0xc0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
index 7c1bb95..be2c11c 100644 (file)
 
                rtc@800 {       // Real time clock
                        compatible = "fsl,mpc5200b-rtc","fsl,mpc5200-rtc";
-                       device_type = "rtc";
                        reg = <0x800 0x100>;
                        interrupts = <0x1 0x5 0x0 0x1 0x6 0x0>;
                        interrupt-parent = <&mpc5200_pic>;
                        interrupt-parent = <&mpc5200_pic>;
                        fsl5200-clocking;
                        rtc@51 {
-                               device_type = "rtc";
                                compatible = "nxp,pcf8563";
                                reg = <0x51>;
                        };
index 3008bf8..906302e 100644 (file)
                        fsl5200-clocking;
 
                         rtc@68 {
-                               device_type = "rtc";
                                compatible = "dallas,ds1307";
                                reg = <0x68>;
                        };
index 9276327..bb8b9b3 100644 (file)
@@ -185,7 +185,7 @@ void fdt_init(void *blob)
 
        /* Make sure the dt blob is the right version and so forth */
        fdt = blob;
-       bufsize = fdt_totalsize(fdt) + 4;
+       bufsize = fdt_totalsize(fdt) + EXPAND_GRANULARITY;
        buf = malloc(bufsize);
        if(!buf)
                fatal("malloc failed. can't relocate the device tree\n\r");
index 07ccaf8..cd1ffa4 100644 (file)
@@ -1397,8 +1397,11 @@ CONFIG_USB_STORAGE=y
 # CONFIG_ACCESSIBILITY is not set
 # CONFIG_INFINIBAND is not set
 # CONFIG_EDAC is not set
-CONFIG_RTC_LIB=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
 
 #
 # RTC interfaces
@@ -1424,6 +1427,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
+CONFIG_RTC_DRV_RX8581=y
 
 #
 # SPI RTC drivers
index cfc94cf..034a1fb 100644 (file)
@@ -267,7 +267,7 @@ CONFIG_PCI_SYSCALL=y
 # CONFIG_PCIEPORTBUS is not set
 CONFIG_ARCH_SUPPORTS_MSI=y
 # CONFIG_PCI_MSI is not set
-CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_LEGACY is not set
 # CONFIG_PCI_DEBUG is not set
 # CONFIG_PCCARD is not set
 # CONFIG_HOTPLUG_PCI is not set
@@ -354,7 +354,7 @@ CONFIG_IPV6_NDISC_NODETYPE=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
+CONFIG_BRIDGE=m
 # CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
 # CONFIG_DECNET is not set
@@ -579,7 +579,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_BONDING is not set
 # CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
 # CONFIG_VETH is not set
 # CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
@@ -1001,11 +1001,11 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 # CONFIG_USB_TMC is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
 #
 
 #
-# may also be needed; see USB_STORAGE Help for more information
+# see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
@@ -1418,6 +1418,6 @@ CONFIG_CRYPTO_LZO=m
 # CONFIG_PPC_CLOCK is not set
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM=y
-CONFIG_KVM_BOOKE_HOST=y
+CONFIG_KVM_440=y
 # CONFIG_VIRTIO_PCI is not set
 # CONFIG_VIRTIO_BALLOON is not set
index f3fc733..499be5b 100644 (file)
@@ -111,7 +111,7 @@ static __inline__ void atomic_inc(atomic_t *v)
        bne-    1b"
        : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc");
+       : "cc", "xer");
 }
 
 static __inline__ int atomic_inc_return(atomic_t *v)
@@ -128,7 +128,7 @@ static __inline__ int atomic_inc_return(atomic_t *v)
        ISYNC_ON_SMP
        : "=&r" (t)
        : "r" (&v->counter)
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
@@ -155,7 +155,7 @@ static __inline__ void atomic_dec(atomic_t *v)
        bne-    1b"
        : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc");
+       : "cc", "xer");
 }
 
 static __inline__ int atomic_dec_return(atomic_t *v)
@@ -172,7 +172,7 @@ static __inline__ int atomic_dec_return(atomic_t *v)
        ISYNC_ON_SMP
        : "=&r" (t)
        : "r" (&v->counter)
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
@@ -346,7 +346,7 @@ static __inline__ void atomic64_inc(atomic64_t *v)
        bne-    1b"
        : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc");
+       : "cc", "xer");
 }
 
 static __inline__ long atomic64_inc_return(atomic64_t *v)
@@ -362,7 +362,7 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
        ISYNC_ON_SMP
        : "=&r" (t)
        : "r" (&v->counter)
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
@@ -388,7 +388,7 @@ static __inline__ void atomic64_dec(atomic64_t *v)
        bne-    1b"
        : "=&r" (t), "+m" (v->counter)
        : "r" (&v->counter)
-       : "cc");
+       : "cc", "xer");
 }
 
 static __inline__ long atomic64_dec_return(atomic64_t *v)
@@ -404,7 +404,7 @@ static __inline__ long atomic64_dec_return(atomic64_t *v)
        ISYNC_ON_SMP
        : "=&r" (t)
        : "r" (&v->counter)
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
@@ -431,7 +431,7 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
        "\n\
 2:"    : "=&r" (t)
        : "r" (&v->counter)
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
index e55d1f6..64e1fdc 100644 (file)
@@ -3,6 +3,7 @@
 #ifdef __KERNEL__
 
 #include <asm/asm-compat.h>
+
 /*
  * Define an illegal instr to trap on the bug.
  * We don't use 0 because that marks the end of a function
@@ -14,6 +15,7 @@
 #ifdef CONFIG_BUG
 
 #ifdef __ASSEMBLY__
+#include <asm/asm-offsets.h>
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 .macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"a"
@@ -26,7 +28,7 @@
         .previous
 .endm
 #else
- .macro EMIT_BUG_ENTRY addr,file,line,flags
+.macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"a"
 5001:   PPC_LONG \addr
         .short \flags
 #define HAVE_ARCH_BUG_ON
 #define HAVE_ARCH_WARN_ON
 #endif /* __ASSEMBLY __ */
+#else
+#ifdef __ASSEMBLY__
+.macro EMIT_BUG_ENTRY addr,file,line,flags
+.endm
+#else /* !__ASSEMBLY__ */
+#define _EMIT_BUG_ENTRY
+#endif
 #endif /* CONFIG_BUG */
 
 #include <asm-generic/bug.h>
index b377522..d5de325 100644 (file)
@@ -11,6 +11,8 @@
 #include <asm/types.h>
 #include <linux/compiler.h>
 
+#define __BIG_ENDIAN
+
 #ifdef __GNUC__
 #ifdef __KERNEL__
 
@@ -21,12 +23,19 @@ static __inline__ __u16 ld_le16(const volatile __u16 *addr)
        __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
        return val;
 }
+#define __arch_swab16p ld_le16
 
 static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
 {
        __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
 }
 
+static inline void __arch_swab16s(__u16 *addr)
+{
+       st_le16(addr, *addr);
+}
+#define __arch_swab16s __arch_swab16s
+
 static __inline__ __u32 ld_le32(const volatile __u32 *addr)
 {
        __u32 val;
@@ -34,13 +43,20 @@ static __inline__ __u32 ld_le32(const volatile __u32 *addr)
        __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
        return val;
 }
+#define __arch_swab32p ld_le32
 
 static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
 {
        __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
 }
 
-static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
+static inline void __arch_swab32s(__u32 *addr)
+{
+       st_le32(addr, *addr);
+}
+#define __arch_swab32s __arch_swab32s
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
 {
        __u16 result;
 
@@ -49,8 +65,9 @@ static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
            : "r" (value), "0" (value >> 8));
        return result;
 }
+#define __arch_swab16 __arch_swab16
 
-static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
 {
        __u32 result;
 
@@ -61,29 +78,16 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
            : "r" (value), "0" (value >> 24));
        return result;
 }
-
-#define __arch__swab16(x) ___arch__swab16(x)
-#define __arch__swab32(x) ___arch__swab32(x)
-
-/* The same, but returns converted value from the location pointer by addr. */
-#define __arch__swab16p(addr) ld_le16(addr)
-#define __arch__swab32p(addr) ld_le32(addr)
-
-/* The same, but do the conversion in situ, ie. put the value back to addr. */
-#define __arch__swab16s(addr) st_le16(addr,*addr)
-#define __arch__swab32s(addr) st_le32(addr,*addr)
+#define __arch_swab32 __arch_swab32
 
 #endif /* __KERNEL__ */
 
-#ifndef __STRICT_ANSI__
-#define __BYTEORDER_HAS_U64__
 #ifndef __powerpc64__
 #define __SWAB_64_THRU_32__
 #endif /* __powerpc64__ */
-#endif /* __STRICT_ANSI__ */
 
 #endif /* __GNUC__ */
 
-#include <linux/byteorder/big_endian.h>
+#include <linux/byteorder.h>
 
 #endif /* _ASM_POWERPC_BYTEORDER_H */
index 1e94b07..f3d9d74 100644 (file)
@@ -163,6 +163,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_SPE                    ASM_CONST(0x0000000002000000)
 #define CPU_FTR_NEED_PAIRED_STWCX      ASM_CONST(0x0000000004000000)
 #define CPU_FTR_LWSYNC                 ASM_CONST(0x0000000008000000)
+#define CPU_FTR_NOEXECUTE              ASM_CONST(0x0000000010000000)
 
 /*
  * Add the 64-bit processor unique features in the top half of the word;
@@ -177,7 +178,6 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_SLB                    LONG_ASM_CONST(0x0000000100000000)
 #define CPU_FTR_16M_PAGE               LONG_ASM_CONST(0x0000000200000000)
 #define CPU_FTR_TLBIEL                 LONG_ASM_CONST(0x0000000400000000)
-#define CPU_FTR_NOEXECUTE              LONG_ASM_CONST(0x0000000800000000)
 #define CPU_FTR_IABR                   LONG_ASM_CONST(0x0000002000000000)
 #define CPU_FTR_MMCRA                  LONG_ASM_CONST(0x0000004000000000)
 #define CPU_FTR_CTRL                   LONG_ASM_CONST(0x0000008000000000)
@@ -194,6 +194,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_VSX                    LONG_ASM_CONST(0x0010000000000000)
 #define CPU_FTR_SAO                    LONG_ASM_CONST(0x0020000000000000)
 #define CPU_FTR_CP_USE_DCBTZ           LONG_ASM_CONST(0x0040000000000000)
+#define CPU_FTR_UNALIGNED_LD_STD       LONG_ASM_CONST(0x0080000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -366,19 +367,20 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_CLASSIC32     (CPU_FTR_COMMON | \
            CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_8XX   (CPU_FTR_USE_TB)
-#define CPU_FTRS_40X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_44X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN)
+#define CPU_FTRS_40X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
+#define CPU_FTRS_44X   (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E200  (CPU_FTR_USE_TB | CPU_FTR_SPE_COMP | \
            CPU_FTR_NODSISRALIGN | CPU_FTR_COHERENT_ICACHE | \
-           CPU_FTR_UNIFIED_ID_CACHE)
+           CPU_FTR_UNIFIED_ID_CACHE | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E500  (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-           CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN)
+           CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
+           CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E500_2        (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
            CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_BIG_PHYS | \
-           CPU_FTR_NODSISRALIGN)
+           CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E500MC        (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
            CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_BIG_PHYS | CPU_FTR_NODSISRALIGN | \
-           CPU_FTR_L2CSR | CPU_FTR_LWSYNC)
+           CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_GENERIC_32    (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
@@ -404,7 +406,7 @@ extern const char *powerpc_base_platform;
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
            CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
-           CPU_FTR_DSCR)
+           CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD)
 #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -415,7 +417,8 @@ extern const char *powerpc_base_platform;
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
            CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | \
-           CPU_FTR_CELL_TB_BUG | CPU_FTR_CP_USE_DCBTZ)
+           CPU_FTR_CELL_TB_BUG | CPU_FTR_CP_USE_DCBTZ | \
+           CPU_FTR_UNALIGNED_LD_STD)
 #define CPU_FTRS_PA6T (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
            CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
            CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \
index dfd504c..7d2277c 100644 (file)
@@ -18,4 +18,16 @@ struct dev_archdata {
        void                    *dma_data;
 };
 
+static inline void dev_archdata_set_node(struct dev_archdata *ad,
+                                        struct device_node *np)
+{
+       ad->of_node = np;
+}
+
+static inline struct device_node *
+dev_archdata_get_node(const struct dev_archdata *ad)
+{
+       return ad->of_node;
+}
+
 #endif /* _ASM_POWERPC_DEVICE_H */
index fddb229..86cef7d 100644 (file)
@@ -60,12 +60,6 @@ struct dma_mapping_ops {
                                dma_addr_t *dma_handle, gfp_t flag);
        void            (*free_coherent)(struct device *dev, size_t size,
                                void *vaddr, dma_addr_t dma_handle);
-       dma_addr_t      (*map_single)(struct device *dev, void *ptr,
-                               size_t size, enum dma_data_direction direction,
-                               struct dma_attrs *attrs);
-       void            (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
-                               size_t size, enum dma_data_direction direction,
-                               struct dma_attrs *attrs);
        int             (*map_sg)(struct device *dev, struct scatterlist *sg,
                                int nents, enum dma_data_direction direction,
                                struct dma_attrs *attrs);
@@ -82,6 +76,22 @@ struct dma_mapping_ops {
                                dma_addr_t dma_address, size_t size,
                                enum dma_data_direction direction,
                                struct dma_attrs *attrs);
+#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
+       void            (*sync_single_range_for_cpu)(struct device *hwdev,
+                               dma_addr_t dma_handle, unsigned long offset,
+                               size_t size,
+                               enum dma_data_direction direction);
+       void            (*sync_single_range_for_device)(struct device *hwdev,
+                               dma_addr_t dma_handle, unsigned long offset,
+                               size_t size,
+                               enum dma_data_direction direction);
+       void            (*sync_sg_for_cpu)(struct device *hwdev,
+                               struct scatterlist *sg, int nelems,
+                               enum dma_data_direction direction);
+       void            (*sync_sg_for_device)(struct device *hwdev,
+                               struct scatterlist *sg, int nelems,
+                               enum dma_data_direction direction);
+#endif
 };
 
 /*
@@ -149,10 +159,9 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
 }
 
 /*
- * TODO: map_/unmap_single will ideally go away, to be completely
- * replaced by map/unmap_page.   Until then, we allow dma_ops to have
- * one or the other, or both by checking to see if the specific
- * function requested exists; and if not, falling back on the other set.
+ * map_/unmap_single actually call through to map/unmap_page now that all the
+ * dma_mapping_ops have been converted over. We just have to get the page and
+ * offset to pass through to map_page
  */
 static inline dma_addr_t dma_map_single_attrs(struct device *dev,
                                              void *cpu_addr,
@@ -164,10 +173,6 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev,
 
        BUG_ON(!dma_ops);
 
-       if (dma_ops->map_single)
-               return dma_ops->map_single(dev, cpu_addr, size, direction,
-                                          attrs);
-
        return dma_ops->map_page(dev, virt_to_page(cpu_addr),
                                 (unsigned long)cpu_addr % PAGE_SIZE, size,
                                 direction, attrs);
@@ -183,11 +188,6 @@ static inline void dma_unmap_single_attrs(struct device *dev,
 
        BUG_ON(!dma_ops);
 
-       if (dma_ops->unmap_single) {
-               dma_ops->unmap_single(dev, dma_addr, size, direction, attrs);
-               return;
-       }
-
        dma_ops->unmap_page(dev, dma_addr, size, direction, attrs);
 }
 
@@ -201,12 +201,7 @@ static inline dma_addr_t dma_map_page_attrs(struct device *dev,
 
        BUG_ON(!dma_ops);
 
-       if (dma_ops->map_page)
-               return dma_ops->map_page(dev, page, offset, size, direction,
-                                        attrs);
-
-       return dma_ops->map_single(dev, page_address(page) + offset, size,
-                                  direction, attrs);
+       return dma_ops->map_page(dev, page, offset, size, direction, attrs);
 }
 
 static inline void dma_unmap_page_attrs(struct device *dev,
@@ -219,12 +214,7 @@ static inline void dma_unmap_page_attrs(struct device *dev,
 
        BUG_ON(!dma_ops);
 
-       if (dma_ops->unmap_page) {
-               dma_ops->unmap_page(dev, dma_address, size, direction, attrs);
-               return;
-       }
-
-       dma_ops->unmap_single(dev, dma_address, size, direction, attrs);
+       dma_ops->unmap_page(dev, dma_address, size, direction, attrs);
 }
 
 static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
@@ -308,47 +298,107 @@ static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
        dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
 }
 
+#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
 static inline void dma_sync_single_for_cpu(struct device *dev,
                dma_addr_t dma_handle, size_t size,
                enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
-       __dma_sync(bus_to_virt(dma_handle), size, direction);
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+       BUG_ON(!dma_ops);
+       dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
+                                          size, direction);
 }
 
 static inline void dma_sync_single_for_device(struct device *dev,
                dma_addr_t dma_handle, size_t size,
                enum dma_data_direction direction)
 {
-       BUG_ON(direction == DMA_NONE);
-       __dma_sync(bus_to_virt(dma_handle), size, direction);
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+       BUG_ON(!dma_ops);
+       dma_ops->sync_single_range_for_device(dev, dma_handle,
+                                             0, size, direction);
 }
 
 static inline void dma_sync_sg_for_cpu(struct device *dev,
                struct scatterlist *sgl, int nents,
                enum dma_data_direction direction)
 {
-       struct scatterlist *sg;
-       int i;
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
-       BUG_ON(direction == DMA_NONE);
+       BUG_ON(!dma_ops);
+       dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
+}
+
+static inline void dma_sync_sg_for_device(struct device *dev,
+               struct scatterlist *sgl, int nents,
+               enum dma_data_direction direction)
+{
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+       BUG_ON(!dma_ops);
+       dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
+}
+
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
 
-       for_each_sg(sgl, sg, nents, i)
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+       BUG_ON(!dma_ops);
+       dma_ops->sync_single_range_for_cpu(dev, dma_handle,
+                                          offset, size, direction);
+}
+
+static inline void dma_sync_single_range_for_device(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+       struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+       BUG_ON(!dma_ops);
+       dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
+                                             size, direction);
+}
+#else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */
+static inline void dma_sync_single_for_cpu(struct device *dev,
+               dma_addr_t dma_handle, size_t size,
+               enum dma_data_direction direction)
+{
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+               dma_addr_t dma_handle, size_t size,
+               enum dma_data_direction direction)
+{
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+               struct scatterlist *sgl, int nents,
+               enum dma_data_direction direction)
+{
 }
 
 static inline void dma_sync_sg_for_device(struct device *dev,
                struct scatterlist *sgl, int nents,
                enum dma_data_direction direction)
 {
-       struct scatterlist *sg;
-       int i;
+}
 
-       BUG_ON(direction == DMA_NONE);
+static inline void dma_sync_single_range_for_cpu(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+}
 
-       for_each_sg(sgl, sg, nents, i)
-               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+static inline void dma_sync_single_range_for_device(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
 }
+#endif
 
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
@@ -382,22 +432,6 @@ static inline int dma_get_cache_alignment(void)
 #endif
 }
 
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
-               dma_addr_t dma_handle, unsigned long offset, size_t size,
-               enum dma_data_direction direction)
-{
-       /* just sync everything for now */
-       dma_sync_single_for_cpu(dev, dma_handle, offset + size, direction);
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
-               dma_addr_t dma_handle, unsigned long offset, size_t size,
-               enum dma_data_direction direction)
-{
-       /* just sync everything for now */
-       dma_sync_single_for_device(dev, dma_handle, offset + size, direction);
-}
-
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                enum dma_data_direction direction)
 {
index b886bec..66ea9b8 100644 (file)
@@ -17,8 +17,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#ifndef _PPC64_EEH_H
-#define _PPC64_EEH_H
+#ifndef _POWERPC_EEH_H
+#define _POWERPC_EEH_H
 #ifdef __KERNEL__
 
 #include <linux/init.h>
@@ -110,6 +110,7 @@ static inline void eeh_remove_bus_device(struct pci_dev *dev) { }
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
 #endif /* CONFIG_EEH */
 
+#ifdef CONFIG_PPC64
 /*
  * MMIO read/write operations with EEH support.
  */
@@ -207,5 +208,6 @@ static inline void eeh_readsl(const volatile void __iomem *addr, void * buf,
                eeh_check_failure(addr, *(u32*)buf);
 }
 
+#endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
-#endif /* _PPC64_EEH_H */
+#endif /* _POWERPC_EEH_H */
index 91c5895..7dc52ec 100644 (file)
@@ -85,7 +85,7 @@ static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgpro
        BUG_ON(!pte_none(*(kmap_pte-idx)));
 #endif
        __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
-       flush_tlb_page(NULL, vaddr);
+       local_flush_tlb_page(vaddr);
 
        return (void*) vaddr;
 }
@@ -113,7 +113,7 @@ static inline void kunmap_atomic(void *kvaddr, enum km_type type)
         * this pte without first remap it
         */
        pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       flush_tlb_page(NULL, vaddr);
+       local_flush_tlb_page(vaddr);
 #endif
        pagefault_enable();
 }
index 08266d2..494cd8b 100644 (file)
@@ -713,13 +713,6 @@ static inline void * phys_to_virt(unsigned long address)
  */
 #define page_to_phys(page)     ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
 
-/* We do NOT want virtual merging, it would put too much pressure on
- * our iommu allocator. Instead, we want drivers to be smart enough
- * to coalesce sglists that happen to have been mapped in a contiguous
- * way by the iommu
- */
-#define BIO_VMERGE_BOUNDARY    0
-
 /*
  * 32 bits still uses virt_to_bus() for it's implementation of DMA
  * mappings se we have to keep it defined here. We also have some old
index 612d832..84b457a 100644 (file)
@@ -67,7 +67,7 @@ static __inline__ long local_inc_return(local_t *l)
        bne-    1b"
        : "=&r" (t)
        : "r" (&(l->a.counter))
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
@@ -94,7 +94,7 @@ static __inline__ long local_dec_return(local_t *l)
        bne-    1b"
        : "=&r" (t)
        : "r" (&(l->a.counter))
-       : "cc", "memory");
+       : "cc", "xer", "memory");
 
        return t;
 }
index 2fe268b..25aaa97 100644 (file)
@@ -133,7 +133,8 @@ struct lppaca {
 //=============================================================================
 // CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data
 //=============================================================================
-       u8      pmc_save_area[256];     // PMC interrupt Area           x00-xFF
+       u32     page_ins;                       // CMO Hint - # page ins by OS  x00-x04
+       u8      pmc_save_area[252];     // PMC interrupt Area           x04-xFF
 } __attribute__((__aligned__(0x400)));
 
 extern struct lppaca lppaca[];
index 925d93c..5588a41 100644 (file)
@@ -40,6 +40,8 @@
 #define MAS2_M         0x00000004
 #define MAS2_G         0x00000002
 #define MAS2_E         0x00000001
+#define MAS2_EPN_MASK(size)            (~0 << (2*(size) + 10))
+#define MAS2_VAL(addr, size, flags)    ((addr) & MAS2_EPN_MASK(size) | (flags))
 
 #define MAS3_RPN       0xFFFFF000
 #define MAS3_U0                0x00000200
index 6b993ef..b570209 100644 (file)
@@ -180,6 +180,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
        tsk->thread.pgdir = next->pgd;
 
+       if (!cpu_isset(smp_processor_id(), next->cpu_vm_mask))
+               cpu_set(smp_processor_id(), next->cpu_vm_mask);
+
        /* No need to flush userspace segments if the mm doesnt change */
        if (prev == next)
                return;
index 458c1f7..dabc01c 100644 (file)
@@ -1,9 +1,134 @@
 /*
- * Pull in the generic implementation for the mutex fastpath.
+ * Optimised mutex implementation of include/asm-generic/mutex-dec.h algorithm
+ */
+#ifndef _ASM_POWERPC_MUTEX_H
+#define _ASM_POWERPC_MUTEX_H
+
+static inline int __mutex_cmpxchg_lock(atomic_t *v, int old, int new)
+{
+       int t;
+
+       __asm__ __volatile__ (
+"1:    lwarx   %0,0,%1         # mutex trylock\n\
+       cmpw    0,%0,%2\n\
+       bne-    2f\n"
+       PPC405_ERR77(0,%1)
+"      stwcx.  %3,0,%1\n\
+       bne-    1b"
+       ISYNC_ON_SMP
+       "\n\
+2:"
+       : "=&r" (t)
+       : "r" (&v->counter), "r" (old), "r" (new)
+       : "cc", "memory");
+
+       return t;
+}
+
+static inline int __mutex_dec_return_lock(atomic_t *v)
+{
+       int t;
+
+       __asm__ __volatile__(
+"1:    lwarx   %0,0,%1         # mutex lock\n\
+       addic   %0,%0,-1\n"
+       PPC405_ERR77(0,%1)
+"      stwcx.  %0,0,%1\n\
+       bne-    1b"
+       ISYNC_ON_SMP
+       : "=&r" (t)
+       : "r" (&v->counter)
+       : "cc", "memory");
+
+       return t;
+}
+
+static inline int __mutex_inc_return_unlock(atomic_t *v)
+{
+       int t;
+
+       __asm__ __volatile__(
+       LWSYNC_ON_SMP
+"1:    lwarx   %0,0,%1         # mutex unlock\n\
+       addic   %0,%0,1\n"
+       PPC405_ERR77(0,%1)
+"      stwcx.  %0,0,%1 \n\
+       bne-    1b"
+       : "=&r" (t)
+       : "r" (&v->counter)
+       : "cc", "memory");
+
+       return t;
+}
+
+/**
+ *  __mutex_fastpath_lock - try to take the lock by moving the count
+ *                          from 1 to a 0 value
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function MUST leave the value lower than
+ * 1 even when the "1" assertion wasn't true.
+ */
+static inline void
+__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+       if (unlikely(__mutex_dec_return_lock(count) < 0))
+               fail_fn(count);
+}
+
+/**
+ *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
+ *                                 from 1 to a 0 value
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 1
+ *
+ * Change the count from 1 to a value lower than 1, and call <fail_fn> if
+ * it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
+ * or anything the slow path function returns.
+ */
+static inline int
+__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+       if (unlikely(__mutex_dec_return_lock(count) < 0))
+               return fail_fn(count);
+       return 0;
+}
+
+/**
+ *  __mutex_fastpath_unlock - try to promote the count from 0 to 1
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: function to call if the original value was not 0
+ *
+ * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
+ * In the failure case, this function is allowed to either set the value to
+ * 1, or to set it to a value lower than 1.
+ */
+static inline void
+__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
+{
+       if (unlikely(__mutex_inc_return_unlock(count) <= 0))
+               fail_fn(count);
+}
+
+#define __mutex_slowpath_needs_to_unlock()             1
+
+/**
+ * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
+ *
+ *  @count: pointer of type atomic_t
+ *  @fail_fn: fallback function
  *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
+ * Change the count from 1 to 0, and return 1 (success), or if the count
+ * was not 1, then return 0 (failure).
  */
+static inline int
+__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
+{
+       if (likely(__mutex_cmpxchg_lock(count, 1, 0) == 1))
+               return 1;
+       return 0;
+}
 
-#include <asm-generic/mutex-dec.h>
+#endif
index 9047af7..84007af 100644 (file)
@@ -13,7 +13,6 @@
 
 struct device_node;
 
-extern unsigned int ppc_pci_flags;
 enum {
        /* Force re-assigning all resources (ignore firmware
         * setup completely)
@@ -36,6 +35,31 @@ enum {
        /* ... except for domain 0 */
        PPC_PCI_COMPAT_DOMAIN_0         = 0x00000020,
 };
+#ifdef CONFIG_PCI
+extern unsigned int ppc_pci_flags;
+
+static inline void ppc_pci_set_flags(int flags)
+{
+       ppc_pci_flags = flags;
+}
+
+static inline void ppc_pci_add_flags(int flags)
+{
+       ppc_pci_flags |= flags;
+}
+
+static inline int ppc_pci_has_flag(int flag)
+{
+       return (ppc_pci_flags & flag);
+}
+#else
+static inline void ppc_pci_set_flags(int flags) { }
+static inline void ppc_pci_add_flags(int flags) { }
+static inline int ppc_pci_has_flag(int flag)
+{
+       return 0;
+}
+#endif
 
 
 /*
@@ -241,9 +265,6 @@ extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
 extern void pcibios_add_pci_devices(struct pci_bus *bus);
-extern void pcibios_fixup_new_pci_devices(struct pci_bus *bus);
-
-extern int pcibios_remove_root_bus(struct pci_controller *phb);
 
 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 {
@@ -290,6 +311,7 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 /* Allocate & free a PCI host bridge structure */
 extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
 extern void pcibios_free_controller(struct pci_controller *phb);
+extern void pcibios_setup_phb_resources(struct pci_controller *hose);
 
 #ifdef CONFIG_PCI
 extern unsigned long pci_address_to_pio(phys_addr_t address);
index 57a2a49..3548159 100644 (file)
@@ -38,8 +38,8 @@ struct pci_dev;
  * Set this to 1 if you want the kernel to re-assign all PCI
  * bus numbers (don't do that on ppc64 yet !)
  */
-#define pcibios_assign_all_busses()            (ppc_pci_flags & \
-                                        PPC_PCI_REASSIGN_ALL_BUS)
+#define pcibios_assign_all_busses() \
+       (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
 #define pcibios_scan_all_fns(a, b)     0
 
 static inline void pcibios_set_master(struct pci_dev *dev)
@@ -204,15 +204,14 @@ static inline struct resource *pcibios_select_root(struct pci_dev *pdev,
        return root;
 }
 
-extern void pcibios_setup_new_device(struct pci_dev *dev);
-
 extern void pcibios_claim_one_bus(struct pci_bus *b);
 
-extern void pcibios_allocate_bus_resources(struct pci_bus *bus);
+extern void pcibios_finish_adding_to_bus(struct pci_bus *bus);
 
 extern void pcibios_resource_survey(void);
 
 extern struct pci_controller *init_phb_dynamic(struct device_node *dn);
+extern int remove_phb_dynamic(struct pci_controller *phb);
 
 extern struct pci_dev *of_create_pci_dev(struct device_node *node,
                                        struct pci_bus *bus, int devfn);
@@ -221,6 +220,7 @@ extern void of_scan_pci_bridge(struct device_node *node,
                                struct pci_dev *dev);
 
 extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
+extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
 
 extern int pci_read_irq_line(struct pci_dev *dev);
 
@@ -235,9 +235,8 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
                                 const struct resource *rsrc,
                                 resource_size_t *start, resource_size_t *end);
 
-extern void pcibios_do_bus_setup(struct pci_bus *bus);
-extern void pcibios_fixup_of_probed_bus(struct pci_bus *bus);
-
+extern void pcibios_setup_bus_devices(struct pci_bus *bus);
+extern void pcibios_setup_bus_self(struct pci_bus *bus);
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
index 58c0714..0815eb4 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/threads.h>
 
+#define PTE_NONCACHE_NUM       0  /* dummy for now to share code w/ppc64 */
+
 extern void __bad_pte(pmd_t *pmd);
 
 extern pgd_t *pgd_alloc(struct mm_struct *mm);
@@ -33,10 +35,13 @@ extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 
 extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
 extern pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long addr);
-extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
-extern void pte_free(struct mm_struct *mm, pgtable_t pte);
 
-#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, (pte))
+static inline void pgtable_free(pgtable_free_t pgf)
+{
+       void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
+
+       free_page((unsigned long)p);
+}
 
 #define check_pgt_cache()      do { } while (0)
 
index 812a1d8..afda2bd 100644 (file)
@@ -7,7 +7,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
@@ -108,31 +107,6 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm,
        return page;
 }
 
-static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-       free_page((unsigned long)pte);
-}
-
-static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-       pgtable_page_dtor(ptepage);
-       __free_page(ptepage);
-}
-
-#define PGF_CACHENUM_MASK      0x7
-
-typedef struct pgtable_free {
-       unsigned long val;
-} pgtable_free_t;
-
-static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
-                                               unsigned long mask)
-{
-       BUG_ON(cachenum > PGF_CACHENUM_MASK);
-
-       return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
-}
-
 static inline void pgtable_free(pgtable_free_t pgf)
 {
        void *p = (void *)(pgf.val & ~PGF_CACHENUM_MASK);
@@ -144,14 +118,6 @@ static inline void pgtable_free(pgtable_free_t pgf)
                kmem_cache_free(pgtable_cache[cachenum], p);
 }
 
-extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
-
-#define __pte_free_tlb(tlb,ptepage)    \
-do { \
-       pgtable_page_dtor(ptepage); \
-       pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
-               PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
-} while (0)
 #define __pmd_free_tlb(tlb, pmd)       \
        pgtable_free_tlb(tlb, pgtable_free_cache(pmd, \
                PMD_CACHE_NUM, PMD_TABLE_SIZE-1))
index b4505ed..5d84802 100644 (file)
@@ -2,11 +2,52 @@
 #define _ASM_POWERPC_PGALLOC_H
 #ifdef __KERNEL__
 
+#include <linux/mm.h>
+
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+       free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage)
+{
+       pgtable_page_dtor(ptepage);
+       __free_page(ptepage);
+}
+
+typedef struct pgtable_free {
+       unsigned long val;
+} pgtable_free_t;
+
+#define PGF_CACHENUM_MASK      0x7
+
+static inline pgtable_free_t pgtable_free_cache(void *p, int cachenum,
+                                               unsigned long mask)
+{
+       BUG_ON(cachenum > PGF_CACHENUM_MASK);
+
+       return (pgtable_free_t){.val = ((unsigned long) p & ~mask) | cachenum};
+}
+
 #ifdef CONFIG_PPC64
 #include <asm/pgalloc-64.h>
 #else
 #include <asm/pgalloc-32.h>
 #endif
 
+extern void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf);
+
+#ifdef CONFIG_SMP
+#define __pte_free_tlb(tlb,ptepage)    \
+do { \
+       pgtable_page_dtor(ptepage); \
+       pgtable_free_tlb(tlb, pgtable_free_cache(page_address(ptepage), \
+               PTE_NONCACHE_NUM, PTE_TABLE_SIZE-1)); \
+} while (0)
+#else
+#define __pte_free_tlb(tlb, pte)       pte_free((tlb)->mm, (pte))
+#endif
+
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_PGALLOC_H */
index 4c0a8c6..1f0a330 100644 (file)
 
 #define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY)
 
-/* __pgprot defined in arch/powerpc/incliude/asm/page.h */
+/* __pgprot defined in arch/powerpc/include/asm/page.h */
 #define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
 
 #define PAGE_SHARED    __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER)
index 101ed87..d346649 100644 (file)
@@ -69,8 +69,6 @@ extern int _prep_type;
 
 #ifdef __KERNEL__
 
-extern int have_of;
-
 struct task_struct;
 void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
 void release_thread(struct task_struct *);
@@ -207,6 +205,11 @@ struct thread_struct {
 #define INIT_SP_LIMIT \
        (_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
 
+#ifdef CONFIG_SPE
+#define SPEFSCR_INIT .spefscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | SPEFSCR_FUNFE | SPEFSCR_FOVFE,
+#else
+#define SPEFSCR_INIT
+#endif
 
 #ifdef CONFIG_PPC32
 #define INIT_THREAD { \
@@ -215,6 +218,7 @@ struct thread_struct {
        .fs = KERNEL_DS, \
        .pgdir = swapper_pg_dir, \
        .fpexc_mode = MSR_FE0 | MSR_FE1, \
+       SPEFSCR_INIT \
 }
 #else
 #define INIT_THREAD  { \
index f9e34c4..cff30c0 100644 (file)
@@ -305,30 +305,34 @@ static inline const char* ps3_result(int result)
 /* system bus routines */
 
 enum ps3_match_id {
-       PS3_MATCH_ID_EHCI           = 1,
-       PS3_MATCH_ID_OHCI           = 2,
-       PS3_MATCH_ID_GELIC          = 3,
-       PS3_MATCH_ID_AV_SETTINGS    = 4,
-       PS3_MATCH_ID_SYSTEM_MANAGER = 5,
-       PS3_MATCH_ID_STOR_DISK      = 6,
-       PS3_MATCH_ID_STOR_ROM       = 7,
-       PS3_MATCH_ID_STOR_FLASH     = 8,
-       PS3_MATCH_ID_SOUND          = 9,
-       PS3_MATCH_ID_GRAPHICS       = 10,
-       PS3_MATCH_ID_LPM            = 11,
+       PS3_MATCH_ID_EHCI               = 1,
+       PS3_MATCH_ID_OHCI               = 2,
+       PS3_MATCH_ID_GELIC              = 3,
+       PS3_MATCH_ID_AV_SETTINGS        = 4,
+       PS3_MATCH_ID_SYSTEM_MANAGER     = 5,
+       PS3_MATCH_ID_STOR_DISK          = 6,
+       PS3_MATCH_ID_STOR_ROM           = 7,
+       PS3_MATCH_ID_STOR_FLASH         = 8,
+       PS3_MATCH_ID_SOUND              = 9,
+       PS3_MATCH_ID_GPU                = 10,
+       PS3_MATCH_ID_LPM                = 11,
 };
 
-#define PS3_MODULE_ALIAS_EHCI           "ps3:1"
-#define PS3_MODULE_ALIAS_OHCI           "ps3:2"
-#define PS3_MODULE_ALIAS_GELIC          "ps3:3"
-#define PS3_MODULE_ALIAS_AV_SETTINGS    "ps3:4"
-#define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5"
-#define PS3_MODULE_ALIAS_STOR_DISK      "ps3:6"
-#define PS3_MODULE_ALIAS_STOR_ROM       "ps3:7"
-#define PS3_MODULE_ALIAS_STOR_FLASH     "ps3:8"
-#define PS3_MODULE_ALIAS_SOUND          "ps3:9"
-#define PS3_MODULE_ALIAS_GRAPHICS       "ps3:10"
-#define PS3_MODULE_ALIAS_LPM            "ps3:11"
+enum ps3_match_sub_id {
+       PS3_MATCH_SUB_ID_GPU_FB         = 1,
+};
+
+#define PS3_MODULE_ALIAS_EHCI          "ps3:1:0"
+#define PS3_MODULE_ALIAS_OHCI          "ps3:2:0"
+#define PS3_MODULE_ALIAS_GELIC         "ps3:3:0"
+#define PS3_MODULE_ALIAS_AV_SETTINGS   "ps3:4:0"
+#define PS3_MODULE_ALIAS_SYSTEM_MANAGER        "ps3:5:0"
+#define PS3_MODULE_ALIAS_STOR_DISK     "ps3:6:0"
+#define PS3_MODULE_ALIAS_STOR_ROM      "ps3:7:0"
+#define PS3_MODULE_ALIAS_STOR_FLASH    "ps3:8:0"
+#define PS3_MODULE_ALIAS_SOUND         "ps3:9:0"
+#define PS3_MODULE_ALIAS_GPU_FB                "ps3:10:1"
+#define PS3_MODULE_ALIAS_LPM           "ps3:11:0"
 
 enum ps3_system_bus_device_type {
        PS3_DEVICE_TYPE_IOC0 = 1,
@@ -337,11 +341,6 @@ enum ps3_system_bus_device_type {
        PS3_DEVICE_TYPE_LPM,
 };
 
-enum ps3_match_sub_id {
-       /* for PS3_MATCH_ID_GRAPHICS */
-       PS3_MATCH_SUB_ID_FB             = 1,
-};
-
 /**
  * struct ps3_system_bus_device - a device on the system bus
  */
@@ -516,4 +515,7 @@ void ps3_sync_irq(int node);
 u32 ps3_get_hw_thread_id(int cpu);
 u64 ps3_get_spe_id(void *arg);
 
+/* mutex synchronizing GPU accesses and video mode changes */
+extern struct mutex ps3_gpu_mutex;
+
 #endif
index 5aa22cf..cd24ac1 100644 (file)
@@ -740,8 +740,4 @@ extern int ps3av_audio_mute(int);
 extern int ps3av_audio_mute_analog(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
-extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
-                                   void *flip_data);
-extern void ps3av_flip_ctl(int on);
-
 #endif /* _ASM_POWERPC_PS3AV_H_ */
index 8eaa7b2..e0175be 100644 (file)
@@ -168,6 +168,7 @@ extern void rtas_os_term(char *str);
 extern int rtas_get_sensor(int sensor, int index, int *state);
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
+extern bool rtas_indicator_present(int token, int *maxindex);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
 extern int rtas_set_indicator_fast(int indicator, int index, int new_value);
 extern void rtas_progress(char *s, unsigned short hex);
index ced34f1..3d9f831 100644 (file)
@@ -82,7 +82,7 @@
 #define _FP_MUL_MEAT_S(R,X,Y)   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_D(R,X,Y)   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
 
-#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
 #define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
 
 /* These macros define what NaN looks like. They're supposed to expand to
 
 #define _FP_KEEPNANFRACP 1
 
+#ifdef FP_EX_BOOKE_E500_SPE
+#define FP_EX_INEXACT          (1 << 21)
+#define FP_EX_INVALID          (1 << 20)
+#define FP_EX_DIVZERO          (1 << 19)
+#define FP_EX_UNDERFLOW                (1 << 18)
+#define FP_EX_OVERFLOW         (1 << 17)
+#define FP_INHIBIT_RESULTS     0
+
+#define __FPU_FPSCR    (current->thread.spefscr)
+#define __FPU_ENABLED_EXC              \
+({                                     \
+       (__FPU_FPSCR >> 2) & 0x1f;      \
+})
+#else
 /* Exception flags.  We use the bit positions of the appropriate bits
    in the FPSCR, which also correspond to the FE_* bits.  This makes
    everything easier ;-).  */
 #define FP_EX_DIVZERO         (1 << (31 - 5))
 #define FP_EX_INEXACT         (1 << (31 - 6))
 
-/* This macro appears to be called when both X and Y are NaNs, and
- * has to choose one and copy it to R. i386 goes for the larger of the
- * two, sparc64 just picks Y. I don't understand this at all so I'll
- * go with sparc64 because it's shorter :->   -- PMM
- */
-#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)             \
-  do {                                                 \
-    R##_s = Y##_s;                                     \
-    _FP_FRAC_COPY_##wc(R,Y);                           \
-    R##_c = FP_CLS_NAN;                                        \
-  } while (0)
-
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
 #define __FPU_FPSCR    (current->thread.fpscr.val)
 
 /* We only actually write to the destination register
        (__FPU_FPSCR >> 3) & 0x1f;      \
 })
 
+#endif
+
+/*
+ * If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                     \
+  do {                                                         \
+    if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)         \
+       && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))     \
+      {                                                                \
+       R##_s = X##_s;                                          \
+       _FP_FRAC_COPY_##wc(R,X);                                \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+       R##_s = Y##_s;                                          \
+       _FP_FRAC_COPY_##wc(R,Y);                                \
+      }                                                                \
+    R##_c = FP_CLS_NAN;                                                \
+  } while (0)
+
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
 #define __FPU_TRAP_P(bits) \
        ((__FPU_ENABLED_EXC & (bits)) != 0)
 
index 1866cec..c25f73d 100644 (file)
@@ -81,6 +81,13 @@ extern int cpu_to_core_id(int cpu);
 #define PPC_MSG_CALL_FUNC_SINGLE       2
 #define PPC_MSG_DEBUGGER_BREAK  3
 
+/*
+ * irq controllers that have dedicated ipis per message and don't
+ * need additional code in the action handler may use this
+ */
+extern int smp_request_message_ipi(int virq, int message);
+extern const char *smp_ipi_name[];
+
 void smp_init_iSeries(void);
 void smp_init_pSeries(void);
 void smp_init_cell(void);
index f56a843..3686436 100644 (file)
@@ -277,7 +277,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw)
        bne-            1b"
        : "=&r"(tmp)
        : "r"(&rw->lock)
-       : "cr0", "memory");
+       : "cr0", "xer", "memory");
 }
 
 static inline void __raw_write_unlock(raw_rwlock_t *rw)
index 45963e8..28f6ddb 100644 (file)
@@ -5,6 +5,10 @@
 #include <linux/stringify.h>
 #include <asm/feature-fixups.h>
 
+#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC)
+#define __SUBARCH_HAS_LWSYNC
+#endif
+
 #ifndef __ASSEMBLY__
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
index d6648c1..2a4be19 100644 (file)
  * read_barrier_depends() prevents data-dependent loads being reordered
  *     across this point (nop on PPC).
  *
- * We have to use the sync instructions for mb(), since lwsync doesn't
- * order loads with respect to previous stores.  Lwsync is fine for
- * rmb(), though. Note that rmb() actually uses a sync on 32-bit
- * architectures.
+ * *mb() variants without smp_ prefix must order all types of memory
+ * operations with one another. sync is the only instruction sufficient
+ * to do this.
  *
- * For wmb(), we use sync since wmb is used in drivers to order
- * stores to system memory with respect to writes to the device.
- * However, smp_wmb() can be a lighter-weight lwsync or eieio barrier
- * on SMP since it is only used to order updates to system memory.
+ * For the smp_ barriers, ordering is for cacheable memory operations
+ * only. We have to use the sync instruction for smp_mb(), since lwsync
+ * doesn't order loads with respect to previous stores.  Lwsync can be
+ * used for smp_rmb() and smp_wmb().
+ *
+ * However, on CPUs that don't support lwsync, lwsync actually maps to a
+ * heavy-weight sync, so smp_wmb() can be a lighter-weight eieio.
  */
 #define mb()   __asm__ __volatile__ ("sync" : : : "memory")
 #define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
 #ifdef CONFIG_SMP
 
 #ifdef __SUBARCH_HAS_LWSYNC
-#    define SMPWMB      lwsync
+#    define SMPWMB      LWSYNC
 #else
 #    define SMPWMB      eieio
 #endif
 
 #define smp_mb()       mb()
-#define smp_rmb()      rmb()
-#define smp_wmb()      __asm__ __volatile__ (__stringify(SMPWMB) : : :"memory")
+#define smp_rmb()      __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
+#define smp_wmb()      __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
 #define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define smp_mb()       barrier()
index febd581..27ccb76 100644 (file)
@@ -48,26 +48,6 @@ extern unsigned long ppc_proc_freq;
 extern unsigned long ppc_tb_freq;
 #define DEFAULT_TB_FREQ                125000000UL
 
-/*
- * By putting all of this stuff into a single struct we 
- * reduce the number of cache lines touched by do_gettimeofday.
- * Both by collecting all of the data in one cache line and
- * by touching only one TOC entry on ppc64.
- */
-struct gettimeofday_vars {
-       u64 tb_to_xs;
-       u64 stamp_xsec;
-       u64 tb_orig_stamp;
-};
-
-struct gettimeofday_struct {
-       unsigned long tb_ticks_per_sec;
-       struct gettimeofday_vars vars[2];
-       struct gettimeofday_vars * volatile varp;
-       unsigned      var_idx;
-       unsigned      tb_to_us;
-};
-
 struct div_result {
        u64 result_high;
        u64 result_low;
index a2c6bfd..333c24b 100644 (file)
@@ -6,6 +6,7 @@
  *
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - local_flush_tlb_page(vmaddr) flushes one page on the local processor
  *  - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB
  *  - flush_tlb_range(vma, start, end) flushes a range of pages
  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
@@ -39,11 +40,21 @@ extern void _tlbil_va(unsigned long address, unsigned int pid);
 extern void _tlbia(void);
 #endif
 
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+       _tlbil_pid(mm->context.id);
+}
+
 static inline void flush_tlb_mm(struct mm_struct *mm)
 {
        _tlbil_pid(mm->context.id);
 }
 
+static inline void local_flush_tlb_page(unsigned long vmaddr)
+{
+       _tlbil_va(vmaddr, 0);
+}
+
 static inline void flush_tlb_page(struct vm_area_struct *vma,
                                  unsigned long vmaddr)
 {
@@ -81,6 +92,10 @@ 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);
+static inline void local_flush_tlb_page(unsigned long vmaddr)
+{
+       flush_tlb_page(NULL, vmaddr);
+}
 
 #else
 /*
@@ -138,6 +153,10 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
 {
 }
 
+static inline void local_flush_tlb_page(unsigned long vmaddr)
+{
+}
+
 static inline void flush_tlb_page(struct vm_area_struct *vma,
                                  unsigned long vmaddr)
 {
index f013932..13c2c28 100644 (file)
@@ -39,6 +39,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/unistd.h>
+#include <linux/time.h>
 
 #define SYSCALL_MAP_SIZE      ((__NR_syscalls + 31) / 32)
 
@@ -83,6 +84,7 @@ struct vdso_data {
        __u32 icache_log_block_size;            /* L1 i-cache log block size */
        __s32 wtom_clock_sec;                   /* Wall to monotonic clock */
        __s32 wtom_clock_nsec;
+       struct timespec stamp_xtime;    /* xtime as at tb_orig_stamp */
        __u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls  */
        __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
 };
@@ -102,6 +104,7 @@ struct vdso_data {
        __u32 tz_dsttime;               /* Type of dst correction       0x5C */
        __s32 wtom_clock_sec;                   /* Wall to monotonic clock */
        __s32 wtom_clock_nsec;
+       struct timespec stamp_xtime;    /* xtime as at tb_orig_stamp */
        __u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
        __u32 dcache_block_size;        /* L1 d-cache block size     */
        __u32 icache_block_size;        /* L1 i-cache block size     */
index 75c5dd0..050abfd 100644 (file)
@@ -306,6 +306,7 @@ int main(void)
        DEFINE(CFG_SYSCALL_MAP32, offsetof(struct vdso_data, syscall_map_32));
        DEFINE(WTOM_CLOCK_SEC, offsetof(struct vdso_data, wtom_clock_sec));
        DEFINE(WTOM_CLOCK_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
+       DEFINE(STAMP_XTIME, offsetof(struct vdso_data, stamp_xtime));
        DEFINE(CFG_ICACHE_BLOCKSZ, offsetof(struct vdso_data, icache_block_size));
        DEFINE(CFG_DCACHE_BLOCKSZ, offsetof(struct vdso_data, dcache_block_size));
        DEFINE(CFG_ICACHE_LOGBLOCKSZ, offsetof(struct vdso_data, icache_log_block_size));
index 3a6eaa8..1c5c8a6 100644 (file)
@@ -120,6 +120,26 @@ static inline void dma_direct_unmap_page(struct device *dev,
 {
 }
 
+#ifdef CONFIG_NOT_COHERENT_CACHE
+static inline void dma_direct_sync_sg(struct device *dev,
+               struct scatterlist *sgl, int nents,
+               enum dma_data_direction direction)
+{
+       struct scatterlist *sg;
+       int i;
+
+       for_each_sg(sgl, sg, nents, i)
+               __dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
+}
+
+static inline void dma_direct_sync_single_range(struct device *dev,
+               dma_addr_t dma_handle, unsigned long offset, size_t size,
+               enum dma_data_direction direction)
+{
+       __dma_sync(bus_to_virt(dma_handle+offset), size, direction);
+}
+#endif
+
 struct dma_mapping_ops dma_direct_ops = {
        .alloc_coherent = dma_direct_alloc_coherent,
        .free_coherent  = dma_direct_free_coherent,
@@ -128,5 +148,11 @@ struct dma_mapping_ops dma_direct_ops = {
        .dma_supported  = dma_direct_dma_supported,
        .map_page       = dma_direct_map_page,
        .unmap_page     = dma_direct_unmap_page,
+#ifdef CONFIG_NOT_COHERENT_CACHE
+       .sync_single_range_for_cpu      = dma_direct_sync_single_range,
+       .sync_single_range_for_device   = dma_direct_sync_single_range,
+       .sync_sg_for_cpu                = dma_direct_sync_sg,
+       .sync_sg_for_device             = dma_direct_sync_sg,
+#endif
 };
 EXPORT_SYMBOL(dma_direct_ops);
index 590304c..9a4639c 100644 (file)
@@ -92,6 +92,7 @@ _ENTRY(_start);
  * if needed
  */
 
+_ENTRY(__early_start)
 /* 1. Find the index of the entry we're executing in */
        bl      invstr                          /* Find our address */
 invstr:        mflr    r6                              /* Make it accessible */
@@ -235,36 +236,40 @@ skpinv:   addi    r6,r6,1                         /* Increment */
        tlbivax 0,r9
        TLBSYNC
 
+/* The mapping only needs to be cache-coherent on SMP */
+#ifdef CONFIG_SMP
+#define M_IF_SMP       MAS2_M
+#else
+#define M_IF_SMP       0
+#endif
+
 /* 6. Setup KERNELBASE mapping in TLB1[0] */
        lis     r6,0x1000               /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */
        mtspr   SPRN_MAS0,r6
        lis     r6,(MAS1_VALID|MAS1_IPROT)@h
        ori     r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l
        mtspr   SPRN_MAS1,r6
-       li      r7,0
-       lis     r6,PAGE_OFFSET@h
-       ori     r6,r6,PAGE_OFFSET@l
-       rlwimi  r6,r7,0,20,31
+       lis     r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@h
+       ori     r6,r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@l
        mtspr   SPRN_MAS2,r6
        mtspr   SPRN_MAS3,r8
        tlbwe
 
 /* 7. Jump to KERNELBASE mapping */
-       lis     r6,KERNELBASE@h
-       ori     r6,r6,KERNELBASE@l
-       rlwimi  r6,r7,0,20,31
+       lis     r6,(KERNELBASE & ~0xfff)@h
+       ori     r6,r6,(KERNELBASE & ~0xfff)@l
        lis     r7,MSR_KERNEL@h
        ori     r7,r7,MSR_KERNEL@l
        bl      1f                      /* Find our address */
 1:     mflr    r9
        rlwimi  r6,r9,0,20,31
-       addi    r6,r6,24
+       addi    r6,r6,(2f - 1b)
        mtspr   SPRN_SRR0,r6
        mtspr   SPRN_SRR1,r7
        rfi                             /* start execution out of TLB1[0] entry */
 
 /* 8. Clear out the temp mapping */
-       lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
+2:     lis     r7,0x1000       /* Set MAS0(TLBSEL) = 1 */
        rlwimi  r7,r5,16,4,15   /* Setup MAS0 = TLBSEL | ESEL(r5) */
        mtspr   SPRN_MAS0,r7
        tlbre
@@ -344,6 +349,15 @@ skpinv:    addi    r6,r6,1                         /* Increment */
        mtspr   SPRN_DBSR,r2
 #endif
 
+#ifdef CONFIG_SMP
+       /* Check to see if we're the second processor, and jump
+        * to the secondary_start code if so
+        */
+       mfspr   r24,SPRN_PIR
+       cmpwi   r24,0
+       bne     __secondary_start
+#endif
+
        /*
         * This is where the main kernel code starts.
         */
@@ -685,12 +699,13 @@ interrupt_base:
        /* SPE Floating Point Data */
 #ifdef CONFIG_SPE
        EXCEPTION(0x2030, SPEFloatingPointData, SPEFloatingPointException, EXC_XFER_EE);
-#else
-       EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
-#endif /* CONFIG_SPE */
 
        /* SPE Floating Point Round */
+       EXCEPTION(0x2050, SPEFloatingPointRound, SPEFloatingPointRoundException, EXC_XFER_EE)
+#else
+       EXCEPTION(0x2040, SPEFloatingPointData, unknown_exception, EXC_XFER_EE)
        EXCEPTION(0x2050, SPEFloatingPointRound, unknown_exception, EXC_XFER_EE)
+#endif /* CONFIG_SPE */
 
        /* Performance Monitor */
        EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD)
@@ -735,6 +750,9 @@ finish_tlb_load:
 #else
        rlwimi  r12, r11, 26, 27, 31    /* extract WIMGE from pte */
 #endif
+#ifdef CONFIG_SMP
+       ori     r12, r12, MAS2_M
+#endif
        mtspr   SPRN_MAS2, r12
 
        li      r10, (_PAGE_HWEXEC | _PAGE_PRESENT)
@@ -746,7 +764,7 @@ finish_tlb_load:
        iseleq  r12, r12, r10
        
 #ifdef CONFIG_PTE_64BIT
-2:     rlwimi  r12, r13, 24, 0, 7      /* grab RPN[32:39] */
+       rlwimi  r12, r13, 24, 0, 7      /* grab RPN[32:39] */
        rlwimi  r12, r11, 24, 8, 19     /* grab RPN[40:51] */
        mtspr   SPRN_MAS3, r12
 BEGIN_FTR_SECTION
@@ -754,7 +772,7 @@ BEGIN_FTR_SECTION
        mtspr   SPRN_MAS7, r10
 END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
 #else
-2:     rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
+       rlwimi  r11, r12, 0, 20, 31     /* Extract RPN from PTE and merge with perms */
        mtspr   SPRN_MAS3, r11
 #endif
 #ifdef CONFIG_E200
@@ -1037,6 +1055,63 @@ _GLOBAL(flush_dcache_L1)
 
        blr
 
+#ifdef CONFIG_SMP
+/* When we get here, r24 needs to hold the CPU # */
+       .globl __secondary_start
+__secondary_start:
+       lis     r3,__secondary_hold_acknowledge@h
+       ori     r3,r3,__secondary_hold_acknowledge@l
+       stw     r24,0(r3)
+
+       li      r3,0
+       mr      r4,r24          /* Why? */
+       bl      call_setup_cpu
+
+       lis     r3,tlbcam_index@ha
+       lwz     r3,tlbcam_index@l(r3)
+       mtctr   r3
+       li      r26,0           /* r26 safe? */
+
+       /* Load each CAM entry */
+1:     mr      r3,r26
+       bl      loadcam_entry
+       addi    r26,r26,1
+       bdnz    1b
+
+       /* get current_thread_info and current */
+       lis     r1,secondary_ti@ha
+       lwz     r1,secondary_ti@l(r1)
+       lwz     r2,TI_TASK(r1)
+
+       /* stack */
+       addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+       li      r0,0
+       stw     r0,0(r1)
+
+       /* ptr to current thread */
+       addi    r4,r2,THREAD    /* address of our thread_struct */
+       mtspr   SPRN_SPRG3,r4
+
+       /* Setup the defaults for TLB entries */
+       li      r4,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+       mtspr   SPRN_MAS4,r4
+
+       /* Jump to start_secondary */
+       lis     r4,MSR_KERNEL@h
+       ori     r4,r4,MSR_KERNEL@l
+       lis     r3,start_secondary@h
+       ori     r3,r3,start_secondary@l
+       mtspr   SPRN_SRR0,r3
+       mtspr   SPRN_SRR1,r4
+       sync
+       rfi
+       sync
+
+       .globl __secondary_hold_acknowledge
+__secondary_hold_acknowledge:
+       .long   -1
+#endif
+
 /*
  * We put a few things here that have to be page-aligned. This stuff
  * goes at the beginning of the data segment, which is page-aligned.
index 64299d2..6e3f624 100644 (file)
@@ -47,7 +47,7 @@
 #include <asm/abs_addr.h>
 
 static struct device ibmebus_bus_device = { /* fake "parent" device */
-       .bus_id = "ibmebus",
+       .init_name = "ibmebus",
 };
 
 struct bus_type ibmebus_bus_type;
@@ -231,6 +231,7 @@ void ibmebus_free_irq(u32 ist, void *dev_id)
        unsigned int irq = irq_find_mapping(NULL, ist);
 
        free_irq(irq, dev_id);
+       irq_dispose_mapping(irq);
 }
 EXPORT_SYMBOL(ibmebus_free_irq);
 
index f3c9cae..fa983a5 100644 (file)
@@ -14,7 +14,6 @@ static void of_device_make_bus_id(struct of_device *dev)
 {
        static atomic_t bus_no_reg_magic;
        struct device_node *node = dev->node;
-       char *name = dev->dev.bus_id;
        const u32 *reg;
        u64 addr;
        int magic;
@@ -27,14 +26,12 @@ static void of_device_make_bus_id(struct of_device *dev)
        reg = of_get_property(node, "dcr-reg", NULL);
        if (reg) {
 #ifdef CONFIG_PPC_DCR_NATIVE
-               snprintf(name, BUS_ID_SIZE, "d%x.%s",
-                        *reg, node->name);
+               dev_set_name(&dev->dev, "d%x.%s", *reg, node->name);
 #else /* CONFIG_PPC_DCR_NATIVE */
                addr = of_translate_dcr_address(node, *reg, NULL);
                if (addr != OF_BAD_ADDR) {
-                       snprintf(name, BUS_ID_SIZE,
-                                "D%llx.%s", (unsigned long long)addr,
-                                node->name);
+                       dev_set_name(&dev->dev, "D%llx.%s",
+                                    (unsigned long long)addr, node->name);
                        return;
                }
 #endif /* !CONFIG_PPC_DCR_NATIVE */
@@ -48,9 +45,8 @@ static void of_device_make_bus_id(struct of_device *dev)
        if (reg) {
                addr = of_translate_address(node, reg);
                if (addr != OF_BAD_ADDR) {
-                       snprintf(name, BUS_ID_SIZE,
-                                "%llx.%s", (unsigned long long)addr,
-                                node->name);
+                       dev_set_name(&dev->dev, "%llx.%s",
+                                    (unsigned long long)addr, node->name);
                        return;
                }
        }
@@ -60,7 +56,7 @@ static void of_device_make_bus_id(struct of_device *dev)
         * counter (and pray...)
         */
        magic = atomic_add_return(1, &bus_no_reg_magic);
-       snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1);
+       dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1);
 }
 
 struct of_device *of_device_alloc(struct device_node *np,
@@ -80,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np,
        dev->dev.archdata.of_node = np;
 
        if (bus_id)
-               strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+               dev_set_name(&dev->dev, bus_id);
        else
                of_device_make_bus_id(dev);
 
index 48a3471..c744b32 100644 (file)
@@ -37,6 +37,7 @@ struct lppaca lppaca[] = {
                .end_of_quantum = 0xfffffffffffffffful,
                .slb_count = 64,
                .vmxregs_in_use = 0,
+               .page_ins = 0,
        },
 };
 
index f36936d..1a32db3 100644 (file)
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
 #include <asm/firmware.h>
-
-#ifdef DEBUG
-#include <asm/udbg.h>
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
+#include <asm/eeh.h>
 
 static DEFINE_SPINLOCK(hose_spinlock);
 
@@ -53,8 +47,9 @@ static int global_phb_number;         /* Global phb counter */
 /* ISA Memory physical address */
 resource_size_t isa_mem_base;
 
-/* Default PCI flags is 0 */
-unsigned int ppc_pci_flags;
+/* Default PCI flags is 0 on ppc32, modified at boot on ppc64 */
+unsigned int ppc_pci_flags = 0;
+
 
 static struct dma_mapping_ops *pci_dma_ops;
 
@@ -165,8 +160,6 @@ EXPORT_SYMBOL(pci_domain_nr);
  */
 struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
 {
-       if (!have_of)
-               return NULL;
        while(node) {
                struct pci_controller *hose, *tmp;
                list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
@@ -208,26 +201,6 @@ char __devinit *pcibios_setup(char *str)
        return str;
 }
 
-void __devinit pcibios_setup_new_device(struct pci_dev *dev)
-{
-       struct dev_archdata *sd = &dev->dev.archdata;
-
-       sd->of_node = pci_device_to_OF_node(dev);
-
-       DBG("PCI: device %s OF node: %s\n", pci_name(dev),
-           sd->of_node ? sd->of_node->full_name : "<none>");
-
-       sd->dma_ops = pci_dma_ops;
-#ifdef CONFIG_PPC32
-       sd->dma_data = (void *)PCI_DRAM_OFFSET;
-#endif
-       set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
-
-       if (ppc_md.pci_dma_dev_setup)
-               ppc_md.pci_dma_dev_setup(dev);
-}
-EXPORT_SYMBOL(pcibios_setup_new_device);
-
 /*
  * Reads the interrupt pin to determine if interrupt is use by card.
  * If the interrupt is used, then gets the interrupt line from the
@@ -252,7 +225,7 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
                return -1;
 #endif
 
-       DBG("Try to map irq for %s...\n", pci_name(pci_dev));
+       pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
 
 #ifdef DEBUG
        memset(&oirq, 0xff, sizeof(oirq));
@@ -276,26 +249,26 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
                    line == 0xff || line == 0) {
                        return -1;
                }
-               DBG(" -> no map ! Using line %d (pin %d) from PCI config\n",
-                   line, pin);
+               pr_debug(" No map ! Using line %d (pin %d) from PCI config\n",
+                        line, pin);
 
                virq = irq_create_mapping(NULL, line);
                if (virq != NO_IRQ)
                        set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
        } else {
-               DBG(" -> got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
-                   oirq.size, oirq.specifier[0], oirq.specifier[1],
+               pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+                        oirq.size, oirq.specifier[0], oirq.specifier[1],
                    oirq.controller->full_name);
 
                virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
                                             oirq.size);
        }
        if(virq == NO_IRQ) {
-               DBG(" -> failed to map !\n");
+               pr_debug(" Failed to map !\n");
                return -1;
        }
 
-       DBG(" -> mapped to linux irq %d\n", virq);
+       pr_debug(" Mapped to linux irq %d\n", virq);
 
        pci_dev->irq = virq;
 
@@ -451,8 +424,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
                pci_dev_put(pdev);
        }
 
-       DBG("non-PCI map for %llx, prot: %lx\n",
-           (unsigned long long)offset, prot);
+       pr_debug("PCI: Non-PCI map for %llx, prot: %lx\n",
+                (unsigned long long)offset, prot);
 
        return __pgprot(prot);
 }
@@ -853,15 +826,12 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
 int pci_proc_domain(struct pci_bus *bus)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
-#ifdef CONFIG_PPC64
-       return hose->buid != 0;
-#else
+
        if (!(ppc_pci_flags & PPC_PCI_ENABLE_PROC_DOMAINS))
                return 0;
        if (ppc_pci_flags & PPC_PCI_COMPAT_DOMAIN_0)
                return hose->global_number != 0;
        return 1;
-#endif
 }
 
 void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
@@ -1083,27 +1053,50 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
        }
 }
 
-static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
+void __devinit pcibios_setup_bus_self(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB");
-
-       /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for
-        * now differently between 32 and 64 bits.
-        */
-       if (dev != NULL)
+       /* Fix up the bus resources for P2P bridges */
+       if (bus->self != NULL)
                pcibios_fixup_bridge(bus);
 
-       /* Additional setup that is different between 32 and 64 bits for now */
-       pcibios_do_bus_setup(bus);
-
-       /* Platform specific bus fixups */
+       /* Platform specific bus fixups. This is currently only used
+        * by fsl_pci and I'm hoping to get rid of it at some point
+        */
        if (ppc_md.pcibios_fixup_bus)
                ppc_md.pcibios_fixup_bus(bus);
 
-       /* Read default IRQs and fixup if necessary */
+       /* Setup bus DMA mappings */
+       if (ppc_md.pci_dma_bus_setup)
+               ppc_md.pci_dma_bus_setup(bus);
+}
+
+void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+
+       pr_debug("PCI: Fixup bus devices %d (%s)\n",
+                bus->number, bus->self ? pci_name(bus->self) : "PHB");
+
        list_for_each_entry(dev, &bus->devices, bus_list) {
+               struct dev_archdata *sd = &dev->dev.archdata;
+
+               /* Setup OF node pointer in archdata */
+               sd->of_node = pci_device_to_OF_node(dev);
+
+               /* Fixup NUMA node as it may not be setup yet by the generic
+                * code and is needed by the DMA init
+                */
+               set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
+
+               /* Hook up default DMA ops */
+               sd->dma_ops = pci_dma_ops;
+               sd->dma_data = (void *)PCI_DRAM_OFFSET;
+
+               /* Additional platform DMA/iommu setup */
+               if (ppc_md.pci_dma_dev_setup)
+                       ppc_md.pci_dma_dev_setup(dev);
+
+               /* Read default IRQs and fixup if necessary */
                pci_read_irq_line(dev);
                if (ppc_md.pci_irq_fixup)
                        ppc_md.pci_irq_fixup(dev);
@@ -1113,22 +1106,19 @@ static void __devinit __pcibios_fixup_bus(struct pci_bus *bus)
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
 {
        /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases before proceeding
+        * bases. This is -not- called when generating the PCI tree from
+        * the OF device-tree.
         */
        if (bus->self != NULL)
                pci_read_bridge_bases(bus);
-       __pcibios_fixup_bus(bus);
-}
-EXPORT_SYMBOL(pcibios_fixup_bus);
 
-/* When building a bus from the OF tree rather than probing, we need a
- * slightly different version of the fixup which doesn't read the
- * bridge bases using config space accesses
- */
-void __devinit pcibios_fixup_of_probed_bus(struct pci_bus *bus)
-{
-       __pcibios_fixup_bus(bus);
+       /* Now fixup the bus bus */
+       pcibios_setup_bus_self(bus);
+
+       /* Now fixup devices on that bus */
+       pcibios_setup_bus_devices(bus);
 }
+EXPORT_SYMBOL(pcibios_fixup_bus);
 
 static int skip_isa_ioresource_align(struct pci_dev *dev)
 {
@@ -1198,10 +1188,10 @@ static int __init reparent_resources(struct resource *parent,
        *pp = NULL;
        for (p = res->child; p != NULL; p = p->sibling) {
                p->parent = res;
-               DBG(KERN_INFO "PCI: reparented %s [%llx..%llx] under %s\n",
-                   p->name,
-                   (unsigned long long)p->start,
-                   (unsigned long long)p->end, res->name);
+               pr_debug("PCI: Reparented %s [%llx..%llx] under %s\n",
+                        p->name,
+                        (unsigned long long)p->start,
+                        (unsigned long long)p->end, res->name);
        }
        return 0;
 }
@@ -1245,9 +1235,12 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
        int i;
        struct resource *res, *pr;
 
+       pr_debug("PCI: Allocating bus resources for %04x:%02x...\n",
+                pci_domain_nr(bus), bus->number);
+
        for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) {
                if ((res = bus->resource[i]) == NULL || !res->flags
-                   || res->start > res->end)
+                   || res->start > res->end || res->parent)
                        continue;
                if (bus->parent == NULL)
                        pr = (res->flags & IORESOURCE_IO) ?
@@ -1271,14 +1264,14 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
                        }
                }
 
-               DBG("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
-                   "[0x%x], parent %p (%s)\n",
-                   bus->self ? pci_name(bus->self) : "PHB",
-                   bus->number, i,
-                   (unsigned long long)res->start,
-                   (unsigned long long)res->end,
-                   (unsigned int)res->flags,
-                   pr, (pr && pr->name) ? pr->name : "nil");
+               pr_debug("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx "
+                        "[0x%x], parent %p (%s)\n",
+                        bus->self ? pci_name(bus->self) : "PHB",
+                        bus->number, i,
+                        (unsigned long long)res->start,
+                        (unsigned long long)res->end,
+                        (unsigned int)res->flags,
+                        pr, (pr && pr->name) ? pr->name : "nil");
 
                if (pr && !(pr->flags & IORESOURCE_UNSET)) {
                        if (request_resource(pr, res) == 0)
@@ -1305,11 +1298,11 @@ static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
 {
        struct resource *pr, *r = &dev->resource[idx];
 
-       DBG("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
-           pci_name(dev), idx,
-           (unsigned long long)r->start,
-           (unsigned long long)r->end,
-           (unsigned int)r->flags);
+       pr_debug("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
+                pci_name(dev), idx,
+                (unsigned long long)r->start,
+                (unsigned long long)r->end,
+                (unsigned int)r->flags);
 
        pr = pci_find_parent_resource(dev, r);
        if (!pr || (pr->flags & IORESOURCE_UNSET) ||
@@ -1317,10 +1310,11 @@ static inline void __devinit alloc_resource(struct pci_dev *dev, int idx)
                printk(KERN_WARNING "PCI: Cannot allocate resource region %d"
                       " of device %s, will remap\n", idx, pci_name(dev));
                if (pr)
-                       DBG("PCI:  parent is %p: %016llx-%016llx [%x]\n", pr,
-                           (unsigned long long)pr->start,
-                           (unsigned long long)pr->end,
-                           (unsigned int)pr->flags);
+                       pr_debug("PCI:  parent is %p: %016llx-%016llx [%x]\n",
+                                pr,
+                                (unsigned long long)pr->start,
+                                (unsigned long long)pr->end,
+                                (unsigned int)pr->flags);
                /* We'll assign a new address later */
                r->flags |= IORESOURCE_UNSET;
                r->end -= r->start;
@@ -1358,7 +1352,8 @@ static void __init pcibios_allocate_resources(int pass)
                         * but keep it unregistered.
                         */
                        u32 reg;
-                       DBG("PCI: Switching off ROM of %s\n", pci_name(dev));
+                       pr_debug("PCI: Switching off ROM of %s\n",
+                                pci_name(dev));
                        r->flags &= ~IORESOURCE_ROM_ENABLE;
                        pci_read_config_dword(dev, dev->rom_base_reg, &reg);
                        pci_write_config_dword(dev, dev->rom_base_reg,
@@ -1383,7 +1378,7 @@ void __init pcibios_resource_survey(void)
        }
 
        if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) {
-               DBG("PCI: Assigning unassigned resouces...\n");
+               pr_debug("PCI: Assigning unassigned resouces...\n");
                pci_assign_unassigned_resources();
        }
 
@@ -1393,9 +1388,11 @@ void __init pcibios_resource_survey(void)
 }
 
 #ifdef CONFIG_HOTPLUG
-/* This is used by the pSeries hotplug driver to allocate resource
+
+/* This is used by the PCI hotplug driver to allocate resource
  * of newly plugged busses. We can try to consolidate with the
- * rest of the code later, for now, keep it as-is
+ * rest of the code later, for now, keep it as-is as our main
+ * resource allocation function doesn't deal with sub-trees yet.
  */
 void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
 {
@@ -1410,6 +1407,14 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
 
                        if (r->parent || !r->start || !r->flags)
                                continue;
+
+                       pr_debug("PCI: Claiming %s: "
+                                "Resource %d: %016llx..%016llx [%x]\n",
+                                pci_name(dev), i,
+                                (unsigned long long)r->start,
+                                (unsigned long long)r->end,
+                                (unsigned int)r->flags);
+
                        pci_claim_resource(dev, i);
                }
        }
@@ -1418,6 +1423,31 @@ void __devinit pcibios_claim_one_bus(struct pci_bus *bus)
                pcibios_claim_one_bus(child_bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_claim_one_bus);
+
+
+/* pcibios_finish_adding_to_bus
+ *
+ * This is to be called by the hotplug code after devices have been
+ * added to a bus, this include calling it for a PHB that is just
+ * being added
+ */
+void pcibios_finish_adding_to_bus(struct pci_bus *bus)
+{
+       pr_debug("PCI: Finishing adding to hotplug bus %04x:%02x\n",
+                pci_domain_nr(bus), bus->number);
+
+       /* Allocate bus and devices resources */
+       pcibios_allocate_bus_resources(bus);
+       pcibios_claim_one_bus(bus);
+
+       /* Add new devices to global lists.  Register in proc, sysfs. */
+       pci_bus_add_devices(bus);
+
+       /* Fixup EEH */
+       eeh_add_device_tree_late(bus);
+}
+EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
+
 #endif /* CONFIG_HOTPLUG */
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
@@ -1428,3 +1458,61 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
        return pci_enable_resources(dev, mask);
 }
+
+void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
+{
+       struct pci_bus *bus = hose->bus;
+       struct resource *res;
+       int i;
+
+       /* Hookup PHB IO resource */
+       bus->resource[0] = res = &hose->io_resource;
+
+       if (!res->flags) {
+               printk(KERN_WARNING "PCI: I/O resource not set for host"
+                      " bridge %s (domain %d)\n",
+                      hose->dn->full_name, hose->global_number);
+#ifdef CONFIG_PPC32
+               /* Workaround for lack of IO resource only on 32-bit */
+               res->start = (unsigned long)hose->io_base_virt - isa_io_base;
+               res->end = res->start + IO_SPACE_LIMIT;
+               res->flags = IORESOURCE_IO;
+#endif /* CONFIG_PPC32 */
+       }
+
+       pr_debug("PCI: PHB IO resource    = %016llx-%016llx [%lx]\n",
+                (unsigned long long)res->start,
+                (unsigned long long)res->end,
+                (unsigned long)res->flags);
+
+       /* Hookup PHB Memory resources */
+       for (i = 0; i < 3; ++i) {
+               res = &hose->mem_resources[i];
+               if (!res->flags) {
+                       if (i > 0)
+                               continue;
+                       printk(KERN_ERR "PCI: Memory resource 0 not set for "
+                              "host bridge %s (domain %d)\n",
+                              hose->dn->full_name, hose->global_number);
+#ifdef CONFIG_PPC32
+                       /* Workaround for lack of MEM resource only on 32-bit */
+                       res->start = hose->pci_mem_offset;
+                       res->end = (resource_size_t)-1LL;
+                       res->flags = IORESOURCE_MEM;
+#endif /* CONFIG_PPC32 */
+               }
+               bus->resource[i+1] = res;
+
+               pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i,
+                        (unsigned long long)res->start,
+                        (unsigned long long)res->end,
+                        (unsigned long)res->flags);
+       }
+
+       pr_debug("PCI: PHB MEM offset     = %016llx\n",
+                (unsigned long long)hose->pci_mem_offset);
+       pr_debug("PCI: PHB IO  offset     = %08lx\n",
+                (unsigned long)hose->io_base_virt - _IO_BASE);
+
+}
+
index 131b1df..132cd80 100644 (file)
 
 #undef DEBUG
 
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
 unsigned long isa_io_base     = 0;
 unsigned long pci_dram_offset = 0;
 int pcibios_assign_bus_offset = 1;
@@ -272,17 +266,14 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn)
 {
        struct device_node *parent, *np;
 
-       if (!have_of)
-               return NULL;
-
-       DBG("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
+       pr_debug("pci_busdev_to_OF_node(%d,0x%x)\n", bus->number, devfn);
        parent = scan_OF_for_pci_bus(bus);
        if (parent == NULL)
                return NULL;
-       DBG(" parent is %s\n", parent ? parent->full_name : "<NULL>");
+       pr_debug(" parent is %s\n", parent ? parent->full_name : "<NULL>");
        np = scan_OF_for_pci_dev(parent, devfn);
        of_node_put(parent);
-       DBG(" result is %s\n", np ? np->full_name : "<NULL>");
+       pr_debug(" result is %s\n", np ? np->full_name : "<NULL>");
 
        /* XXX most callers don't release the returned node
         * mostly because ppc64 doesn't increase the refcount,
@@ -315,8 +306,6 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
        struct pci_controller* hose;
        struct pci_dev* dev = NULL;
        
-       if (!have_of)
-               return -ENODEV;
        /* Make sure it's really a PCI device */
        hose = pci_find_hose_for_OF_device(node);
        if (!hose || !hose->dn)
@@ -379,10 +368,41 @@ void pcibios_make_OF_bus_map(void)
 }
 #endif /* CONFIG_PPC_OF */
 
+static void __devinit pcibios_scan_phb(struct pci_controller *hose)
+{
+       struct pci_bus *bus;
+       struct device_node *node = hose->dn;
+       unsigned long io_offset;
+       struct resource *res = &hose->io_resource;
+
+       pr_debug("PCI: Scanning PHB %s\n",
+                node ? node->full_name : "<NO NAME>");
+
+       /* Create an empty bus for the toplevel */
+       bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
+       if (bus == NULL) {
+               printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
+                      hose->global_number);
+               return;
+       }
+       bus->secondary = hose->first_busno;
+       hose->bus = bus;
+
+       /* Fixup IO space offset */
+       io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+       res->start = (res->start + io_offset) & 0xffffffffu;
+       res->end = (res->end + io_offset) & 0xffffffffu;
+
+       /* Wire up PHB bus resources */
+       pcibios_setup_phb_resources(hose);
+
+       /* Scan children */
+       hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
+}
+
 static int __init pcibios_init(void)
 {
        struct pci_controller *hose, *tmp;
-       struct pci_bus *bus;
        int next_busno = 0;
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
@@ -395,12 +415,8 @@ static int __init pcibios_init(void)
                if (pci_assign_all_buses)
                        hose->first_busno = next_busno;
                hose->last_busno = 0xff;
-               bus = pci_scan_bus_parented(hose->parent, hose->first_busno,
-                                           hose->ops, hose);
-               if (bus) {
-                       pci_bus_add_devices(bus);
-                       hose->last_busno = bus->subordinate;
-               }
+               pcibios_scan_phb(hose);
+               pci_bus_add_devices(hose->bus);
                if (pci_assign_all_buses || next_busno <= hose->last_busno)
                        next_busno = hose->last_busno + pcibios_assign_bus_offset;
        }
@@ -410,7 +426,7 @@ static int __init pcibios_init(void)
         * numbers vs. kernel bus numbers since we may have to
         * remap them.
         */
-       if (pci_assign_all_buses && have_of)
+       if (pci_assign_all_buses)
                pcibios_make_OF_bus_map();
 
        /* Call common code to handle resource allocation */
@@ -425,54 +441,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
-{
-       struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
-       unsigned long io_offset;
-       struct resource *res;
-       int i;
-       struct pci_dev *dev;
-
-       /* Hookup PHB resources */
-       io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
-       if (bus->parent == NULL) {
-               /* This is a host bridge - fill in its resources */
-               hose->bus = bus;
-
-               bus->resource[0] = res = &hose->io_resource;
-               if (!res->flags) {
-                       if (io_offset)
-                               printk(KERN_ERR "I/O resource not set for host"
-                                      " bridge %d\n", hose->global_number);
-                       res->start = 0;
-                       res->end = IO_SPACE_LIMIT;
-                       res->flags = IORESOURCE_IO;
-               }
-               res->start = (res->start + io_offset) & 0xffffffffu;
-               res->end = (res->end + io_offset) & 0xffffffffu;
-
-               for (i = 0; i < 3; ++i) {
-                       res = &hose->mem_resources[i];
-                       if (!res->flags) {
-                               if (i > 0)
-                                       continue;
-                               printk(KERN_ERR "Memory resource not set for "
-                                      "host bridge %d\n", hose->global_number);
-                               res->start = hose->pci_mem_offset;
-                               res->end = ~0U;
-                               res->flags = IORESOURCE_MEM;
-                       }
-                       bus->resource[i+1] = res;
-               }
-       }
-
-       if (ppc_md.pci_dma_bus_setup)
-               ppc_md.pci_dma_bus_setup(bus);
-
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               pcibios_setup_new_device(dev);
-}
-
 /* the next one is stolen from the alpha port... */
 void __init
 pcibios_update_irq(struct pci_dev *dev, int irq)
index 3502b91..39fadc6 100644 (file)
 #include <asm/machdep.h>
 #include <asm/ppc-pci.h>
 
-#ifdef DEBUG
-#include <asm/udbg.h>
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
 unsigned long pci_probe_only = 1;
 
 /* pci_io_base -- the base address from which io bars are offsets.
@@ -102,7 +95,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
        addrs = of_get_property(node, "assigned-addresses", &proplen);
        if (!addrs)
                return;
-       DBG("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
+       pr_debug("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
        for (; proplen >= 20; proplen -= 20, addrs += 5) {
                flags = pci_parse_of_flags(addrs[0]);
                if (!flags)
@@ -112,8 +105,9 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
                if (!size)
                        continue;
                i = addrs[0] & 0xff;
-               DBG("  base: %llx, size: %llx, i: %x\n",
-                   (unsigned long long)base, (unsigned long long)size, i);
+               pr_debug("  base: %llx, size: %llx, i: %x\n",
+                        (unsigned long long)base,
+                        (unsigned long long)size, i);
 
                if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
                        res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
@@ -144,7 +138,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        if (type == NULL)
                type = "";
 
-       DBG("    create device, devfn: %x, type: %s\n", devfn, type);
+       pr_debug("    create device, devfn: %x, type: %s\n", devfn, type);
 
        dev->bus = bus;
        dev->sysdata = node;
@@ -165,8 +159,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
        dev->class = get_int_prop(node, "class-code", 0);
        dev->revision = get_int_prop(node, "revision-id", 0);
 
-       DBG("    class: 0x%x\n", dev->class);
-       DBG("    revision: 0x%x\n", dev->revision);
+       pr_debug("    class: 0x%x\n", dev->class);
+       pr_debug("    revision: 0x%x\n", dev->revision);
 
        dev->current_state = 4;         /* unknown power state */
        dev->error_state = pci_channel_io_normal;
@@ -187,7 +181,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 
        pci_parse_of_addrs(node, dev);
 
-       DBG("    adding to system ...\n");
+       pr_debug("    adding to system ...\n");
 
        pci_device_add(dev, bus);
 
@@ -195,19 +189,20 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 }
 EXPORT_SYMBOL(of_create_pci_dev);
 
-void __devinit of_scan_bus(struct device_node *node,
-                          struct pci_bus *bus)
+static void __devinit __of_scan_bus(struct device_node *node,
+                                   struct pci_bus *bus, int rescan_existing)
 {
        struct device_node *child;
        const u32 *reg;
        int reglen, devfn;
        struct pci_dev *dev;
 
-       DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
+       pr_debug("of_scan_bus(%s) bus no %d... \n",
+                node->full_name, bus->number);
 
        /* Scan direct children */
        for_each_child_of_node(node, child) {
-               DBG("  * %s\n", child->full_name);
+               pr_debug("  * %s\n", child->full_name);
                reg = of_get_property(child, "reg", &reglen);
                if (reg == NULL || reglen < 20)
                        continue;
@@ -217,11 +212,15 @@ void __devinit of_scan_bus(struct device_node *node,
                dev = of_create_pci_dev(child, bus, devfn);
                if (!dev)
                        continue;
-               DBG("    dev header type: %x\n", dev->hdr_type);
+               pr_debug("    dev header type: %x\n", dev->hdr_type);
        }
 
-       /* Ally all fixups */
-       pcibios_fixup_of_probed_bus(bus);
+       /* Apply all fixups necessary. We don't fixup the bus "self"
+        * for an existing bridge that is being rescanned
+        */
+       if (!rescan_existing)
+               pcibios_setup_bus_self(bus);
+       pcibios_setup_bus_devices(bus);
 
        /* Now scan child busses */
        list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -233,7 +232,20 @@ void __devinit of_scan_bus(struct device_node *node,
                }
        }
 }
-EXPORT_SYMBOL(of_scan_bus);
+
+void __devinit of_scan_bus(struct device_node *node,
+                          struct pci_bus *bus)
+{
+       __of_scan_bus(node, bus, 0);
+}
+EXPORT_SYMBOL_GPL(of_scan_bus);
+
+void __devinit of_rescan_bus(struct device_node *node,
+                            struct pci_bus *bus)
+{
+       __of_scan_bus(node, bus, 1);
+}
+EXPORT_SYMBOL_GPL(of_rescan_bus);
 
 void __devinit of_scan_pci_bridge(struct device_node *node,
                                  struct pci_dev *dev)
@@ -245,7 +257,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
        unsigned int flags;
        u64 size;
 
-       DBG("of_scan_pci_bridge(%s)\n", node->full_name);
+       pr_debug("of_scan_pci_bridge(%s)\n", node->full_name);
 
        /* parse bus-range property */
        busrange = of_get_property(node, "bus-range", &len);
@@ -309,12 +321,12 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
        }
        sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
                bus->number);
-       DBG("    bus name: %s\n", bus->name);
+       pr_debug("    bus name: %s\n", bus->name);
 
        mode = PCI_PROBE_NORMAL;
        if (ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
-       DBG("    probe mode: %d\n", mode);
+       pr_debug("    probe mode: %d\n", mode);
 
        if (mode == PCI_PROBE_DEVTREE)
                of_scan_bus(node, bus);
@@ -327,9 +339,10 @@ void __devinit scan_phb(struct pci_controller *hose)
 {
        struct pci_bus *bus;
        struct device_node *node = hose->dn;
-       int i, mode;
+       int mode;
 
-       DBG("PCI: Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+       pr_debug("PCI: Scanning PHB %s\n",
+                node ? node->full_name : "<NO NAME>");
 
        /* Create an empty bus for the toplevel */
        bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
@@ -345,26 +358,13 @@ void __devinit scan_phb(struct pci_controller *hose)
        pcibios_map_io_space(bus);
 
        /* Wire up PHB bus resources */
-       DBG("PCI: PHB IO resource    = %016lx-%016lx [%lx]\n",
-           hose->io_resource.start, hose->io_resource.end,
-           hose->io_resource.flags);
-       bus->resource[0] = &hose->io_resource;
-       for (i = 0; i < 3; ++i) {
-               DBG("PCI: PHB MEM resource %d = %016lx-%016lx [%lx]\n", i,
-                   hose->mem_resources[i].start,
-                   hose->mem_resources[i].end,
-                   hose->mem_resources[i].flags);
-               bus->resource[i+1] = &hose->mem_resources[i];
-       }
-       DBG("PCI: PHB MEM offset     = %016lx\n", hose->pci_mem_offset);
-       DBG("PCI: PHB IO  offset     = %08lx\n",
-           (unsigned long)hose->io_base_virt - _IO_BASE);
+       pcibios_setup_phb_resources(hose);
 
        /* Get probe mode and perform scan */
        mode = PCI_PROBE_NORMAL;
        if (node && ppc_md.pci_probe_mode)
                mode = ppc_md.pci_probe_mode(bus);
-       DBG("    probe mode: %d\n", mode);
+       pr_debug("    probe mode: %d\n", mode);
        if (mode == PCI_PROBE_DEVTREE) {
                bus->subordinate = hose->last_busno;
                of_scan_bus(node, bus);
@@ -380,7 +380,7 @@ static int __init pcibios_init(void)
 
        printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
-       /* For now, override phys_mem_access_prot. If we need it,
+       /* For now, override phys_mem_access_prot. If we need it,g
         * later, we may move that initialization to each ppc_md
         */
        ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
@@ -388,6 +388,11 @@ static int __init pcibios_init(void)
        if (pci_probe_only)
                ppc_pci_flags |= PPC_PCI_PROBE_ONLY;
 
+       /* On ppc64, we always enable PCI domains and we keep domain 0
+        * backward compatible in /proc for video cards
+        */
+       ppc_pci_flags |= PPC_PCI_ENABLE_PROC_DOMAINS | PPC_PCI_COMPAT_DOMAIN_0;
+
        /* Scan all of the recorded PCI controllers.  */
        list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
                scan_phb(hose);
@@ -422,8 +427,8 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
        if (bus->self) {
                struct resource *res = bus->resource[0];
 
-               DBG("IO unmapping for PCI-PCI bridge %s\n",
-                   pci_name(bus->self));
+               pr_debug("IO unmapping for PCI-PCI bridge %s\n",
+                        pci_name(bus->self));
 
                __flush_hash_table_range(&init_mm, res->start + _IO_BASE,
                                         res->end + _IO_BASE + 1);
@@ -437,8 +442,8 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
        if (hose->io_base_alloc == 0)
                return 0;
 
-       DBG("IO unmapping for PHB %s\n", hose->dn->full_name);
-       DBG("  alloc=0x%p\n", hose->io_base_alloc);
+       pr_debug("IO unmapping for PHB %s\n", hose->dn->full_name);
+       pr_debug("  alloc=0x%p\n", hose->io_base_alloc);
 
        /* This is a PHB, we fully unmap the IO area */
        vunmap(hose->io_base_alloc);
@@ -463,11 +468,11 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
         * thus HPTEs will be faulted in when needed
         */
        if (bus->self) {
-               DBG("IO mapping for PCI-PCI bridge %s\n",
-                   pci_name(bus->self));
-               DBG("  virt=0x%016lx...0x%016lx\n",
-                   bus->resource[0]->start + _IO_BASE,
-                   bus->resource[0]->end + _IO_BASE);
+               pr_debug("IO mapping for PCI-PCI bridge %s\n",
+                        pci_name(bus->self));
+               pr_debug("  virt=0x%016lx...0x%016lx\n",
+                        bus->resource[0]->start + _IO_BASE,
+                        bus->resource[0]->end + _IO_BASE);
                return 0;
        }
 
@@ -496,11 +501,11 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
        hose->io_base_virt = (void __iomem *)(area->addr +
                                              hose->io_base_phys - phys_page);
 
-       DBG("IO mapping for PHB %s\n", hose->dn->full_name);
-       DBG("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
-           hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
-       DBG("  size=0x%016lx (alloc=0x%016lx)\n",
-           hose->pci_io_size, size_page);
+       pr_debug("IO mapping for PHB %s\n", hose->dn->full_name);
+       pr_debug("  phys=0x%016lx, virt=0x%p (alloc=0x%p)\n",
+                hose->io_base_phys, hose->io_base_virt, hose->io_base_alloc);
+       pr_debug("  size=0x%016lx (alloc=0x%016lx)\n",
+                hose->pci_io_size, size_page);
 
        /* Establish the mapping */
        if (__ioremap_at(phys_page, area->addr, size_page,
@@ -512,24 +517,13 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
        hose->io_resource.start += io_virt_offset;
        hose->io_resource.end += io_virt_offset;
 
-       DBG("  hose->io_resource=0x%016lx...0x%016lx\n",
-           hose->io_resource.start, hose->io_resource.end);
+       pr_debug("  hose->io_resource=0x%016lx...0x%016lx\n",
+                hose->io_resource.start, hose->io_resource.end);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(pcibios_map_io_space);
 
-void __devinit pcibios_do_bus_setup(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-
-       if (ppc_md.pci_dma_bus_setup)
-               ppc_md.pci_dma_bus_setup(bus);
-
-       list_for_each_entry(dev, &bus->devices, bus_list)
-               pcibios_setup_new_device(dev);
-}
-
 unsigned long pci_address_to_pio(phys_addr_t address)
 {
        struct pci_controller *hose, *tmp;
index 957bded..51b201d 100644 (file)
@@ -467,6 +467,8 @@ static struct regbit {
        {MSR_VEC,       "VEC"},
        {MSR_VSX,       "VSX"},
        {MSR_ME,        "ME"},
+       {MSR_CE,        "CE"},
+       {MSR_DE,        "DE"},
        {MSR_IR,        "IR"},
        {MSR_DR,        "DR"},
        {0,             NULL}
@@ -998,7 +1000,7 @@ unsigned long get_wchan(struct task_struct *p)
        return 0;
 }
 
-static int kstack_depth_to_print = 64;
+static int kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
 
 void show_stack(struct task_struct *tsk, unsigned long *stack)
 {
index a11d689..8c13355 100644 (file)
@@ -734,10 +734,7 @@ void of_irq_map_init(unsigned int flags)
        if (flags & OF_IMAP_NO_PHANDLE) {
                struct device_node *np;
 
-               for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) {
-                       if (of_get_property(np, "interrupt-controller", NULL)
-                           == NULL)
-                               continue;
+               for_each_node_with_property(np, "interrupt-controller") {
                        /* Skip /chosen/interrupt-controller */
                        if (strcmp(np->name, "chosen") == 0)
                                continue;
index 1f8505c..fdfe14c 100644 (file)
@@ -566,6 +566,32 @@ int rtas_get_sensor(int sensor, int index, int *state)
 }
 EXPORT_SYMBOL(rtas_get_sensor);
 
+bool rtas_indicator_present(int token, int *maxindex)
+{
+       int proplen, count, i;
+       const struct indicator_elem {
+               u32 token;
+               u32 maxindex;
+       } *indicators;
+
+       indicators = of_get_property(rtas.dev, "rtas-indicators", &proplen);
+       if (!indicators)
+               return false;
+
+       count = proplen / sizeof(struct indicator_elem);
+
+       for (i = 0; i < count; i++) {
+               if (indicators[i].token != token)
+                       continue;
+               if (maxindex)
+                       *maxindex = indicators[i].maxindex;
+               return true;
+       }
+
+       return false;
+}
+EXPORT_SYMBOL(rtas_indicator_present);
+
 int rtas_set_indicator(int indicator, int index, int new_value)
 {
        int token = rtas_token("set-indicator");
index 589a279..8869001 100644 (file)
@@ -301,51 +301,3 @@ void __init find_and_init_phbs(void)
 #endif /* CONFIG_PPC32 */
        }
 }
-
-/* RPA-specific bits for removing PHBs */
-int pcibios_remove_root_bus(struct pci_controller *phb)
-{
-       struct pci_bus *b = phb->bus;
-       struct resource *res;
-       int rc, i;
-
-       res = b->resource[0];
-       if (!res->flags) {
-               printk(KERN_ERR "%s: no IO resource for PHB %s\n", __func__,
-                               b->name);
-               return 1;
-       }
-
-       rc = pcibios_unmap_io_space(b);
-       if (rc) {
-               printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
-                       __func__, b->name);
-               return 1;
-       }
-
-       if (release_resource(res)) {
-               printk(KERN_ERR "%s: failed to release IO on bus %s\n",
-                               __func__, b->name);
-               return 1;
-       }
-
-       for (i = 1; i < 3; ++i) {
-               res = b->resource[i];
-               if (!res->flags && i == 0) {
-                       printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
-                               __func__, b->name);
-                       return 1;
-               }
-               if (res->flags && release_resource(res)) {
-                       printk(KERN_ERR
-                              "%s: failed to release IO %d on bus %s\n",
-                               __func__, i, b->name);
-                       return 1;
-               }
-       }
-
-       pcibios_free_controller(phb);
-
-       return 0;
-}
-EXPORT_SYMBOL(pcibios_remove_root_bus);
index c1a2762..086c23c 100644 (file)
@@ -49,12 +49,12 @@ int boot_cpuid;
 EXPORT_SYMBOL_GPL(boot_cpuid);
 int boot_cpuid_phys;
 
+int smp_hw_index[NR_CPUS];
+
 unsigned long ISA_DMA_THRESHOLD;
 unsigned int DMA_MODE_READ;
 unsigned int DMA_MODE_WRITE;
 
-int have_of = 1;
-
 #ifdef CONFIG_VGA_CONSOLE
 unsigned long vgacon_remap_base;
 EXPORT_SYMBOL(vgacon_remap_base);
index 169d74c..ce48f5c 100644 (file)
@@ -70,7 +70,6 @@
 #define DBG(fmt...)
 #endif
 
-int have_of = 1;
 int boot_cpuid = 0;
 u64 ppc64_pft_size;
 
@@ -606,8 +605,6 @@ void __init setup_per_cpu_areas(void)
 
        for_each_possible_cpu(i) {
                ptr = alloc_bootmem_pages_node(NODE_DATA(cpu_to_node(i)), size);
-               if (!ptr)
-                       panic("Cannot allocate cpu data for CPU %d\n", i);
 
                paca[i].data_offset = ptr - __per_cpu_start;
                memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
index bc892e6..a5e5452 100644 (file)
@@ -113,7 +113,7 @@ void __devinit smp_generic_give_timebase(void)
 {
        int i, score, score2, old, min=0, max=5000, offset=1000;
 
-       printk("Synchronizing timebase\n");
+       pr_debug("Software timebase sync\n");
 
        /* if this fails then this kernel won't work anyway... */
        tbsync = kzalloc( sizeof(*tbsync), GFP_KERNEL );
@@ -123,13 +123,13 @@ void __devinit smp_generic_give_timebase(void)
        while (!tbsync->ack)
                barrier();
 
-       printk("Got ack\n");
+       pr_debug("Got ack\n");
 
        /* binary search */
        for (old = -1; old != offset ; offset = (min+max) / 2) {
                score = start_contest(kSetAndTest, offset, NUM_ITER);
 
-               printk("score %d, offset %d\n", score, offset );
+               pr_debug("score %d, offset %d\n", score, offset );
 
                if( score > 0 )
                        max = offset;
@@ -140,8 +140,8 @@ void __devinit smp_generic_give_timebase(void)
        score = start_contest(kSetAndTest, min, NUM_ITER);
        score2 = start_contest(kSetAndTest, max, NUM_ITER);
 
-       printk("Min %d (score %d), Max %d (score %d)\n",
-              min, score, max, score2);
+       pr_debug("Min %d (score %d), Max %d (score %d)\n",
+                min, score, max, score2);
        score = abs(score);
        score2 = abs(score2);
        offset = (score < score2) ? min : max;
@@ -155,7 +155,7 @@ void __devinit smp_generic_give_timebase(void)
                if (score2 <= score || score2 < 20)
                        break;
        }
-       printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
+       pr_debug("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER );
 
        /* exiting */
        tbsync->cmd = kExit;
index ff9f701..ffcb177 100644 (file)
@@ -57,7 +57,6 @@
 #define DBG(fmt...)
 #endif
 
-int smp_hw_index[NR_CPUS];
 struct thread_info *secondary_ti;
 
 cpumask_t cpu_possible_map = CPU_MASK_NONE;
@@ -123,6 +122,65 @@ void smp_message_recv(int msg)
        }
 }
 
+static irqreturn_t call_function_action(int irq, void *data)
+{
+       generic_smp_call_function_interrupt();
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t reschedule_action(int irq, void *data)
+{
+       /* we just need the return path side effect of checking need_resched */
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t call_function_single_action(int irq, void *data)
+{
+       generic_smp_call_function_single_interrupt();
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t debug_ipi_action(int irq, void *data)
+{
+       smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
+       return IRQ_HANDLED;
+}
+
+static irq_handler_t smp_ipi_action[] = {
+       [PPC_MSG_CALL_FUNCTION] =  call_function_action,
+       [PPC_MSG_RESCHEDULE] = reschedule_action,
+       [PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
+       [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
+};
+
+const char *smp_ipi_name[] = {
+       [PPC_MSG_CALL_FUNCTION] =  "ipi call function",
+       [PPC_MSG_RESCHEDULE] = "ipi reschedule",
+       [PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
+       [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
+};
+
+/* optional function to request ipi, for controllers with >= 4 ipis */
+int smp_request_message_ipi(int virq, int msg)
+{
+       int err;
+
+       if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
+               return -EINVAL;
+       }
+#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
+       if (msg == PPC_MSG_DEBUGGER_BREAK) {
+               return 1;
+       }
+#endif
+       err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+                         smp_ipi_name[msg], 0);
+       WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
+               virq, smp_ipi_name[msg], err);
+
+       return err;
+}
+
 void smp_send_reschedule(int cpu)
 {
        if (likely(smp_ops))
index e2ee66b..e1f3a51 100644 (file)
@@ -164,8 +164,6 @@ static u64 tb_to_ns_scale __read_mostly;
 static unsigned tb_to_ns_shift __read_mostly;
 static unsigned long boot_tb __read_mostly;
 
-static struct gettimeofday_struct do_gtod;
-
 extern struct timezone sys_tz;
 static long timezone_offset;
 
@@ -415,31 +413,9 @@ void udelay(unsigned long usecs)
 }
 EXPORT_SYMBOL(udelay);
 
-
-/*
- * There are two copies of tb_to_xs and stamp_xsec so that no
- * lock is needed to access and use these values in
- * do_gettimeofday.  We alternate the copies and as long as a
- * reasonable time elapses between changes, there will never
- * be inconsistent values.  ntpd has a minimum of one minute
- * between updates.
- */
 static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
                               u64 new_tb_to_xs)
 {
-       unsigned temp_idx;
-       struct gettimeofday_vars *temp_varp;
-
-       temp_idx = (do_gtod.var_idx == 0);
-       temp_varp = &do_gtod.vars[temp_idx];
-
-       temp_varp->tb_to_xs = new_tb_to_xs;
-       temp_varp->tb_orig_stamp = new_tb_stamp;
-       temp_varp->stamp_xsec = new_stamp_xsec;
-       smp_mb();
-       do_gtod.varp = temp_varp;
-       do_gtod.var_idx = temp_idx;
-
        /*
         * tb_update_count is used to allow the userspace gettimeofday code
         * to assure itself that it sees a consistent view of the tb_to_xs and
@@ -456,6 +432,7 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec,
        vdso_data->tb_to_xs = new_tb_to_xs;
        vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
        vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
+       vdso_data->stamp_xtime = xtime;
        smp_wmb();
        ++(vdso_data->tb_update_count);
 }
@@ -514,9 +491,7 @@ static int __init iSeries_tb_recal(void)
                                tb_ticks_per_sec   = new_tb_ticks_per_sec;
                                calc_cputime_factors();
                                div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres );
-                               do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
                                tb_to_xs = divres.result_low;
-                               do_gtod.varp->tb_to_xs = tb_to_xs;
                                vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
                                vdso_data->tb_to_xs = tb_to_xs;
                        }
@@ -988,15 +963,6 @@ void __init time_init(void)
                sys_tz.tz_dsttime = 0;
         }
 
-       do_gtod.varp = &do_gtod.vars[0];
-       do_gtod.var_idx = 0;
-       do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
-       __get_cpu_var(last_jiffy) = tb_last_jiffy;
-       do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
-       do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
-       do_gtod.varp->tb_to_xs = tb_to_xs;
-       do_gtod.tb_to_us = tb_to_us;
-
        vdso_data->tb_orig_stamp = tb_last_jiffy;
        vdso_data->tb_update_count = 0;
        vdso_data->tb_ticks_per_sec = tb_ticks_per_sec;
index f5def6c..5457e95 100644 (file)
@@ -1160,37 +1160,85 @@ void CacheLockingException(struct pt_regs *regs, unsigned long address,
 #ifdef CONFIG_SPE
 void SPEFloatingPointException(struct pt_regs *regs)
 {
+       extern int do_spe_mathemu(struct pt_regs *regs);
        unsigned long spefscr;
        int fpexc_mode;
        int code = 0;
+       int err;
+
+       preempt_disable();
+       if (regs->msr & MSR_SPE)
+               giveup_spe(current);
+       preempt_enable();
 
        spefscr = current->thread.spefscr;
        fpexc_mode = current->thread.fpexc_mode;
 
-       /* Hardware does not neccessarily set sticky
-        * underflow/overflow/invalid flags */
        if ((spefscr & SPEFSCR_FOVF) && (fpexc_mode & PR_FP_EXC_OVF)) {
                code = FPE_FLTOVF;
-               spefscr |= SPEFSCR_FOVFS;
        }
        else if ((spefscr & SPEFSCR_FUNF) && (fpexc_mode & PR_FP_EXC_UND)) {
                code = FPE_FLTUND;
-               spefscr |= SPEFSCR_FUNFS;
        }
        else if ((spefscr & SPEFSCR_FDBZ) && (fpexc_mode & PR_FP_EXC_DIV))
                code = FPE_FLTDIV;
        else if ((spefscr & SPEFSCR_FINV) && (fpexc_mode & PR_FP_EXC_INV)) {
                code = FPE_FLTINV;
-               spefscr |= SPEFSCR_FINVS;
        }
        else if ((spefscr & (SPEFSCR_FG | SPEFSCR_FX)) && (fpexc_mode & PR_FP_EXC_RES))
                code = FPE_FLTRES;
 
-       current->thread.spefscr = spefscr;
+       err = do_spe_mathemu(regs);
+       if (err == 0) {
+               regs->nip += 4;         /* skip emulated instruction */
+               emulate_single_step(regs);
+               return;
+       }
+
+       if (err == -EFAULT) {
+               /* got an error reading the instruction */
+               _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+       } else if (err == -EINVAL) {
+               /* didn't recognize the instruction */
+               printk(KERN_ERR "unrecognized spe instruction "
+                      "in %s at %lx\n", current->comm, regs->nip);
+       } else {
+               _exception(SIGFPE, regs, code, regs->nip);
+       }
 
-       _exception(SIGFPE, regs, code, regs->nip);
        return;
 }
+
+void SPEFloatingPointRoundException(struct pt_regs *regs)
+{
+       extern int speround_handler(struct pt_regs *regs);
+       int err;
+
+       preempt_disable();
+       if (regs->msr & MSR_SPE)
+               giveup_spe(current);
+       preempt_enable();
+
+       regs->nip -= 4;
+       err = speround_handler(regs);
+       if (err == 0) {
+               regs->nip += 4;         /* skip emulated instruction */
+               emulate_single_step(regs);
+               return;
+       }
+
+       if (err == -EFAULT) {
+               /* got an error reading the instruction */
+               _exception(SIGSEGV, regs, SEGV_ACCERR, regs->nip);
+       } else if (err == -EINVAL) {
+               /* didn't recognize the instruction */
+               printk(KERN_ERR "unrecognized spe instruction "
+                      "in %s at %lx\n", current->comm, regs->nip);
+       } else {
+               _exception(SIGFPE, regs, 0, regs->nip);
+               return;
+       }
+}
 #endif
 
 /*
index 72ca26d..ee038d4 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 
+/* Offset for the low 32-bit part of a field of long type */
+#ifdef CONFIG_PPC64
+#define LOPART 4
+#else
+#define LOPART 0
+#endif
+
        .text
 /*
  * Exact prototype of gettimeofday
@@ -90,101 +97,53 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
 
        mflr    r12                     /* r12 saves lr */
   .cfi_register lr,r12
-       mr      r10,r3                  /* r10 saves id */
        mr      r11,r4                  /* r11 saves tp */
        bl      __get_datapage@local    /* get data page */
        mr      r9,r3                   /* datapage ptr in r9 */
-       beq     cr1,50f                 /* if monotonic -> jump there */
-
-       /*
-        * CLOCK_REALTIME
-        */
-
-       bl      __do_get_xsec@local     /* get xsec from tb & kernel */
-       bne-    98f                     /* out of line -> do syscall */
-
-       /* seconds are xsec >> 20 */
-       rlwinm  r5,r4,12,20,31
-       rlwimi  r5,r3,12,0,19
-       stw     r5,TSPC32_TV_SEC(r11)
 
-       /* get remaining xsec and convert to nsec. we scale
-        * up remaining xsec by 12 bits and get the top 32 bits
-        * of the multiplication, then we multiply by 1000
-        */
-       rlwinm  r5,r4,12,0,19
-       lis     r6,1000000@h
-       ori     r6,r6,1000000@l
-       mulhwu  r5,r5,r6
-       mulli   r5,r5,1000
-       stw     r5,TSPC32_TV_NSEC(r11)
-       mtlr    r12
-       crclr   cr0*4+so
-       li      r3,0
-       blr
+50:    bl      __do_get_tspec@local    /* get sec/nsec from tb & kernel */
+       bne     cr1,80f                 /* not monotonic -> all done */
 
        /*
         * CLOCK_MONOTONIC
         */
 
-50:    bl      __do_get_xsec@local     /* get xsec from tb & kernel */
-       bne-    98f                     /* out of line -> do syscall */
-
-       /* seconds are xsec >> 20 */
-       rlwinm  r6,r4,12,20,31
-       rlwimi  r6,r3,12,0,19
-
-       /* get remaining xsec and convert to nsec. we scale
-        * up remaining xsec by 12 bits and get the top 32 bits
-        * of the multiplication, then we multiply by 1000
-        */
-       rlwinm  r7,r4,12,0,19
-       lis     r5,1000000@h
-       ori     r5,r5,1000000@l
-       mulhwu  r7,r7,r5
-       mulli   r7,r7,1000
-
        /* now we must fixup using wall to monotonic. We need to snapshot
         * that value and do the counter trick again. Fortunately, we still
         * have the counter value in r8 that was returned by __do_get_xsec.
-        * At this point, r6,r7 contain our sec/nsec values, r3,r4 and r5
-        * can be used
+        * At this point, r3,r4 contain our sec/nsec values, r5 and r6
+        * can be used, r7 contains NSEC_PER_SEC.
         */
 
-       lwz     r3,WTOM_CLOCK_SEC(r9)
-       lwz     r4,WTOM_CLOCK_NSEC(r9)
+       lwz     r5,WTOM_CLOCK_SEC(r9)
+       lwz     r6,WTOM_CLOCK_NSEC(r9)
 
-       /* We now have our result in r3,r4. We create a fake dependency
-        * on that result and re-check the counter
+       /* We now have our offset in r5,r6. We create a fake dependency
+        * on that value and re-check the counter
         */
-       or      r5,r4,r3
-       xor     r0,r5,r5
+       or      r0,r6,r5
+       xor     r0,r0,r0
        add     r9,r9,r0
-#ifdef CONFIG_PPC64
-       lwz     r0,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
-       lwz     r0,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
+       lwz     r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
         cmpl    cr0,r8,r0              /* check if updated */
        bne-    50b
 
-       /* Calculate and store result. Note that this mimmics the C code,
+       /* Calculate and store result. Note that this mimics the C code,
         * which may cause funny results if nsec goes negative... is that
         * possible at all ?
         */
-       add     r3,r3,r6
-       add     r4,r4,r7
-       lis     r5,NSEC_PER_SEC@h
-       ori     r5,r5,NSEC_PER_SEC@l
-       cmpl    cr0,r4,r5
-       cmpli   cr1,r4,0
+       add     r3,r3,r5
+       add     r4,r4,r6
+       cmpw    cr0,r4,r7
+       cmpwi   cr1,r4,0
        blt     1f
-       subf    r4,r5,r4
+       subf    r4,r7,r4
        addi    r3,r3,1
-1:     bge     cr1,1f
+1:     bge     cr1,80f
        addi    r3,r3,-1
-       add     r4,r4,r5
-1:     stw     r3,TSPC32_TV_SEC(r11)
+       add     r4,r4,r7
+
+80:    stw     r3,TSPC32_TV_SEC(r11)
        stw     r4,TSPC32_TV_NSEC(r11)
 
        mtlr    r12
@@ -195,10 +154,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
        /*
         * syscall fallback
         */
-98:
-       mtlr    r12
-       mr      r3,r10
-       mr      r4,r11
 99:
        li      r0,__NR_clock_gettime
        sc
@@ -254,11 +209,7 @@ __do_get_xsec:
        /* Check for update count & load values. We use the low
         * order 32 bits of the update count
         */
-#ifdef CONFIG_PPC64
-1:     lwz     r8,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
-1:     lwz     r8,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
+1:     lwz     r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
        andi.   r0,r8,1                 /* pending update ? loop */
        bne-    1b
        xor     r0,r8,r8                /* create dependency */
@@ -305,11 +256,7 @@ __do_get_xsec:
        or      r6,r4,r3
        xor     r0,r6,r6
        add     r9,r9,r0
-#ifdef CONFIG_PPC64
-       lwz     r0,(CFG_TB_UPDATE_COUNT+4)(r9)
-#else
-       lwz     r0,(CFG_TB_UPDATE_COUNT)(r9)
-#endif
+       lwz     r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
         cmpl    cr0,r8,r0              /* check if updated */
        bne-    1b
 
@@ -322,3 +269,98 @@ __do_get_xsec:
         */
 3:     blr
   .cfi_endproc
+
+/*
+ * This is the core of clock_gettime(), it returns the current
+ * time in seconds and nanoseconds in r3 and r4.
+ * It expects the datapage ptr in r9 and doesn't clobber it.
+ * It clobbers r0, r5, r6, r10 and returns NSEC_PER_SEC in r7.
+ * On return, r8 contains the counter value that can be reused.
+ * This clobbers cr0 but not any other cr field.
+ */
+__do_get_tspec:
+  .cfi_startproc
+       /* Check for update count & load values. We use the low
+        * order 32 bits of the update count
+        */
+1:     lwz     r8,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
+       andi.   r0,r8,1                 /* pending update ? loop */
+       bne-    1b
+       xor     r0,r8,r8                /* create dependency */
+       add     r9,r9,r0
+
+       /* Load orig stamp (offset to TB) */
+       lwz     r5,CFG_TB_ORIG_STAMP(r9)
+       lwz     r6,(CFG_TB_ORIG_STAMP+4)(r9)
+
+       /* Get a stable TB value */
+2:     mftbu   r3
+       mftbl   r4
+       mftbu   r0
+       cmpl    cr0,r3,r0
+       bne-    2b
+
+       /* Subtract tb orig stamp and shift left 12 bits.
+        */
+       subfc   r7,r6,r4
+       subfe   r0,r5,r3
+       slwi    r0,r0,12
+       rlwimi. r0,r7,12,20,31
+       slwi    r7,r7,12
+
+       /* Load scale factor & do multiplication */
+       lwz     r5,CFG_TB_TO_XS(r9)     /* load values */
+       lwz     r6,(CFG_TB_TO_XS+4)(r9)
+       mulhwu  r3,r7,r6
+       mullw   r10,r7,r5
+       mulhwu  r4,r7,r5
+       addc    r10,r3,r10
+       li      r3,0
+
+       beq+    4f                      /* skip high part computation if 0 */
+       mulhwu  r3,r0,r5
+       mullw   r7,r0,r5
+       mulhwu  r5,r0,r6
+       mullw   r6,r0,r6
+       adde    r4,r4,r7
+       addze   r3,r3
+       addc    r4,r4,r5
+       addze   r3,r3
+       addc    r10,r10,r6
+
+4:     addze   r4,r4                   /* add in carry */
+       lis     r7,NSEC_PER_SEC@h
+       ori     r7,r7,NSEC_PER_SEC@l
+       mulhwu  r4,r4,r7                /* convert to nanoseconds */
+
+       /* At this point, we have seconds & nanoseconds since the xtime
+        * stamp in r3+CA and r4.  Load & add the xtime stamp.
+        */
+#ifdef CONFIG_PPC64
+       lwz     r5,STAMP_XTIME+TSPC64_TV_SEC+LOPART(r9)
+       lwz     r6,STAMP_XTIME+TSPC64_TV_NSEC+LOPART(r9)
+#else
+       lwz     r5,STAMP_XTIME+TSPC32_TV_SEC(r9)
+       lwz     r6,STAMP_XTIME+TSPC32_TV_NSEC(r9)
+#endif
+       add     r4,r4,r6
+       adde    r3,r3,r5
+
+       /* We now have our result in r3,r4. We create a fake dependency
+        * on that result and re-check the counter
+        */
+       or      r6,r4,r3
+       xor     r0,r6,r6
+       add     r9,r9,r0
+       lwz     r0,(CFG_TB_UPDATE_COUNT+LOPART)(r9)
+        cmpl    cr0,r8,r0              /* check if updated */
+       bne-    1b
+
+       /* check for nanosecond overflow and adjust if necessary */
+       cmpw    r4,r7
+       bltlr                           /* all done if no overflow */
+       subf    r4,r7,r4                /* adjust if overflow */
+       addi    r3,r3,1
+
+       blr
+  .cfi_endproc
index c6401f9..262cd58 100644 (file)
@@ -75,90 +75,49 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
 
        mflr    r12                     /* r12 saves lr */
   .cfi_register lr,r12
-       mr      r10,r3                  /* r10 saves id */
        mr      r11,r4                  /* r11 saves tp */
        bl      V_LOCAL_FUNC(__get_datapage)    /* get data page */
-       beq     cr1,50f                 /* if monotonic -> jump there */
-
-       /*
-        * CLOCK_REALTIME
-        */
-
-       bl      V_LOCAL_FUNC(__do_get_xsec)     /* get xsec from tb & kernel */
-
-       lis     r7,15                   /* r7 = 1000000 = USEC_PER_SEC */
-       ori     r7,r7,16960
-       rldicl  r5,r4,44,20             /* r5 = sec = xsec / XSEC_PER_SEC */
-       rldicr  r6,r5,20,43             /* r6 = sec * XSEC_PER_SEC */
-       std     r5,TSPC64_TV_SEC(r11)   /* store sec in tv */
-       subf    r0,r6,r4                /* r0 = xsec = (xsec - r6) */
-       mulld   r0,r0,r7                /* usec = (xsec * USEC_PER_SEC) /
-                                        * XSEC_PER_SEC
-                                        */
-       rldicl  r0,r0,44,20
-       mulli   r0,r0,1000              /* nsec = usec * 1000 */
-       std     r0,TSPC64_TV_NSEC(r11)  /* store nsec in tp */
-
-       mtlr    r12
-       crclr   cr0*4+so
-       li      r3,0
-       blr
+50:    bl      V_LOCAL_FUNC(__do_get_tspec)    /* get time from tb & kernel */
+       bne     cr1,80f                 /* if not monotonic, all done */
 
        /*
         * CLOCK_MONOTONIC
         */
 
-50:    bl      V_LOCAL_FUNC(__do_get_xsec)     /* get xsec from tb & kernel */
-
-       lis     r7,15                   /* r7 = 1000000 = USEC_PER_SEC */
-       ori     r7,r7,16960
-       rldicl  r5,r4,44,20             /* r5 = sec = xsec / XSEC_PER_SEC */
-       rldicr  r6,r5,20,43             /* r6 = sec * XSEC_PER_SEC */
-       subf    r0,r6,r4                /* r0 = xsec = (xsec - r6) */
-       mulld   r0,r0,r7                /* usec = (xsec * USEC_PER_SEC) /
-                                        * XSEC_PER_SEC
-                                        */
-       rldicl  r6,r0,44,20
-       mulli   r6,r6,1000              /* nsec = usec * 1000 */
-
        /* now we must fixup using wall to monotonic. We need to snapshot
         * that value and do the counter trick again. Fortunately, we still
-        * have the counter value in r8 that was returned by __do_get_xsec.
-        * At this point, r5,r6 contain our sec/nsec values.
-        * can be used
+        * have the counter value in r8 that was returned by __do_get_tspec.
+        * At this point, r4,r5 contain our sec/nsec values.
         */
 
-       lwa     r4,WTOM_CLOCK_SEC(r3)
-       lwa     r7,WTOM_CLOCK_NSEC(r3)
+       lwa     r6,WTOM_CLOCK_SEC(r3)
+       lwa     r9,WTOM_CLOCK_NSEC(r3)
 
-       /* We now have our result in r4,r7. We create a fake dependency
+       /* We now have our result in r6,r9. We create a fake dependency
         * on that result and re-check the counter
         */
-       or      r9,r4,r7
-       xor     r0,r9,r9
+       or      r0,r6,r9
+       xor     r0,r0,r0
        add     r3,r3,r0
        ld      r0,CFG_TB_UPDATE_COUNT(r3)
         cmpld   cr0,r0,r8              /* check if updated */
        bne-    50b
 
-       /* Calculate and store result. Note that this mimmics the C code,
-        * which may cause funny results if nsec goes negative... is that
-        * possible at all ?
+       /* Add wall->monotonic offset and check for overflow or underflow.
         */
-       add     r4,r4,r5
-       add     r7,r7,r6
-       lis     r9,NSEC_PER_SEC@h
-       ori     r9,r9,NSEC_PER_SEC@l
-       cmpl    cr0,r7,r9
-       cmpli   cr1,r7,0
+       add     r4,r4,r6
+       add     r5,r5,r9
+       cmpd    cr0,r5,r7
+       cmpdi   cr1,r5,0
        blt     1f
-       subf    r7,r9,r7
+       subf    r5,r7,r5
        addi    r4,r4,1
-1:     bge     cr1,1f
+1:     bge     cr1,80f
        addi    r4,r4,-1
-       add     r7,r7,r9
-1:     std     r4,TSPC64_TV_SEC(r11)
-       std     r7,TSPC64_TV_NSEC(r11)
+       add     r5,r5,r7
+
+80:    std     r4,TSPC64_TV_SEC(r11)
+       std     r5,TSPC64_TV_NSEC(r11)
 
        mtlr    r12
        crclr   cr0*4+so
@@ -168,10 +127,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
        /*
         * syscall fallback
         */
-98:
-       mtlr    r12
-       mr      r3,r10
-       mr      r4,r11
 99:
        li      r0,__NR_clock_gettime
        sc
@@ -253,3 +208,59 @@ V_FUNCTION_BEGIN(__do_get_xsec)
        blr
   .cfi_endproc
 V_FUNCTION_END(__do_get_xsec)
+
+/*
+ * This is the core of clock_gettime(), it returns the current
+ * time in seconds and nanoseconds in r4 and r5.
+ * It expects the datapage ptr in r3 and doesn't clobber it.
+ * It clobbers r0 and r6 and returns NSEC_PER_SEC in r7.
+ * On return, r8 contains the counter value that can be reused.
+ * This clobbers cr0 but not any other cr field.
+ */
+V_FUNCTION_BEGIN(__do_get_tspec)
+  .cfi_startproc
+       /* check for update count & load values */
+1:     ld      r8,CFG_TB_UPDATE_COUNT(r3)
+       andi.   r0,r8,1                 /* pending update ? loop */
+       bne-    1b
+       xor     r0,r8,r8                /* create dependency */
+       add     r3,r3,r0
+
+       /* Get TB & offset it. We use the MFTB macro which will generate
+        * workaround code for Cell.
+        */
+       MFTB(r7)
+       ld      r9,CFG_TB_ORIG_STAMP(r3)
+       subf    r7,r9,r7
+
+       /* Scale result */
+       ld      r5,CFG_TB_TO_XS(r3)
+       sldi    r7,r7,12                /* compute time since stamp_xtime */
+       mulhdu  r6,r7,r5                /* in units of 2^-32 seconds */
+
+       /* Add stamp since epoch */
+       ld      r4,STAMP_XTIME+TSPC64_TV_SEC(r3)
+       ld      r5,STAMP_XTIME+TSPC64_TV_NSEC(r3)
+       or      r0,r4,r5
+       or      r0,r0,r6
+       xor     r0,r0,r0
+       add     r3,r3,r0
+       ld      r0,CFG_TB_UPDATE_COUNT(r3)
+       cmpld   r0,r8                   /* check if updated */
+       bne-    1b                      /* reload if so */
+
+       /* convert to seconds & nanoseconds and add to stamp */
+       lis     r7,NSEC_PER_SEC@h
+       ori     r7,r7,NSEC_PER_SEC@l
+       mulhwu  r0,r6,r7                /* compute nanoseconds and */
+       srdi    r6,r6,32                /* seconds since stamp_xtime */
+       clrldi  r0,r0,32
+       add     r5,r5,r0                /* add nanoseconds together */
+       cmpd    r5,r7                   /* overflow? */
+       add     r4,r4,r6
+       bltlr                           /* all done if no overflow */
+       subf    r5,r7,r5                /* if overflow, adjust */
+       addi    r4,r4,1
+       blr
+  .cfi_endproc
+V_FUNCTION_END(__do_get_tspec)
index a11e6bc..94aa7b0 100644 (file)
@@ -41,9 +41,9 @@
 static struct bus_type vio_bus_type;
 
 static struct vio_dev vio_bus_device  = { /* fake "parent" device */
-       .name = vio_bus_device.dev.bus_id,
+       .name = "vio",
        .type = "",
-       .dev.bus_id = "vio",
+       .dev.init_name = "vio",
        .dev.bus = &vio_bus_type,
 };
 
@@ -1216,7 +1216,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
 
        viodev->irq = irq_of_parse_and_map(of_node, 0);
 
-       snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+       dev_set_name(&viodev->dev, "%x", *unit_address);
        viodev->name = of_node->name;
        viodev->type = of_node->type;
        viodev->unit_address = *unit_address;
@@ -1243,7 +1243,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
        /* register with generic device framework */
        if (device_register(&viodev->dev)) {
                printk(KERN_ERR "%s: failed to register device %s\n",
-                               __func__, viodev->dev.bus_id);
+                               __func__, dev_name(&viodev->dev));
                /* XXX free TCE table */
                kfree(viodev);
                return NULL;
@@ -1400,13 +1400,13 @@ static struct vio_dev *vio_find_name(const char *name)
 struct vio_dev *vio_find_node(struct device_node *vnode)
 {
        const uint32_t *unit_address;
-       char kobj_name[BUS_ID_SIZE];
+       char kobj_name[20];
 
        /* construct the kobject name from the device node */
        unit_address = of_get_property(vnode, "reg", NULL);
        if (!unit_address)
                return NULL;
-       snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+       snprintf(kobj_name, sizeof(kobj_name), "%x", *unit_address);
 
        return vio_find_name(kobj_name);
 }
index 25ec537..70693a5 100644 (file)
@@ -26,11 +26,24 @@ _GLOBAL(__copy_tofrom_user)
        andi.   r6,r6,7
        PPC_MTOCRF      0x01,r5
        blt     cr1,.Lshort_copy
+/* Below we want to nop out the bne if we're on a CPU that has the
+ * CPU_FTR_UNALIGNED_LD_STD bit set and the CPU_FTR_CP_USE_DCBTZ bit
+ * cleared.
+ * At the time of writing the only CPU that has this combination of bits
+ * set is Power6.
+ */
+BEGIN_FTR_SECTION
+       nop
+FTR_SECTION_ELSE
        bne     .Ldst_unaligned
+ALT_FTR_SECTION_END(CPU_FTR_UNALIGNED_LD_STD | CPU_FTR_CP_USE_DCBTZ, \
+                   CPU_FTR_UNALIGNED_LD_STD)
 .Ldst_aligned:
-       andi.   r0,r4,7
        addi    r3,r3,-16
+BEGIN_FTR_SECTION
+       andi.   r0,r4,7
        bne     .Lsrc_unaligned
+END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        srdi    r7,r5,4
 20:    ld      r9,0(r4)
        addi    r4,r4,-8
@@ -138,7 +151,7 @@ _GLOBAL(__copy_tofrom_user)
        PPC_MTOCRF      0x01,r6         /* put #bytes to 8B bdry into cr7 */
        subf    r5,r6,r5
        li      r7,0
-       cmpldi  r1,r5,16
+       cmpldi  cr1,r5,16
        bf      cr7*4+3,1f
 35:    lbz     r0,0(r4)
 81:    stb     r0,0(r3)
index 31734c0..2b1ce18 100644 (file)
@@ -320,7 +320,6 @@ static int __init dma_alloc_init(void)
                        ret = -ENOMEM;
                        break;
                }
-               WARN_ON(!pmd_none(*pmd));
 
                pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
                if (!pte) {
index 3f13112..fe2d34e 100644 (file)
@@ -18,11 +18,23 @@ _GLOBAL(memcpy)
        andi.   r6,r6,7
        dcbt    0,r4
        blt     cr1,.Lshort_copy
+/* Below we want to nop out the bne if we're on a CPU that has the
+   CPU_FTR_UNALIGNED_LD_STD bit set and the CPU_FTR_CP_USE_DCBTZ bit
+   cleared.
+   At the time of writing the only CPU that has this combination of bits
+   set is Power6. */
+BEGIN_FTR_SECTION
+       nop
+FTR_SECTION_ELSE
        bne     .Ldst_unaligned
+ALT_FTR_SECTION_END(CPU_FTR_UNALIGNED_LD_STD | CPU_FTR_CP_USE_DCBTZ, \
+                    CPU_FTR_UNALIGNED_LD_STD)
 .Ldst_aligned:
-       andi.   r0,r4,7
        addi    r3,r3,-16
+BEGIN_FTR_SECTION
+       andi.   r0,r4,7
        bne     .Lsrc_unaligned
+END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
        srdi    r7,r5,4
        ld      r9,0(r4)
        addi    r4,r4,-8
@@ -131,7 +143,7 @@ _GLOBAL(memcpy)
        PPC_MTOCRF      0x01,r6         # put #bytes to 8B bdry into cr7
        subf    r5,r6,r5
        li      r7,0
-       cmpldi  r1,r5,16
+       cmpldi  cr1,r5,16
        bf      cr7*4+3,1f
        lbz     r0,0(r4)
        stb     r0,0(r3)
index 03aa98d..f9e506a 100644 (file)
@@ -11,6 +11,8 @@ obj-$(CONFIG_MATH_EMULATION)  += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \
                                        mcrfs.o mffs.o mtfsb0.o mtfsb1.o \
                                        mtfsf.o mtfsfi.o stfiwx.o stfs.o
 
+obj-$(CONFIG_SPE)              += math_efp.o
+
 CFLAGS_fabs.o = -fno-builtin-fabs
 CFLAGS_math.o = -fno-builtin-fabs
 
index 04d3b4a..0158a16 100644 (file)
@@ -13,7 +13,6 @@ fadd(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
index b5dc449..5bce011 100644 (file)
@@ -14,7 +14,6 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
        FP_DECL_EX;
        int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) };
        long cmp;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p (%08x) %d %p %p\n", __func__, ccr, *ccr, crfD, frA, frB);
@@ -29,7 +28,7 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
 #endif
 
        if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN)
-               ret |= EFLAG_VXVC;
+               FP_SET_EXCEPTION(EFLAG_VXVC);
 
        FP_CMP_D(cmp, A, B, 2);
        cmp = code[(cmp + 1) & 3];
@@ -44,5 +43,5 @@ fcmpo(u32 *ccr, int crfD, void *frA, void *frB)
        printk("CR: %08x\n", *ccr);
 #endif
 
-       return ret;
+       return FP_CUR_EXCEPTIONS;
 }
index 2db1509..a29239c 100644 (file)
@@ -13,7 +13,6 @@ fdiv(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -28,22 +27,22 @@ fdiv(void *frD, void *frA, void *frB)
 #endif
 
        if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
-               ret |= EFLAG_VXZDZ;
+               FP_SET_EXCEPTION(EFLAG_VXZDZ);
 #ifdef DEBUG
                printk("%s: FPSCR_VXZDZ raised\n", __func__);
 #endif
        }
        if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
-               ret |= EFLAG_VXIDI;
+               FP_SET_EXCEPTION(EFLAG_VXIDI);
 #ifdef DEBUG
                printk("%s: FPSCR_VXIDI raised\n", __func__);
 #endif
        }
 
        if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
-               ret |= EFLAG_DIVZERO;
+               FP_SET_EXCEPTION(EFLAG_DIVZERO);
                if (__FPU_TRAP_P(EFLAG_DIVZERO))
-                       return ret;
+                       return FP_CUR_EXCEPTIONS;
        }
        FP_DIV_D(R, A, B);
 
index 797f6a9..526bc26 100644 (file)
@@ -14,7 +14,6 @@ fdivs(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -29,22 +28,22 @@ fdivs(void *frD, void *frA, void *frB)
 #endif
 
        if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) {
-               ret |= EFLAG_VXZDZ;
+               FP_SET_EXCEPTION(EFLAG_VXZDZ);
 #ifdef DEBUG
                printk("%s: FPSCR_VXZDZ raised\n", __func__);
 #endif
        }
        if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) {
-               ret |= EFLAG_VXIDI;
+               FP_SET_EXCEPTION(EFLAG_VXIDI);
 #ifdef DEBUG
                printk("%s: FPSCR_VXIDI raised\n", __func__);
 #endif
        }
 
        if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) {
-               ret |= EFLAG_DIVZERO;
+               FP_SET_EXCEPTION(EFLAG_DIVZERO);
                if (__FPU_TRAP_P(EFLAG_DIVZERO))
-                       return ret;
+                       return FP_CUR_EXCEPTIONS;
        }
 
        FP_DIV_D(R, A, B);
index 925313a..8c3f20a 100644 (file)
@@ -15,7 +15,6 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -33,12 +32,12 @@ fmadd(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-                ret |= EFLAG_VXIMZ;
+                FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index aea80ef..794fb31 100644 (file)
@@ -16,7 +16,6 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -34,12 +33,12 @@ fmadds(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-                ret |= EFLAG_VXIMZ;
+                FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index a644d52..626f6fe 100644 (file)
@@ -15,7 +15,6 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -33,7 +32,7 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
@@ -41,7 +40,7 @@ fmsub(void *frD, void *frA, void *frB, void *frC)
                B_s ^= 1;
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index 2fdeeb9..3425bc8 100644 (file)
@@ -16,7 +16,6 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -34,7 +33,7 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
@@ -42,7 +41,7 @@ fmsubs(void *frD, void *frA, void *frB, void *frC)
                B_s ^= 1;
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index 391fd17..2c19297 100644 (file)
@@ -13,7 +13,6 @@ fmul(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -31,7 +30,7 @@ fmul(void *frD, void *frA, void *frB)
 
        if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(R, A, B);
 
index 2d3ec5f..f5ad5c9 100644 (file)
@@ -14,7 +14,6 @@ fmuls(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -32,7 +31,7 @@ fmuls(void *frD, void *frA, void *frB)
 
        if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(R, A, B);
 
index 2497b86..e817bc5 100644 (file)
@@ -15,7 +15,6 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -33,12 +32,12 @@ fnmadd(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-                ret |= EFLAG_VXIMZ;
+                FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index ee9d71e..4db4b7d 100644 (file)
@@ -16,7 +16,6 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -34,12 +33,12 @@ fnmadds(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-                ret |= EFLAG_VXIMZ;
+                FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index 3885a77..f65979f 100644 (file)
@@ -15,7 +15,6 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -33,7 +32,7 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
@@ -41,7 +40,7 @@ fnmsub(void *frD, void *frA, void *frB, void *frC)
                B_s ^= 1;
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index f835dfe..9021dac 100644 (file)
@@ -16,7 +16,6 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
        FP_DECL_D(C);
        FP_DECL_D(T);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frA, frB, frC);
@@ -34,7 +33,7 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
 
        if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) ||
            (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF))
-               ret |= EFLAG_VXIMZ;
+               FP_SET_EXCEPTION(EFLAG_VXIMZ);
 
        FP_MUL_D(T, A, C);
 
@@ -42,7 +41,7 @@ fnmsubs(void *frD, void *frA, void *frB, void *frC)
                B_s ^= 1;
 
        if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, T, B);
 
index 3e90072..a55fc7d 100644 (file)
@@ -12,7 +12,6 @@ fsqrt(void *frD, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frB);
@@ -25,9 +24,9 @@ fsqrt(void *frD, void *frB)
 #endif
 
        if (B_s && B_c != FP_CLS_ZERO)
-               ret |= EFLAG_VXSQRT;
+               FP_SET_EXCEPTION(EFLAG_VXSQRT);
        if (B_c == FP_CLS_NAN)
-               ret |= EFLAG_VXSNAN;
+               FP_SET_EXCEPTION(EFLAG_VXSNAN);
 
        FP_SQRT_D(R, B);
 
index 2843be9..31dccbf 100644 (file)
@@ -13,7 +13,6 @@ fsqrts(void *frD, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p %p\n", __func__, frD, frB);
@@ -26,9 +25,9 @@ fsqrts(void *frD, void *frB)
 #endif
 
        if (B_s && B_c != FP_CLS_ZERO)
-               ret |= EFLAG_VXSQRT;
+               FP_SET_EXCEPTION(EFLAG_VXSQRT);
        if (B_c == FP_CLS_NAN)
-               ret |= EFLAG_VXSNAN;
+               FP_SET_EXCEPTION(EFLAG_VXSNAN);
 
        FP_SQRT_D(R, B);
 
index 78b0944..02c5dff 100644 (file)
@@ -13,7 +13,6 @@ fsub(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -31,7 +30,7 @@ fsub(void *frD, void *frA, void *frB)
                B_s ^= 1;
 
        if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, A, B);
 
index d3bf908..5d9b18c 100644 (file)
@@ -14,7 +14,6 @@ fsubs(void *frD, void *frA, void *frB)
        FP_DECL_D(B);
        FP_DECL_D(R);
        FP_DECL_EX;
-       int ret = 0;
 
 #ifdef DEBUG
        printk("%s: %p %p %p\n", __func__, frD, frA, frB);
@@ -32,7 +31,7 @@ fsubs(void *frD, void *frA, void *frB)
                B_s ^= 1;
 
        if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF)
-               ret |= EFLAG_VXISI;
+               FP_SET_EXCEPTION(EFLAG_VXISI);
 
        FP_ADD_D(R, A, B);
 
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c
new file mode 100644 (file)
index 0000000..41f4ef3
--- /dev/null
@@ -0,0 +1,720 @@
+/*
+ * arch/powerpc/math-emu/math_efp.c
+ *
+ * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Ebony Zhu,  <ebony.zhu@freescale.com>
+ *         Yu Liu,     <yu.liu@freescale.com>
+ *
+ * Derived from arch/alpha/math-emu/math.c
+ *              arch/powerpc/math-emu/math.c
+ *
+ * Description:
+ * This file is the exception handler to make E500 SPE instructions
+ * fully comply with IEEE-754 floating point standard.
+ *
+ * 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 <linux/types.h>
+
+#include <asm/uaccess.h>
+#include <asm/reg.h>
+
+#define FP_EX_BOOKE_E500_SPE
+#include <asm/sfp-machine.h>
+
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+#include <math-emu/double.h>
+
+#define EFAPU          0x4
+
+#define VCT            0x4
+#define SPFP           0x6
+#define DPFP           0x7
+
+#define EFSADD         0x2c0
+#define EFSSUB         0x2c1
+#define EFSABS         0x2c4
+#define EFSNABS                0x2c5
+#define EFSNEG         0x2c6
+#define EFSMUL         0x2c8
+#define EFSDIV         0x2c9
+#define EFSCMPGT       0x2cc
+#define EFSCMPLT       0x2cd
+#define EFSCMPEQ       0x2ce
+#define EFSCFD         0x2cf
+#define EFSCFSI                0x2d1
+#define EFSCTUI                0x2d4
+#define EFSCTSI                0x2d5
+#define EFSCTUF                0x2d6
+#define EFSCTSF                0x2d7
+#define EFSCTUIZ       0x2d8
+#define EFSCTSIZ       0x2da
+
+#define EVFSADD                0x280
+#define EVFSSUB                0x281
+#define EVFSABS                0x284
+#define EVFSNABS       0x285
+#define EVFSNEG                0x286
+#define EVFSMUL                0x288
+#define EVFSDIV                0x289
+#define EVFSCMPGT      0x28c
+#define EVFSCMPLT      0x28d
+#define EVFSCMPEQ      0x28e
+#define EVFSCTUI       0x294
+#define EVFSCTSI       0x295
+#define EVFSCTUF       0x296
+#define EVFSCTSF       0x297
+#define EVFSCTUIZ      0x298
+#define EVFSCTSIZ      0x29a
+
+#define EFDADD         0x2e0
+#define EFDSUB         0x2e1
+#define EFDABS         0x2e4
+#define EFDNABS                0x2e5
+#define EFDNEG         0x2e6
+#define EFDMUL         0x2e8
+#define EFDDIV         0x2e9
+#define EFDCTUIDZ      0x2ea
+#define EFDCTSIDZ      0x2eb
+#define EFDCMPGT       0x2ec
+#define EFDCMPLT       0x2ed
+#define EFDCMPEQ       0x2ee
+#define EFDCFS         0x2ef
+#define EFDCTUI                0x2f4
+#define EFDCTSI                0x2f5
+#define EFDCTUF                0x2f6
+#define EFDCTSF                0x2f7
+#define EFDCTUIZ       0x2f8
+#define EFDCTSIZ       0x2fa
+
+#define AB     2
+#define XA     3
+#define XB     4
+#define XCR    5
+#define NOTYPE 0
+
+#define SIGN_BIT_S     (1UL << 31)
+#define SIGN_BIT_D     (1ULL << 63)
+#define FP_EX_MASK     (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
+                       FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
+
+union dw_union {
+       u64 dp[1];
+       u32 wp[2];
+};
+
+static unsigned long insn_type(unsigned long speinsn)
+{
+       unsigned long ret = NOTYPE;
+
+       switch (speinsn & 0x7ff) {
+       case EFSABS:    ret = XA;       break;
+       case EFSADD:    ret = AB;       break;
+       case EFSCFD:    ret = XB;       break;
+       case EFSCMPEQ:  ret = XCR;      break;
+       case EFSCMPGT:  ret = XCR;      break;
+       case EFSCMPLT:  ret = XCR;      break;
+       case EFSCTSF:   ret = XB;       break;
+       case EFSCTSI:   ret = XB;       break;
+       case EFSCTSIZ:  ret = XB;       break;
+       case EFSCTUF:   ret = XB;       break;
+       case EFSCTUI:   ret = XB;       break;
+       case EFSCTUIZ:  ret = XB;       break;
+       case EFSDIV:    ret = AB;       break;
+       case EFSMUL:    ret = AB;       break;
+       case EFSNABS:   ret = XA;       break;
+       case EFSNEG:    ret = XA;       break;
+       case EFSSUB:    ret = AB;       break;
+       case EFSCFSI:   ret = XB;       break;
+
+       case EVFSABS:   ret = XA;       break;
+       case EVFSADD:   ret = AB;       break;
+       case EVFSCMPEQ: ret = XCR;      break;
+       case EVFSCMPGT: ret = XCR;      break;
+       case EVFSCMPLT: ret = XCR;      break;
+       case EVFSCTSF:  ret = XB;       break;
+       case EVFSCTSI:  ret = XB;       break;
+       case EVFSCTSIZ: ret = XB;       break;
+       case EVFSCTUF:  ret = XB;       break;
+       case EVFSCTUI:  ret = XB;       break;
+       case EVFSCTUIZ: ret = XB;       break;
+       case EVFSDIV:   ret = AB;       break;
+       case EVFSMUL:   ret = AB;       break;
+       case EVFSNABS:  ret = XA;       break;
+       case EVFSNEG:   ret = XA;       break;
+       case EVFSSUB:   ret = AB;       break;
+
+       case EFDABS:    ret = XA;       break;
+       case EFDADD:    ret = AB;       break;
+       case EFDCFS:    ret = XB;       break;
+       case EFDCMPEQ:  ret = XCR;      break;
+       case EFDCMPGT:  ret = XCR;      break;
+       case EFDCMPLT:  ret = XCR;      break;
+       case EFDCTSF:   ret = XB;       break;
+       case EFDCTSI:   ret = XB;       break;
+       case EFDCTSIDZ: ret = XB;       break;
+       case EFDCTSIZ:  ret = XB;       break;
+       case EFDCTUF:   ret = XB;       break;
+       case EFDCTUI:   ret = XB;       break;
+       case EFDCTUIDZ: ret = XB;       break;
+       case EFDCTUIZ:  ret = XB;       break;
+       case EFDDIV:    ret = AB;       break;
+       case EFDMUL:    ret = AB;       break;
+       case EFDNABS:   ret = XA;       break;
+       case EFDNEG:    ret = XA;       break;
+       case EFDSUB:    ret = AB;       break;
+
+       default:
+               printk(KERN_ERR "\nOoops! SPE instruction no type found.");
+               printk(KERN_ERR "\ninst code: %08lx\n", speinsn);
+       }
+
+       return ret;
+}
+
+int do_spe_mathemu(struct pt_regs *regs)
+{
+       FP_DECL_EX;
+       int IR, cmp;
+
+       unsigned long type, func, fc, fa, fb, src, speinsn;
+       union dw_union vc, va, vb;
+
+       if (get_user(speinsn, (unsigned int __user *) regs->nip))
+               return -EFAULT;
+       if ((speinsn >> 26) != EFAPU)
+               return -EINVAL;         /* not an spe instruction */
+
+       type = insn_type(speinsn);
+       if (type == NOTYPE)
+               return -ENOSYS;
+
+       func = speinsn & 0x7ff;
+       fc = (speinsn >> 21) & 0x1f;
+       fa = (speinsn >> 16) & 0x1f;
+       fb = (speinsn >> 11) & 0x1f;
+       src = (speinsn >> 5) & 0x7;
+
+       vc.wp[0] = current->thread.evr[fc];
+       vc.wp[1] = regs->gpr[fc];
+       va.wp[0] = current->thread.evr[fa];
+       va.wp[1] = regs->gpr[fa];
+       vb.wp[0] = current->thread.evr[fb];
+       vb.wp[1] = regs->gpr[fb];
+
+       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+
+#ifdef DEBUG
+       printk("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
+       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
+#endif
+
+       switch (src) {
+       case SPFP: {
+               FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+
+               switch (type) {
+               case AB:
+               case XCR:
+                       FP_UNPACK_SP(SA, va.wp + 1);
+               case XB:
+                       FP_UNPACK_SP(SB, vb.wp + 1);
+                       break;
+               case XA:
+                       FP_UNPACK_SP(SA, va.wp + 1);
+                       break;
+               }
+
+#ifdef DEBUG
+               printk("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
+               printk("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
+#endif
+
+               switch (func) {
+               case EFSABS:
+                       vc.wp[1] = va.wp[1] & ~SIGN_BIT_S;
+                       goto update_regs;
+
+               case EFSNABS:
+                       vc.wp[1] = va.wp[1] | SIGN_BIT_S;
+                       goto update_regs;
+
+               case EFSNEG:
+                       vc.wp[1] = va.wp[1] ^ SIGN_BIT_S;
+                       goto update_regs;
+
+               case EFSADD:
+                       FP_ADD_S(SR, SA, SB);
+                       goto pack_s;
+
+               case EFSSUB:
+                       FP_SUB_S(SR, SA, SB);
+                       goto pack_s;
+
+               case EFSMUL:
+                       FP_MUL_S(SR, SA, SB);
+                       goto pack_s;
+
+               case EFSDIV:
+                       FP_DIV_S(SR, SA, SB);
+                       goto pack_s;
+
+               case EFSCMPEQ:
+                       cmp = 0;
+                       goto cmp_s;
+
+               case EFSCMPGT:
+                       cmp = 1;
+                       goto cmp_s;
+
+               case EFSCMPLT:
+                       cmp = -1;
+                       goto cmp_s;
+
+               case EFSCTSF:
+               case EFSCTUF:
+                       if (!((vb.wp[1] >> 23) == 0xff && ((vb.wp[1] & 0x7fffff) > 0))) {
+                               /* NaN */
+                               if (((vb.wp[1] >> 23) & 0xff) == 0) {
+                                       /* denorm */
+                                       vc.wp[1] = 0x0;
+                               } else if ((vb.wp[1] >> 31) == 0) {
+                                       /* positive normal */
+                                       vc.wp[1] = (func == EFSCTSF) ?
+                                               0x7fffffff : 0xffffffff;
+                               } else { /* negative normal */
+                                       vc.wp[1] = (func == EFSCTSF) ?
+                                               0x80000000 : 0x0;
+                               }
+                       } else { /* rB is NaN */
+                               vc.wp[1] = 0x0;
+                       }
+                       goto update_regs;
+
+               case EFSCFD: {
+                       FP_DECL_D(DB);
+                       FP_CLEAR_EXCEPTIONS;
+                       FP_UNPACK_DP(DB, vb.dp);
+#ifdef DEBUG
+                       printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+                                       DB_s, DB_f1, DB_f0, DB_e, DB_c);
+#endif
+                       FP_CONV(S, D, 1, 2, SR, DB);
+                       goto pack_s;
+               }
+
+               case EFSCTSI:
+               case EFSCTSIZ:
+               case EFSCTUI:
+               case EFSCTUIZ:
+                       if (func & 0x4) {
+                               _FP_ROUND(1, SB);
+                       } else {
+                               _FP_ROUND_ZERO(1, SB);
+                       }
+                       FP_TO_INT_S(vc.wp[1], SB, 32, ((func & 0x3) != 0));
+                       goto update_regs;
+
+               default:
+                       goto illegal;
+               }
+               break;
+
+pack_s:
+#ifdef DEBUG
+               printk("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
+#endif
+               FP_PACK_SP(vc.wp + 1, SR);
+               goto update_regs;
+
+cmp_s:
+               FP_CMP_S(IR, SA, SB, 3);
+               if (IR == 3 && (FP_ISSIGNAN_S(SA) || FP_ISSIGNAN_S(SB)))
+                       FP_SET_EXCEPTION(FP_EX_INVALID);
+               if (IR == cmp) {
+                       IR = 0x4;
+               } else {
+                       IR = 0;
+               }
+               goto update_ccr;
+       }
+
+       case DPFP: {
+               FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
+
+               switch (type) {
+               case AB:
+               case XCR:
+                       FP_UNPACK_DP(DA, va.dp);
+               case XB:
+                       FP_UNPACK_DP(DB, vb.dp);
+                       break;
+               case XA:
+                       FP_UNPACK_DP(DA, va.dp);
+                       break;
+               }
+
+#ifdef DEBUG
+               printk("DA: %ld %08lx %08lx %ld (%ld)\n",
+                               DA_s, DA_f1, DA_f0, DA_e, DA_c);
+               printk("DB: %ld %08lx %08lx %ld (%ld)\n",
+                               DB_s, DB_f1, DB_f0, DB_e, DB_c);
+#endif
+
+               switch (func) {
+               case EFDABS:
+                       vc.dp[0] = va.dp[0] & ~SIGN_BIT_D;
+                       goto update_regs;
+
+               case EFDNABS:
+                       vc.dp[0] = va.dp[0] | SIGN_BIT_D;
+                       goto update_regs;
+
+               case EFDNEG:
+                       vc.dp[0] = va.dp[0] ^ SIGN_BIT_D;
+                       goto update_regs;
+
+               case EFDADD:
+                       FP_ADD_D(DR, DA, DB);
+                       goto pack_d;
+
+               case EFDSUB:
+                       FP_SUB_D(DR, DA, DB);
+                       goto pack_d;
+
+               case EFDMUL:
+                       FP_MUL_D(DR, DA, DB);
+                       goto pack_d;
+
+               case EFDDIV:
+                       FP_DIV_D(DR, DA, DB);
+                       goto pack_d;
+
+               case EFDCMPEQ:
+                       cmp = 0;
+                       goto cmp_d;
+
+               case EFDCMPGT:
+                       cmp = 1;
+                       goto cmp_d;
+
+               case EFDCMPLT:
+                       cmp = -1;
+                       goto cmp_d;
+
+               case EFDCTSF:
+               case EFDCTUF:
+                       if (!((vb.wp[0] >> 20) == 0x7ff &&
+                          ((vb.wp[0] & 0xfffff) > 0 || (vb.wp[1] > 0)))) {
+                               /* not a NaN */
+                               if (((vb.wp[0] >> 20) & 0x7ff) == 0) {
+                                       /* denorm */
+                                       vc.wp[1] = 0x0;
+                               } else if ((vb.wp[0] >> 31) == 0) {
+                                       /* positive normal */
+                                       vc.wp[1] = (func == EFDCTSF) ?
+                                               0x7fffffff : 0xffffffff;
+                               } else { /* negative normal */
+                                       vc.wp[1] = (func == EFDCTSF) ?
+                                               0x80000000 : 0x0;
+                               }
+                       } else { /* NaN */
+                               vc.wp[1] = 0x0;
+                       }
+                       goto update_regs;
+
+               case EFDCFS: {
+                       FP_DECL_S(SB);
+                       FP_CLEAR_EXCEPTIONS;
+                       FP_UNPACK_SP(SB, vb.wp + 1);
+#ifdef DEBUG
+                       printk("SB: %ld %08lx %ld (%ld)\n",
+                                       SB_s, SB_f, SB_e, SB_c);
+#endif
+                       FP_CONV(D, S, 2, 1, DR, SB);
+                       goto pack_d;
+               }
+
+               case EFDCTUIDZ:
+               case EFDCTSIDZ:
+                       _FP_ROUND_ZERO(2, DB);
+                       FP_TO_INT_D(vc.dp[0], DB, 64, ((func & 0x1) == 0));
+                       goto update_regs;
+
+               case EFDCTUI:
+               case EFDCTSI:
+               case EFDCTUIZ:
+               case EFDCTSIZ:
+                       if (func & 0x4) {
+                               _FP_ROUND(2, DB);
+                       } else {
+                               _FP_ROUND_ZERO(2, DB);
+                       }
+                       FP_TO_INT_D(vc.wp[1], DB, 32, ((func & 0x3) != 0));
+                       goto update_regs;
+
+               default:
+                       goto illegal;
+               }
+               break;
+
+pack_d:
+#ifdef DEBUG
+               printk("DR: %ld %08lx %08lx %ld (%ld)\n",
+                               DR_s, DR_f1, DR_f0, DR_e, DR_c);
+#endif
+               FP_PACK_DP(vc.dp, DR);
+               goto update_regs;
+
+cmp_d:
+               FP_CMP_D(IR, DA, DB, 3);
+               if (IR == 3 && (FP_ISSIGNAN_D(DA) || FP_ISSIGNAN_D(DB)))
+                       FP_SET_EXCEPTION(FP_EX_INVALID);
+               if (IR == cmp) {
+                       IR = 0x4;
+               } else {
+                       IR = 0;
+               }
+               goto update_ccr;
+
+       }
+
+       case VCT: {
+               FP_DECL_S(SA0); FP_DECL_S(SB0); FP_DECL_S(SR0);
+               FP_DECL_S(SA1); FP_DECL_S(SB1); FP_DECL_S(SR1);
+               int IR0, IR1;
+
+               switch (type) {
+               case AB:
+               case XCR:
+                       FP_UNPACK_SP(SA0, va.wp);
+                       FP_UNPACK_SP(SA1, va.wp + 1);
+               case XB:
+                       FP_UNPACK_SP(SB0, vb.wp);
+                       FP_UNPACK_SP(SB1, vb.wp + 1);
+                       break;
+               case XA:
+                       FP_UNPACK_SP(SA0, va.wp);
+                       FP_UNPACK_SP(SA1, va.wp + 1);
+                       break;
+               }
+
+#ifdef DEBUG
+               printk("SA0: %ld %08lx %ld (%ld)\n", SA0_s, SA0_f, SA0_e, SA0_c);
+               printk("SA1: %ld %08lx %ld (%ld)\n", SA1_s, SA1_f, SA1_e, SA1_c);
+               printk("SB0: %ld %08lx %ld (%ld)\n", SB0_s, SB0_f, SB0_e, SB0_c);
+               printk("SB1: %ld %08lx %ld (%ld)\n", SB1_s, SB1_f, SB1_e, SB1_c);
+#endif
+
+               switch (func) {
+               case EVFSABS:
+                       vc.wp[0] = va.wp[0] & ~SIGN_BIT_S;
+                       vc.wp[1] = va.wp[1] & ~SIGN_BIT_S;
+                       goto update_regs;
+
+               case EVFSNABS:
+                       vc.wp[0] = va.wp[0] | SIGN_BIT_S;
+                       vc.wp[1] = va.wp[1] | SIGN_BIT_S;
+                       goto update_regs;
+
+               case EVFSNEG:
+                       vc.wp[0] = va.wp[0] ^ SIGN_BIT_S;
+                       vc.wp[1] = va.wp[1] ^ SIGN_BIT_S;
+                       goto update_regs;
+
+               case EVFSADD:
+                       FP_ADD_S(SR0, SA0, SB0);
+                       FP_ADD_S(SR1, SA1, SB1);
+                       goto pack_vs;
+
+               case EVFSSUB:
+                       FP_SUB_S(SR0, SA0, SB0);
+                       FP_SUB_S(SR1, SA1, SB1);
+                       goto pack_vs;
+
+               case EVFSMUL:
+                       FP_MUL_S(SR0, SA0, SB0);
+                       FP_MUL_S(SR1, SA1, SB1);
+                       goto pack_vs;
+
+               case EVFSDIV:
+                       FP_DIV_S(SR0, SA0, SB0);
+                       FP_DIV_S(SR1, SA1, SB1);
+                       goto pack_vs;
+
+               case EVFSCMPEQ:
+                       cmp = 0;
+                       goto cmp_vs;
+
+               case EVFSCMPGT:
+                       cmp = 1;
+                       goto cmp_vs;
+
+               case EVFSCMPLT:
+                       cmp = -1;
+                       goto cmp_vs;
+
+               case EVFSCTSF:
+                       __asm__ __volatile__ ("mtspr 512, %4\n"
+                               "efsctsf %0, %2\n"
+                               "efsctsf %1, %3\n"
+                               : "=r" (vc.wp[0]), "=r" (vc.wp[1])
+                               : "r" (vb.wp[0]), "r" (vb.wp[1]), "r" (0));
+                       goto update_regs;
+
+               case EVFSCTUF:
+                       __asm__ __volatile__ ("mtspr 512, %4\n"
+                               "efsctuf %0, %2\n"
+                               "efsctuf %1, %3\n"
+                               : "=r" (vc.wp[0]), "=r" (vc.wp[1])
+                               : "r" (vb.wp[0]), "r" (vb.wp[1]), "r" (0));
+                       goto update_regs;
+
+               case EVFSCTUI:
+               case EVFSCTSI:
+               case EVFSCTUIZ:
+               case EVFSCTSIZ:
+                       if (func & 0x4) {
+                               _FP_ROUND(1, SB0);
+                               _FP_ROUND(1, SB1);
+                       } else {
+                               _FP_ROUND_ZERO(1, SB0);
+                               _FP_ROUND_ZERO(1, SB1);
+                       }
+                       FP_TO_INT_S(vc.wp[0], SB0, 32, ((func & 0x3) != 0));
+                       FP_TO_INT_S(vc.wp[1], SB1, 32, ((func & 0x3) != 0));
+                       goto update_regs;
+
+               default:
+                       goto illegal;
+               }
+               break;
+
+pack_vs:
+#ifdef DEBUG
+               printk("SR0: %ld %08lx %ld (%ld)\n", SR0_s, SR0_f, SR0_e, SR0_c);
+               printk("SR1: %ld %08lx %ld (%ld)\n", SR1_s, SR1_f, SR1_e, SR1_c);
+#endif
+               FP_PACK_SP(vc.wp, SR0);
+               FP_PACK_SP(vc.wp + 1, SR1);
+               goto update_regs;
+
+cmp_vs:
+               {
+                       int ch, cl;
+
+                       FP_CMP_S(IR0, SA0, SB0, 3);
+                       FP_CMP_S(IR1, SA1, SB1, 3);
+                       if (IR0 == 3 && (FP_ISSIGNAN_S(SA0) || FP_ISSIGNAN_S(SB0)))
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       if (IR1 == 3 && (FP_ISSIGNAN_S(SA1) || FP_ISSIGNAN_S(SB1)))
+                               FP_SET_EXCEPTION(FP_EX_INVALID);
+                       ch = (IR0 == cmp) ? 1 : 0;
+                       cl = (IR1 == cmp) ? 1 : 0;
+                       IR = (ch << 3) | (cl << 2) | ((ch | cl) << 1) |
+                               ((ch & cl) << 0);
+                       goto update_ccr;
+               }
+       }
+       default:
+               return -EINVAL;
+       }
+
+update_ccr:
+       regs->ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2));
+       regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2));
+
+update_regs:
+       __FPU_FPSCR &= ~FP_EX_MASK;
+       __FPU_FPSCR |= (FP_CUR_EXCEPTIONS & FP_EX_MASK);
+       mtspr(SPRN_SPEFSCR, __FPU_FPSCR);
+
+       current->thread.evr[fc] = vc.wp[0];
+       regs->gpr[fc] = vc.wp[1];
+
+#ifdef DEBUG
+       printk("ccr = %08lx\n", regs->ccr);
+       printk("cur exceptions = %08x spefscr = %08lx\n",
+                       FP_CUR_EXCEPTIONS, __FPU_FPSCR);
+       printk("vc: %08x  %08x\n", vc.wp[0], vc.wp[1]);
+       printk("va: %08x  %08x\n", va.wp[0], va.wp[1]);
+       printk("vb: %08x  %08x\n", vb.wp[0], vb.wp[1]);
+#endif
+
+       return 0;
+
+illegal:
+       printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
+       return -ENOSYS;
+}
+
+int speround_handler(struct pt_regs *regs)
+{
+       union dw_union fgpr;
+       int s_lo, s_hi;
+       unsigned long speinsn, type, fc;
+
+       if (get_user(speinsn, (unsigned int __user *) regs->nip))
+               return -EFAULT;
+       if ((speinsn >> 26) != 4)
+               return -EINVAL;         /* not an spe instruction */
+
+       type = insn_type(speinsn & 0x7ff);
+       if (type == XCR) return -ENOSYS;
+
+       fc = (speinsn >> 21) & 0x1f;
+       s_lo = regs->gpr[fc] & SIGN_BIT_S;
+       s_hi = current->thread.evr[fc] & SIGN_BIT_S;
+       fgpr.wp[0] = current->thread.evr[fc];
+       fgpr.wp[1] = regs->gpr[fc];
+
+       __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
+
+       switch ((speinsn >> 5) & 0x7) {
+       /* Since SPE instructions on E500 core can handle round to nearest
+        * and round toward zero with IEEE-754 complied, we just need
+        * to handle round toward +Inf and round toward -Inf by software.
+        */
+       case SPFP:
+               if ((FP_ROUNDMODE) == FP_RND_PINF) {
+                       if (!s_lo) fgpr.wp[1]++; /* Z > 0, choose Z1 */
+               } else { /* round to -Inf */
+                       if (s_lo) fgpr.wp[1]++; /* Z < 0, choose Z2 */
+               }
+               break;
+
+       case DPFP:
+               if (FP_ROUNDMODE == FP_RND_PINF) {
+                       if (!s_hi) fgpr.dp[0]++; /* Z > 0, choose Z1 */
+               } else { /* round to -Inf */
+                       if (s_hi) fgpr.dp[0]++; /* Z < 0, choose Z2 */
+               }
+               break;
+
+       case VCT:
+               if (FP_ROUNDMODE == FP_RND_PINF) {
+                       if (!s_lo) fgpr.wp[1]++; /* Z_low > 0, choose Z1 */
+                       if (!s_hi) fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */
+               } else { /* round to -Inf */
+                       if (s_lo) fgpr.wp[1]++; /* Z_low < 0, choose Z2 */
+                       if (s_hi) fgpr.wp[0]++; /* Z_high < 0, choose Z2 */
+               }
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       current->thread.evr[fc] = fgpr.wp[0];
+       regs->gpr[fc] = fgpr.wp[1];
+
+       return 0;
+}
index e7392b4..148de35 100644 (file)
@@ -6,7 +6,7 @@ ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS   += -mno-minimal-toc
 endif
 
-obj-y                          := fault.o mem.o \
+obj-y                          := fault.o mem.o pgtable.o \
                                   init_$(CONFIG_WORD_SIZE).o \
                                   pgtable_$(CONFIG_WORD_SIZE).o \
                                   mmu_context_$(CONFIG_WORD_SIZE).o
@@ -16,7 +16,7 @@ obj-$(CONFIG_PPC64)           += hash_utils_64.o \
                                   gup.o mmap.o $(hash-y)
 obj-$(CONFIG_PPC_STD_MMU_32)   += ppc_mmu_32.o
 obj-$(CONFIG_PPC_STD_MMU)      += hash_low_$(CONFIG_WORD_SIZE).o \
-                                  tlb_$(CONFIG_WORD_SIZE).o
+                                  tlb_hash$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_40x)              += 40x_mmu.o
 obj-$(CONFIG_44x)              += 44x_mmu.o
 obj-$(CONFIG_FSL_BOOKE)                += fsl_booke_mmu.o
index 565b7a2..7df0409 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
+#include <asm/firmware.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
@@ -318,9 +319,16 @@ good_area:
                        goto do_sigbus;
                BUG();
        }
-       if (ret & VM_FAULT_MAJOR)
+       if (ret & VM_FAULT_MAJOR) {
                current->maj_flt++;
-       else
+#ifdef CONFIG_PPC_SMLPAR
+               if (firmware_has_feature(FW_FEATURE_CMO)) {
+                       preempt_disable();
+                       get_lppaca()->page_ins += (1 << PAGE_FACTOR);
+                       preempt_enable();
+               }
+#endif
+       } else
                current->min_flt++;
        up_read(&mm->mmap_sem);
        return 0;
index 7bffb70..c5536b8 100644 (file)
@@ -36,36 +36,6 @@ mmu_hash_lock:
 #endif /* CONFIG_SMP */
 
 /*
- * Sync CPUs with hash_page taking & releasing the hash
- * table lock
- */
-#ifdef CONFIG_SMP
-       .text
-_GLOBAL(hash_page_sync)
-       mfmsr   r10
-       rlwinm  r0,r10,0,17,15          /* clear bit 16 (MSR_EE) */
-       mtmsr   r0
-       lis     r8,mmu_hash_lock@h
-       ori     r8,r8,mmu_hash_lock@l
-       lis     r0,0x0fff
-       b       10f
-11:    lwz     r6,0(r8)
-       cmpwi   0,r6,0
-       bne     11b
-10:    lwarx   r6,0,r8
-       cmpwi   0,r6,0
-       bne-    11b
-       stwcx.  r0,0,r8
-       bne-    10b
-       isync
-       eieio
-       li      r0,0
-       stw     r0,0(r8)
-       mtmsr   r10
-       blr
-#endif /* CONFIG_SMP */
-
-/*
  * Load a PTE into the hash table, if possible.
  * The address is in r4, and r3 contains an access flag:
  * _PAGE_RW (0x400) if a write.
index f0c3b88..201c7a5 100644 (file)
@@ -53,8 +53,7 @@ unsigned int mmu_huge_psizes[MMU_PAGE_COUNT] = { }; /* initialize all to 0 */
 
 /* Subtract one from array size because we don't need a cache for 4K since
  * is not a huge page size */
-#define huge_pgtable_cache(psize)      (pgtable_cache[HUGEPTE_CACHE_NUM \
-                                                       + psize-1])
+#define HUGE_PGTABLE_INDEX(psize)      (HUGEPTE_CACHE_NUM + psize - 1)
 #define HUGEPTE_CACHE_NAME(psize)      (huge_pgtable_cache_name[psize])
 
 static const char *huge_pgtable_cache_name[MMU_PAGE_COUNT] = {
@@ -113,7 +112,7 @@ static inline pte_t *hugepte_offset(hugepd_t *hpdp, unsigned long addr,
 static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
                           unsigned long address, unsigned int psize)
 {
-       pte_t *new = kmem_cache_zalloc(huge_pgtable_cache(psize),
+       pte_t *new = kmem_cache_zalloc(pgtable_cache[HUGE_PGTABLE_INDEX(psize)],
                                      GFP_KERNEL|__GFP_REPEAT);
 
        if (! new)
@@ -121,7 +120,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
 
        spin_lock(&mm->page_table_lock);
        if (!hugepd_none(*hpdp))
-               kmem_cache_free(huge_pgtable_cache(psize), new);
+               kmem_cache_free(pgtable_cache[HUGE_PGTABLE_INDEX(psize)], new);
        else
                hpdp->pd = (unsigned long)new | HUGEPD_OK;
        spin_unlock(&mm->page_table_lock);
@@ -763,13 +762,14 @@ static int __init hugetlbpage_init(void)
 
        for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
                if (mmu_huge_psizes[psize]) {
-                       huge_pgtable_cache(psize) = kmem_cache_create(
-                                               HUGEPTE_CACHE_NAME(psize),
-                                               HUGEPTE_TABLE_SIZE(psize),
-                                               HUGEPTE_TABLE_SIZE(psize),
-                                               0,
-                                               NULL);
-                       if (!huge_pgtable_cache(psize))
+                       pgtable_cache[HUGE_PGTABLE_INDEX(psize)] =
+                               kmem_cache_create(
+                                       HUGEPTE_CACHE_NAME(psize),
+                                       HUGEPTE_TABLE_SIZE(psize),
+                                       HUGEPTE_TABLE_SIZE(psize),
+                                       0,
+                                       NULL);
+                       if (!pgtable_cache[HUGE_PGTABLE_INDEX(psize)])
                                panic("hugetlbpage_init(): could not create %s"\
                                      "\n", HUGEPTE_CACHE_NAME(psize));
                }
index fab3cfa..b4344fd 100644 (file)
@@ -58,17 +58,14 @@ extern phys_addr_t lowmem_end_addr;
  * architectures.  -- Dan
  */
 #if defined(CONFIG_8xx)
-#define flush_HPTE(X, va, pg)  _tlbie(va, 0 /* 8xx doesn't care about PID */)
 #define MMU_init_hw()          do { } while(0)
 #define mmu_mapin_ram()                (0UL)
 
 #elif defined(CONFIG_4xx)
-#define flush_HPTE(pid, va, pg)        _tlbie(va, pid)
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(void);
 
 #elif defined(CONFIG_FSL_BOOKE)
-#define flush_HPTE(pid, va, pg)        _tlbie(va, pid)
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(void);
 extern void adjust_total_lowmem(void);
@@ -77,18 +74,4 @@ extern void adjust_total_lowmem(void);
 /* anything 32-bit except 4xx or 8xx */
 extern void MMU_init_hw(void);
 extern unsigned long mmu_mapin_ram(void);
-
-/* Be careful....this needs to be updated if we ever encounter 603 SMPs,
- * which includes all new 82xx processors.  We need tlbie/tlbsync here
- * in that case (I think). -- Dan.
- */
-static inline void flush_HPTE(unsigned context, unsigned long va,
-                             unsigned long pdval)
-{
-       if ((Hash != 0) &&
-           cpu_has_feature(CPU_FTR_HPTE_TABLE))
-               flush_hash_pages(0, va, pdval, 1);
-       else
-               _tlbie(va);
-}
 #endif
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
new file mode 100644 (file)
index 0000000..6d94116
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * This file contains common routines for dealing with free of page tables
+ *
+ *  Derived from arch/powerpc/mm/tlb_64.c:
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Paul Mackerras
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  Dave Engebretsen <engebret@us.ibm.com>
+ *      Rework for PPC64 port.
+ *
+ *  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 <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
+
+static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
+static unsigned long pte_freelist_forced_free;
+
+struct pte_freelist_batch
+{
+       struct rcu_head rcu;
+       unsigned int    index;
+       pgtable_free_t  tables[0];
+};
+
+#define PTE_FREELIST_SIZE \
+       ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
+         / sizeof(pgtable_free_t))
+
+static void pte_free_smp_sync(void *arg)
+{
+       /* Do nothing, just ensure we sync with all CPUs */
+}
+
+/* This is only called when we are critically out of memory
+ * (and fail to get a page in pte_free_tlb).
+ */
+static void pgtable_free_now(pgtable_free_t pgf)
+{
+       pte_freelist_forced_free++;
+
+       smp_call_function(pte_free_smp_sync, NULL, 1);
+
+       pgtable_free(pgf);
+}
+
+static void pte_free_rcu_callback(struct rcu_head *head)
+{
+       struct pte_freelist_batch *batch =
+               container_of(head, struct pte_freelist_batch, rcu);
+       unsigned int i;
+
+       for (i = 0; i < batch->index; i++)
+               pgtable_free(batch->tables[i]);
+
+       free_page((unsigned long)batch);
+}
+
+static void pte_free_submit(struct pte_freelist_batch *batch)
+{
+       INIT_RCU_HEAD(&batch->rcu);
+       call_rcu(&batch->rcu, pte_free_rcu_callback);
+}
+
+void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
+{
+       /* This is safe since tlb_gather_mmu has disabled preemption */
+        cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
+       struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+
+       if (atomic_read(&tlb->mm->mm_users) < 2 ||
+           cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
+               pgtable_free(pgf);
+               return;
+       }
+
+       if (*batchp == NULL) {
+               *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
+               if (*batchp == NULL) {
+                       pgtable_free_now(pgf);
+                       return;
+               }
+               (*batchp)->index = 0;
+       }
+       (*batchp)->tables[(*batchp)->index++] = pgf;
+       if ((*batchp)->index == PTE_FREELIST_SIZE) {
+               pte_free_submit(*batchp);
+               *batchp = NULL;
+       }
+}
+
+void pte_free_finish(void)
+{
+       /* This is safe since tlb_gather_mmu has disabled preemption */
+       struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
+
+       if (*batchp == NULL)
+               return;
+       pte_free_submit(*batchp);
+       *batchp = NULL;
+}
index c31d6d2..3414724 100644 (file)
@@ -48,10 +48,6 @@ EXPORT_SYMBOL(ioremap_bot);  /* aka VMALLOC_END */
 
 extern char etext[], _stext[];
 
-#ifdef CONFIG_SMP
-extern void hash_page_sync(void);
-#endif
-
 #ifdef HAVE_BATS
 extern phys_addr_t v_mapped_by_bats(unsigned long va);
 extern unsigned long p_mapped_by_bats(phys_addr_t pa);
@@ -125,23 +121,6 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
        return ptepage;
 }
 
-void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
-{
-#ifdef CONFIG_SMP
-       hash_page_sync();
-#endif
-       free_page((unsigned long)pte);
-}
-
-void pte_free(struct mm_struct *mm, pgtable_t ptepage)
-{
-#ifdef CONFIG_SMP
-       hash_page_sync();
-#endif
-       pgtable_page_dtor(ptepage);
-       __free_page(ptepage);
-}
-
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
 {
@@ -363,7 +342,11 @@ static int __change_page_attr(struct page *page, pgprot_t prot)
                return -EINVAL;
        set_pte_at(&init_mm, address, kpte, mk_pte(page, prot));
        wmb();
-       flush_HPTE(0, address, pmd_val(*kpmd));
+#ifdef CONFIG_PPC_STD_MMU
+       flush_hash_pages(0, address, pmd_val(*kpmd), 1);
+#else
+       flush_tlb_page(NULL, address);
+#endif
        pte_unmap(kpte);
 
        return 0;
similarity index 75%
rename from arch/powerpc/mm/tlb_64.c
rename to arch/powerpc/mm/tlb_hash64.c
index be7dd42..c931bc7 100644 (file)
@@ -37,81 +37,6 @@ DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch);
  * arch/powerpc/include/asm/tlb.h file -- tgall
  */
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
-static unsigned long pte_freelist_forced_free;
-
-struct pte_freelist_batch
-{
-       struct rcu_head rcu;
-       unsigned int    index;
-       pgtable_free_t  tables[0];
-};
-
-#define PTE_FREELIST_SIZE \
-       ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
-         / sizeof(pgtable_free_t))
-
-static void pte_free_smp_sync(void *arg)
-{
-       /* Do nothing, just ensure we sync with all CPUs */
-}
-
-/* This is only called when we are critically out of memory
- * (and fail to get a page in pte_free_tlb).
- */
-static void pgtable_free_now(pgtable_free_t pgf)
-{
-       pte_freelist_forced_free++;
-
-       smp_call_function(pte_free_smp_sync, NULL, 1);
-
-       pgtable_free(pgf);
-}
-
-static void pte_free_rcu_callback(struct rcu_head *head)
-{
-       struct pte_freelist_batch *batch =
-               container_of(head, struct pte_freelist_batch, rcu);
-       unsigned int i;
-
-       for (i = 0; i < batch->index; i++)
-               pgtable_free(batch->tables[i]);
-
-       free_page((unsigned long)batch);
-}
-
-static void pte_free_submit(struct pte_freelist_batch *batch)
-{
-       INIT_RCU_HEAD(&batch->rcu);
-       call_rcu(&batch->rcu, pte_free_rcu_callback);
-}
-
-void pgtable_free_tlb(struct mmu_gather *tlb, pgtable_free_t pgf)
-{
-       /* This is safe since tlb_gather_mmu has disabled preemption */
-        cpumask_t local_cpumask = cpumask_of_cpu(smp_processor_id());
-       struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
-
-       if (atomic_read(&tlb->mm->mm_users) < 2 ||
-           cpus_equal(tlb->mm->cpu_vm_mask, local_cpumask)) {
-               pgtable_free(pgf);
-               return;
-       }
-
-       if (*batchp == NULL) {
-               *batchp = (struct pte_freelist_batch *)__get_free_page(GFP_ATOMIC);
-               if (*batchp == NULL) {
-                       pgtable_free_now(pgf);
-                       return;
-               }
-               (*batchp)->index = 0;
-       }
-       (*batchp)->tables[(*batchp)->index++] = pgf;
-       if ((*batchp)->index == PTE_FREELIST_SIZE) {
-               pte_free_submit(*batchp);
-               *batchp = NULL;
-       }
-}
 
 /*
  * A linux PTE was changed and the corresponding hash table entry
@@ -229,17 +154,6 @@ void __flush_tlb_pending(struct ppc64_tlb_batch *batch)
        batch->index = 0;
 }
 
-void pte_free_finish(void)
-{
-       /* This is safe since tlb_gather_mmu has disabled preemption */
-       struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur);
-
-       if (*batchp == NULL)
-               return;
-       pte_free_submit(*batchp);
-       *batchp = NULL;
-}
-
 /**
  * __flush_hash_table_range - Flush all HPTEs for a given address range
  *                            from the hash table (and the TLB). But keeps
index ae2e7f6..4058fd1 100644 (file)
@@ -100,7 +100,7 @@ static void __init ep405_setup_arch(void)
        /* Find & init the BCSR CPLD */
        ep405_init_bcsr();
 
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
 }
 
 static int __init ep405_probe(void)
index 1dd24ff..fd7d934 100644 (file)
@@ -44,7 +44,7 @@ static int __init kilauea_probe(void)
        if (!of_flat_dt_is_compatible(root, "amcc,kilauea"))
                return 0;
 
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index 4498a86..f40ac9b 100644 (file)
@@ -61,7 +61,7 @@ static int __init ppc40x_probe(void)
 
        for (i = 0; i < ARRAY_SIZE(board); i++) {
                if (of_flat_dt_is_compatible(root, board[i])) {
-                       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+                       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
                        return 1;
                }
        }
index a0e8fe4..88b9117 100644 (file)
@@ -54,7 +54,7 @@ static int __init ebony_probe(void)
        if (!of_flat_dt_is_compatible(root, "ibm,ebony"))
                return 0;
 
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index 2967126..76fdc51 100644 (file)
@@ -69,7 +69,7 @@ static int __init ppc44x_probe(void)
 
        for (i = 0; i < ARRAY_SIZE(board); i++) {
                if (of_flat_dt_is_compatible(root, board[i])) {
-                       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+                       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
                        return 1;
                }
        }
index 47f10e6..a78e8eb 100644 (file)
@@ -51,7 +51,7 @@ static int __init sam440ep_probe(void)
        if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
                return 0;
 
-       ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+       ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
 
        return 1;
 }
index b49a185..c3f2c21 100644 (file)
@@ -375,7 +375,7 @@ mpc52xx_add_bridge(struct device_node *node)
 
        pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
 
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
 
        if (of_address_to_resource(node, 0, &rsrc) != 0) {
                printk(KERN_ERR "Can't get %s resources\n", node->full_name);
index 1b75902..9761a59 100644 (file)
@@ -53,7 +53,7 @@ static void __init pq2_pci_add_bridge(struct device_node *np)
        if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
                goto err;
 
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
 
        hose = pcibios_alloc_controller(np);
        if (!hose)
index cb3054e..f0798c0 100644 (file)
@@ -1,6 +1,8 @@
 #
 # Makefile for the PowerPC 85xx linux kernel.
 #
+obj-$(CONFIG_SMP) += smp.o
+
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
index 613bf8c..a8301c8 100644 (file)
@@ -63,6 +63,7 @@ void __init mpc85xx_ds_pic_init(void)
        struct device_node *cascade_node = NULL;
        int cascade_irq;
 #endif
+       unsigned long root = of_get_flat_dt_root();
 
        np = of_find_node_by_type(NULL, "open-pic");
        if (np == NULL) {
@@ -76,11 +77,19 @@ void __init mpc85xx_ds_pic_init(void)
                return;
        }
 
-       mpic = mpic_alloc(np, r.start,
+       if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
+               mpic = mpic_alloc(np, r.start,
+                       MPIC_PRIMARY |
+                       MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS,
+                       0, 256, " OpenPIC  ");
+       } else {
+               mpic = mpic_alloc(np, r.start,
                          MPIC_PRIMARY | MPIC_WANTS_RESET |
                          MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
                          MPIC_SINGLE_DEST_CPU,
                        0, 256, " OpenPIC  ");
+       }
+
        BUG_ON(mpic == NULL);
        of_node_put(np);
 
index 2494c51..658a36f 100644 (file)
@@ -231,7 +231,7 @@ static void __init mpc85xx_mds_setup_arch(void)
 
 static int __init board_fixups(void)
 {
-       char phy_id[BUS_ID_SIZE];
+       char phy_id[20];
        char *compstrs[2] = {"fsl,gianfar-mdio", "fsl,ucc-mdio"};
        struct device_node *mdio;
        struct resource res;
@@ -241,13 +241,15 @@ static int __init board_fixups(void)
                mdio = of_find_compatible_node(NULL, NULL, compstrs[i]);
 
                of_address_to_resource(mdio, 0, &res);
-               snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 1);
+               snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
+                       (unsigned long long)res.start, 1);
 
                phy_register_fixup_for_id(phy_id, mpc8568_fixup_125_clock);
                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 
                /* Register a workaround for errata */
-               snprintf(phy_id, BUS_ID_SIZE, "%x:%02x", res.start, 7);
+               snprintf(phy_id, sizeof(phy_id), "%llx:%02x",
+                       (unsigned long long)res.start, 7);
                phy_register_fixup_for_id(phy_id, mpc8568_mds_phy_fixups);
 
                of_node_put(mdio);
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
new file mode 100644 (file)
index 0000000..d652c71
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Author: Andy Fleming <afleming@freescale.com>
+ *        Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2006-2008 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 <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/mpic.h>
+#include <asm/cacheflush.h>
+
+#include <sysdev/fsl_soc.h>
+
+extern volatile unsigned long __secondary_hold_acknowledge;
+extern void __early_start(void);
+
+#define BOOT_ENTRY_ADDR_UPPER  0
+#define BOOT_ENTRY_ADDR_LOWER  1
+#define BOOT_ENTRY_R3_UPPER    2
+#define BOOT_ENTRY_R3_LOWER    3
+#define BOOT_ENTRY_RESV                4
+#define BOOT_ENTRY_PIR         5
+#define BOOT_ENTRY_R6_UPPER    6
+#define BOOT_ENTRY_R6_LOWER    7
+#define NUM_BOOT_ENTRY         8
+#define SIZE_BOOT_ENTRY                (NUM_BOOT_ENTRY * sizeof(u32))
+
+static void __init
+smp_85xx_kick_cpu(int nr)
+{
+       unsigned long flags;
+       const u64 *cpu_rel_addr;
+       __iomem u32 *bptr_vaddr;
+       struct device_node *np;
+       int n = 0;
+
+       WARN_ON (nr < 0 || nr >= NR_CPUS);
+
+       pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
+
+       local_irq_save(flags);
+
+       np = of_get_cpu_node(nr, NULL);
+       cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
+
+       if (cpu_rel_addr == NULL) {
+               printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
+               return;
+       }
+
+       /* Map the spin table */
+       bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY);
+
+       out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr);
+       out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start));
+
+       /* Wait a bit for the CPU to ack. */
+       while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
+               mdelay(1);
+
+       iounmap(bptr_vaddr);
+
+       local_irq_restore(flags);
+
+       pr_debug("waited %d msecs for CPU #%d.\n", n, nr);
+}
+
+static void __init
+smp_85xx_setup_cpu(int cpu_nr)
+{
+       mpic_setup_this_cpu();
+
+       /* Clear any pending timer interrupts */
+       mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+       /* Enable decrementer interrupt */
+       mtspr(SPRN_TCR, TCR_DIE);
+}
+
+struct smp_ops_t smp_85xx_ops = {
+       .message_pass = smp_mpic_message_pass,
+       .probe = smp_mpic_probe,
+       .kick_cpu = smp_85xx_kick_cpu,
+       .setup_cpu = smp_85xx_setup_cpu,
+};
+
+void __init
+mpc85xx_smp_init(void)
+{
+       smp_ops = &smp_85xx_ops;
+}
index 77dd797..8e56939 100644 (file)
@@ -34,6 +34,8 @@ config MPC8610_HPCD
 config GEF_SBC610
        bool "GE Fanuc SBC610"
        select DEFAULT_UIMAGE
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
        select HAS_RAPIDIO
        help
          This option enables support for GE Fanuc's SBC610.
index 4a56ff6..31e540c 100644 (file)
@@ -7,4 +7,5 @@ obj-$(CONFIG_SMP)               += mpc86xx_smp.o
 obj-$(CONFIG_MPC8641_HPCN)     += mpc86xx_hpcn.o
 obj-$(CONFIG_SBC8641D)         += sbc8641d.o
 obj-$(CONFIG_MPC8610_HPCD)     += mpc8610_hpcd.o
-obj-$(CONFIG_GEF_SBC610)       += gef_sbc610.o gef_pic.o
+gef-gpio-$(CONFIG_GPIOLIB)     += gef_gpio.o
+obj-$(CONFIG_GEF_SBC610)       += gef_sbc610.o gef_pic.o $(gef-gpio-y)
diff --git a/arch/powerpc/platforms/86xx/gef_gpio.c b/arch/powerpc/platforms/86xx/gef_gpio.c
new file mode 100644 (file)
index 0000000..85b2800
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Driver for GE Fanuc's FPGA based GPIO pins
+ *
+ * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ *
+ * 2008 (c) GE Fanuc Intelligent Platforms Embedded Systems, 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.
+ */
+
+/* TODO
+ *
+ * Configuration of output modes (totem-pole/open-drain)
+ * Interrupt configuration - interrupts are always generated the FPGA relies on
+ *     the I/O interrupt controllers mask to stop them propergating
+ */
+
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+
+#define GEF_GPIO_DIRECT                0x00
+#define GEF_GPIO_IN            0x04
+#define GEF_GPIO_OUT           0x08
+#define GEF_GPIO_TRIG          0x0C
+#define GEF_GPIO_POLAR_A       0x10
+#define GEF_GPIO_POLAR_B       0x14
+#define GEF_GPIO_INT_STAT      0x18
+#define GEF_GPIO_OVERRUN       0x1C
+#define GEF_GPIO_MODE          0x20
+
+#define NUM_GPIO 19
+
+static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+{
+       unsigned int data;
+
+       data = ioread32be(reg);
+       /* value: 0=low; 1=high */
+       if (value & 0x1)
+               data = data | (0x1 << offset);
+       else
+               data = data & ~(0x1 << offset);
+
+       iowrite32be(data, reg);
+}
+
+
+static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int data;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
+       data = data | (0x1 << offset);
+       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
+
+       return 0;
+}
+
+static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+       unsigned int data;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       /* Set direction before switching to input */
+       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
+       data = data & ~(0x1 << offset);
+       iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
+
+       return 0;
+}
+
+static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+       unsigned int data;
+       int state = 0;
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       data = ioread32be(mmchip->regs + GEF_GPIO_IN);
+       state = (int)((data >> offset) & 0x1);
+
+       return state;
+}
+
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
+
+       _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+}
+
+static int __init gef_gpio_init(void)
+{
+       struct device_node *np;
+
+       for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
+               int retval;
+               struct of_mm_gpio_chip *gef_gpio_chip;
+
+               pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
+
+               /* Allocate chip structure */
+               gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
+               if (!gef_gpio_chip) {
+                       pr_err("%s: Unable to allocate structure\n",
+                               np->full_name);
+                       continue;
+               }
+
+               /* Setup pointers to chip functions */
+               gef_gpio_chip->of_gc.gpio_cells = 2;
+               gef_gpio_chip->of_gc.gc.ngpio = NUM_GPIO;
+               gef_gpio_chip->of_gc.gc.direction_input = gef_gpio_dir_in;
+               gef_gpio_chip->of_gc.gc.direction_output = gef_gpio_dir_out;
+               gef_gpio_chip->of_gc.gc.get = gef_gpio_get;
+               gef_gpio_chip->of_gc.gc.set = gef_gpio_set;
+
+               /* This function adds a memory mapped GPIO chip */
+               retval = of_mm_gpiochip_add(np, gef_gpio_chip);
+               if (retval) {
+                       kfree(gef_gpio_chip);
+                       pr_err("%s: Unable to add GPIO\n", np->full_name);
+               }
+       }
+
+       return 0;
+};
+arch_initcall(gef_gpio_init);
+
+MODULE_DESCRIPTION("GE Fanuc I/O FPGA GPIO driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_LICENSE("GPL");
index 3168272..86db4dd 100644 (file)
@@ -1053,10 +1053,7 @@ static int __init cell_iommu_fixed_mapping_init(void)
        }
 
        /* We must have dma-ranges properties for fixed mapping to work */
-       for (np = NULL; (np = of_find_all_nodes(np));) {
-               if (of_find_property(np, "dma-ranges", NULL))
-                       break;
-       }
+       np = of_find_node_with_property(NULL, "dma-ranges");
        of_node_put(np);
 
        if (!np) {
index d3cde6b..f6b0c51 100644 (file)
@@ -141,6 +141,7 @@ hydra_init(void)
                of_node_put(np);
                return 0;
        }
+       of_node_put(np);
        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",
@@ -198,7 +199,7 @@ static void __init setup_peg2(struct pci_controller *hose, struct device_node *d
                printk ("RTAS supporting Pegasos OF not found, please upgrade"
                        " your firmware\n");
        }
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
        /* keep the reference to the root node */
 }
 
index bcf50d7..54b7b76 100644 (file)
@@ -729,7 +729,7 @@ static void __init setup_bandit(struct pci_controller *hose,
 static int __init setup_uninorth(struct pci_controller *hose,
                                 struct resource *addr)
 {
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
        has_uninorth = 1;
        hose->ops = &macrisc_pci_ops;
        hose->cfg_addr = ioremap(addr->start + 0x800000, 0x1000);
@@ -996,7 +996,7 @@ void __init pmac_pci_init(void)
        struct device_node *np, *root;
        struct device_node *ht = NULL;
 
-       ppc_pci_flags = PPC_PCI_CAN_SKIP_ISA_ALIGN;
+       ppc_pci_set_flags(PPC_PCI_CAN_SKIP_ISA_ALIGN);
 
        root = of_find_node_by_path("/");
        if (root == NULL) {
@@ -1055,7 +1055,7 @@ void __init pmac_pci_init(void)
         * some offset between bus number and domains for now when we
         * assign all busses should help for now
         */
-       if (ppc_pci_flags & PPC_PCI_REASSIGN_ALL_BUS)
+       if (ppc_pci_has_flag(PPC_PCI_REASSIGN_ALL_BUS))
                pcibios_assign_bus_offset = 0x10;
 #endif
 }
index 82c14d2..1293772 100644 (file)
@@ -310,9 +310,7 @@ static void __init pmac_setup_arch(void)
        }
 
        /* See if newworld or oldworld */
-       for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; )
-               if (of_get_property(ic, "interrupt-controller", NULL))
-                       break;
+       ic = of_find_node_with_property(NULL, "interrupt-controller");
        if (ic) {
                pmac_newworld = 1;
                of_node_put(ic);
index 40f72c2..6b0711c 100644 (file)
@@ -739,7 +739,7 @@ static void __init smp_core99_setup(int ncpus)
 
                /* XXX should get this from reg properties */
                for (i = 1; i < ncpus; ++i)
-                       smp_hw_index[i] = i;
+                       set_hard_smp_processor_id(i, i);
        }
 #endif
 
index ffdd8e9..dbc124e 100644 (file)
@@ -314,11 +314,17 @@ static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,
 
        result = ps3_system_bus_device_register(&p->dev);
 
-       if (result)
+       if (result) {
                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
                        __func__, __LINE__);
-
+               goto fail_device_register;
+       }
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
+
+fail_device_register:
+       kfree(p);
+       pr_debug(" <- %s:%d fail\n", __func__, __LINE__);
        return result;
 }
 
@@ -463,11 +469,17 @@ static int __init ps3_register_sound_devices(void)
 
        result = ps3_system_bus_device_register(&p->dev);
 
-       if (result)
+       if (result) {
                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
                        __func__, __LINE__);
-
+               goto fail_device_register;
+       }
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
+
+fail_device_register:
+       kfree(p);
+       pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
        return result;
 }
 
@@ -485,17 +497,24 @@ static int __init ps3_register_graphics_devices(void)
        if (!p)
                return -ENOMEM;
 
-       p->dev.match_id = PS3_MATCH_ID_GRAPHICS;
-       p->dev.match_sub_id = PS3_MATCH_SUB_ID_FB;
+       p->dev.match_id = PS3_MATCH_ID_GPU;
+       p->dev.match_sub_id = PS3_MATCH_SUB_ID_GPU_FB;
        p->dev.dev_type = PS3_DEVICE_TYPE_IOC0;
 
        result = ps3_system_bus_device_register(&p->dev);
 
-       if (result)
+       if (result) {
                pr_debug("%s:%d ps3_system_bus_device_register failed\n",
                        __func__, __LINE__);
+               goto fail_device_register;
+       }
 
        pr_debug(" <- %s:%d\n", __func__, __LINE__);
+       return 0;
+
+fail_device_register:
+       kfree(p);
+       pr_debug(" <- %s:%d failed\n", __func__, __LINE__);
        return result;
 }
 
index 3a58ffa..a4d49dd 100644 (file)
@@ -649,7 +649,7 @@ static int dma_sb_region_create(struct ps3_dma_region *r)
 {
        int result;
 
-       pr_info(" -> %s:%d:\n", __func__, __LINE__);
+       DBG(" -> %s:%d:\n", __func__, __LINE__);
 
        BUG_ON(!r);
 
index 77bc330..bfc33fb 100644 (file)
 #define DBG pr_debug
 #endif
 
+/* mutex synchronizing GPU accesses and video mode changes */
+DEFINE_MUTEX(ps3_gpu_mutex);
+EXPORT_SYMBOL_GPL(ps3_gpu_mutex);
+
 #if !defined(CONFIG_SMP)
 static void smp_send_stop(void) {}
 #endif
index 661e9f7..ee0d229 100644 (file)
@@ -31,7 +31,7 @@
 #include "platform.h"
 
 static struct device ps3_system_bus = {
-       .bus_id = "ps3_system",
+       .init_name = "ps3_system",
 };
 
 /* FIXME: need device usage counters! */
@@ -175,7 +175,7 @@ int ps3_open_hv_device(struct ps3_system_bus_device *dev)
                return ps3_open_hv_device_sb(dev);
 
        case PS3_MATCH_ID_SOUND:
-       case PS3_MATCH_ID_GRAPHICS:
+       case PS3_MATCH_ID_GPU:
                return ps3_open_hv_device_gpu(dev);
 
        case PS3_MATCH_ID_AV_SETTINGS:
@@ -213,7 +213,7 @@ int ps3_close_hv_device(struct ps3_system_bus_device *dev)
                return ps3_close_hv_device_sb(dev);
 
        case PS3_MATCH_ID_SOUND:
-       case PS3_MATCH_ID_GRAPHICS:
+       case PS3_MATCH_ID_GPU:
                return ps3_close_hv_device_gpu(dev);
 
        case PS3_MATCH_ID_AV_SETTINGS:
@@ -356,12 +356,12 @@ static int ps3_system_bus_match(struct device *_dev,
        if (result)
                pr_info("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): match\n",
                        __func__, __LINE__,
-                       dev->match_id, dev->match_sub_id, dev->core.bus_id,
+                       dev->match_id, dev->match_sub_id, dev_name(&dev->core),
                        drv->match_id, drv->match_sub_id, drv->core.name);
        else
                pr_debug("%s:%d: dev=%u.%u(%s), drv=%u.%u(%s): miss\n",
                        __func__, __LINE__,
-                       dev->match_id, dev->match_sub_id, dev->core.bus_id,
+                       dev->match_id, dev->match_sub_id, dev_name(&dev->core),
                        drv->match_id, drv->match_sub_id, drv->core.name);
 
        return result;
@@ -383,9 +383,9 @@ static int ps3_system_bus_probe(struct device *_dev)
                result = drv->probe(dev);
        else
                pr_debug("%s:%d: %s no probe method\n", __func__, __LINE__,
-                       dev->core.bus_id);
+                       dev_name(&dev->core));
 
-       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core));
        return result;
 }
 
@@ -407,7 +407,7 @@ static int ps3_system_bus_remove(struct device *_dev)
                dev_dbg(&dev->core, "%s:%d %s: no remove method\n",
                        __func__, __LINE__, drv->core.name);
 
-       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id);
+       pr_debug(" <- %s:%d: %s\n", __func__, __LINE__, dev_name(&dev->core));
        return result;
 }
 
@@ -432,7 +432,7 @@ static void ps3_system_bus_shutdown(struct device *_dev)
        BUG_ON(!drv);
 
        dev_dbg(&dev->core, "%s:%d: %s -> %s\n", __func__, __LINE__,
-               dev->core.bus_id, drv->core.name);
+               dev_name(&dev->core), drv->core.name);
 
        if (drv->shutdown)
                drv->shutdown(dev);
@@ -453,7 +453,8 @@ static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *en
 {
        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
 
-       if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id))
+       if (add_uevent_var(env, "MODALIAS=ps3:%d:%d", dev->match_id,
+                          dev->match_sub_id))
                return -ENOMEM;
        return 0;
 }
@@ -462,7 +463,8 @@ static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
        char *buf)
 {
        struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
-       int len = snprintf(buf, PAGE_SIZE, "ps3:%d\n", dev->match_id);
+       int len = snprintf(buf, PAGE_SIZE, "ps3:%d:%d\n", dev->match_id,
+                          dev->match_sub_id);
 
        return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
 }
@@ -742,22 +744,18 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
        switch (dev->dev_type) {
        case PS3_DEVICE_TYPE_IOC0:
                dev->core.archdata.dma_ops = &ps3_ioc0_dma_ops;
-               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
-                       "ioc0_%02x", ++dev_ioc0_count);
+               dev_set_name(&dev->core, "ioc0_%02x", ++dev_ioc0_count);
                break;
        case PS3_DEVICE_TYPE_SB:
                dev->core.archdata.dma_ops = &ps3_sb_dma_ops;
-               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
-                       "sb_%02x", ++dev_sb_count);
+               dev_set_name(&dev->core, "sb_%02x", ++dev_sb_count);
 
                break;
        case PS3_DEVICE_TYPE_VUART:
-               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
-                       "vuart_%02x", ++dev_vuart_count);
+               dev_set_name(&dev->core, "vuart_%02x", ++dev_vuart_count);
                break;
        case PS3_DEVICE_TYPE_LPM:
-               snprintf(dev->core.bus_id, sizeof(dev->core.bus_id),
-                       "lpm_%02x", ++dev_lpm_count);
+               dev_set_name(&dev->core, "lpm_%02x", ++dev_lpm_count);
                break;
        default:
                BUG();
@@ -766,7 +764,7 @@ int ps3_system_bus_device_register(struct ps3_system_bus_device *dev)
        dev->core.archdata.of_node = NULL;
        set_dev_node(&dev->core, 0);
 
-       pr_debug("%s:%d add %s\n", __func__, __LINE__, dev->core.bus_id);
+       pr_debug("%s:%d add %s\n", __func__, __LINE__, dev_name(&dev->core));
 
        result = device_register(&dev->core);
        return result;
index 54816d7..989d646 100644 (file)
@@ -21,6 +21,8 @@
  * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
  */
 
+#undef DEBUG
+
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/list.h>
@@ -488,10 +490,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
        if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
            pdn->eeh_mode & EEH_MODE_NOCHECK) {
                ignored_check++;
-#ifdef DEBUG
-               printk ("EEH:ignored check (%x) for %s %s\n", 
-                       pdn->eeh_mode, pci_name (dev), dn->full_name);
-#endif
+               pr_debug("EEH: Ignored check (%x) for %s %s\n",
+                        pdn->eeh_mode, pci_name (dev), dn->full_name);
                return 0;
        }
 
@@ -1014,10 +1014,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
                        eeh_subsystem_enabled = 1;
                        pdn->eeh_mode |= EEH_MODE_SUPPORTED;
 
-#ifdef DEBUG
-                       printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n",
-                              dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr);
-#endif
+                       pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
+                                dn->full_name, pdn->eeh_config_addr,
+                                pdn->eeh_pe_config_addr);
                } else {
 
                        /* This device doesn't support EEH, but it may have an
@@ -1161,13 +1160,17 @@ static void eeh_add_device_late(struct pci_dev *dev)
        if (!dev || !eeh_subsystem_enabled)
                return;
 
-#ifdef DEBUG
-       printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
-#endif
+       pr_debug("EEH: Adding device %s\n", pci_name(dev));
 
-       pci_dev_get (dev);
        dn = pci_device_to_OF_node(dev);
        pdn = PCI_DN(dn);
+       if (pdn->pcidev == dev) {
+               pr_debug("EEH: Already referenced !\n");
+               return;
+       }
+       WARN_ON(pdn->pcidev);
+
+       pci_dev_get (dev);
        pdn->pcidev = dev;
 
        pci_addr_cache_insert_device(dev);
@@ -1206,17 +1209,18 @@ static void eeh_remove_device(struct pci_dev *dev)
                return;
 
        /* Unregister the device with the EEH/PCI address search system */
-#ifdef DEBUG
-       printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
-#endif
-       pci_addr_cache_remove_device(dev);
-       eeh_sysfs_remove_device(dev);
+       pr_debug("EEH: Removing device %s\n", pci_name(dev));
 
        dn = pci_device_to_OF_node(dev);
-       if (PCI_DN(dn)->pcidev) {
-               PCI_DN(dn)->pcidev = NULL;
-               pci_dev_put (dev);
+       if (PCI_DN(dn)->pcidev == NULL) {
+               pr_debug("EEH: Not referenced !\n");
+               return;
        }
+       PCI_DN(dn)->pcidev = NULL;
+       pci_dev_put (dev);
+
+       pci_addr_cache_remove_device(dev);
+       eeh_sysfs_remove_device(dev);
 }
 
 void eeh_remove_bus_device(struct pci_dev *dev)
index 7190493..5e1ed3d 100644 (file)
@@ -25,6 +25,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#undef DEBUG
+
 #include <linux/pci.h>
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
@@ -69,74 +71,25 @@ EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
  */
-void
-pcibios_remove_pci_devices(struct pci_bus *bus)
+void pcibios_remove_pci_devices(struct pci_bus *bus)
 {
-       struct pci_dev *dev, *tmp;
+       struct pci_dev *dev, *tmp;
+       struct pci_bus *child_bus;
+
+       /* First go down child busses */
+       list_for_each_entry(child_bus, &bus->children, node)
+               pcibios_remove_pci_devices(child_bus);
 
+       pr_debug("PCI: Removing devices on bus %04x:%02x\n",
+                pci_domain_nr(bus),  bus->number);
        list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+               pr_debug("     * Removing %s...\n", pci_name(dev));
                eeh_remove_bus_device(dev);
-               pci_remove_bus_device(dev);
-       }
+               pci_remove_bus_device(dev);
+       }
 }
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
-/* Must be called before pci_bus_add_devices */
-void
-pcibios_fixup_new_pci_devices(struct pci_bus *bus)
-{
-       struct pci_dev *dev;
-
-       list_for_each_entry(dev, &bus->devices, bus_list) {
-               /* Skip already-added devices */
-               if (!dev->is_added) {
-                       int i;
-
-                       /* Fill device archdata and setup iommu table */
-                       pcibios_setup_new_device(dev);
-
-                       pci_read_irq_line(dev);
-                       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-                               struct resource *r = &dev->resource[i];
-
-                               if (r->parent || !r->start || !r->flags)
-                                       continue;
-                               pci_claim_resource(dev, i);
-                       }
-               }
-       }
-}
-EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
-
-static int
-pcibios_pci_config_bridge(struct pci_dev *dev)
-{
-       u8 sec_busno;
-       struct pci_bus *child_bus;
-
-       /* Get busno of downstream bus */
-       pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
-
-       /* Add to children of PCI bridge dev->bus */
-       child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
-       if (!child_bus) {
-               printk (KERN_ERR "%s: could not add second bus\n", __func__);
-               return -EIO;
-       }
-       sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
-
-       pci_scan_child_bus(child_bus);
-
-       /* Fixup new pci devices */
-       pcibios_fixup_new_pci_devices(child_bus);
-
-       /* Make the discovered devices available */
-       pci_bus_add_devices(child_bus);
-
-       eeh_add_device_tree_late(child_bus);
-       return 0;
-}
-
 /**
  * pcibios_add_pci_devices - adds new pci devices to bus
  *
@@ -147,10 +100,9 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
  * is how this routine differs from other, similar pcibios
  * routines.)
  */
-void
-pcibios_add_pci_devices(struct pci_bus * bus)
+void pcibios_add_pci_devices(struct pci_bus * bus)
 {
-       int slotno, num, mode;
+       int slotno, num, mode, pass, max;
        struct pci_dev *dev;
        struct device_node *dn = pci_bus_to_OF_node(bus);
 
@@ -162,26 +114,23 @@ pcibios_add_pci_devices(struct pci_bus * bus)
 
        if (mode == PCI_PROBE_DEVTREE) {
                /* use ofdt-based probe */
-               of_scan_bus(dn, bus);
-               if (!list_empty(&bus->devices)) {
-                       pcibios_fixup_new_pci_devices(bus);
-                       pci_bus_add_devices(bus);
-                       eeh_add_device_tree_late(bus);
-               }
+               of_rescan_bus(dn, bus);
        } else if (mode == PCI_PROBE_NORMAL) {
                /* use legacy probe */
                slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
                num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
-               if (num) {
-                       pcibios_fixup_new_pci_devices(bus);
-                       pci_bus_add_devices(bus);
-                       eeh_add_device_tree_late(bus);
+               if (!num)
+                       return;
+               pcibios_setup_bus_devices(bus);
+               max = bus->secondary;
+               for (pass=0; pass < 2; pass++)
+                       list_for_each_entry(dev, &bus->devices, bus_list) {
+                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+                           dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+                               max = pci_scan_bridge(bus, dev, max, pass);
                }
-
-               list_for_each_entry(dev, &bus->devices, bus_list)
-                       if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-                               pcibios_pci_config_bridge(dev);
        }
+       pcibios_finish_adding_to_bus(bus);
 }
 EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
 
@@ -190,6 +139,8 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
        struct pci_controller *phb;
        int primary;
 
+       pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name);
+
        primary = list_empty(&hose_list);
        phb = pcibios_alloc_controller(dn);
        if (!phb)
@@ -203,11 +154,59 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
                eeh_add_device_tree_early(dn);
 
        scan_phb(phb);
-       pcibios_allocate_bus_resources(phb->bus);
-       pcibios_fixup_new_pci_devices(phb->bus);
-       pci_bus_add_devices(phb->bus);
-       eeh_add_device_tree_late(phb->bus);
+       pcibios_finish_adding_to_bus(phb->bus);
 
        return phb;
 }
 EXPORT_SYMBOL_GPL(init_phb_dynamic);
+
+/* RPA-specific bits for removing PHBs */
+int remove_phb_dynamic(struct pci_controller *phb)
+{
+       struct pci_bus *b = phb->bus;
+       struct resource *res;
+       int rc, i;
+
+       pr_debug("PCI: Removing PHB %04x:%02x... \n",
+                pci_domain_nr(b), b->number);
+
+       /* We cannot to remove a root bus that has children */
+       if (!(list_empty(&b->children) && list_empty(&b->devices)))
+               return -EBUSY;
+
+       /* We -know- there aren't any child devices anymore at this stage
+        * and thus, we can safely unmap the IO space as it's not in use
+        */
+       res = &phb->io_resource;
+       if (res->flags & IORESOURCE_IO) {
+               rc = pcibios_unmap_io_space(b);
+               if (rc) {
+                       printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+                              __func__, b->name);
+                       return 1;
+               }
+       }
+
+       /* Unregister the bridge device from sysfs and remove the PCI bus */
+       device_unregister(b->bridge);
+       phb->bus = NULL;
+       pci_remove_bus(b);
+
+       /* Now release the IO resource */
+       if (res->flags & IORESOURCE_IO)
+               release_resource(res);
+
+       /* Release memory resources */
+       for (i = 0; i < 3; ++i) {
+               res = &phb->mem_resources[i];
+               if (!(res->flags & IORESOURCE_MEM))
+                       continue;
+               release_resource(res);
+       }
+
+       /* Free pci_controller data structure */
+       pcibios_free_controller(phb);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(remove_phb_dynamic);
index e190477..f7a6902 100644 (file)
@@ -579,7 +579,7 @@ static void xics_update_irq_servers(void)
        int i, j;
        struct device_node *np;
        u32 ilen;
-       const u32 *ireg, *isize;
+       const u32 *ireg;
        u32 hcpuid;
 
        /* Find the server numbers for the boot cpu. */
@@ -607,11 +607,6 @@ static void xics_update_irq_servers(void)
                }
        }
 
-       /* get the bit size of server numbers */
-       isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
-       if (isize)
-               interrupt_server_size = *isize;
-
        of_node_put(np);
 }
 
@@ -682,6 +677,7 @@ void __init xics_init_IRQ(void)
        struct device_node *np;
        u32 indx = 0;
        int found = 0;
+       const u32 *isize;
 
        ppc64_boot_msg(0x20, "XICS Init");
 
@@ -701,6 +697,26 @@ void __init xics_init_IRQ(void)
        if (found == 0)
                return;
 
+       /* get the bit size of server numbers */
+       found = 0;
+
+       for_each_compatible_node(np, NULL, "ibm,ppc-xics") {
+               isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
+
+               if (!isize)
+                       continue;
+
+               if (!found) {
+                       interrupt_server_size = *isize;
+                       found = 1;
+               } else if (*isize != interrupt_server_size) {
+                       printk(KERN_WARNING "XICS: "
+                              "mismatched ibm,interrupt-server#-size\n");
+                       interrupt_server_size = max(*isize,
+                                                   interrupt_server_size);
+               }
+       }
+
        xics_update_irq_servers();
        xics_init_host();
 
@@ -728,9 +744,18 @@ static void xics_set_cpu_priority(unsigned char cppr)
 /* Have the calling processor join or leave the specified global queue */
 static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
 {
-       int status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
-               (1UL << interrupt_server_size) - 1 - gserver, join);
-       WARN_ON(status < 0);
+       int index;
+       int status;
+
+       if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL))
+               return;
+
+       index = (1UL << interrupt_server_size) - 1 - gserver;
+
+       status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
+
+       WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n",
+            GLOBAL_INTERRUPT_QUEUE, index, join, status);
 }
 
 void xics_setup_cpu(void)
index 5b264eb..d5f9ae0 100644 (file)
@@ -187,7 +187,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
                printk(KERN_WARNING "Can't get bus-range for %s, assume"
                        " bus 0\n", dev->full_name);
 
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
@@ -300,7 +300,7 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
                       " bus 0\n", dev->full_name);
        }
 
-       ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+       ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
        hose = pcibios_alloc_controller(dev);
        if (!hose)
                return -ENOMEM;
index d502927..5da37c2 100644 (file)
@@ -57,7 +57,7 @@ void __init setup_grackle(struct pci_controller *hose)
 {
        setup_indirect_pci(hose, 0xfec00000, 0xfee00000, 0);
        if (machine_is_compatible("PowerMac1,1"))
-               ppc_pci_flags |= PPC_PCI_REASSIGN_ALL_BUS;
+               ppc_pci_add_flags(PPC_PCI_REASSIGN_ALL_BUS);
        if (machine_is_compatible("AAPL,PowerBook1998"))
                grackle_set_loop_snoop(hose, 1);
 #if 0  /* Disabled for now, HW problems ??? */
index 1890fb0..c82babb 100644 (file)
@@ -661,17 +661,6 @@ static inline void mpic_eoi(struct mpic *mpic)
        (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI));
 }
 
-#ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *data)
-{
-       long ipi = (long)data;
-
-       smp_message_recv(ipi);
-
-       return IRQ_HANDLED;
-}
-#endif /* CONFIG_SMP */
-
 /*
  * Linux descriptor level callbacks
  */
@@ -1548,13 +1537,7 @@ unsigned int mpic_get_mcirq(void)
 void mpic_request_ipis(void)
 {
        struct mpic *mpic = mpic_primary;
-       long i, err;
-       static char *ipi_names[] = {
-               "IPI0 (call function)",
-               "IPI1 (reschedule)",
-               "IPI2 (call function single)",
-               "IPI3 (debugger break)",
-       };
+       int i;
        BUG_ON(mpic == NULL);
 
        printk(KERN_INFO "mpic: requesting IPIs ... \n");
@@ -1563,17 +1546,10 @@ void mpic_request_ipis(void)
                unsigned int vipi = irq_create_mapping(mpic->irqhost,
                                                       mpic->ipi_vecs[0] + i);
                if (vipi == NO_IRQ) {
-                       printk(KERN_ERR "Failed to map IPI %ld\n", i);
-                       break;
-               }
-               err = request_irq(vipi, mpic_ipi_action,
-                                 IRQF_DISABLED|IRQF_PERCPU,
-                                 ipi_names[i], (void *)i);
-               if (err) {
-                       printk(KERN_ERR "Request of irq %d for IPI %ld failed\n",
-                              vipi, i);
-                       break;
+                       printk(KERN_ERR "Failed to map %s\n", smp_ipi_name[i]);
+                       continue;
                }
+               smp_request_message_ipi(vipi, i);
        }
 }
 
index d3e4d61..77fae5f 100644 (file)
@@ -194,11 +194,41 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
  * 4xx PCI 2.x part
  */
 
+static int __init ppc4xx_setup_one_pci_PMM(struct pci_controller       *hose,
+                                          void __iomem                 *reg,
+                                          u64                          plb_addr,
+                                          u64                          pci_addr,
+                                          u64                          size,
+                                          unsigned int                 flags,
+                                          int                          index)
+{
+       u32 ma, pcila, pciha;
+
+       if ((plb_addr + size) > 0xffffffffull || !is_power_of_2(size) ||
+           size < 0x1000 || (plb_addr & (size - 1)) != 0) {
+               printk(KERN_WARNING "%s: Resource out of range\n",
+                      hose->dn->full_name);
+               return -1;
+       }
+       ma = (0xffffffffu << ilog2(size)) | 1;
+       if (flags & IORESOURCE_PREFETCH)
+               ma |= 2;
+
+       pciha = RES_TO_U32_HIGH(pci_addr);
+       pcila = RES_TO_U32_LOW(pci_addr);
+
+       writel(plb_addr, reg + PCIL0_PMM0LA + (0x10 * index));
+       writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * index));
+       writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * index));
+       writel(ma, reg + PCIL0_PMM0MA + (0x10 * index));
+
+       return 0;
+}
+
 static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
                                             void __iomem *reg)
 {
-       u32 la, ma, pcila, pciha;
-       int i, j;
+       int i, j, found_isa_hole = 0;
 
        /* Setup outbound memory windows */
        for (i = j = 0; i < 3; i++) {
@@ -213,28 +243,29 @@ static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
                        break;
                }
 
-               /* Calculate register values */
-               la = res->start;
-               pciha = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
-               pcila = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
-
-               ma = res->end + 1 - res->start;
-               if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) {
-                       printk(KERN_WARNING "%s: Resource out of range\n",
-                              hose->dn->full_name);
-                       continue;
+               /* Configure the resource */
+               if (ppc4xx_setup_one_pci_PMM(hose, reg,
+                                            res->start,
+                                            res->start - hose->pci_mem_offset,
+                                            res->end + 1 - res->start,
+                                            res->flags,
+                                            j) == 0) {
+                       j++;
+
+                       /* If the resource PCI address is 0 then we have our
+                        * ISA memory hole
+                        */
+                       if (res->start == hose->pci_mem_offset)
+                               found_isa_hole = 1;
                }
-               ma = (0xffffffffu << ilog2(ma)) | 0x1;
-               if (res->flags & IORESOURCE_PREFETCH)
-                       ma |= 0x2;
-
-               /* Program register values */
-               writel(la, reg + PCIL0_PMM0LA + (0x10 * j));
-               writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j));
-               writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j));
-               writel(ma, reg + PCIL0_PMM0MA + (0x10 * j));
-               j++;
        }
+
+       /* Handle ISA memory hole if not already covered */
+       if (j <= 2 && !found_isa_hole && hose->isa_mem_size)
+               if (ppc4xx_setup_one_pci_PMM(hose, reg, hose->isa_mem_phys, 0,
+                                            hose->isa_mem_size, 0, j) == 0)
+                       printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
+                              hose->dn->full_name);
 }
 
 static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
@@ -352,11 +383,52 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
  * 4xx PCI-X part
  */
 
+static int __init ppc4xx_setup_one_pcix_POM(struct pci_controller      *hose,
+                                           void __iomem                *reg,
+                                           u64                         plb_addr,
+                                           u64                         pci_addr,
+                                           u64                         size,
+                                           unsigned int                flags,
+                                           int                         index)
+{
+       u32 lah, lal, pciah, pcial, sa;
+
+       if (!is_power_of_2(size) || size < 0x1000 ||
+           (plb_addr & (size - 1)) != 0) {
+               printk(KERN_WARNING "%s: Resource out of range\n",
+                      hose->dn->full_name);
+               return -1;
+       }
+
+       /* Calculate register values */
+       lah = RES_TO_U32_HIGH(plb_addr);
+       lal = RES_TO_U32_LOW(plb_addr);
+       pciah = RES_TO_U32_HIGH(pci_addr);
+       pcial = RES_TO_U32_LOW(pci_addr);
+       sa = (0xffffffffu << ilog2(size)) | 0x1;
+
+       /* Program register values */
+       if (index == 0) {
+               writel(lah, reg + PCIX0_POM0LAH);
+               writel(lal, reg + PCIX0_POM0LAL);
+               writel(pciah, reg + PCIX0_POM0PCIAH);
+               writel(pcial, reg + PCIX0_POM0PCIAL);
+               writel(sa, reg + PCIX0_POM0SA);
+       } else {
+               writel(lah, reg + PCIX0_POM1LAH);
+               writel(lal, reg + PCIX0_POM1LAL);
+               writel(pciah, reg + PCIX0_POM1PCIAH);
+               writel(pcial, reg + PCIX0_POM1PCIAL);
+               writel(sa, reg + PCIX0_POM1SA);
+       }
+
+       return 0;
+}
+
 static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
                                              void __iomem *reg)
 {
-       u32 lah, lal, pciah, pcial, sa;
-       int i, j;
+       int i, j, found_isa_hole = 0;
 
        /* Setup outbound memory windows */
        for (i = j = 0; i < 3; i++) {
@@ -371,36 +443,29 @@ static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
                        break;
                }
 
-               /* Calculate register values */
-               lah = RES_TO_U32_HIGH(res->start);
-               lal = RES_TO_U32_LOW(res->start);
-               pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
-               pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
-               sa = res->end + 1 - res->start;
-               if (!is_power_of_2(sa) || sa < 0x100000 ||
-                   sa > 0xffffffffu) {
-                       printk(KERN_WARNING "%s: Resource out of range\n",
-                              hose->dn->full_name);
-                       continue;
+               /* Configure the resource */
+               if (ppc4xx_setup_one_pcix_POM(hose, reg,
+                                             res->start,
+                                             res->start - hose->pci_mem_offset,
+                                             res->end + 1 - res->start,
+                                             res->flags,
+                                             j) == 0) {
+                       j++;
+
+                       /* If the resource PCI address is 0 then we have our
+                        * ISA memory hole
+                        */
+                       if (res->start == hose->pci_mem_offset)
+                               found_isa_hole = 1;
                }
-               sa = (0xffffffffu << ilog2(sa)) | 0x1;
-
-               /* Program register values */
-               if (j == 0) {
-                       writel(lah, reg + PCIX0_POM0LAH);
-                       writel(lal, reg + PCIX0_POM0LAL);
-                       writel(pciah, reg + PCIX0_POM0PCIAH);
-                       writel(pcial, reg + PCIX0_POM0PCIAL);
-                       writel(sa, reg + PCIX0_POM0SA);
-               } else {
-                       writel(lah, reg + PCIX0_POM1LAH);
-                       writel(lal, reg + PCIX0_POM1LAL);
-                       writel(pciah, reg + PCIX0_POM1PCIAH);
-                       writel(pcial, reg + PCIX0_POM1PCIAL);
-                       writel(sa, reg + PCIX0_POM1SA);
-               }
-               j++;
        }
+
+       /* Handle ISA memory hole if not already covered */
+       if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
+               if (ppc4xx_setup_one_pcix_POM(hose, reg, hose->isa_mem_phys, 0,
+                                             hose->isa_mem_size, 0, j) == 0)
+                       printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
+                              hose->dn->full_name);
 }
 
 static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
@@ -1317,12 +1382,72 @@ static struct pci_ops ppc4xx_pciex_pci_ops =
        .write = ppc4xx_pciex_write_config,
 };
 
+static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port  *port,
+                                            struct pci_controller      *hose,
+                                            void __iomem               *mbase,
+                                            u64                        plb_addr,
+                                            u64                        pci_addr,
+                                            u64                        size,
+                                            unsigned int               flags,
+                                            int                        index)
+{
+       u32 lah, lal, pciah, pcial, sa;
+
+       if (!is_power_of_2(size) ||
+           (index < 2 && size < 0x100000) ||
+           (index == 2 && size < 0x100) ||
+           (plb_addr & (size - 1)) != 0) {
+               printk(KERN_WARNING "%s: Resource out of range\n",
+                      hose->dn->full_name);
+               return -1;
+       }
+
+       /* Calculate register values */
+       lah = RES_TO_U32_HIGH(plb_addr);
+       lal = RES_TO_U32_LOW(plb_addr);
+       pciah = RES_TO_U32_HIGH(pci_addr);
+       pcial = RES_TO_U32_LOW(pci_addr);
+       sa = (0xffffffffu << ilog2(size)) | 0x1;
+
+       /* Program register values */
+       switch (index) {
+       case 0:
+               out_le32(mbase + PECFG_POM0LAH, pciah);
+               out_le32(mbase + PECFG_POM0LAL, pcial);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
+               /* Note that 3 here means enabled | single region */
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
+               break;
+       case 1:
+               out_le32(mbase + PECFG_POM1LAH, pciah);
+               out_le32(mbase + PECFG_POM1LAL, pcial);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
+               /* Note that 3 here means enabled | single region */
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
+               break;
+       case 2:
+               out_le32(mbase + PECFG_POM2LAH, pciah);
+               out_le32(mbase + PECFG_POM2LAL, pcial);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
+               /* Note that 3 here means enabled | IO space !!! */
+               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3);
+               break;
+       }
+
+       return 0;
+}
+
 static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
                                               struct pci_controller *hose,
                                               void __iomem *mbase)
 {
-       u32 lah, lal, pciah, pcial, sa;
-       int i, j;
+       int i, j, found_isa_hole = 0;
 
        /* Setup outbound memory windows */
        for (i = j = 0; i < 3; i++) {
@@ -1337,53 +1462,38 @@ static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port,
                        break;
                }
 
-               /* Calculate register values */
-               lah = RES_TO_U32_HIGH(res->start);
-               lal = RES_TO_U32_LOW(res->start);
-               pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset);
-               pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset);
-               sa = res->end + 1 - res->start;
-               if (!is_power_of_2(sa) || sa < 0x100000 ||
-                   sa > 0xffffffffu) {
-                       printk(KERN_WARNING "%s: Resource out of range\n",
-                              port->node->full_name);
-                       continue;
-               }
-               sa = (0xffffffffu << ilog2(sa)) | 0x1;
-
-               /* Program register values */
-               switch (j) {
-               case 0:
-                       out_le32(mbase + PECFG_POM0LAH, pciah);
-                       out_le32(mbase + PECFG_POM0LAL, pcial);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3);
-                       break;
-               case 1:
-                       out_le32(mbase + PECFG_POM1LAH, pciah);
-                       out_le32(mbase + PECFG_POM1LAL, pcial);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
-                       dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3);
-                       break;
+               /* Configure the resource */
+               if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
+                                              res->start,
+                                              res->start - hose->pci_mem_offset,
+                                              res->end + 1 - res->start,
+                                              res->flags,
+                                              j) == 0) {
+                       j++;
+
+                       /* If the resource PCI address is 0 then we have our
+                        * ISA memory hole
+                        */
+                       if (res->start == hose->pci_mem_offset)
+                               found_isa_hole = 1;
                }
-               j++;
        }
 
-       /* Configure IO, always 64K starting at 0 */
-       if (hose->io_resource.flags & IORESOURCE_IO) {
-               lah = RES_TO_U32_HIGH(hose->io_base_phys);
-               lal = RES_TO_U32_LOW(hose->io_base_phys);
-               out_le32(mbase + PECFG_POM2LAH, 0);
-               out_le32(mbase + PECFG_POM2LAL, 0);
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah);
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
-               dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3);
-       }
+       /* Handle ISA memory hole if not already covered */
+       if (j <= 1 && !found_isa_hole && hose->isa_mem_size)
+               if (ppc4xx_setup_one_pciex_POM(port, hose, mbase,
+                                              hose->isa_mem_phys, 0,
+                                              hose->isa_mem_size, 0, j) == 0)
+                       printk(KERN_INFO "%s: Legacy ISA memory support enabled\n",
+                              hose->dn->full_name);
+
+       /* Configure IO, always 64K starting at 0. We hard wire it to 64K !
+        * Note also that it -has- to be region index 2 on this HW
+        */
+       if (hose->io_resource.flags & IORESOURCE_IO)
+               ppc4xx_setup_one_pciex_POM(port, hose, mbase,
+                                          hose->io_base_phys, 0,
+                                          0x10000, IORESOURCE_IO, 2);
 }
 
 static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
index b3b73ae..01bce37 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
+#include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/bootmem.h>
@@ -38,6 +39,8 @@ static void qe_snums_init(void);
 static int qe_sdma_init(void);
 
 static DEFINE_SPINLOCK(qe_lock);
+DEFINE_SPINLOCK(cmxgcr_lock);
+EXPORT_SYMBOL(cmxgcr_lock);
 
 /* QE snum state */
 enum qe_snum_state {
index 1d78071..ebb442e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
+#include <linux/spinlock.h>
 #include <linux/module.h>
 
 #include <asm/irq.h>
@@ -26,9 +27,6 @@
 #include <asm/qe.h>
 #include <asm/ucc.h>
 
-DEFINE_SPINLOCK(cmxgcr_lock);
-EXPORT_SYMBOL(cmxgcr_lock);
-
 int ucc_set_qe_mux_mii_mng(unsigned int ucc_num)
 {
        unsigned long flags;
index 19790eb..3702e08 100644 (file)
@@ -20,4 +20,16 @@ struct dev_archdata {
        int                     numa_node;
 };
 
+static inline void dev_archdata_set_node(struct dev_archdata *ad,
+                                        struct device_node *np)
+{
+       ad->prom_node = np;
+}
+
+static inline struct device_node *
+dev_archdata_get_node(const struct dev_archdata *ad)
+{
+       return ad->prom_node;
+}
+
 #endif /* _ASM_SPARC_DEVICE_H */
index 43d6ba8..f57907a 100644 (file)
@@ -631,6 +631,12 @@ config HVC_XEN
        help
          Xen virtual console device driver
 
+config HVC_UDBG
+       bool "udbg based fake hypervisor console"
+       depends on PPC && EXPERIMENTAL
+       select HVC_DRIVER
+       default n
+
 config VIRTIO_CONSOLE
        tristate "Virtio console"
        depends on VIRTIO
index 438f713..52e1552 100644 (file)
@@ -50,6 +50,7 @@ obj-$(CONFIG_HVC_BEAT)                += hvc_beat.o
 obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
 obj-$(CONFIG_HVC_IRQ)          += hvc_irq.o
 obj-$(CONFIG_HVC_XEN)          += hvc_xen.o
+obj-$(CONFIG_HVC_UDBG)         += hvc_udbg.o
 obj-$(CONFIG_VIRTIO_CONSOLE)   += virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
 obj-$(CONFIG_SGI_SNSC)         += snsc.o snsc_event.o
index 456f54d..977dfb1 100644 (file)
@@ -60,6 +60,8 @@ struct bsr_dev {
        unsigned bsr_num;      /* bsr id number for its type */
        int      bsr_minor;
 
+       struct list_head bsr_list;
+
        dev_t    bsr_dev;
        struct cdev bsr_cdev;
        struct device *bsr_device;
@@ -67,8 +69,8 @@ struct bsr_dev {
 
 };
 
-static unsigned num_bsr_devs;
-static struct bsr_dev *bsr_devs;
+static unsigned total_bsr_devs;
+static struct list_head bsr_devs = LIST_HEAD_INIT(bsr_devs);
 static struct class *bsr_class;
 static int bsr_major;
 
@@ -146,24 +148,25 @@ const static struct file_operations bsr_fops = {
 
 static void bsr_cleanup_devs(void)
 {
-       int i;
-       for (i=0 ; i < num_bsr_devs; i++) {
-               struct bsr_dev *cur = bsr_devs + i;
+       struct bsr_dev *cur, *n;
+
+       list_for_each_entry_safe(cur, n, &bsr_devs, bsr_list) {
                if (cur->bsr_device) {
                        cdev_del(&cur->bsr_cdev);
                        device_del(cur->bsr_device);
                }
+               list_del(&cur->bsr_list);
+               kfree(cur);
        }
-
-       kfree(bsr_devs);
 }
 
-static int bsr_create_devs(struct device_node *bn)
+static int bsr_add_node(struct device_node *bn)
 {
-       int bsr_stride_len, bsr_bytes_len;
+       int bsr_stride_len, bsr_bytes_len, num_bsr_devs;
        const u32 *bsr_stride;
        const u32 *bsr_bytes;
        unsigned i;
+       int ret = -ENODEV;
 
        bsr_stride = of_get_property(bn, "ibm,lock-stride", &bsr_stride_len);
        bsr_bytes  = of_get_property(bn, "ibm,#lock-bytes", &bsr_bytes_len);
@@ -171,35 +174,36 @@ static int bsr_create_devs(struct device_node *bn)
        if (!bsr_stride || !bsr_bytes ||
            (bsr_stride_len != bsr_bytes_len)) {
                printk(KERN_ERR "bsr of-node has missing/incorrect property\n");
-               return -ENODEV;
+               return ret;
        }
 
        num_bsr_devs = bsr_bytes_len / sizeof(u32);
 
-       /* only a warning, its informational since we'll fail and exit */
-       WARN_ON(num_bsr_devs > BSR_MAX_DEVS);
-
-       bsr_devs = kzalloc(sizeof(struct bsr_dev) * num_bsr_devs, GFP_KERNEL);
-       if (!bsr_devs)
-               return -ENOMEM;
-
        for (i = 0 ; i < num_bsr_devs; i++) {
-               struct bsr_dev *cur = bsr_devs + i;
+               struct bsr_dev *cur = kzalloc(sizeof(struct bsr_dev),
+                                             GFP_KERNEL);
                struct resource res;
                int result;
 
+               if (!cur) {
+                       printk(KERN_ERR "Unable to alloc bsr dev\n");
+                       ret = -ENOMEM;
+                       goto out_err;
+               }
+
                result = of_address_to_resource(bn, i, &res);
                if (result < 0) {
-                       printk(KERN_ERR "bsr of-node has invalid reg property\n");
-                       goto out_err;
+                       printk(KERN_ERR "bsr of-node has invalid reg property, skipping\n");
+                       kfree(cur);
+                       continue;
                }
 
-               cur->bsr_minor  = i;
+               cur->bsr_minor  = i + total_bsr_devs;
                cur->bsr_addr   = res.start;
                cur->bsr_len    = res.end - res.start + 1;
                cur->bsr_bytes  = bsr_bytes[i];
                cur->bsr_stride = bsr_stride[i];
-               cur->bsr_dev    = MKDEV(bsr_major, i);
+               cur->bsr_dev    = MKDEV(bsr_major, i + total_bsr_devs);
 
                switch(cur->bsr_bytes) {
                case 8:
@@ -220,14 +224,15 @@ static int bsr_create_devs(struct device_node *bn)
                }
 
                cur->bsr_num = bsr_types[cur->bsr_type];
-               bsr_types[cur->bsr_type] = cur->bsr_num + 1;
                snprintf(cur->bsr_name, 32, "bsr%d_%d",
                         cur->bsr_bytes, cur->bsr_num);
 
                cdev_init(&cur->bsr_cdev, &bsr_fops);
                result = cdev_add(&cur->bsr_cdev, cur->bsr_dev, 1);
-               if (result)
+               if (result) {
+                       kfree(cur);
                        goto out_err;
+               }
 
                cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
                                                cur, cur->bsr_name);
@@ -235,16 +240,37 @@ static int bsr_create_devs(struct device_node *bn)
                        printk(KERN_ERR "device_create failed for %s\n",
                               cur->bsr_name);
                        cdev_del(&cur->bsr_cdev);
+                       kfree(cur);
                        goto out_err;
                }
+
+               bsr_types[cur->bsr_type] = cur->bsr_num + 1;
+               list_add_tail(&cur->bsr_list, &bsr_devs);
        }
 
+       total_bsr_devs += num_bsr_devs;
+
        return 0;
 
  out_err:
 
        bsr_cleanup_devs();
-       return -ENODEV;
+       return ret;
+}
+
+static int bsr_create_devs(struct device_node *bn)
+{
+       int ret;
+
+       while (bn) {
+               ret = bsr_add_node(bn);
+               if (ret) {
+                       of_node_put(bn);
+                       return ret;
+               }
+               bn = of_find_compatible_node(bn, NULL, "ibm,bsr");
+       }
+       return 0;
 }
 
 static int __init bsr_init(void)
@@ -254,7 +280,7 @@ static int __init bsr_init(void)
        int ret = -ENODEV;
        int result;
 
-       np = of_find_compatible_node(NULL, "ibm,bsr", "ibm,bsr");
+       np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
        if (!np)
                goto out_err;
 
@@ -272,10 +298,10 @@ static int __init bsr_init(void)
                goto out_err_2;
        }
 
-       if ((ret = bsr_create_devs(np)) < 0)
+       if ((ret = bsr_create_devs(np)) < 0) {
+               np = NULL;
                goto out_err_3;
-
-       of_node_put(np);
+       }
 
        return 0;
 
index 5b819b1..74ecb5b 100644 (file)
@@ -689,10 +689,8 @@ EXPORT_SYMBOL_GPL(hvc_poll);
  */
 void hvc_resize(struct hvc_struct *hp, struct winsize ws)
 {
-       if ((hp->ws.ws_row != ws.ws_row) || (hp->ws.ws_col != ws.ws_col)) {
-               hp->ws = ws;
-               schedule_work(&hp->tty_resize);
-       }
+       hp->ws = ws;
+       schedule_work(&hp->tty_resize);
 }
 
 /*
index 8297dbc..3c85d78 100644 (file)
@@ -48,7 +48,7 @@ struct hvc_struct {
        spinlock_t lock;
        int index;
        struct tty_struct *tty;
-       unsigned int count;
+       int count;
        int do_wakeup;
        char *outbuf;
        int outbuf_size;
index b74a2f8..449727b 100644 (file)
@@ -575,8 +575,10 @@ static int __init hvc_find_vtys(void)
                 * of console adapters.
                 */
                if ((num_found >= MAX_NR_HVC_CONSOLES) ||
-                               (num_found >= VTTY_PORTS))
+                               (num_found >= VTTY_PORTS)) {
+                       of_node_put(vty);
                        break;
+               }
 
                vtermno = of_get_property(vty, "reg", NULL);
                if (!vtermno)
diff --git a/drivers/char/hvc_udbg.c b/drivers/char/hvc_udbg.c
new file mode 100644 (file)
index 0000000..bd63ba8
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * udbg interface to hvc_console.c
+ *
+ * (C) Copyright David Gibson, IBM Corporation 2008.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/irq.h>
+
+#include <asm/udbg.h>
+
+#include "hvc_console.h"
+
+struct hvc_struct *hvc_udbg_dev;
+
+static int hvc_udbg_put(uint32_t vtermno, const char *buf, int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               udbg_putc(buf[i]);
+
+       return i;
+}
+
+static int hvc_udbg_get(uint32_t vtermno, char *buf, int count)
+{
+       int i, c;
+
+       if (!udbg_getc_poll)
+               return 0;
+
+       for (i = 0; i < count; i++) {
+               if ((c = udbg_getc_poll()) == -1)
+                       break;
+               buf[i] = c;
+       }
+
+       return i;
+}
+
+static struct hv_ops hvc_udbg_ops = {
+       .get_chars = hvc_udbg_get,
+       .put_chars = hvc_udbg_put,
+};
+
+static int __init hvc_udbg_init(void)
+{
+       struct hvc_struct *hp;
+
+       BUG_ON(hvc_udbg_dev);
+
+       hp = hvc_alloc(0, NO_IRQ, &hvc_udbg_ops, 16);
+       if (IS_ERR(hp))
+               return PTR_ERR(hp);
+
+       hvc_udbg_dev = hp;
+
+       return 0;
+}
+module_init(hvc_udbg_init);
+
+static void __exit hvc_udbg_exit(void)
+{
+       if (hvc_udbg_dev)
+               hvc_remove(hvc_udbg_dev);
+}
+module_exit(hvc_udbg_exit);
+
+static int __init hvc_udbg_console_init(void)
+{
+       hvc_instantiate(0, 0, &hvc_udbg_ops);
+       add_preferred_console("hvc", 0, NULL);
+
+       return 0;
+}
+console_initcall(hvc_udbg_console_init);
index 019e0b5..bd62dc8 100644 (file)
@@ -153,8 +153,10 @@ static int hvc_find_vtys(void)
                /* We have statically defined space for only a certain number
                 * of console adapters.
                 */
-               if (num_found >= MAX_NR_HVC_CONSOLES)
+               if (num_found >= MAX_NR_HVC_CONSOLES) {
+                       of_node_put(vty);
                        break;
+               }
 
                vtermno = of_get_property(vty, "reg", NULL);
                if (!vtermno)
index 473d9b1..6e6eb44 100644 (file)
@@ -269,7 +269,7 @@ struct hvcs_struct {
        unsigned int index;
 
        struct tty_struct *tty;
-       unsigned int open_count;
+       int open_count;
 
        /*
         * Used to tell the driver kernel_thread what operations need to take
index 59c6f9a..af05528 100644 (file)
@@ -75,7 +75,7 @@ struct hvsi_struct {
        spinlock_t lock;
        int index;
        struct tty_struct *tty;
-       unsigned int count;
+       int count;
        uint8_t throttle_buf[128];
        uint8_t outbuf[N_OUTBUF]; /* to implement write_room and chars_in_buffer */
        /* inbuf is for packet reassembly. leave a little room for leftovers. */
index 7f2be4b..7847e98 100644 (file)
@@ -87,11 +87,12 @@ struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id,
                return NULL;
        }
 
-       len = i2c_smbus_read_word_data(&sat->i2c, 9);
-       if (len < 0) {
+       err = i2c_smbus_read_word_data(&sat->i2c, 9);
+       if (err < 0) {
                printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n");
                return NULL;
        }
+       len = err;
        if (len == 0) {
                printk(KERN_ERR "smu_sat_get_sdb_part no partition %x\n", id);
                return NULL;
index 7c79e94..4f884a3 100644 (file)
@@ -329,6 +329,41 @@ struct device_node *of_find_compatible_node(struct device_node *from,
 EXPORT_SYMBOL(of_find_compatible_node);
 
 /**
+ *     of_find_node_with_property - Find a node which has a property with
+ *                                   the given name.
+ *     @from:          The node to start searching from or NULL, the node
+ *                     you pass will not be searched, only the next one
+ *                     will; typically, you pass what the previous call
+ *                     returned. of_node_put() will be called on it
+ *     @prop_name:     The name of the property to look for.
+ *
+ *     Returns a node pointer with refcount incremented, use
+ *     of_node_put() on it when done.
+ */
+struct device_node *of_find_node_with_property(struct device_node *from,
+       const char *prop_name)
+{
+       struct device_node *np;
+       struct property *pp;
+
+       read_lock(&devtree_lock);
+       np = from ? from->allnext : allnodes;
+       for (; np; np = np->allnext) {
+               for (pp = np->properties; pp != 0; pp = pp->next) {
+                       if (of_prop_cmp(pp->name, prop_name) == 0) {
+                               of_node_get(np);
+                               goto out;
+                       }
+               }
+       }
+out:
+       of_node_put(from);
+       read_unlock(&devtree_lock);
+       return np;
+}
+EXPORT_SYMBOL(of_find_node_with_property);
+
+/**
  * of_match_node - Tell if an device_node has a matching of_match structure
  *     @matches:       array of of device match structures to search in
  *     @node:          the of device structure to match against
index 7cd7301..a4ba217 100644 (file)
 #include <asm/prom.h>
 
 /**
- * of_get_gpio - Get a GPIO number from the device tree to use with GPIO API
+ * of_get_gpio_flags - Get a GPIO number and flags to use with GPIO API
  * @np:                device node to get GPIO from
  * @index:     index of the GPIO
+ * @flags:     a flags pointer to fill in
  *
  * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
- * value on the error condition.
+ * value on the error condition. If @flags is not NULL the function also fills
+ * in flags for the GPIO.
  */
-int of_get_gpio(struct device_node *np, int index)
+int of_get_gpio_flags(struct device_node *np, int index,
+                     enum of_gpio_flags *flags)
 {
        int ret;
        struct device_node *gc;
@@ -59,7 +62,11 @@ int of_get_gpio(struct device_node *np, int index)
                goto err1;
        }
 
-       ret = of_gc->xlate(of_gc, np, gpio_spec);
+       /* .xlate might decide to not fill in the flags, so clear it. */
+       if (flags)
+               *flags = 0;
+
+       ret = of_gc->xlate(of_gc, np, gpio_spec, flags);
        if (ret < 0)
                goto err1;
 
@@ -70,26 +77,41 @@ err0:
        pr_debug("%s exited with status %d\n", __func__, ret);
        return ret;
 }
-EXPORT_SYMBOL(of_get_gpio);
+EXPORT_SYMBOL(of_get_gpio_flags);
 
 /**
- * of_gpio_simple_xlate - translate gpio_spec to the GPIO number
+ * of_gpio_simple_xlate - translate gpio_spec to the GPIO number and flags
  * @of_gc:     pointer to the of_gpio_chip structure
  * @np:                device node of the GPIO chip
  * @gpio_spec: gpio specifier as found in the device tree
+ * @flags:     a flags pointer to fill in
  *
  * This is simple translation function, suitable for the most 1:1 mapped
  * gpio chips. This function performs only one sanity check: whether gpio
  * is less than ngpios (that is specified in the gpio_chip).
  */
 int of_gpio_simple_xlate(struct of_gpio_chip *of_gc, struct device_node *np,
-                        const void *gpio_spec)
+                        const void *gpio_spec, enum of_gpio_flags *flags)
 {
        const u32 *gpio = gpio_spec;
 
+       /*
+        * We're discouraging gpio_cells < 2, since that way you'll have to
+        * write your own xlate function (that will have to retrive the GPIO
+        * number and the flags from a single gpio cell -- this is possible,
+        * but not recommended).
+        */
+       if (of_gc->gpio_cells < 2) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
        if (*gpio > of_gc->gc.ngpio)
                return -EINVAL;
 
+       if (flags)
+               *flags = gpio[1];
+
        return *gpio;
 }
 EXPORT_SYMBOL(of_gpio_simple_xlate);
index 24bbef7..e1b0ad6 100644 (file)
@@ -24,6 +24,7 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
 
        for_each_child_of_node(adap_node, node) {
                struct i2c_board_info info = {};
+               struct dev_archdata dev_ad = {};
                const u32 *addr;
                int len;
 
@@ -41,6 +42,9 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
 
                info.addr = *addr;
 
+               dev_archdata_set_node(&dev_ad, node);
+               info.archdata = &dev_ad;
+
                request_module("%s", info.type);
 
                result = i2c_new_device(adap, &info);
@@ -51,6 +55,13 @@ void of_register_i2c_devices(struct i2c_adapter *adap,
                        irq_dispose_mapping(info.irq);
                        continue;
                }
+
+               /*
+                * Get the node to not lose the dev_archdata->of_node.
+                * Currently there is no way to put it back, as well as no
+                * of_unregister_i2c_devices() call.
+                */
+               of_node_get(node);
        }
 }
 EXPORT_SYMBOL(of_register_i2c_devices);
index 9c2a22f..4e3e038 100644 (file)
@@ -14,6 +14,9 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
+
+#undef DEBUG
+
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
@@ -151,20 +154,20 @@ static void dlpar_pci_add_bus(struct device_node *dn)
                return;
        }
 
+       /* Scan below the new bridge */
        if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
            dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
                of_scan_pci_bridge(dn, dev);
 
-       pcibios_fixup_new_pci_devices(dev->subordinate);
-
-       /* Claim new bus resources */
-       pcibios_claim_one_bus(dev->bus);
-
        /* Map IO space for child bus, which may or may not succeed */
        pcibios_map_io_space(dev->subordinate);
 
-       /* Add new devices to global lists.  Register in proc, sysfs. */
-       pci_bus_add_devices(phb->bus);
+       /* Finish adding it : resource allocation, adding devices, etc...
+        * Note that we need to perform the finish pass on the -parent-
+        * bus of the EADS bridge so the bridge device itself gets
+        * properly added
+        */
+       pcibios_finish_adding_to_bus(phb->bus);
 }
 
 static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
@@ -203,27 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
        return 0;
 }
 
-static int dlpar_remove_root_bus(struct pci_controller *phb)
-{
-       struct pci_bus *phb_bus;
-       int rc;
-
-       phb_bus = phb->bus;
-       if (!(list_empty(&phb_bus->children) &&
-             list_empty(&phb_bus->devices))) {
-               return -EBUSY;
-       }
-
-       rc = pcibios_remove_root_bus(phb);
-       if (rc)
-               return -EIO;
-
-       device_unregister(phb_bus->bridge);
-       pci_remove_bus(phb_bus);
-
-       return 0;
-}
-
 static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
 {
        struct slot *slot;
@@ -235,18 +217,15 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
 
        /* If pci slot is hotplugable, use hotplug to remove it */
        slot = find_php_slot(dn);
-       if (slot) {
-               if (rpaphp_deregister_slot(slot)) {
-                       printk(KERN_ERR
-                               "%s: unable to remove hotplug slot %s\n",
-                               __func__, drc_name);
-                       return -EIO;
-               }
+       if (slot && rpaphp_deregister_slot(slot)) {
+               printk(KERN_ERR "%s: unable to remove hotplug slot %s\n",
+                      __func__, drc_name);
+               return -EIO;
        }
 
        pdn = dn->data;
        BUG_ON(!pdn || !pdn->phb);
-       rc = dlpar_remove_root_bus(pdn->phb);
+       rc = remove_phb_dynamic(pdn->phb);
        if (rc < 0)
                return rc;
 
@@ -378,26 +357,38 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
        if (!bus)
                return -EINVAL;
 
-       /* If pci slot is hotplugable, use hotplug to remove it */
+       pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",
+                bus->self ? pci_name(bus->self) : "<!PHB!>");
+
        slot = find_php_slot(dn);
        if (slot) {
+               pr_debug("PCI: Removing hotplug slot for %04x:%02x...\n",
+                        pci_domain_nr(bus), bus->number);
+
                if (rpaphp_deregister_slot(slot)) {
                        printk(KERN_ERR
                                "%s: unable to remove hotplug slot %s\n",
                                __func__, drc_name);
                        return -EIO;
                }
-       } else
-               pcibios_remove_pci_devices(bus);
+       }
+
+       /* Remove all devices below slot */
+       pcibios_remove_pci_devices(bus);
 
+       /* Unmap PCI IO space */
        if (pcibios_unmap_io_space(bus)) {
                printk(KERN_ERR "%s: failed to unmap bus range\n",
                        __func__);
                return -ERANGE;
        }
 
+       /* Remove the EADS bridge device itself */
        BUG_ON(!bus->self);
+       pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));
+       eeh_remove_bus_device(bus->self);
        pci_remove_bus_device(bus->self);
+
        return 0;
 }
 
index 06848b2..5324978 100644 (file)
@@ -59,8 +59,6 @@ static struct ps3av {
                struct ps3av_reply_hdr reply_hdr;
                u8 raw[PS3AV_BUF_SIZE];
        } recv_buf;
-       void (*flip_ctl)(int on, void *data);
-       void *flip_data;
 } *ps3av;
 
 /* color space */
@@ -939,24 +937,6 @@ int ps3av_audio_mute(int mute)
 
 EXPORT_SYMBOL_GPL(ps3av_audio_mute);
 
-void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
-                            void *flip_data)
-{
-       mutex_lock(&ps3av->mutex);
-       ps3av->flip_ctl = flip_ctl;
-       ps3av->flip_data = flip_data;
-       mutex_unlock(&ps3av->mutex);
-}
-EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl);
-
-void ps3av_flip_ctl(int on)
-{
-       mutex_lock(&ps3av->mutex);
-       if (ps3av->flip_ctl)
-               ps3av->flip_ctl(on, ps3av->flip_data);
-       mutex_unlock(&ps3av->mutex);
-}
-
 static int ps3av_probe(struct ps3_system_bus_device *dev)
 {
        int res;
index 11eb503..716596e 100644 (file)
@@ -864,7 +864,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
 {
        int res;
 
-       ps3av_flip_ctl(0);      /* flip off */
+       mutex_lock(&ps3_gpu_mutex);
 
        /* avb packet */
        res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb),
@@ -878,7 +878,7 @@ int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len)
                         res);
 
       out:
-       ps3av_flip_ctl(1);      /* flip on */
+       mutex_unlock(&ps3_gpu_mutex);
        return res;
 }
 
index 643a6b9..5c13f61 100644 (file)
@@ -365,15 +365,15 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
                                rdid++)
                        rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
                rdev->rswitch = rswitch;
-               sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
-                       rdev->rswitch->switchid);
+               dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
+                            rdev->rswitch->switchid);
                rio_route_set_ops(rdev);
 
                list_add_tail(&rswitch->node, &rio_switches);
 
        } else
-               sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id,
-                       rdev->destid);
+               dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id,
+                            rdev->destid);
 
        rdev->dev.bus = &rio_bus_type;
 
index 317b061..ad34885 100644 (file)
@@ -1383,6 +1383,29 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser)
        return -EINVAL;
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+
+static int pmz_poll_get_char(struct uart_port *port)
+{
+       struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
+
+       while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0)
+               udelay(5);
+       return read_zsdata(uap);
+}
+
+static void pmz_poll_put_char(struct uart_port *port, unsigned char c)
+{
+       struct uart_pmac_port *uap = (struct uart_pmac_port *)port;
+
+       /* Wait for the transmit buffer to empty. */
+       while ((read_zsreg(uap, R0) & Tx_BUF_EMP) == 0)
+               udelay(5);
+       write_zsdata(uap, c);
+}
+
+#endif
+
 static struct uart_ops pmz_pops = {
        .tx_empty       =       pmz_tx_empty,
        .set_mctrl      =       pmz_set_mctrl,
@@ -1400,6 +1423,10 @@ static struct uart_ops pmz_pops = {
        .request_port   =       pmz_request_port,
        .config_port    =       pmz_config_port,
        .verify_port    =       pmz_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char  =       pmz_poll_get_char,
+       .poll_put_char  =       pmz_poll_put_char,
+#endif
 };
 
 /*
index 4b5d807..38ac805 100644 (file)
@@ -460,12 +460,16 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset,
                line_length |= (u64)src_line_length << 32;
 
        src_offset += GPU_FB_START;
+
+       mutex_lock(&ps3_gpu_mutex);
        status = lv1_gpu_context_attribute(ps3fb.context_handle,
                                           L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT,
                                           dst_offset, GPU_IOIF + src_offset,
                                           L1GPU_FB_BLIT_WAIT_FOR_COMPLETION |
                                           (width << 16) | height,
                                           line_length);
+       mutex_unlock(&ps3_gpu_mutex);
+
        if (status)
                dev_err(dev,
                        "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n",
@@ -784,15 +788,6 @@ static int ps3fb_wait_for_vsync(u32 crtc)
        return 0;
 }
 
-static void ps3fb_flip_ctl(int on, void *data)
-{
-       struct ps3fb_priv *priv = data;
-       if (on)
-               atomic_dec_if_positive(&priv->ext_flip);
-       else
-               atomic_inc(&priv->ext_flip);
-}
-
 
     /*
      * ioctl
@@ -1228,7 +1223,6 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
        }
 
        ps3fb.task = task;
-       ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb);
 
        return 0;
 
@@ -1258,10 +1252,9 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 
        dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 
-       ps3fb_flip_ctl(0, &ps3fb);      /* flip off */
+       atomic_inc(&ps3fb.ext_flip);    /* flip off */
        ps3fb.dinfo->irq.mask = 0;
 
-       ps3av_register_flip_ctl(NULL, NULL);
        if (ps3fb.task) {
                struct task_struct *task = ps3fb.task;
                ps3fb.task = NULL;
@@ -1296,8 +1289,8 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 }
 
 static struct ps3_system_bus_driver ps3fb_driver = {
-       .match_id       = PS3_MATCH_ID_GRAPHICS,
-       .match_sub_id   = PS3_MATCH_SUB_ID_FB,
+       .match_id       = PS3_MATCH_ID_GPU,
+       .match_sub_id   = PS3_MATCH_SUB_ID_GPU_FB,
        .core.name      = DEVICE_NAME,
        .core.owner     = THIS_MODULE,
        .probe          = ps3fb_probe,
@@ -1355,4 +1348,4 @@ module_exit(ps3fb_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("PS3 GPU Frame Buffer Driver");
 MODULE_AUTHOR("Sony Computer Entertainment Inc.");
-MODULE_ALIAS(PS3_MODULE_ALIAS_GRAPHICS);
+MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_FB);
index d777789..de2bba5 100644 (file)
@@ -218,8 +218,7 @@ void proc_device_tree_add_node(struct device_node *np,
 void __init proc_device_tree_init(void)
 {
        struct device_node *root;
-       if ( !have_of )
-               return;
+
        proc_device_tree = proc_mkdir("device-tree", NULL);
        if (proc_device_tree == 0)
                return;
index e2488f5..6a7efa2 100644 (file)
@@ -57,6 +57,12 @@ extern struct device_node *of_get_next_child(const struct device_node *node,
        for (child = of_get_next_child(parent, NULL); child != NULL; \
             child = of_get_next_child(parent, child))
 
+extern struct device_node *of_find_node_with_property(
+       struct device_node *from, const char *prop_name);
+#define for_each_node_with_property(dn, prop_name) \
+       for (dn = of_find_node_with_property(NULL, prop_name); dn; \
+            dn = of_find_node_with_property(dn, prop_name))
+
 extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
                                         int *lenp);
index 67db101..e25abf6 100644 (file)
 #ifndef __LINUX_OF_GPIO_H
 #define __LINUX_OF_GPIO_H
 
+#include <linux/compiler.h>
+#include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/gpio.h>
 
+struct device_node;
+
+/*
+ * This is Linux-specific flags. By default controllers' and Linux' mapping
+ * match, but GPIO controllers are free to translate their own flags to
+ * Linux-specific in their .xlate callback. Though, 1:1 mapping is recommended.
+ */
+enum of_gpio_flags {
+       OF_GPIO_ACTIVE_LOW = 0x1,
+};
+
 #ifdef CONFIG_OF_GPIO
 
 /*
@@ -26,7 +39,7 @@ struct of_gpio_chip {
        struct gpio_chip gc;
        int gpio_cells;
        int (*xlate)(struct of_gpio_chip *of_gc, struct device_node *np,
-                    const void *gpio_spec);
+                    const void *gpio_spec, enum of_gpio_flags *flags);
 };
 
 static inline struct of_gpio_chip *to_of_gpio_chip(struct gpio_chip *gc)
@@ -50,20 +63,37 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc)
        return container_of(of_gc, struct of_mm_gpio_chip, of_gc);
 }
 
-extern int of_get_gpio(struct device_node *np, int index);
+extern int of_get_gpio_flags(struct device_node *np, int index,
+                            enum of_gpio_flags *flags);
+
 extern int of_mm_gpiochip_add(struct device_node *np,
                              struct of_mm_gpio_chip *mm_gc);
 extern int of_gpio_simple_xlate(struct of_gpio_chip *of_gc,
                                struct device_node *np,
-                               const void *gpio_spec);
+                               const void *gpio_spec,
+                               enum of_gpio_flags *flags);
 #else
 
 /* Drivers may not strictly depend on the GPIO support, so let them link. */
-static inline int of_get_gpio(struct device_node *np, int index)
+static inline int of_get_gpio_flags(struct device_node *np, int index,
+                                   enum of_gpio_flags *flags)
 {
        return -ENOSYS;
 }
 
 #endif /* CONFIG_OF_GPIO */
 
+/**
+ * of_get_gpio - Get a GPIO number to use with GPIO API
+ * @np:                device node to get GPIO from
+ * @index:     index of the GPIO
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or one of the errno
+ * value on the error condition.
+ */
+static inline int of_get_gpio(struct device_node *np, int index)
+{
+       return of_get_gpio_flags(np, index, NULL);
+}
+
 #endif /* __LINUX_OF_GPIO_H */
index 90987b7..32c0547 100644 (file)
@@ -427,9 +427,9 @@ void rio_dev_put(struct rio_dev *);
  * Get the unique RIO device identifier. Returns the device
  * identifier string.
  */
-static inline char *rio_name(struct rio_dev *rdev)
+static inline const char *rio_name(struct rio_dev *rdev)
 {
-       return rdev->dev.bus_id;
+       return dev_name(&rdev->dev);
 }
 
 /**