Merge commit 'origin/master'
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 16 Jul 2008 01:07:59 +0000 (11:07 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 16 Jul 2008 01:07:59 +0000 (11:07 +1000)
Manual merge of:

arch/powerpc/Kconfig
arch/powerpc/kernel/stacktrace.c
arch/powerpc/mm/slice.c
arch/ppc/kernel/smp.c

13 files changed:
1  2 
MAINTAINERS
Makefile
arch/powerpc/Kconfig
arch/powerpc/kernel/machine_kexec_64.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/stacktrace.c
arch/powerpc/kernel/time.c
arch/powerpc/mm/slice.c
arch/powerpc/mm/tlb_64.c
arch/powerpc/sysdev/mpic.c
drivers/i2c/busses/i2c-mpc.c
include/asm-powerpc/smp.h

diff --combined MAINTAINERS
@@@ -1686,6 -1686,13 +1686,13 @@@ L:    linuxppc-embedded@ozlabs.or
  L:    linux-kernel@vger.kernel.org
  S:    Maintained
  
+ FREESCALE I2C CPM DRIVER
+ P:    Jochen Friedrich
+ M:    jochen@scram.de
+ L:    linuxppc-dev@ozlabs.org
+ L:    i2c@lm-sensors.org
+ S:    Maintained
  FREESCALE SOC FS_ENET DRIVER
  P:    Pantelis Antoniou
  M:    pantelis.antoniou@gmail.com
@@@ -1770,6 -1777,11 +1777,11 @@@ M:    hch@infradead.or
  W:    ftp://ftp.openlinux.org/pub/people/hch/vxfs
  S:    Maintained
  
+ FTRACE
+ P:    Steven Rostedt
+ M:    srostedt@redhat.com
+ S:    Maintained
  FUJITSU FR-V (FRV) PORT
  P:    David Howells
  M:    dhowells@redhat.com
@@@ -2509,11 -2521,13 +2521,11 @@@ W:   http://www.penguinppc.org
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
 -LINUX FOR POWERPC EMBEDDED MPC52XX
 +LINUX FOR POWERPC EMBEDDED MPC5XXX
  P:    Sylvain Munaut
  M:    tnt@246tNt.com
  P:    Grant Likely
  M:    grant.likely@secretlab.ca
 -W:    http://www.246tNt.com/mpc52xx/
 -W:    http://www.penguinppc.org/
  L:    linuxppc-dev@ozlabs.org
  S:    Maintained
  
diff --combined Makefile
+++ b/Makefile
@@@ -1,4 -1,3 +1,4 @@@
 +FRED=42
  VERSION = 2
  PATCHLEVEL = 6
  SUBLEVEL = 26
@@@ -451,7 -450,7 +451,7 @@@ scripts: scripts_basic include/config/a
  
  # Objects we will link into vmlinux / subdirs we need to visit
  init-y                := init/
- drivers-y     := drivers/ sound/
+ drivers-y     := drivers/ sound/ firmware/
  net-y         := net/
  libs-y                := lib/
  core-y                := usr/
@@@ -999,6 -998,16 +999,16 @@@ PHONY += depend de
  depend dep:
        @echo '*** Warning: make $@ is unnecessary now.'
  
+ # ---------------------------------------------------------------------------
+ # Firmware install
+ INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware
+ export INSTALL_FW_PATH
+ PHONY += firmware_install
+ firmware_install: FORCE
+       @mkdir -p $(objtree)/firmware
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install
  # ---------------------------------------------------------------------------
  # Kernel headers
  INSTALL_HDR_PATH=$(objtree)/usr
@@@ -1085,6 -1094,7 +1095,7 @@@ _modinst_
  # boot script depmod is the master version.
  PHONY += _modinst_post
  _modinst_post: _modinst_
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
        $(call cmd,depmod)
  
  else # CONFIG_MODULES
@@@ -1202,6 -1212,8 +1213,8 @@@ help
        @echo  '* vmlinux         - Build the bare kernel'
        @echo  '* modules         - Build all modules'
        @echo  '  modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
+       @echo  '  firmware_install- Install all firmware to INSTALL_FW_PATH'
+       @echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
        @echo  '  dir/            - Build all files in dir and below'
        @echo  '  dir/file.[ois]  - Build specified target only'
        @echo  '  dir/file.ko     - Build module including final link'
diff --combined arch/powerpc/Kconfig
@@@ -53,9 -53,6 +53,9 @@@ config STACKTRACE_SUPPOR
        bool
        default y
  
 +config HAVE_LATENCYTOP_SUPPORT
 +      def_bool y
 +
  config TRACE_IRQFLAGS_SUPPORT
        bool
        depends on PPC64
@@@ -114,7 -111,7 +114,8 @@@ config PP
        select HAVE_KPROBES
        select HAVE_KRETPROBES
        select HAVE_LMB
 +      select HAVE_DMA_ATTRS if PPC64
+       select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_OPROFILE
  
  config EARLY_PRINTK
@@@ -314,8 -311,8 +315,8 @@@ config KEXE
          strongly in flux, so no good recommendation can be made.
  
  config CRASH_DUMP
 -      bool "Build a kdump crash kernel (EXPERIMENTAL)"
 -      depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL
 +      bool "Build a kdump crash kernel"
 +      depends on PPC_MULTIPLATFORM && PPC64
        help
          Build a kernel suitable for use as a kdump capture kernel.
          The kernel will be linked at a different address than normal, and
@@@ -464,19 -461,6 +465,19 @@@ config CMDLIN
          some command-line options at build time by entering them here.  In
          most cases you will need to specify the root device here.
  
 +config EXTRA_TARGETS
 +      string "Additional default image types"
 +      help
 +        List additional targets to be built by the bootwrapper here (separated
 +        by spaces).  This is useful for targets that depend of device tree
 +        files in the .dts directory.
 +
 +        Targets in this list will be build as part of the default build
 +        target, or when the user does a 'make zImage' or a
 +        'make zImage.initrd'.
 +
 +        If unsure, leave blank
 +
  if !44x || BROKEN
  config ARCH_WANTS_FREEZER_CONTROL
        def_bool y
@@@ -557,12 -541,6 +558,12 @@@ config FSL_LB
        help
          Freescale Localbus support
  
 +config FSL_GTM
 +      bool
 +      depends on PPC_83xx || QUICC_ENGINE || CPM2
 +      help
 +        Freescale General-purpose Timers support
 +
  # Yes MCA RS/6000s exist but Linux-PPC does not currently support any
  config MCA
        bool
@@@ -158,7 -158,7 +158,7 @@@ void kexec_copy_flush(struct kimage *im
   * on calling the interrupts, but we would like to call it off irq level
   * so that the interrupt controller is clean.
   */
 -void kexec_smp_down(void *arg)
 +static void kexec_smp_down(void *arg)
  {
        if (ppc_md.kexec_cpu_down)
                ppc_md.kexec_cpu_down(0, 1);
@@@ -172,7 -172,7 +172,7 @@@ static void kexec_prepare_cpus(void
  {
        int my_cpu, i, notified=-1;
  
-       smp_call_function(kexec_smp_down, NULL, 0, /* wait */0);
+       smp_call_function(kexec_smp_down, NULL, /* wait */0);
        my_cpu = get_cpu();
  
        /* check the others cpus are now down (via paca hw cpu id == -1) */
@@@ -249,7 -249,7 +249,7 @@@ static void kexec_prepare_cpus(void
   * We could use a smaller stack if we don't care about anything using
   * current, but that audit has not been performed.
   */
 -union thread_union kexec_stack
 +static union thread_union kexec_stack
        __attribute__((__section__(".data.init_task"))) = { };
  
  /* Our assembly helper, in kexec_stub.S */
@@@ -340,8 -340,8 +340,8 @@@ int rtas_get_error_log_max(void
  EXPORT_SYMBOL(rtas_get_error_log_max);
  
  
 -char rtas_err_buf[RTAS_ERROR_LOG_MAX];
 -int rtas_last_error_token;
 +static char rtas_err_buf[RTAS_ERROR_LOG_MAX];
 +static int rtas_last_error_token;
  
  /** Return a copy of the detailed error text associated with the
   *  most recent failed call to rtas.  Because the error text
@@@ -484,7 -484,7 +484,7 @@@ unsigned int rtas_busy_delay(int status
  }
  EXPORT_SYMBOL(rtas_busy_delay);
  
 -int rtas_error_rc(int rtas_rc)
 +static int rtas_error_rc(int rtas_rc)
  {
        int rc;
  
@@@ -747,7 -747,7 +747,7 @@@ static int rtas_ibm_suspend_me(struct r
        /* Call function on all CPUs.  One of us will make the
         * rtas call
         */
-       if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
+       if (on_each_cpu(rtas_percpu_suspend_me, &data, 0))
                data.error = -EINVAL;
  
        wait_for_completion(&done);
@@@ -72,12 -72,8 +72,8 @@@ struct smp_ops_t *smp_ops
  
  static volatile unsigned int cpu_callin_map[NR_CPUS];
  
- void smp_call_function_interrupt(void);
  int smt_enabled_at_boot = 1;
  
- static int ipi_fail_ok;
  static void (*crash_ipi_function_ptr)(struct pt_regs *) = NULL;
  
  #ifdef CONFIG_PPC64
@@@ -99,12 -95,15 +95,15 @@@ void smp_message_recv(int msg
  {
        switch(msg) {
        case PPC_MSG_CALL_FUNCTION:
-               smp_call_function_interrupt();
+               generic_smp_call_function_interrupt();
                break;
        case PPC_MSG_RESCHEDULE:
                /* XXX Do we have to do this? */
                set_need_resched();
                break;
+       case PPC_MSG_CALL_FUNC_SINGLE:
+               generic_smp_call_function_single_interrupt();
+               break;
        case PPC_MSG_DEBUGGER_BREAK:
                if (crash_ipi_function_ptr) {
                        crash_ipi_function_ptr(get_irq_regs());
@@@ -128,6 -127,19 +127,19 @@@ void smp_send_reschedule(int cpu
                smp_ops->message_pass(cpu, PPC_MSG_RESCHEDULE);
  }
  
+ void arch_send_call_function_single_ipi(int cpu)
+ {
+       smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNC_SINGLE);
+ }
+ void arch_send_call_function_ipi(cpumask_t mask)
+ {
+       unsigned int cpu;
+       for_each_cpu_mask(cpu, mask)
+               smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
+ }
  #ifdef CONFIG_DEBUGGER
  void smp_send_debugger_break(int cpu)
  {
@@@ -154,219 -166,17 +166,13 @@@ static void stop_this_cpu(void *dummy
                ;
  }
  
- /*
-  * Structure and data for smp_call_function(). This is designed to minimise
-  * static memory requirements. It also looks cleaner.
-  * Stolen from the i386 version.
-  */
- static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(call_lock);
- static struct call_data_struct {
-       void (*func) (void *info);
-       void *info;
-       atomic_t started;
-       atomic_t finished;
-       int wait;
- } *call_data;
- /* delay of at least 8 seconds */
- #define SMP_CALL_TIMEOUT      8
- /*
-  * These functions send a 'generic call function' IPI to other online
-  * CPUS in the system.
-  *
-  * [SUMMARY] Run a function on other CPUs.
-  * <func> The function to run. This must be fast and non-blocking.
-  * <info> An arbitrary pointer to pass to the function.
-  * <nonatomic> currently unused.
-  * <wait> If true, wait (atomically) until function has completed on other CPUs.
-  * [RETURNS] 0 on success, else a negative status code. Does not return until
-  * remote CPUs are nearly ready to execute <<func>> or are or have executed.
-  * <map> is a cpu map of the cpus to send IPI to.
-  *
-  * You must not call this function with disabled interrupts or from a
-  * hardware interrupt handler or from a bottom half handler.
-  */
- static int __smp_call_function_map(void (*func) (void *info), void *info,
-                                  int nonatomic, int wait, cpumask_t map)
- {
-       struct call_data_struct data;
-       int ret = -1, num_cpus;
-       int cpu;
-       u64 timeout;
-       if (unlikely(smp_ops == NULL))
-               return ret;
-       data.func = func;
-       data.info = info;
-       atomic_set(&data.started, 0);
-       data.wait = wait;
-       if (wait)
-               atomic_set(&data.finished, 0);
-       /* remove 'self' from the map */
-       if (cpu_isset(smp_processor_id(), map))
-               cpu_clear(smp_processor_id(), map);
-       /* sanity check the map, remove any non-online processors. */
-       cpus_and(map, map, cpu_online_map);
-       num_cpus = cpus_weight(map);
-       if (!num_cpus)
-               goto done;
-       call_data = &data;
-       smp_wmb();
-       /* Send a message to all CPUs in the map */
-       for_each_cpu_mask(cpu, map)
-               smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION);
-       timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec;
-       /* Wait for indication that they have received the message */
-       while (atomic_read(&data.started) != num_cpus) {
-               HMT_low();
-               if (get_tb() >= timeout) {
-                       printk("smp_call_function on cpu %d: other cpus not "
-                               "responding (%d)\n", smp_processor_id(),
-                               atomic_read(&data.started));
-                       if (!ipi_fail_ok)
-                               debugger(NULL);
-                       goto out;
-               }
-       }
-       /* optionally wait for the CPUs to complete */
-       if (wait) {
-               while (atomic_read(&data.finished) != num_cpus) {
-                       HMT_low();
-                       if (get_tb() >= timeout) {
-                               printk("smp_call_function on cpu %d: other "
-                                       "cpus not finishing (%d/%d)\n",
-                                       smp_processor_id(),
-                                       atomic_read(&data.finished),
-                                       atomic_read(&data.started));
-                               debugger(NULL);
-                               goto out;
-                       }
-               }
-       }
-  done:
-       ret = 0;
-  out:
-       call_data = NULL;
-       HMT_medium();
-       return ret;
- }
- static int __smp_call_function(void (*func)(void *info), void *info,
-                              int nonatomic, int wait)
- {
-       int ret;
-       spin_lock(&call_lock);
-       ret =__smp_call_function_map(func, info, nonatomic, wait,
-                                      cpu_online_map);
-       spin_unlock(&call_lock);
-       return ret;
- }
- int smp_call_function(void (*func) (void *info), void *info, int nonatomic,
-                       int wait)
- {
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-       return __smp_call_function(func, info, nonatomic, wait);
- }
- EXPORT_SYMBOL(smp_call_function);
- int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
-                            int nonatomic, int wait)
- {
-       cpumask_t map = CPU_MASK_NONE;
-       int ret = 0;
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON(irqs_disabled());
-       if (!cpu_online(cpu))
-               return -EINVAL;
-       cpu_set(cpu, map);
-       if (cpu != get_cpu()) {
-               spin_lock(&call_lock);
-               ret = __smp_call_function_map(func, info, nonatomic, wait, map);
-               spin_unlock(&call_lock);
-       } else {
-               local_irq_disable();
-               func(info);
-               local_irq_enable();
-       }
-       put_cpu();
-       return ret;
- }
- EXPORT_SYMBOL(smp_call_function_single);
  void smp_send_stop(void)
  {
-       int nolock;
-       /* It's OK to fail sending the IPI, since the alternative is to
-        * be stuck forever waiting on the other CPU to take the interrupt.
-        *
-        * It's better to at least continue and go through reboot, since this
-        * function is usually called at panic or reboot time in the first
-        * place.
-        */
-       ipi_fail_ok = 1;
-       /* Don't deadlock in case we got called through panic */
-       nolock = !spin_trylock(&call_lock);
-       __smp_call_function_map(stop_this_cpu, NULL, 1, 0, cpu_online_map);
-       if (!nolock)
-               spin_unlock(&call_lock);
- }
- void smp_call_function_interrupt(void)
- {
-       void (*func) (void *info);
-       void *info;
-       int wait;
-       /* call_data will be NULL if the sender timed out while
-        * waiting on us to receive the call.
-        */
-       if (!call_data)
-               return;
-       func = call_data->func;
-       info = call_data->info;
-       wait = call_data->wait;
-       if (!wait)
-               smp_mb__before_atomic_inc();
-       /*
-        * Notify initiating CPU that I've grabbed the data and am
-        * about to execute the function
-        */
-       atomic_inc(&call_data->started);
-       /*
-        * At this point the info structure may be out of scope unless wait==1
-        */
-       (*func)(info);
-       if (wait) {
-               smp_mb__before_atomic_inc();
-               atomic_inc(&call_data->finished);
-       }
+       smp_call_function(stop_this_cpu, NULL, 0);
  }
  
 -extern struct gettimeofday_struct do_gtod;
 -
  struct thread_info *current_set[NR_CPUS];
  
 -DECLARE_PER_CPU(unsigned int, pvr);
 -
  static void __devinit smp_store_cpu_info(int id)
  {
        per_cpu(pvr, id) = mfspr(SPRN_PVR);
@@@ -592,9 -402,9 +398,9 @@@ int __devinit start_secondary(void *unu
  
        secondary_cpu_time_init();
  
-       spin_lock(&call_lock);
+       ipi_call_lock();
        cpu_set(cpu, cpu_online_map);
-       spin_unlock(&call_lock);
+       ipi_call_unlock();
  
        local_irq_enable();
  
   *      2 of the License, or (at your option) any later version.
   */
  
 +#include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/stacktrace.h>
+ #include <linux/module.h>
  #include <asm/ptrace.h>
 +#include <asm/processor.h>
  
  /*
   * Save stack-backtrace addresses into a stack_trace buffer.
   */
 -void save_stack_trace(struct stack_trace *trace)
 +static void save_context_stack(struct stack_trace *trace, unsigned long sp,
 +                      struct task_struct *tsk, int savesched)
  {
 -      unsigned long sp;
 -
 -      asm("mr %0,1" : "=r" (sp));
 -
        for (;;) {
                unsigned long *stack = (unsigned long *) sp;
                unsigned long newsp, ip;
  
 -              if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
 +              if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
                        return;
  
                newsp = stack[0];
                ip = stack[STACK_FRAME_LR_SAVE];
  
 -              if (!trace->skip)
 -                      trace->entries[trace->nr_entries++] = ip;
 -              else
 -                      trace->skip--;
 +              if (savesched || !in_sched_functions(ip)) {
 +                      if (!trace->skip)
 +                              trace->entries[trace->nr_entries++] = ip;
 +                      else
 +                              trace->skip--;
 +              }
  
                if (trace->nr_entries >= trace->max_entries)
                        return;
                sp = newsp;
        }
  }
 +
 +void save_stack_trace(struct stack_trace *trace)
 +{
 +      unsigned long sp;
 +
 +      asm("mr %0,1" : "=r" (sp));
 +
 +      save_context_stack(trace, sp, current, 1);
 +}
  EXPORT_SYMBOL_GPL(save_stack_trace);
 +
 +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 +{
 +      save_context_stack(trace, tsk->thread.regs->gpr[1], tsk, 0);
 +}
 +EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
@@@ -129,7 -129,7 +129,7 @@@ static unsigned long __initdata iSeries
  static signed long __initdata iSeries_recal_tb;
  
  /* Forward declaration is only needed for iSereis compiles */
 -void __init clocksource_init(void);
 +static void __init clocksource_init(void);
  #endif
  
  #define XSEC_PER_SEC (1024*1024)
@@@ -150,8 -150,8 +150,8 @@@ u64 tb_to_xs
  unsigned tb_to_us;
  
  #define TICKLEN_SCALE NTP_SCALE_SHIFT
 -u64 last_tick_len;    /* units are ns / 2^TICKLEN_SCALE */
 -u64 ticklen_to_xs;    /* 0.64 fraction */
 +static u64 last_tick_len;     /* units are ns / 2^TICKLEN_SCALE */
 +static u64 ticklen_to_xs;     /* 0.64 fraction */
  
  /* If last_tick_len corresponds to about 1/HZ seconds, then
     last_tick_len << TICKLEN_SHIFT will be about 2^63. */
@@@ -164,7 -164,7 +164,7 @@@ static u64 tb_to_ns_scale __read_mostly
  static unsigned tb_to_ns_shift __read_mostly;
  static unsigned long boot_tb __read_mostly;
  
 -struct gettimeofday_struct do_gtod;
 +static struct gettimeofday_struct do_gtod;
  
  extern struct timezone sys_tz;
  static long timezone_offset;
@@@ -322,7 -322,7 +322,7 @@@ void snapshot_timebases(void
  {
        if (!cpu_has_feature(CPU_FTR_PURR))
                return;
-       on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1);
+       on_each_cpu(snapshot_tb_and_purr, NULL, 1);
  }
  
  /*
@@@ -742,6 -742,10 +742,6 @@@ void __init generic_calibrate_decr(void
        }
  
  #if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
 -      /* Set the time base to zero */
 -      mtspr(SPRN_TBWL, 0);
 -      mtspr(SPRN_TBWU, 0);
 -
        /* Clear any pending timer interrupts */
        mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
  
@@@ -828,7 -832,7 +828,7 @@@ void update_vsyscall_tz(void
        ++vdso_data->tb_update_count;
  }
  
 -void __init clocksource_init(void)
 +static void __init clocksource_init(void)
  {
        struct clocksource *clock;
  
diff --combined arch/powerpc/mm/slice.c
@@@ -215,7 -215,10 +215,7 @@@ static void slice_convert(struct mm_str
                  mm->context.high_slices_psize);
  
        spin_unlock_irqrestore(&slice_convert_lock, flags);
 -      mb();
  
 -      /* XXX this is sub-optimal but will do for now */
 -      on_each_cpu(slice_flush_segments, mm, 1);
  #ifdef CONFIG_SPU_BASE
        spu_flush_all_slbs(mm);
  #endif
@@@ -381,34 -384,17 +381,34 @@@ static unsigned long slice_find_area(st
                return slice_find_area_bottomup(mm, len, mask, psize, use_cache);
  }
  
 +#define or_mask(dst, src)     do {                    \
 +      (dst).low_slices |= (src).low_slices;           \
 +      (dst).high_slices |= (src).high_slices;         \
 +} while (0)
 +
 +#define andnot_mask(dst, src) do {                    \
 +      (dst).low_slices &= ~(src).low_slices;          \
 +      (dst).high_slices &= ~(src).high_slices;        \
 +} while (0)
 +
 +#ifdef CONFIG_PPC_64K_PAGES
 +#define MMU_PAGE_BASE MMU_PAGE_64K
 +#else
 +#define MMU_PAGE_BASE MMU_PAGE_4K
 +#endif
 +
  unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
                                      unsigned long flags, unsigned int psize,
                                      int topdown, int use_cache)
  {
 -      struct slice_mask mask;
 +      struct slice_mask mask = {0, 0};
        struct slice_mask good_mask;
        struct slice_mask potential_mask = {0,0} /* silence stupid warning */;
 -      int pmask_set = 0;
 +      struct slice_mask compat_mask = {0, 0};
        int fixed = (flags & MAP_FIXED);
        int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
        struct mm_struct *mm = current->mm;
 +      unsigned long newaddr;
  
        /* Sanity checks */
        BUG_ON(mm->task_size == 0);
        if (!fixed && addr) {
                addr = _ALIGN_UP(addr, 1ul << pshift);
                slice_dbg(" aligned addr=%lx\n", addr);
 +              /* Ignore hint if it's too large or overlaps a VMA */
 +              if (addr > mm->task_size - len ||
 +                  !slice_area_is_free(mm, addr, len))
 +                      addr = 0;
        }
  
 -      /* First makeup a "good" mask of slices that have the right size
 +      /* First make up a "good" mask of slices that have the right size
         * already
         */
        good_mask = slice_mask_for_size(mm, psize);
        slice_print_mask(" good_mask", good_mask);
  
 -      /* First check hint if it's valid or if we have MAP_FIXED */
 -      if ((addr != 0 || fixed) && (mm->task_size - len) >= addr) {
 +      /*
 +       * Here "good" means slices that are already the right page size,
 +       * "compat" means slices that have a compatible page size (i.e.
 +       * 4k in a 64k pagesize kernel), and "free" means slices without
 +       * any VMAs.
 +       *
 +       * If MAP_FIXED:
 +       *      check if fits in good | compat => OK
 +       *      check if fits in good | compat | free => convert free
 +       *      else bad
 +       * If have hint:
 +       *      check if hint fits in good => OK
 +       *      check if hint fits in good | free => convert free
 +       * Otherwise:
 +       *      search in good, found => OK
 +       *      search in good | free, found => convert free
 +       *      search in good | compat | free, found => convert free.
 +       */
  
 -              /* Don't bother with hint if it overlaps a VMA */
 -              if (!fixed && !slice_area_is_free(mm, addr, len))
 -                      goto search;
 +#ifdef CONFIG_PPC_64K_PAGES
 +      /* If we support combo pages, we can allow 64k pages in 4k slices */
 +      if (psize == MMU_PAGE_64K) {
 +              compat_mask = slice_mask_for_size(mm, MMU_PAGE_4K);
 +              if (fixed)
 +                      or_mask(good_mask, compat_mask);
 +      }
 +#endif
  
 +      /* First check hint if it's valid or if we have MAP_FIXED */
 +      if (addr != 0 || fixed) {
                /* Build a mask for the requested range */
                mask = slice_range_to_mask(addr, len);
                slice_print_mask(" mask", mask);
                        slice_dbg(" fits good !\n");
                        return addr;
                }
 -
 -              /* We don't fit in the good mask, check what other slices are
 -               * empty and thus can be converted
 +      } else {
 +              /* Now let's see if we can find something in the existing
 +               * slices for that size
                 */
 -              potential_mask = slice_mask_for_free(mm);
 -              potential_mask.low_slices |= good_mask.low_slices;
 -              potential_mask.high_slices |= good_mask.high_slices;
 -              pmask_set = 1;
 -              slice_print_mask(" potential", potential_mask);
 -              if (slice_check_fit(mask, potential_mask)) {
 -                      slice_dbg(" fits potential !\n");
 -                      goto convert;
 +              newaddr = slice_find_area(mm, len, good_mask, psize, topdown,
 +                                        use_cache);
 +              if (newaddr != -ENOMEM) {
 +                      /* Found within the good mask, we don't have to setup,
 +                       * we thus return directly
 +                       */
 +                      slice_dbg(" found area at 0x%lx\n", newaddr);
 +                      return newaddr;
                }
        }
  
 -      /* If we have MAP_FIXED and failed the above step, then error out */
 +      /* We don't fit in the good mask, check what other slices are
 +       * empty and thus can be converted
 +       */
 +      potential_mask = slice_mask_for_free(mm);
 +      or_mask(potential_mask, good_mask);
 +      slice_print_mask(" potential", potential_mask);
 +
 +      if ((addr != 0 || fixed) && slice_check_fit(mask, potential_mask)) {
 +              slice_dbg(" fits potential !\n");
 +              goto convert;
 +      }
 +
 +      /* If we have MAP_FIXED and failed the above steps, then error out */
        if (fixed)
                return -EBUSY;
  
 - search:
        slice_dbg(" search...\n");
  
 -      /* Now let's see if we can find something in the existing slices
 -       * for that size
 +      /* If we had a hint that didn't work out, see if we can fit
 +       * anywhere in the good area.
         */
 -      addr = slice_find_area(mm, len, good_mask, psize, topdown, use_cache);
 -      if (addr != -ENOMEM) {
 -              /* Found within the good mask, we don't have to setup,
 -               * we thus return directly
 -               */
 -              slice_dbg(" found area at 0x%lx\n", addr);
 -              return addr;
 -      }
 -
 -      /* Won't fit, check what can be converted */
 -      if (!pmask_set) {
 -              potential_mask = slice_mask_for_free(mm);
 -              potential_mask.low_slices |= good_mask.low_slices;
 -              potential_mask.high_slices |= good_mask.high_slices;
 -              pmask_set = 1;
 -              slice_print_mask(" potential", potential_mask);
 +      if (addr) {
 +              addr = slice_find_area(mm, len, good_mask, psize, topdown,
 +                                     use_cache);
 +              if (addr != -ENOMEM) {
 +                      slice_dbg(" found area at 0x%lx\n", addr);
 +                      return addr;
 +              }
        }
  
        /* Now let's see if we can find something in the existing slices
 -       * for that size
 +       * for that size plus free slices
         */
        addr = slice_find_area(mm, len, potential_mask, psize, topdown,
                               use_cache);
 +
 +#ifdef CONFIG_PPC_64K_PAGES
 +      if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
 +              /* retry the search with 4k-page slices included */
 +              or_mask(potential_mask, compat_mask);
 +              addr = slice_find_area(mm, len, potential_mask, psize,
 +                                     topdown, use_cache);
 +      }
 +#endif
 +
        if (addr == -ENOMEM)
                return -ENOMEM;
  
        slice_print_mask(" mask", mask);
  
   convert:
 -      slice_convert(mm, mask, psize);
 +      andnot_mask(mask, good_mask);
 +      andnot_mask(mask, compat_mask);
 +      if (mask.low_slices || mask.high_slices) {
 +              slice_convert(mm, mask, psize);
 +              if (psize > MMU_PAGE_BASE)
-                       on_each_cpu(slice_flush_segments, mm, 0, 1);
++                      on_each_cpu(slice_flush_segments, mm, 1);
 +      }
        return addr;
  
  }
@@@ -657,36 -598,6 +657,36 @@@ void slice_set_user_psize(struct mm_str
        spin_unlock_irqrestore(&slice_convert_lock, flags);
  }
  
 +void slice_set_psize(struct mm_struct *mm, unsigned long address,
 +                   unsigned int psize)
 +{
 +      unsigned long i, flags;
 +      u64 *p;
 +
 +      spin_lock_irqsave(&slice_convert_lock, flags);
 +      if (address < SLICE_LOW_TOP) {
 +              i = GET_LOW_SLICE_INDEX(address);
 +              p = &mm->context.low_slices_psize;
 +      } else {
 +              i = GET_HIGH_SLICE_INDEX(address);
 +              p = &mm->context.high_slices_psize;
 +      }
 +      *p = (*p & ~(0xful << (i * 4))) | ((unsigned long) psize << (i * 4));
 +      spin_unlock_irqrestore(&slice_convert_lock, flags);
 +
 +#ifdef CONFIG_SPU_BASE
 +      spu_flush_all_slbs(mm);
 +#endif
 +}
 +
 +void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 +                         unsigned long len, unsigned int psize)
 +{
 +      struct slice_mask mask = slice_range_to_mask(start, len);
 +
 +      slice_convert(mm, mask, psize);
 +}
 +
  /*
   * is_hugepage_only_range() is used by generic code to verify wether
   * a normal mmap mapping (non hugetlbfs) is valid on a given area.
diff --combined arch/powerpc/mm/tlb_64.c
@@@ -37,8 -37,8 +37,8 @@@ DEFINE_PER_CPU(struct ppc64_tlb_batch, 
   * include/asm-powerpc/tlb.h file -- tgall
   */
  DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 -DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 -unsigned long pte_freelist_forced_free;
 +static DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 +static unsigned long pte_freelist_forced_free;
  
  struct pte_freelist_batch
  {
@@@ -47,6 -47,9 +47,6 @@@
        pgtable_free_t  tables[0];
  };
  
 -DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur);
 -unsigned long pte_freelist_forced_free;
 -
  #define PTE_FREELIST_SIZE \
        ((PAGE_SIZE - sizeof(struct pte_freelist_batch)) \
          / sizeof(pgtable_free_t))
@@@ -63,7 -66,7 +63,7 @@@ static void pgtable_free_now(pgtable_fr
  {
        pte_freelist_forced_free++;
  
-       smp_call_function(pte_free_smp_sync, NULL, 0, 1);
+       smp_call_function(pte_free_smp_sync, NULL, 1);
  
        pgtable_free(pgf);
  }
@@@ -1016,11 -1016,13 +1016,11 @@@ struct mpic * __init mpic_alloc(struct 
        memset(mpic, 0, sizeof(struct mpic));
        mpic->name = name;
  
 -      mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
 +      mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
                                       isu_size, &mpic_host_ops,
                                       flags & MPIC_LARGE_VECTORS ? 2048 : 256);
 -      if (mpic->irqhost == NULL) {
 -              of_node_put(node);
 +      if (mpic->irqhost == NULL)
                return NULL;
 -      }
  
        mpic->irqhost->host_data = mpic;
        mpic->hc_irq = mpic_irq_chip;
        greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
        mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
                          >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
 -      if (isu_size == 0)
 -              mpic->num_sources =
 -                      ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
 -                       >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 +      if (isu_size == 0) {
 +              if (flags & MPIC_BROKEN_FRR_NIRQS)
 +                      mpic->num_sources = mpic->irq_count;
 +              else
 +                      mpic->num_sources =
 +                              ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
 +                               >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
 +      }
  
        /* Map the per-CPU registers */
        for (i = 0; i < mpic->num_cpus; i++) {
@@@ -1496,7 -1494,7 +1496,7 @@@ void mpic_request_ipis(void
        static char *ipi_names[] = {
                "IPI0 (call function)",
                "IPI1 (reschedule)",
-               "IPI2 (unused)",
+               "IPI2 (call function single)",
                "IPI3 (debugger break)",
        };
        BUG_ON(mpic == NULL);
@@@ -17,8 -17,7 +17,8 @@@
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/init.h>
 -#include <linux/platform_device.h>
 +#include <linux/of_platform.h>
 +#include <linux/of_i2c.h>
  
  #include <asm/io.h>
  #include <linux/fsl_devices.h>
  #include <linux/interrupt.h>
  #include <linux/delay.h>
  
 -#define MPC_I2C_ADDR  0x00
 +#define DRV_NAME "mpc-i2c"
 +
  #define MPC_I2C_FDR   0x04
  #define MPC_I2C_CR    0x08
  #define MPC_I2C_SR    0x0c
  #define MPC_I2C_DR    0x10
  #define MPC_I2C_DFSRR 0x14
 -#define MPC_I2C_REGION 0x20
  
  #define CCR_MEN  0x80
  #define CCR_MIEN 0x40
@@@ -312,121 -311,106 +312,121 @@@ static struct i2c_adapter mpc_ops = 
        .name = "MPC adapter",
        .id = I2C_HW_MPC107,
        .algo = &mpc_algo,
-       .class = I2C_CLASS_HWMON,
+       .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .timeout = 1,
  };
  
 -static int fsl_i2c_probe(struct platform_device *pdev)
 +static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match)
  {
        int result = 0;
        struct mpc_i2c *i2c;
 -      struct fsl_i2c_platform_data *pdata;
 -      struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 -
 -      pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
  
        i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
        if (!i2c)
                return -ENOMEM;
  
 -      i2c->irq = platform_get_irq(pdev, 0);
 -      if (i2c->irq < 0)
 -              i2c->irq = NO_IRQ; /* Use polling */
 +      if (of_get_property(op->node, "dfsrr", NULL))
 +              i2c->flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
  
 -      i2c->flags = pdata->device_flags;
 -      init_waitqueue_head(&i2c->queue);
 +      if (of_device_is_compatible(op->node, "fsl,mpc5200-i2c") ||
 +                      of_device_is_compatible(op->node, "mpc5200-i2c"))
 +              i2c->flags |= FSL_I2C_DEV_CLOCK_5200;
  
 -      i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
 +      init_waitqueue_head(&i2c->queue);
  
 +      i2c->base = of_iomap(op->node, 0);
        if (!i2c->base) {
                printk(KERN_ERR "i2c-mpc - failed to map controller\n");
                result = -ENOMEM;
                goto fail_map;
        }
  
 -      if (i2c->irq != NO_IRQ)
 -              if ((result = request_irq(i2c->irq, mpc_i2c_isr,
 -                                        IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
 -                      printk(KERN_ERR
 -                             "i2c-mpc - failed to attach interrupt\n");
 -                      goto fail_irq;
 +      i2c->irq = irq_of_parse_and_map(op->node, 0);
 +      if (i2c->irq != NO_IRQ) { /* i2c->irq = NO_IRQ implies polling */
 +              result = request_irq(i2c->irq, mpc_i2c_isr,
 +                                   IRQF_SHARED, "i2c-mpc", i2c);
 +              if (result < 0) {
 +                      printk(KERN_ERR "i2c-mpc - failed to attach interrupt\n");
 +                      goto fail_request;
                }
 -
 +      }
 +      
        mpc_i2c_setclock(i2c);
 -      platform_set_drvdata(pdev, i2c);
 +
 +      dev_set_drvdata(&op->dev, i2c);
  
        i2c->adap = mpc_ops;
 -      i2c->adap.nr = pdev->id;
        i2c_set_adapdata(&i2c->adap, i2c);
 -      i2c->adap.dev.parent = &pdev->dev;
 -      if ((result = i2c_add_numbered_adapter(&i2c->adap)) < 0) {
 +      i2c->adap.dev.parent = &op->dev;
 +
 +      result = i2c_add_adapter(&i2c->adap);
 +      if (result < 0) {
                printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
                goto fail_add;
        }
 +      of_register_i2c_devices(&i2c->adap, op->node);
  
        return result;
  
 -      fail_add:
 -      if (i2c->irq != NO_IRQ)
 -              free_irq(i2c->irq, i2c);
 -      fail_irq:
 -      iounmap(i2c->base);
 -      fail_map:
 + fail_add:
 +      dev_set_drvdata(&op->dev, NULL);
 +      free_irq(i2c->irq, i2c);
 + fail_request:
 +      irq_dispose_mapping(i2c->irq);
 +      iounmap(i2c->base);
 + fail_map:
        kfree(i2c);
        return result;
  };
  
 -static int fsl_i2c_remove(struct platform_device *pdev)
 +static int __devexit fsl_i2c_remove(struct of_device *op)
  {
 -      struct mpc_i2c *i2c = platform_get_drvdata(pdev);
 +      struct mpc_i2c *i2c = dev_get_drvdata(&op->dev);
  
        i2c_del_adapter(&i2c->adap);
 -      platform_set_drvdata(pdev, NULL);
 +      dev_set_drvdata(&op->dev, NULL);
  
        if (i2c->irq != NO_IRQ)
                free_irq(i2c->irq, i2c);
  
 +      irq_dispose_mapping(i2c->irq);
        iounmap(i2c->base);
        kfree(i2c);
        return 0;
  };
  
 -/* work with hotplug and coldplug */
 -MODULE_ALIAS("platform:fsl-i2c");
 +static const struct of_device_id mpc_i2c_of_match[] = {
 +      {.compatible = "fsl-i2c",},
 +      {},
 +};
 +MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
 +
  
  /* Structure for a device driver */
 -static struct platform_driver fsl_i2c_driver = {
 -      .probe = fsl_i2c_probe,
 -      .remove = fsl_i2c_remove,
 -      .driver = {
 -              .owner = THIS_MODULE,
 -              .name = "fsl-i2c",
 +static struct of_platform_driver mpc_i2c_driver = {
 +      .match_table    = mpc_i2c_of_match,
 +      .probe          = fsl_i2c_probe,
 +      .remove         = __devexit_p(fsl_i2c_remove),
 +      .driver         = {
 +              .owner  = THIS_MODULE,
 +              .name   = DRV_NAME,
        },
  };
  
  static int __init fsl_i2c_init(void)
  {
 -      return platform_driver_register(&fsl_i2c_driver);
 +      int rv;
 +
 +      rv = of_register_platform_driver(&mpc_i2c_driver);
 +      if (rv)
 +              printk(KERN_ERR DRV_NAME 
 +                     " of_register_platform_driver failed (%i)\n", rv);
 +      return rv;
  }
  
  static void __exit fsl_i2c_exit(void)
  {
 -      platform_driver_unregister(&fsl_i2c_driver);
 +      of_unregister_platform_driver(&mpc_i2c_driver);
  }
  
  module_init(fsl_i2c_init);
@@@ -37,8 -37,6 +37,8 @@@ extern void cpu_die(void)
  extern void smp_send_debugger_break(int cpu);
  extern void smp_message_recv(int);
  
 +DECLARE_PER_CPU(unsigned int, pvr);
 +
  #ifdef CONFIG_HOTPLUG_CPU
  extern void fixup_irqs(cpumask_t map);
  int generic_cpu_disable(void);
@@@ -69,10 -67,7 +69,7 @@@ DECLARE_PER_CPU(cpumask_t, cpu_sibling_
   * in /proc/interrupts will be wrong!!! --Troy */
  #define PPC_MSG_CALL_FUNCTION   0
  #define PPC_MSG_RESCHEDULE      1
- /* This is unused now */
- #if 0
- #define PPC_MSG_MIGRATE_TASK    2
- #endif
+ #define PPC_MSG_CALL_FUNC_SINGLE      2
  #define PPC_MSG_DEBUGGER_BREAK  3
  
  void smp_init_iSeries(void);
@@@ -119,6 -114,9 +116,9 @@@ extern void smp_generic_take_timebase(v
  
  extern struct smp_ops_t *smp_ops;
  
+ extern void arch_send_call_function_single_ipi(int cpu);
+ extern void arch_send_call_function_ipi(cpumask_t mask);
  #endif /* __ASSEMBLY__ */
  
  #endif /* __KERNEL__ */