Merge branch 'linux-2.6' into for-linus
authorPaul Mackerras <paulus@samba.org>
Mon, 4 Dec 2006 04:59:07 +0000 (15:59 +1100)
committerPaul Mackerras <paulus@samba.org>
Mon, 4 Dec 2006 04:59:07 +0000 (15:59 +1100)
17 files changed:
1  2 
arch/powerpc/Kconfig
arch/powerpc/boot/Makefile
arch/powerpc/configs/cell_defconfig
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/hw_ops.c
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/sysdev/qe_lib/qe.c
include/asm-powerpc/iommu.h
include/asm-powerpc/pci.h
include/asm-powerpc/prom.h

diff --combined arch/powerpc/Kconfig
@@@ -386,14 -386,6 +386,14 @@@ config PPC_CHR
        select PPC_UDBG_16550
        default y
  
 +config PPC_EFIKA
 +      bool "bPlan Efika 5k2. MPC5200B based computer"
 +      depends on PPC_MULTIPLATFORM && PPC32
 +      select PPC_RTAS
 +      select RTAS_PROC
 +      select PPC_MPC52xx
 +      default y
 +
  config PPC_PMAC
        bool "Apple PowerMac based machines"
        depends on PPC_MULTIPLATFORM
@@@ -433,7 -425,7 +433,7 @@@ config PPC_MAPL
        default n
        help
            This option enables support for the Maple 970FX Evaluation Board.
-         For more informations, refer to <http://www.970eval.com>
+         For more information, refer to <http://www.970eval.com>
  
  config PPC_PASEMI
        depends on PPC_MULTIPLATFORM && PPC64
@@@ -602,6 -594,12 +602,6 @@@ config TAU_AVERAG
  
          If in doubt, say N here.
  
 -config PPC_TODC
 -      depends on EMBEDDED6xx
 -      bool "Generic Time-of-day Clock (TODC) support"
 -      ---help---
 -        This adds support for many TODC/RTC chips.
 -
  endmenu
  
  source arch/powerpc/platforms/embedded6xx/Kconfig
@@@ -742,7 -740,7 +742,7 @@@ config ARCH_SPARSEMEM_ENABL
  
  config ARCH_SPARSEMEM_DEFAULT
        def_bool y
-       depends on SMP && PPC_PSERIES
+       depends on (SMP && PPC_PSERIES) || PPC_CELL
  
  config ARCH_POPULATES_NODE_MAP
        def_bool y
@@@ -753,6 -751,15 +753,15 @@@ config ARCH_MEMORY_PROB
        def_bool y
        depends on MEMORY_HOTPLUG
  
+ # Some NUMA nodes have memory ranges that span
+ # other nodes.  Even though a pfn is valid and
+ # between a node's start and end pfns, it may not
+ # reside on that node.  See memmap_init_zone()
+ # for details.
+ config NODES_SPAN_OTHER_NODES
+       def_bool y
+       depends on NEED_MULTIPLE_NODES
  config PPC_64K_PAGES
        bool "64k page size"
        depends on PPC64
@@@ -40,8 -40,7 +40,8 @@@ zliblinuxheader := zlib.h zconf.h zutil
  $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) \
                $(addprefix $(obj)/,$(zlibheader))
  
 -src-wlib := string.S stdio.c main.c div64.S $(zlib)
 +src-wlib := string.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 +              ns16550.c serial.c simple_alloc.c div64.S util.S $(zlib)
  src-plat := of.c
  src-boot := crt0.S $(src-wlib) $(src-plat) empty.c
  
@@@ -75,7 -74,7 +75,7 @@@ $(obj)/zImage.lds $(obj)/zImage.coff.ld
        @cp $< $@
  
  clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
 -              $(obj)/empty.c
 +              empty.c zImage zImage.coff.lds zImage.lds zImage.sandpoint
  
  quiet_cmd_bootcc = BOOTCC  $@
        cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
@@@ -94,13 -93,13 +94,13 @@@ $(patsubst %.S,%.o, $(filter %.S, $(src
  $(obj)/wrapper.a: $(obj-wlib)
        $(call cmd,bootar)
  
 -hostprogs-y   := addnote addRamDisk hack-coff
 +hostprogs-y   := addnote addRamDisk hack-coff mktree
  
  extra-y               := $(obj)/crt0.o $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
                   $(obj)/zImage.lds $(obj)/zImage.coff.lds
  
  wrapper               :=$(srctree)/$(src)/wrapper
 -wrapperbits   := $(extra-y) $(addprefix $(obj)/,addnote hack-coff)
 +wrapperbits   := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree)
  
  #############
  # Bits for building various flavours of zImage
@@@ -116,7 -115,7 +116,7 @@@ endi
  quiet_cmd_wrap        = WRAP    $@
        cmd_wrap        =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux
  quiet_cmd_wrap_initrd = WRAP    $@
-       cmd_wrap_initrd =$(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
+       cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
                                -i $(obj)/ramdisk.image.gz vmlinux
  
  $(obj)/zImage.chrp: vmlinux $(wrapperbits)
@@@ -139,19 -139,7 +139,19 @@@ CONFIG_RTAS_FLASH=
  CONFIG_MMIO_NVRAM=y
  # CONFIG_PPC_MPC106 is not set
  # CONFIG_PPC_970_NAP is not set
 -# CONFIG_CPU_FREQ is not set
 +CONFIG_CPU_FREQ=y
 +CONFIG_CPU_FREQ_TABLE=y
 +CONFIG_CPU_FREQ_DEBUG=y
 +CONFIG_CPU_FREQ_STAT=y
 +# CONFIG_CPU_FREQ_STAT_DETAILS is not set
 +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
 +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
 +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 +CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 +CONFIG_CPU_FREQ_GOV_USERSPACE=y
 +CONFIG_CPU_FREQ_GOV_ONDEMAND=y
 +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 +# CONFIG_CPU_FREQ_PMAC64 is not set
  # CONFIG_WANT_EARLY_SERIAL is not set
  # CONFIG_MPIC is not set
  
  CONFIG_SPU_FS=m
  CONFIG_SPU_BASE=y
  CONFIG_CBE_RAS=y
 +CONFIG_CBE_THERM=m
 +CONFIG_CBE_CPUFREQ=m
  
  #
  # Kernel options
@@@ -268,6 -254,7 +268,7 @@@ CONFIG_SYN_COOKIES=
  CONFIG_INET_TUNNEL=y
  CONFIG_INET_XFRM_MODE_TRANSPORT=y
  CONFIG_INET_XFRM_MODE_TUNNEL=y
+ # CONFIG_INET_XFRM_MODE_BEET is not set
  CONFIG_INET_DIAG=y
  CONFIG_INET_TCP_DIAG=y
  # CONFIG_TCP_CONG_ADVANCED is not set
@@@ -289,7 -276,9 +290,9 @@@ CONFIG_INET6_XFRM_TUNNEL=
  CONFIG_INET6_TUNNEL=m
  CONFIG_INET6_XFRM_MODE_TRANSPORT=y
  CONFIG_INET6_XFRM_MODE_TUNNEL=y
+ # CONFIG_INET6_XFRM_MODE_BEET is not set
  # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+ # CONFIG_IPV6_SIT is not set
  CONFIG_IPV6_TUNNEL=m
  # CONFIG_IPV6_SUBTREES is not set
  # CONFIG_IPV6_MULTIPLE_TABLES is not set
@@@ -419,6 -408,12 +422,12 @@@ CONFIG_BLK_DEV_INITRD=
  # CONFIG_CDROM_PKTCDVD is not set
  # CONFIG_ATA_OVER_ETH is not set
  
+ #
+ # Misc devices
+ #
+ # CONFIG_SGI_IOC4 is not set
+ # CONFIG_TIFM_CORE is not set
  #
  # ATA/ATAPI/MFM/RLL support
  #
@@@ -752,7 -747,6 +761,6 @@@ CONFIG_GEN_RTC=
  # TPM devices
  #
  # CONFIG_TCG_TPM is not set
- # CONFIG_TELCLOCK is not set
  
  #
  # I2C support
@@@ -816,6 -810,7 +824,7 @@@ CONFIG_I2C_ALGOBIT=
  #
  # Dallas's 1-wire bus
  #
+ # CONFIG_W1 is not set
  
  #
  # Hardware Monitoring support
  # CONFIG_HWMON is not set
  # CONFIG_HWMON_VID is not set
  
- #
- # Misc devices
- #
  #
  # Multimedia devices
  #
  # CONFIG_VIDEO_DEV is not set
- CONFIG_VIDEO_V4L2=y
  
  #
  # Digital Video Broadcasting Devices
@@@ -937,6 -927,7 +941,7 @@@ CONFIG_EXT3_FS=
  CONFIG_EXT3_FS_XATTR=y
  # CONFIG_EXT3_FS_POSIX_ACL is not set
  # CONFIG_EXT3_FS_SECURITY is not set
+ # CONFIG_EXT4DEV_FS is not set
  CONFIG_JBD=y
  # CONFIG_JBD_DEBUG is not set
  CONFIG_FS_MBCACHE=y
  # CONFIG_JFS_FS is not set
  CONFIG_FS_POSIX_ACL=y
  # CONFIG_XFS_FS is not set
+ # CONFIG_GFS2_FS is not set
  # CONFIG_OCFS2_FS is not set
  # CONFIG_MINIX_FS is not set
  # CONFIG_ROMFS_FS is not set
@@@ -1143,6 -1135,7 +1149,7 @@@ CONFIG_DEBUG_FS=
  # CONFIG_DEBUG_VM is not set
  # CONFIG_DEBUG_LIST is not set
  # CONFIG_FORCED_INLINING is not set
+ # CONFIG_HEADERS_CHECK is not set
  # CONFIG_RCU_TORTURE_TEST is not set
  # CONFIG_DEBUG_STACKOVERFLOW is not set
  # CONFIG_DEBUG_STACK_USAGE is not set
@@@ -17,7 -17,7 +17,7 @@@ obj-y                         += vdso32
  obj-$(CONFIG_PPC64)           += setup_64.o binfmt_elf32.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
                                   paca.o cpu_setup_ppc970.o \
 -                                 firmware.o sysfs.o
 +                                 firmware.o sysfs.o nvram_64.o
  obj-$(CONFIG_PPC64)           += vdso64/
  obj-$(CONFIG_ALTIVEC)         += vecemu.o vector.o
  obj-$(CONFIG_PPC_970_NAP)     += idle_power4.o
@@@ -32,12 -32,12 +32,11 @@@ obj-$(CONFIG_LPARCFG)              += lparcfg.
  obj-$(CONFIG_IBMVIO)          += vio.o
  obj-$(CONFIG_IBMEBUS)           += ibmebus.o
  obj-$(CONFIG_GENERIC_TBSYNC)  += smp-tbsync.o
 -obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o
  obj-$(CONFIG_CRASH_DUMP)      += crash_dump.o
  obj-$(CONFIG_6xx)             += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o
  obj-$(CONFIG_TAU)             += tau_6xx.o
  obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o
  obj32-$(CONFIG_MODULES)               += module_32.o
- obj-$(CONFIG_E500)            += perfmon_fsl_booke.o
  
  ifeq ($(CONFIG_PPC_MERGE),y)
  
@@@ -18,6 -18,7 +18,7 @@@
  
  #include <asm/oprofile_impl.h>
  #include <asm/cputable.h>
+ #include <asm/prom.h>         /* for PTRRELOC on ARCH=ppc */
  
  struct cpu_spec* cur_cpu_spec = NULL;
  EXPORT_SYMBOL(cur_cpu_spec);
@@@ -41,7 -42,6 +42,7 @@@ extern void __setup_cpu_745x(unsigned l
  #endif /* CONFIG_PPC32 */
  #ifdef CONFIG_PPC64
  extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
 +extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
  extern void __restore_cpu_ppc970(void);
  #endif /* CONFIG_PPC64 */
  
@@@ -74,7 -74,7 +75,7 @@@
  #define PPC_FEATURE_SPE_COMP  0
  #endif
  
- struct cpu_spec       cpu_specs[] = {
+ static struct cpu_spec cpu_specs[] = {
  #ifdef CONFIG_PPC64
        {       /* Power3 */
                .pvr_mask               = 0xffff0000,
                .icache_bsize           = 128,
                .dcache_bsize           = 128,
                .num_pmcs               = 8,
 -              .cpu_setup              = __setup_cpu_ppc970,
 +              .cpu_setup              = __setup_cpu_ppc970MP,
                .cpu_restore            = __restore_cpu_ppc970,
                .oprofile_cpu_type      = "ppc64/970",
                .oprofile_type          = PPC_OPROFILE_POWER4,
                .platform               = "ppc970",
        },
+       {       /* PPC970GX */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x00450000,
+               .cpu_name               = "PPC970GX",
+               .cpu_features           = CPU_FTRS_PPC970,
+               .cpu_user_features      = COMMON_USER_POWER4 |
+                       PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 128,
+               .dcache_bsize           = 128,
+               .num_pmcs               = 8,
+               .cpu_setup              = __setup_cpu_ppc970,
+               .oprofile_cpu_type      = "ppc64/970",
+               .oprofile_type          = PPC_OPROFILE_POWER4,
+               .platform               = "ppc970",
+       },
        {       /* Power5 GR */
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x003a0000,
  #endif /* !CLASSIC_PPC */
  #endif /* CONFIG_PPC32 */
  };
+ struct cpu_spec *identify_cpu(unsigned long offset)
+ {
+       struct cpu_spec *s = cpu_specs;
+       struct cpu_spec **cur = &cur_cpu_spec;
+       unsigned int pvr = mfspr(SPRN_PVR);
+       int i;
+       s = PTRRELOC(s);
+       cur = PTRRELOC(cur);
+       if (*cur != NULL)
+               return PTRRELOC(*cur);
+       for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
+               if ((pvr & s->pvr_mask) == s->pvr_value) {
+                       *cur = cpu_specs + i;
+ #ifdef CONFIG_PPC64
+                       /* ppc64 expects identify_cpu to also call setup_cpu
+                        * for that processor. I will consolidate that at a
+                        * later time, for now, just use our friend #ifdef.
+                        * we also don't need to PTRRELOC the function pointer
+                        * on ppc64 as we are running at 0 in real mode.
+                        */
+                       if (s->cpu_setup) {
+                               s->cpu_setup(offset, s);
+                       }
+ #endif /* CONFIG_PPC64 */
+                       return s;
+               }
+       BUG();
+       return NULL;
+ }
+ void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end)
+ {
+       struct fixup_entry {
+               unsigned long   mask;
+               unsigned long   value;
+               long            start_off;
+               long            end_off;
+       } *fcur, *fend;
+       fcur = fixup_start;
+       fend = fixup_end;
+       for (; fcur < fend; fcur++) {
+               unsigned int *pstart, *pend, *p;
+               if ((value & fcur->mask) == fcur->value)
+                       continue;
+               /* These PTRRELOCs will disappear once the new scheme for
+                * modules and vdso is implemented
+                */
+               pstart = ((unsigned int *)fcur) + (fcur->start_off / 4);
+               pend = ((unsigned int *)fcur) + (fcur->end_off / 4);
+               for (p = pstart; p < pend; p++) {
+                       *p = 0x60000000u;
+                       asm volatile ("dcbst 0, %0" : : "r" (p));
+               }
+               asm volatile ("sync" : : : "memory");
+               for (p = pstart; p < pend; p++)
+                       asm volatile ("icbi 0,%0" : : "r" (p));
+               asm volatile ("sync; isync" : : : "memory");
+       }
+ }
@@@ -35,7 -35,9 +35,7 @@@
  #include <asm/thread_info.h>
  #include <asm/firmware.h>
  
 -#ifdef CONFIG_PPC_ISERIES
  #define DO_SOFT_DISABLE
 -#endif
  
  /*
   * We layout physical memory as follows:
        .text
        .globl  _stext
  _stext:
 -#ifdef CONFIG_PPC_MULTIPLATFORM
  _GLOBAL(__start)
        /* NOP this out unconditionally */
  BEGIN_FTR_SECTION
        b       .__start_initialization_multiplatform
  END_FTR_SECTION(0, 1)
 -#endif /* CONFIG_PPC_MULTIPLATFORM */
  
        /* Catch branch to 0 in real mode */
        trap
@@@ -304,9 -308,7 +304,9 @@@ exception_marker
        std     r9,_LINK(r1);                                              \
        mfctr   r10;                    /* save CTR in stackframe       */ \
        std     r10,_CTR(r1);                                              \
 +      lbz     r10,PACASOFTIRQEN(r13);                            \
        mfspr   r11,SPRN_XER;           /* save XER in stackframe       */ \
 +      std     r10,SOFTE(r1);                                             \
        std     r11,_XER(r1);                                              \
        li      r9,(n)+1;                                                  \
        std     r9,_TRAP(r1);           /* set trap number              */ \
@@@ -341,34 -343,6 +341,34 @@@ label##_pSeries:                                 
        EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
  
  
 +#define MASKABLE_EXCEPTION_PSERIES(n, label)                          \
 +      . = n;                                                          \
 +      .globl label##_pSeries;                                         \
 +label##_pSeries:                                                      \
 +      HMT_MEDIUM;                                                     \
 +      mtspr   SPRN_SPRG1,r13;         /* save r13 */                  \
 +      mfspr   r13,SPRN_SPRG3;         /* get paca address into r13 */ \
 +      std     r9,PACA_EXGEN+EX_R9(r13);       /* save r9, r10 */      \
 +      std     r10,PACA_EXGEN+EX_R10(r13);                             \
 +      lbz     r10,PACASOFTIRQEN(r13);                                 \
 +      mfcr    r9;                                                     \
 +      cmpwi   r10,0;                                                  \
 +      beq     masked_interrupt;                                       \
 +      mfspr   r10,SPRN_SPRG1;                                         \
 +      std     r10,PACA_EXGEN+EX_R13(r13);                             \
 +      std     r11,PACA_EXGEN+EX_R11(r13);                             \
 +      std     r12,PACA_EXGEN+EX_R12(r13);                             \
 +      clrrdi  r12,r13,32;             /* get high part of &label */   \
 +      mfmsr   r10;                                                    \
 +      mfspr   r11,SPRN_SRR0;          /* save SRR0 */                 \
 +      LOAD_HANDLER(r12,label##_common)                                \
 +      ori     r10,r10,MSR_IR|MSR_DR|MSR_RI;                           \
 +      mtspr   SPRN_SRR0,r12;                                          \
 +      mfspr   r12,SPRN_SRR1;          /* and SRR1 */                  \
 +      mtspr   SPRN_SRR1,r10;                                          \
 +      rfid;                                                           \
 +      b       .       /* prevent speculative execution */
 +
  #define STD_EXCEPTION_ISERIES(n, label, area)         \
        .globl label##_iSeries;                         \
  label##_iSeries:                                      \
@@@ -384,32 -358,40 +384,32 @@@ label##_iSeries:                                                        
        HMT_MEDIUM;                                                     \
        mtspr   SPRN_SPRG1,r13;         /* save r13 */                  \
        EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);                         \
 -      lbz     r10,PACAPROCENABLED(r13);                               \
 +      lbz     r10,PACASOFTIRQEN(r13);                                 \
        cmpwi   0,r10,0;                                                \
        beq-    label##_iSeries_masked;                                 \
        EXCEPTION_PROLOG_ISERIES_2;                                     \
        b       label##_common;                                         \
  
 -#ifdef DO_SOFT_DISABLE
 +#ifdef CONFIG_PPC_ISERIES
  #define DISABLE_INTS                          \
 -BEGIN_FW_FTR_SECTION;                         \
 -      lbz     r10,PACAPROCENABLED(r13);       \
        li      r11,0;                          \
 -      std     r10,SOFTE(r1);                  \
 +      stb     r11,PACASOFTIRQEN(r13);         \
 +BEGIN_FW_FTR_SECTION;                         \
 +      stb     r11,PACAHARDIRQEN(r13);         \
 +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
 +BEGIN_FW_FTR_SECTION;                         \
        mfmsr   r10;                            \
 -      stb     r11,PACAPROCENABLED(r13);       \
        ori     r10,r10,MSR_EE;                 \
        mtmsrd  r10,1;                          \
  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
  
 -#define ENABLE_INTS                           \
 -BEGIN_FW_FTR_SECTION;                         \
 -      lbz     r10,PACAPROCENABLED(r13);       \
 -      mfmsr   r11;                            \
 -      std     r10,SOFTE(r1);                  \
 -      ori     r11,r11,MSR_EE;                 \
 -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
 -BEGIN_FW_FTR_SECTION;                         \
 -      ld      r12,_MSR(r1);                   \
 -      mfmsr   r11;                            \
 -      rlwimi  r11,r12,0,MSR_EE;               \
 -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
 -      mtmsrd  r11,1
 +#else
 +#define DISABLE_INTS                          \
 +      li      r11,0;                          \
 +      stb     r11,PACASOFTIRQEN(r13);         \
 +      stb     r11,PACAHARDIRQEN(r13)
  
 -#else /* hard enable/disable interrupts */
 -#define DISABLE_INTS
 +#endif /* CONFIG_PPC_ISERIES */
  
  #define ENABLE_INTS                           \
        ld      r12,_MSR(r1);                   \
        rlwimi  r11,r12,0,MSR_EE;               \
        mtmsrd  r11,1
  
 -#endif
 -
  #define STD_EXCEPTION_COMMON(trap, label, hdlr)               \
        .align  7;                                      \
        .globl label##_common;                          \
@@@ -503,7 -487,7 +503,7 @@@ BEGIN_FTR_SECTIO
        rlwimi  r13,r12,16,0x20
        mfcr    r12
        cmpwi   r13,0x2c
-       beq     .do_stab_bolted_pSeries
+       beq     do_stab_bolted_pSeries
        mtcrf   0x80,r12
        mfspr   r12,SPRN_SPRG2
  END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
@@@ -557,11 -541,11 +557,11 @@@ instruction_access_slb_pSeries
        mfspr   r12,SPRN_SRR1           /* and SRR1 */
        b       .slb_miss_realmode      /* Rel. branch works in real mode */
  
 -      STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)
 +      MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
        STD_EXCEPTION_PSERIES(0x600, alignment)
        STD_EXCEPTION_PSERIES(0x700, program_check)
        STD_EXCEPTION_PSERIES(0x800, fp_unavailable)
 -      STD_EXCEPTION_PSERIES(0x900, decrementer)
 +      MASKABLE_EXCEPTION_PSERIES(0x900, decrementer)
        STD_EXCEPTION_PSERIES(0xa00, trap_0a)
        STD_EXCEPTION_PSERIES(0xb00, trap_0b)
  
@@@ -613,27 -597,10 +613,27 @@@ system_call_pSeries
  /*** pSeries interrupt support ***/
  
        /* moved from 0xf00 */
 -      STD_EXCEPTION_PSERIES(., performance_monitor)
 +      MASKABLE_EXCEPTION_PSERIES(., performance_monitor)
 +
 +/*
 + * An interrupt came in while soft-disabled; clear EE in SRR1,
 + * clear paca->hard_enabled and return.
 + */
 +masked_interrupt:
 +      stb     r10,PACAHARDIRQEN(r13)
 +      mtcrf   0x80,r9
 +      ld      r9,PACA_EXGEN+EX_R9(r13)
 +      mfspr   r10,SPRN_SRR1
 +      rldicl  r10,r10,48,1            /* clear MSR_EE */
 +      rotldi  r10,r10,16
 +      mtspr   SPRN_SRR1,r10
 +      ld      r10,PACA_EXGEN+EX_R10(r13)
 +      mfspr   r13,SPRN_SPRG1
 +      rfid
 +      b       .
  
        .align  7
- _GLOBAL(do_stab_bolted_pSeries)
+ do_stab_bolted_pSeries:
        mtcrf   0x80,r12
        mfspr   r12,SPRN_SPRG2
        EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
@@@ -959,18 -926,10 +959,18 @@@ bad_stack
   * any task or sent any task a signal, you should use
   * ret_from_except or ret_from_except_lite instead of this.
   */
 +fast_exc_return_irq:                  /* restores irq state too */
 +      ld      r3,SOFTE(r1)
 +      ld      r12,_MSR(r1)
 +      stb     r3,PACASOFTIRQEN(r13)   /* restore paca->soft_enabled */
 +      rldicl  r4,r12,49,63            /* get MSR_EE to LSB */
 +      stb     r4,PACAHARDIRQEN(r13)   /* restore paca->hard_enabled */
 +      b       1f
 +
        .globl  fast_exception_return
  fast_exception_return:
        ld      r12,_MSR(r1)
 -      ld      r11,_NIP(r1)
 +1:    ld      r11,_NIP(r1)
        andi.   r3,r12,MSR_RI           /* check if RI is set */
        beq-    unrecov_fer
  
        REST_8GPRS(2, r1)
  
        mfmsr   r10
 -      clrrdi  r10,r10,2               /* clear RI (LE is 0 already) */
 +      rldicl  r10,r10,48,1            /* clear EE */
 +      rldicr  r10,r10,16,61           /* clear RI (LE is 0 already) */
        mtmsrd  r10,1
  
        mtspr   SPRN_SRR1,r12
@@@ -1088,7 -1046,7 +1088,7 @@@ slb_miss_fault
        li      r5,0
        std     r4,_DAR(r1)
        std     r5,_DSISR(r1)
-       b       .handle_page_fault
+       b       handle_page_fault
  
  unrecov_user_slb:
        EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
@@@ -1216,12 -1174,13 +1216,13 @@@ program_check_common
        .globl fp_unavailable_common
  fp_unavailable_common:
        EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
-       bne     .load_up_fpu            /* if from user, just load it up */
+       bne     1f                      /* if from user, just load it up */
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
        ENABLE_INTS
        bl      .kernel_fp_unavailable_exception
        BUG_OPCODE
+ 1:    b       .load_up_fpu
  
        .align  7
        .globl altivec_unavailable_common
@@@ -1321,10 -1280,10 +1322,10 @@@ _GLOBAL(do_hash_page
        std     r4,_DSISR(r1)
  
        andis.  r0,r4,0xa450            /* weird error? */
-       bne-    .handle_page_fault      /* if not, try to insert a HPTE */
+       bne-    handle_page_fault       /* if not, try to insert a HPTE */
  BEGIN_FTR_SECTION
        andis.  r0,r4,0x0020            /* Is it a segment table fault? */
-       bne-    .do_ste_alloc           /* If so handle it */
+       bne-    do_ste_alloc            /* If so handle it */
  END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
  
        /*
@@@ -1366,17 -1325,7 +1367,17 @@@ BEGIN_FW_FTR_SECTIO
         * because ret_from_except_lite will check for and handle pending
         * interrupts if necessary.
         */
-       beq     .ret_from_except_lite
+       beq     13f
 +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 +#endif
 +BEGIN_FW_FTR_SECTION
 +      /*
 +       * Here we have interrupts hard-disabled, so it is sufficient
 +       * to restore paca->{soft,hard}_enable and get out.
 +       */
 +      beq     fast_exc_return_irq     /* Return from exception on success */
 +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 +
        /* For a hash failure, we don't bother re-enabling interrupts */
        ble-    12f
  
        ld      r3,SOFTE(r1)
        bl      .local_irq_restore
        b       11f
 -END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 -#endif
 -BEGIN_FW_FTR_SECTION
 -      beq     fast_exception_return   /* Return from exception on success */
 -      ble-    12f                     /* Failure return from hash_page */
 -
 -      /* fall through */
 -END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
  
  /* Here we have a page fault that hash_page can't handle. */
- _GLOBAL(handle_page_fault)
+ handle_page_fault:
        ENABLE_INTS
  11:   ld      r4,_DAR(r1)
        ld      r5,_DSISR(r1)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .do_page_fault
        cmpdi   r3,0
-       beq+    .ret_from_except_lite
+       beq+    13f
        bl      .save_nvgprs
        mr      r5,r3
        addi    r3,r1,STACK_FRAME_OVERHEAD
        bl      .bad_page_fault
        b       .ret_from_except
  
++13:   b       .ret_from_except_lite
++
  /* We have a page fault that hash_page could handle but HV refused
   * the PTE insertion
   */
        bl      .low_hash_fault
        b       .ret_from_except
  
 -13:   b       .ret_from_except_lite
 -
        /* here we have a segment miss */
- _GLOBAL(do_ste_alloc)
+ do_ste_alloc:
        bl      .ste_allocate           /* try to insert stab entry */
        cmpdi   r3,0
-       beq+    fast_exception_return
-       b       .handle_page_fault
+       bne-    handle_page_fault
+       b       fast_exception_return
  
  /*
   * r13 points to the PACA, r9 contains the saved CR,
@@@ -1624,11 -1583,6 +1627,6 @@@ _STATIC(__start_initialization_iSeries
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
  
-       LOAD_REG_IMMEDIATE(r3,cpu_specs)
-       LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
-       li      r5,0
-       bl      .identify_cpu
        LOAD_REG_IMMEDIATE(r2,__toc_start)
        addi    r2,r2,0x4000
        addi    r2,r2,0x4000
        b       .start_here_common
  #endif /* CONFIG_PPC_ISERIES */
  
 -#ifdef CONFIG_PPC_MULTIPLATFORM
  
  _STATIC(__mmu_off)
        mfmsr   r3
   *
   */
  _GLOBAL(__start_initialization_multiplatform)
 -#ifdef CONFIG_PPC_MULTIPLATFORM
        /*
         * Are we booted from a PROM Of-type client-interface ?
         */
        cmpldi  cr0,r5,0
        bne     .__boot_from_prom               /* yes -> prom */
 -#endif
  
        /* Save parameters */
        mr      r31,r3
        cmpwi   r0,0x3c         /* 970FX */
        beq     1f
        cmpwi   r0,0x44         /* 970MP */
+       beq     1f
+       cmpwi   r0,0x45         /* 970GX */
        bne     2f
  1:    bl      .__cpu_preinit_ppc970
  2:
        bl      .__mmu_off
        b       .__after_prom_start
  
 -#ifdef CONFIG_PPC_MULTIPLATFORM
  _STATIC(__boot_from_prom)
        /* Save parameters */
        mr      r31,r3
        bl      .prom_init
        /* We never return */
        trap
 -#endif
  
  /*
   * At this point, r3 contains the physical address we are running at,
@@@ -1791,6 -1752,8 +1791,6 @@@ _STATIC(__after_prom_start
        bl      .copy_and_flush         /* copy the rest */
        b       .start_here_multiplatform
  
 -#endif /* CONFIG_PPC_MULTIPLATFORM */
 -
  /*
   * Copy routine used to copy the kernel to start at physical address 0
   * and flush and invalidate the caches as needed.
@@@ -1914,16 -1877,11 +1914,16 @@@ _GLOBAL(__secondary_start
        /* enable MMU and jump to start_secondary */
        LOAD_REG_ADDR(r3, .start_secondary_prolog)
        LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
 -#ifdef DO_SOFT_DISABLE
 +#ifdef CONFIG_PPC_ISERIES
  BEGIN_FW_FTR_SECTION
        ori     r4,r4,MSR_EE
  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
  #endif
 +BEGIN_FW_FTR_SECTION
 +      stb     r7,PACASOFTIRQEN(r13)
 +      stb     r7,PACAHARDIRQEN(r13)
 +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 +
        mtspr   SPRN_SRR0,r3
        mtspr   SPRN_SRR1,r4
        rfid
@@@ -1955,6 -1913,7 +1955,6 @@@ _GLOBAL(enable_64b_mode
        isync
        blr
  
 -#ifdef CONFIG_PPC_MULTIPLATFORM
  /*
   * This is where the main kernel code starts.
   */
@@@ -2005,13 -1964,6 +2005,6 @@@ _STATIC(start_here_multiplatform
        addi    r2,r2,0x4000
        add     r2,r2,r26
  
-       LOAD_REG_IMMEDIATE(r3, cpu_specs)
-       add     r3,r3,r26
-       LOAD_REG_IMMEDIATE(r4,cur_cpu_spec)
-       add     r4,r4,r26
-       mr      r5,r26
-       bl      .identify_cpu
        /* Do very early kernel initializations, including initial hash table,
         * stab and slb setup before we turn on relocation.     */
  
        mtspr   SPRN_SRR1,r4
        rfid
        b       .       /* prevent speculative execution */
 -#endif /* CONFIG_PPC_MULTIPLATFORM */
        
        /* This is where all platforms converge execution */
  _STATIC(start_here_common)
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
  
-       /* Apply the CPUs-specific fixups (nop out sections not relevant
-        * to this CPU
-        */
-       li      r3,0
-       bl      .do_cpu_ftr_fixups
-       bl      .do_fw_ftr_fixups
        /* ptr to current */
        LOAD_REG_IMMEDIATE(r4, init_task)
        std     r4,PACACURRENT(r13)
  
        /* Load up the kernel context */
  5:
 -#ifdef DO_SOFT_DISABLE
 -BEGIN_FW_FTR_SECTION
        li      r5,0
 -      stb     r5,PACAPROCENABLED(r13) /* Soft Disabled */
 +      stb     r5,PACASOFTIRQEN(r13)   /* Soft Disabled */
 +#ifdef CONFIG_PPC_ISERIES
 +BEGIN_FW_FTR_SECTION
        mfmsr   r5
        ori     r5,r5,MSR_EE            /* Hard Enabled */
        mtmsrd  r5
  END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
  #endif
 +BEGIN_FW_FTR_SECTION
 +      stb     r5,PACAHARDIRQEN(r13)
 +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
  
        bl .start_kernel
  
@@@ -1014,7 -1014,7 +1014,7 @@@ EXPORT_SYMBOL(find_all_nodes)
  /** Checks if the given "compat" string matches one of the strings in
   * the device's "compatible" property
   */
- int device_is_compatible(struct device_node *device, const char *compat)
+ int device_is_compatible(const struct device_node *device, const char *compat)
  {
        const char* cp;
        int cplen, l;
@@@ -1491,7 -1491,8 +1491,8 @@@ static int __init prom_reconfig_setup(v
  __initcall(prom_reconfig_setup);
  #endif
  
- struct property *of_find_property(struct device_node *np, const char *name,
+ struct property *of_find_property(const struct device_node *np,
+                                 const char *name,
                                  int *lenp)
  {
        struct property *pp;
   * Find a property with a given name for a given node
   * and return the value.
   */
- const void *get_property(struct device_node *np, const char *name, int *lenp)
+ const void *get_property(const struct device_node *np, const char *name,
+                        int *lenp)
  {
        struct property *pp = of_find_property(np,name,lenp);
        return pp ? pp->value : NULL;
@@@ -1672,7 -1674,6 +1674,7 @@@ struct device_node *of_get_cpu_node(in
        }
        return NULL;
  }
 +EXPORT_SYMBOL(of_get_cpu_node);
  
  #ifdef DEBUG
  static struct debugfs_blob_wrapper flat_dt_blob;
@@@ -63,6 -63,10 +63,6 @@@ unsigned int DMA_MODE_WRITE
  
  int have_of = 1;
  
 -#ifdef CONFIG_PPC_MULTIPLATFORM
 -dev_t boot_dev;
 -#endif /* CONFIG_PPC_MULTIPLATFORM */
 -
  #ifdef CONFIG_VGA_CONSOLE
  unsigned long vgacon_remap_base;
  #endif
@@@ -87,6 -91,7 +87,7 @@@ int ucache_bsize
  unsigned long __init early_init(unsigned long dt_ptr)
  {
        unsigned long offset = reloc_offset();
+       struct cpu_spec *spec;
  
        /* First zero the BSS -- use memset_io, some platforms don't have
         * caches on yet */
         * Identify the CPU type and fix up code sections
         * that depend on which cpu we have.
         */
-       identify_cpu(offset, 0);
-       do_cpu_ftr_fixups(offset);
+       spec = identify_cpu(offset);
+       do_feature_fixups(spec->cpu_features,
+                         PTRRELOC(&__start___ftr_fixup),
+                         PTRRELOC(&__stop___ftr_fixup));
  
        return KERNELBASE + offset;
  }
@@@ -71,6 -71,7 +71,6 @@@
  
  int have_of = 1;
  int boot_cpuid = 0;
 -dev_t boot_dev;
  u64 ppc64_pft_size;
  
  /* Pick defaults since we might want to patch instructions
@@@ -169,6 -170,9 +169,9 @@@ void __init setup_paca(int cpu
  
  void __init early_setup(unsigned long dt_ptr)
  {
+       /* Identify CPU type */
+       identify_cpu(0);
        /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
        setup_paca(0);
  
@@@ -222,8 -226,8 +225,8 @@@ void early_setup_secondary(void
  {
        struct paca_struct *lpaca = get_paca();
  
 -      /* Mark enabled in PACA */
 -      lpaca->proc_enabled = 0;
 +      /* Mark interrupts enabled in PACA */
 +      lpaca->soft_enabled = 0;
  
        /* Initialize hash table for that CPU */
        htab_initialize_secondary();
@@@ -347,6 -351,14 +350,14 @@@ void __init setup_system(void
  {
        DBG(" -> setup_system()\n");
  
+       /* Apply the CPUs-specific and firmware specific fixups to kernel
+        * text (nop out sections not relevant to this CPU or this firmware)
+        */
+       do_feature_fixups(cur_cpu_spec->cpu_features,
+                         &__start___ftr_fixup, &__stop___ftr_fixup);
+       do_feature_fixups(powerpc_firmware_features,
+                         &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
        /*
         * Unflatten the device-tree passed by prom_init or kexec
         */
         * setting up the hash table pointers. It also sets up some interrupt-mapping
         * related options that will be used by finish_device_tree()
         */
 -      ppc_md.init_early();
 +      if (ppc_md.init_early)
 +              ppc_md.init_early();
  
        /*
         * We can discover serial ports now since the above did setup the
@@@ -38,7 -38,6 +38,7 @@@
  #include <asm/spu.h>
  #include <asm/spu_priv1.h>
  #include <asm/mmu_context.h>
 +#include <asm/xmon.h>
  
  #include "interrupt.h"
  
@@@ -90,30 -89,7 +90,30 @@@ static int __spu_trap_data_seg(struct s
                printk("%s: invalid access during switch!\n", __func__);
                return 1;
        }
 -      if (!mm || (REGION_ID(ea) != USER_REGION_ID)) {
 +      esid = (ea & ESID_MASK) | SLB_ESID_V;
 +
 +      switch(REGION_ID(ea)) {
 +      case USER_REGION_ID:
 +#ifdef CONFIG_HUGETLB_PAGE
 +              if (in_hugepage_area(mm->context, ea))
 +                      llp = mmu_psize_defs[mmu_huge_psize].sllp;
 +              else
 +#endif
 +                      llp = mmu_psize_defs[mmu_virtual_psize].sllp;
 +              vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
 +                              SLB_VSID_USER | llp;
 +              break;
 +      case VMALLOC_REGION_ID:
 +              llp = mmu_psize_defs[mmu_virtual_psize].sllp;
 +              vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
 +                      SLB_VSID_KERNEL | llp;
 +              break;
 +      case KERNEL_REGION_ID:
 +              llp = mmu_psize_defs[mmu_linear_psize].sllp;
 +              vsid = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
 +                      SLB_VSID_KERNEL | llp;
 +              break;
 +      default:
                /* Future: support kernel segments so that drivers
                 * can use SPUs.
                 */
                return 1;
        }
  
 -      esid = (ea & ESID_MASK) | SLB_ESID_V;
 -#ifdef CONFIG_HUGETLB_PAGE
 -      if (in_hugepage_area(mm->context, ea))
 -              llp = mmu_psize_defs[mmu_huge_psize].sllp;
 -      else
 -#endif
 -              llp = mmu_psize_defs[mmu_virtual_psize].sllp;
 -      vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
 -                      SLB_VSID_USER | llp;
 -
        out_be64(&priv2->slb_index_W, spu->slb_replace);
        out_be64(&priv2->slb_vsid_RW, vsid);
        out_be64(&priv2->slb_esid_RW, esid);
@@@ -334,7 -320,6 +334,7 @@@ static void spu_free_irqs(struct spu *s
  }
  
  static struct list_head spu_list[MAX_NUMNODES];
 +static LIST_HEAD(spu_full_list);
  static DEFINE_MUTEX(spu_mutex);
  
  static void spu_init_channels(struct spu *spu)
@@@ -379,7 -364,8 +379,7 @@@ struct spu *spu_alloc_node(int node
        if (!list_empty(&spu_list[node])) {
                spu = list_entry(spu_list[node].next, struct spu, list);
                list_del_init(&spu->list);
 -              pr_debug("Got SPU %x %d %d\n",
 -                       spu->isrc, spu->number, spu->node);
 +              pr_debug("Got SPU %d %d\n", spu->number, spu->node);
                spu_init_channels(spu);
        }
        mutex_unlock(&spu_mutex);
@@@ -605,6 -591,7 +605,6 @@@ static int __init spu_map_interrupts_ol
  
        /* Add the node number */
        isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
 -      spu->isrc = isrc;
  
        /* Now map interrupts of all 3 classes */
        spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
@@@ -668,14 -655,19 +668,19 @@@ static int __init spu_map_interrupts(st
  
        for (i=0; i < 3; i++) {
                ret = of_irq_map_one(np, i, &oirq);
-               if (ret)
+               if (ret) {
+                       pr_debug("spu_new: failed to get irq %d\n", i);
                        goto err;
+               }
                ret = -EINVAL;
+               pr_debug("  irq %d no 0x%x on %s\n", i, oirq.specifier[0],
+                        oirq.controller->full_name);
                spu->irqs[i] = irq_create_of_mapping(oirq.controller,
                                        oirq.specifier, oirq.size);
-               if (spu->irqs[i] == NO_IRQ)
+               if (spu->irqs[i] == NO_IRQ) {
+                       pr_debug("spu_new: failed to map it !\n");
                        goto err;
+               }
        }
        return 0;
  
@@@ -694,7 -686,7 +699,7 @@@ static int spu_map_resource(struct devi
        struct resource resource = { };
        int ret;
  
-       ret = of_address_to_resource(node, 0, &resource);
+       ret = of_address_to_resource(node, nr, &resource);
        if (ret)
                goto out;
  
@@@ -717,22 -709,42 +722,42 @@@ static int __init spu_map_device(struc
  
        ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store,
                                        &spu->local_store_phys);
-       if (ret)
+       if (ret) {
+               pr_debug("spu_new: failed to map %s resource 0\n",
+                        node->full_name);
                goto out;
+       }
        ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem,
                                        &spu->problem_phys);
-       if (ret)
+       if (ret) {
+               pr_debug("spu_new: failed to map %s resource 1\n",
+                        node->full_name);
                goto out_unmap;
+       }
        ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2,
                                        NULL);
-       if (ret)
+       if (ret) {
+               pr_debug("spu_new: failed to map %s resource 2\n",
+                        node->full_name);
                goto out_unmap;
+       }
  
        if (!firmware_has_feature(FW_FEATURE_LPAR))
                ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1,
                                        NULL);
-       if (ret)
+       if (ret) {
+               pr_debug("spu_new: failed to map %s resource 3\n",
+                        node->full_name);
                goto out_unmap;
+       }
+       pr_debug("spu_new: %s maps:\n", node->full_name);
+       pr_debug("  local store   : 0x%016lx -> 0x%p\n",
+                spu->local_store_phys, spu->local_store);
+       pr_debug("  problem state : 0x%016lx -> 0x%p\n",
+                spu->problem_phys, spu->problem);
+       pr_debug("  priv2         :                       0x%p\n", spu->priv2);
+       pr_debug("  priv1         :                       0x%p\n", spu->priv1);
        return 0;
  
  out_unmap:
@@@ -746,56 -758,15 +771,56 @@@ struct sysdev_class spu_sysdev_class = 
        set_kset_name("spu")
  };
  
 -static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
 +int spu_add_sysdev_attr(struct sysdev_attribute *attr)
  {
 -      struct spu *spu = container_of(sysdev, struct spu, sysdev);
 -      return sprintf(buf, "%d\n", spu->isrc);
 +      struct spu *spu;
 +      mutex_lock(&spu_mutex);
 +
 +      list_for_each_entry(spu, &spu_full_list, full_list)
 +              sysdev_create_file(&spu->sysdev, attr);
  
 +      mutex_unlock(&spu_mutex);
 +      return 0;
  }
 -static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL);
 +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr);
 +
 +int spu_add_sysdev_attr_group(struct attribute_group *attrs)
 +{
 +      struct spu *spu;
 +      mutex_lock(&spu_mutex);
  
 -extern int attach_sysdev_to_node(struct sys_device *dev, int nid);
 +      list_for_each_entry(spu, &spu_full_list, full_list)
 +              sysfs_create_group(&spu->sysdev.kobj, attrs);
 +
 +      mutex_unlock(&spu_mutex);
 +      return 0;
 +}
 +EXPORT_SYMBOL_GPL(spu_add_sysdev_attr_group);
 +
 +
 +void spu_remove_sysdev_attr(struct sysdev_attribute *attr)
 +{
 +      struct spu *spu;
 +      mutex_lock(&spu_mutex);
 +
 +      list_for_each_entry(spu, &spu_full_list, full_list)
 +              sysdev_remove_file(&spu->sysdev, attr);
 +
 +      mutex_unlock(&spu_mutex);
 +}
 +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr);
 +
 +void spu_remove_sysdev_attr_group(struct attribute_group *attrs)
 +{
 +      struct spu *spu;
 +      mutex_lock(&spu_mutex);
 +
 +      list_for_each_entry(spu, &spu_full_list, full_list)
 +              sysfs_remove_group(&spu->sysdev.kobj, attrs);
 +
 +      mutex_unlock(&spu_mutex);
 +}
 +EXPORT_SYMBOL_GPL(spu_remove_sysdev_attr_group);
  
  static int spu_create_sysdev(struct spu *spu)
  {
                return ret;
        }
  
 -      if (spu->isrc != 0)
 -              sysdev_create_file(&spu->sysdev, &attr_isrc);
        sysfs_add_device_to_node(&spu->sysdev, spu->nid);
  
        return 0;
  
  static void spu_destroy_sysdev(struct spu *spu)
  {
 -      sysdev_remove_file(&spu->sysdev, &attr_isrc);
        sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
        sysdev_unregister(&spu->sysdev);
  }
@@@ -856,7 -830,7 +881,7 @@@ static int __init create_spu(struct dev
        if (ret)
                goto out_unmap;
        spin_lock_init(&spu->register_lock);
 -      spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
 +      spu_mfc_sdr_setup(spu);
        spu_mfc_sr1_set(spu, 0x33);
        mutex_lock(&spu_mutex);
  
                goto out_free_irqs;
  
        list_add(&spu->list, &spu_list[spu->node]);
 +      list_add(&spu->full_list, &spu_full_list);
 +      spu->devnode = of_node_get(spe);
 +
        mutex_unlock(&spu_mutex);
  
 -      pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n",
 -              spu->name, spu->isrc, spu->local_store,
 +      pr_debug(KERN_DEBUG "Using SPE %s %p %p %p %p %d\n",
 +              spu->name, spu->local_store,
                spu->problem, spu->priv1, spu->priv2, spu->number);
        goto out;
  
@@@ -895,9 -866,6 +920,9 @@@ out
  static void destroy_spu(struct spu *spu)
  {
        list_del_init(&spu->list);
 +      list_del_init(&spu->full_list);
 +
 +      of_node_put(spu->devnode);
  
        spu_destroy_sysdev(spu);
        spu_free_irqs(spu);
@@@ -944,9 -912,6 +969,9 @@@ static int __init init_spu_base(void
                        break;
                }
        }
 +
 +      xmon_register_spus(&spu_full_list);
 +
        return ret;
  }
  module_init(init_spu_base);
@@@ -385,7 -385,7 +385,7 @@@ static ssize_t spufs_mbox_read(struct f
        udata = (void __user *)buf;
  
        spu_acquire(ctx);
-       for (count = 0; count <= len; count += 4, udata++) {
+       for (count = 0; (count + 4) <= len; count += 4, udata++) {
                int ret;
                ret = ctx->ops->mbox_read(ctx, &mbox_data);
                if (ret == 0)
@@@ -1343,37 -1343,6 +1343,37 @@@ static struct file_operations spufs_mfc
        .mmap    = spufs_mfc_mmap,
  };
  
 +
 +static int spufs_recycle_open(struct inode *inode, struct file *file)
 +{
 +      file->private_data = SPUFS_I(inode)->i_ctx;
 +      return nonseekable_open(inode, file);
 +}
 +
 +static ssize_t spufs_recycle_write(struct file *file,
 +              const char __user *buffer, size_t size, loff_t *pos)
 +{
 +      struct spu_context *ctx = file->private_data;
 +      int ret;
 +
 +      if (!(ctx->flags & SPU_CREATE_ISOLATE))
 +              return -EINVAL;
 +
 +      if (size < 1)
 +              return -EINVAL;
 +
 +      ret = spu_recycle_isolated(ctx);
 +
 +      if (ret)
 +              return ret;
 +      return size;
 +}
 +
 +static struct file_operations spufs_recycle_fops = {
 +      .open    = spufs_recycle_open,
 +      .write   = spufs_recycle_write,
 +};
 +
  static void spufs_npc_set(void *data, u64 val)
  {
        struct spu_context *ctx = data;
@@@ -1562,26 -1531,3 +1562,26 @@@ struct tree_descr spufs_dir_contents[] 
        { "object-id", &spufs_object_id_ops, 0666, },
        {},
  };
 +
 +struct tree_descr spufs_dir_nosched_contents[] = {
 +      { "mem",  &spufs_mem_fops,  0666, },
 +      { "mbox", &spufs_mbox_fops, 0444, },
 +      { "ibox", &spufs_ibox_fops, 0444, },
 +      { "wbox", &spufs_wbox_fops, 0222, },
 +      { "mbox_stat", &spufs_mbox_stat_fops, 0444, },
 +      { "ibox_stat", &spufs_ibox_stat_fops, 0444, },
 +      { "wbox_stat", &spufs_wbox_stat_fops, 0444, },
 +      { "signal1", &spufs_signal1_fops, 0666, },
 +      { "signal2", &spufs_signal2_fops, 0666, },
 +      { "signal1_type", &spufs_signal1_type, 0666, },
 +      { "signal2_type", &spufs_signal2_type, 0666, },
 +      { "mss", &spufs_mss_fops, 0666, },
 +      { "mfc", &spufs_mfc_fops, 0666, },
 +      { "cntl", &spufs_cntl_fops,  0666, },
 +      { "npc", &spufs_npc_ops, 0666, },
 +      { "psmap", &spufs_psmap_fops, 0666, },
 +      { "phys-id", &spufs_id_ops, 0666, },
 +      { "object-id", &spufs_object_id_ops, 0666, },
 +      { "recycle", &spufs_recycle_fops, 0222, },
 +      {},
 +};
@@@ -147,7 -147,7 +147,7 @@@ static void spu_hw_signal1_write(struc
  
  static u32 spu_hw_signal2_read(struct spu_context *ctx)
  {
-       return in_be32(&ctx->spu->problem->signal_notify1);
+       return in_be32(&ctx->spu->problem->signal_notify2);
  }
  
  static void spu_hw_signal2_write(struct spu_context *ctx, u32 data)
@@@ -219,11 -219,8 +219,11 @@@ static char *spu_hw_get_ls(struct spu_c
  
  static void spu_hw_runcntl_write(struct spu_context *ctx, u32 val)
  {
 -      eieio();
 +      spin_lock_irq(&ctx->spu->register_lock);
 +      if (val & SPU_RUNCNTL_ISOLATE)
 +              out_be64(&ctx->spu->priv2->spu_privcntl_RW, 4LL);
        out_be32(&ctx->spu->problem->spu_runcntl_RW, val);
 +      spin_unlock_irq(&ctx->spu->register_lock);
  }
  
  static void spu_hw_runcntl_stop(struct spu_context *ctx)
@@@ -21,6 -21,7 +21,6 @@@
  #include <linux/smp.h>
  #include <linux/param.h>
  #include <linux/string.h>
 -#include <linux/initrd.h>
  #include <linux/seq_file.h>
  #include <linux/kdev_t.h>
  #include <linux/major.h>
@@@ -79,6 -80,8 +79,6 @@@ extern void iSeries_pci_final_fixup(voi
  static void iSeries_pci_final_fixup(void) { }
  #endif
  
 -extern int rd_size;           /* Defined in drivers/block/rd.c */
 -
  extern unsigned long iSeries_recal_tb;
  extern unsigned long iSeries_recal_titan;
  
@@@ -292,6 -295,24 +292,6 @@@ static void __init iSeries_init_early(v
  {
        DBG(" -> iSeries_init_early()\n");
  
 -#if defined(CONFIG_BLK_DEV_INITRD)
 -      /*
 -       * If the init RAM disk has been configured and there is
 -       * a non-zero starting address for it, set it up
 -       */
 -      if (naca.xRamDisk) {
 -              initrd_start = (unsigned long)__va(naca.xRamDisk);
 -              initrd_end = initrd_start + naca.xRamDiskSize * HW_PAGE_SIZE;
 -              initrd_below_start_ok = 1;      // ramdisk in kernel space
 -              ROOT_DEV = Root_RAM0;
 -              if (((rd_size * 1024) / HW_PAGE_SIZE) < naca.xRamDiskSize)
 -                      rd_size = (naca.xRamDiskSize * HW_PAGE_SIZE) / 1024;
 -      } else
 -#endif /* CONFIG_BLK_DEV_INITRD */
 -      {
 -          /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */
 -      }
 -
        iSeries_recal_tb = get_tb();
        iSeries_recal_titan = HvCallXm_loadTod();
  
  
        mf_init();
  
 -      /* If we were passed an initrd, set the ROOT_DEV properly if the values
 -       * look sensible. If not, clear initrd reference.
 -       */
 -#ifdef CONFIG_BLK_DEV_INITRD
 -      if (initrd_start >= KERNELBASE && initrd_end >= KERNELBASE &&
 -          initrd_end > initrd_start)
 -              ROOT_DEV = Root_RAM0;
 -      else
 -              initrd_start = initrd_end = 0;
 -#endif /* CONFIG_BLK_DEV_INITRD */
 -
        DBG(" <- iSeries_init_early()\n");
  }
  
@@@ -662,6 -694,11 +662,11 @@@ void * __init iSeries_early_setup(void
  {
        unsigned long phys_mem_size;
  
+       /* Identify CPU type. This is done again by the common code later
+        * on but calling this function multiple times is fine.
+        */
+       identify_cpu(0);
        powerpc_firmware_features |= FW_FEATURE_ISERIES;
        powerpc_firmware_features |= FW_FEATURE_LPAR;
  
@@@ -122,8 -122,7 +122,7 @@@ int qe_issue_cmd(u32 cmd, u32 device, u
                                mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
                }
  
-               out_be32(&qe_immr->cp.cecdr,
-                        immrbar_virt_to_phys((void *)cmd_input));
+               out_be32(&qe_immr->cp.cecdr, cmd_input);
                out_be32(&qe_immr->cp.cecr,
                         (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
                          mcn_protocol << mcn_shift));
@@@ -175,7 -174,8 +174,7 @@@ void qe_setbrg(u32 brg, u32 rate
        u32 divisor, tempval;
        int div16 = 0;
  
 -      bp = &qe_immr->brg.brgc1;
 -      bp += brg;
 +      bp = &qe_immr->brg.brgc[brg];
  
        divisor = (get_brg_clk() / rate);
        if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
  #define _ASM_IOMMU_H
  #ifdef __KERNEL__
  
- #include <asm/types.h>
+ #include <linux/compiler.h>
  #include <linux/spinlock.h>
  #include <linux/device.h>
  #include <linux/dma-mapping.h>
+ #include <asm/types.h>
+ #include <asm/bitops.h>
+ #define IOMMU_PAGE_SHIFT      12
+ #define IOMMU_PAGE_SIZE       (ASM_CONST(1) << IOMMU_PAGE_SHIFT)
+ #define IOMMU_PAGE_MASK       (~((1 << IOMMU_PAGE_SHIFT) - 1))
+ #define IOMMU_PAGE_ALIGN(addr) _ALIGN_UP(addr, IOMMU_PAGE_SIZE)
+ #ifndef __ASSEMBLY__
+ /* Pure 2^n version of get_order */
+ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)
+ {
+       return __ilog2((size - 1) >> IOMMU_PAGE_SHIFT) + 1;
+ }
+ #endif   /* __ASSEMBLY__ */
  
  /*
   * IOMAP_MAX_ORDER defines the largest contiguous block
   * of dma space we can get.  IOMAP_MAX_ORDER = 13
   * allows up to 2**12 pages (4096 * 4096) = 16 MB
   */
- #define IOMAP_MAX_ORDER 13
+ #define IOMAP_MAX_ORDER               13
  
  struct iommu_table {
        unsigned long  it_busno;     /* Bus number this table belongs to */
  struct scatterlist;
  struct device_node;
  
 -#ifdef CONFIG_PPC_MULTIPLATFORM
 -
 -/* Walks all buses and creates iommu tables */
 -extern void iommu_setup_pSeries(void);
 -extern void iommu_setup_dart(void);
 -
  /* Frees table for an individual device node */
  extern void iommu_free_table(struct device_node *dn);
  
 -#endif /* CONFIG_PPC_MULTIPLATFORM */
 -
  /* Initializes an iommu_table based in values set in the passed-in
   * structure
   */
@@@ -62,19 -62,13 +62,13 @@@ static inline int pci_get_legacy_ide_ir
  }
  
  #ifdef CONFIG_PPC64
- #define HAVE_ARCH_PCI_MWI 1
- static inline int pcibios_prep_mwi(struct pci_dev *dev)
- {
-       /*
-        * We would like to avoid touching the cacheline size or MWI bit
-        * but we cant do that with the current pcibios_prep_mwi 
-        * interface. pSeries firmware sets the cacheline size (which is not
-        * the cpu cacheline size in all cases) and hardware treats MWI 
-        * the same as memory write. So we dont touch the cacheline size
-        * here and allow the generic code to set the MWI bit.
-        */
-       return 0;
- }
+ /*
+  * We want to avoid touching the cacheline size or MWI bit.
+  * pSeries firmware sets the cacheline size (which is not the cpu cacheline
+  * size in all cases) and hardware treats MWI the same as memory write.
+  */
+ #define PCI_DISABLE_MWI
  
  extern struct dma_mapping_ops pci_dma_ops;
  
@@@ -238,10 -232,12 +232,10 @@@ extern pgprot_t pci_phys_mem_access_pro
                                         unsigned long size,
                                         pgprot_t prot);
  
 -#if defined(CONFIG_PPC_MULTIPLATFORM) || defined(CONFIG_PPC32)
  #define HAVE_ARCH_PCI_RESOURCE_TO_USER
  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);
 -#endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */
  
  #endif        /* __KERNEL__ */
  #endif /* __ASM_POWERPC_PCI_H */
@@@ -17,7 -17,6 +17,7 @@@
   */
  #include <linux/types.h>
  #include <linux/proc_fs.h>
 +#include <linux/platform_device.h>
  #include <asm/atomic.h>
  
  /* Definitions used by the flattened device tree */
@@@ -135,7 -134,7 +135,7 @@@ extern struct device_node *of_find_all_
  extern struct device_node *of_get_parent(const struct device_node *node);
  extern struct device_node *of_get_next_child(const struct device_node *node,
                                             struct device_node *prev);
- extern struct property *of_find_property(struct device_node *np,
+ extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
                                         int *lenp);
  extern struct device_node *of_node_get(struct device_node *node);
@@@ -159,10 -158,12 +159,12 @@@ extern void of_detach_node(const struc
  extern void finish_device_tree(void);
  extern void unflatten_device_tree(void);
  extern void early_init_devtree(void *);
- extern int device_is_compatible(struct device_node *device, const char *);
+ extern int device_is_compatible(const struct device_node *device,
+                               const char *);
  extern int machine_is_compatible(const char *compat);
- extern const void *get_property(struct device_node *node, const char *name,
-               int *lenp);
+ extern const void *get_property(const struct device_node *node,
+                               const char *name,
+                               int *lenp);
  extern void print_properties(struct device_node *node);
  extern int prom_n_addr_cells(struct device_node* np);
  extern int prom_n_size_cells(struct device_node* np);
@@@ -332,20 -333,6 +334,20 @@@ extern int of_irq_map_one(struct device
  struct pci_dev;
  extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
  
 +static inline int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
 +{
 +      int irq = irq_of_parse_and_map(dev, index);
 +
 +      /* Only dereference the resource if both the
 +       * resource and the irq are valid. */
 +      if (r && irq != NO_IRQ) {
 +              r->start = r->end = irq;
 +              r->flags = IORESOURCE_IRQ;
 +      }
 +
 +      return irq;
 +}
 +
  
  #endif /* __KERNEL__ */
  #endif /* _POWERPC_PROM_H */