Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / arch / ia64 / kernel / perfmon.c
index 410d480..c7ccd6e 100644 (file)
@@ -19,7 +19,6 @@
  *     http://www.hpl.hp.com/research/linux/perfmon
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -38,7 +37,9 @@
 #include <linux/pagemap.h>
 #include <linux/mount.h>
 #include <linux/bitops.h>
+#include <linux/capability.h>
 #include <linux/rcupdate.h>
+#include <linux/completion.h>
 
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
@@ -285,7 +286,7 @@ typedef struct pfm_context {
 
        unsigned long           ctx_ovfl_regs[4];       /* which registers overflowed (notification) */
 
-       struct semaphore        ctx_restart_sem;        /* use for blocking notification mode */
+       struct completion       ctx_restart_done;       /* use for blocking notification mode */
 
        unsigned long           ctx_used_pmds[4];       /* bitmask of PMD used            */
        unsigned long           ctx_all_pmds[4];        /* bitmask of all accessible PMDs */
@@ -530,7 +531,6 @@ static ctl_table pfm_sysctl_root[] = {
 static struct ctl_table_header *pfm_sysctl_header;
 
 static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
-static int pfm_flush(struct file *filp);
 
 #define pfm_get_cpu_var(v)             __ia64_per_cpu_var(v)
 #define pfm_get_cpu_data(a,b)          per_cpu(a, b)
@@ -593,10 +593,11 @@ pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 }
 
 
-static struct super_block *
-pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
+static int
+pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
+            struct vfsmount *mnt)
 {
-       return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC);
+       return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt);
 }
 
 static struct file_system_type pfm_fs_type = {
@@ -627,9 +628,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count,
 
 #include "perfmon_itanium.h"
 #include "perfmon_mckinley.h"
+#include "perfmon_montecito.h"
 #include "perfmon_generic.h"
 
 static pmu_config_t *pmu_confs[]={
+       &pmu_conf_mont,
        &pmu_conf_mck,
        &pmu_conf_ita,
        &pmu_conf_gen, /* must be last */
@@ -1709,7 +1712,7 @@ static void
 pfm_syswide_force_stop(void *info)
 {
        pfm_context_t   *ctx = (pfm_context_t *)info;
-       struct pt_regs *regs = ia64_task_regs(current);
+       struct pt_regs *regs = task_pt_regs(current);
        struct task_struct *owner;
        unsigned long flags;
        int ret;
@@ -1769,7 +1772,7 @@ pfm_syswide_cleanup_other_cpu(pfm_context_t *ctx)
  * When caller is self-monitoring, the context is unloaded.
  */
 static int
-pfm_flush(struct file *filp)
+pfm_flush(struct file *filp, fl_owner_t id)
 {
        pfm_context_t *ctx;
        struct task_struct *task;
@@ -1814,7 +1817,7 @@ pfm_flush(struct file *filp)
        is_system = ctx->ctx_fl_system;
 
        task = PFM_CTX_TASK(ctx);
-       regs = ia64_task_regs(task);
+       regs = task_pt_regs(task);
 
        DPRINT(("ctx_state=%d is_current=%d\n",
                state,
@@ -1944,7 +1947,7 @@ pfm_close(struct inode *inode, struct file *filp)
        is_system = ctx->ctx_fl_system;
 
        task = PFM_CTX_TASK(ctx);
-       regs = ia64_task_regs(task);
+       regs = task_pt_regs(task);
 
        DPRINT(("ctx_state=%d is_current=%d\n", 
                state,
@@ -1988,7 +1991,7 @@ pfm_close(struct inode *inode, struct file *filp)
                /*
                 * force task to wake up from MASKED state
                 */
-               up(&ctx->ctx_restart_sem);
+               complete(&ctx->ctx_restart_done);
 
                DPRINT(("waking up ctx_state=%d\n", state));
 
@@ -2703,7 +2706,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
        /*
         * init restart semaphore to locked
         */
-       sema_init(&ctx->ctx_restart_sem, 0);
+       init_completion(&ctx->ctx_restart_done);
 
        /*
         * activation is used in SMP only
@@ -3684,7 +3687,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
         */
        if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) {
                DPRINT(("unblocking [%d] \n", task->pid));
-               up(&ctx->ctx_restart_sem);
+               complete(&ctx->ctx_restart_done);
        } else {
                DPRINT(("[%d] armed exit trap\n", task->pid));
 
@@ -4051,7 +4054,7 @@ pfm_stop(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                 */
                ia64_psr(regs)->up = 0;
        } else {
-               tregs = ia64_task_regs(task);
+               tregs = task_pt_regs(task);
 
                /*
                 * stop monitoring at the user level
@@ -4133,7 +4136,7 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                ia64_psr(regs)->up = 1;
 
        } else {
-               tregs = ia64_task_regs(ctx->ctx_task);
+               tregs = task_pt_regs(ctx->ctx_task);
 
                /*
                 * start monitoring at the kernel level the next
@@ -4403,7 +4406,7 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                /*
                 * when not current, task MUST be stopped, so this is safe
                 */
-               regs = ia64_task_regs(task);
+               regs = task_pt_regs(task);
 
                /* force a full reload */
                ctx->ctx_last_activation = PFM_INVALID_ACTIVATION;
@@ -4529,7 +4532,7 @@ pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg
        /*
         * per-task mode
         */
-       tregs = task == current ? regs : ia64_task_regs(task);
+       tregs = task == current ? regs : task_pt_regs(task);
 
        if (task == current) {
                /*
@@ -4592,7 +4595,7 @@ pfm_exit_thread(struct task_struct *task)
 {
        pfm_context_t *ctx;
        unsigned long flags;
-       struct pt_regs *regs = ia64_task_regs(task);
+       struct pt_regs *regs = task_pt_regs(task);
        int ret, state;
        int free_ok = 0;
 
@@ -4925,7 +4928,7 @@ restart_args:
        if (unlikely(ret)) goto abort_locked;
 
 skip_fd:
-       ret = (*func)(ctx, args_k, count, ia64_task_regs(current));
+       ret = (*func)(ctx, args_k, count, task_pt_regs(current));
 
        call_made = 1;
 
@@ -5049,7 +5052,7 @@ pfm_handle_work(void)
 
        pfm_clear_task_notify();
 
-       regs = ia64_task_regs(current);
+       regs = task_pt_regs(current);
 
        /*
         * extract reason for being here and clear
@@ -5086,7 +5089,7 @@ pfm_handle_work(void)
         * may go through without blocking on SMP systems
         * if restart has been received already by the time we call down()
         */
-       ret = down_interruptible(&ctx->ctx_restart_sem);
+       ret = wait_for_completion_interruptible(&ctx->ctx_restart_done);
 
        DPRINT(("after block sleeping ret=%d\n", ret));
 
@@ -5793,7 +5796,7 @@ pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_c
         * on every CPU, so we can rely on the pid to identify the idle task.
         */
        if ((info & PFM_CPUINFO_EXCL_IDLE) == 0 || task->pid) {
-               regs = ia64_task_regs(task);
+               regs = task_pt_regs(task);
                ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0;
                return;
        }
@@ -5876,7 +5879,7 @@ pfm_save_regs(struct task_struct *task)
        flags = pfm_protect_ctx_ctxsw(ctx);
 
        if (ctx->ctx_state == PFM_CTX_ZOMBIE) {
-               struct pt_regs *regs = ia64_task_regs(task);
+               struct pt_regs *regs = task_pt_regs(task);
 
                pfm_clear_psr_up();
 
@@ -6076,7 +6079,7 @@ pfm_load_regs (struct task_struct *task)
        BUG_ON(psr & IA64_PSR_I);
 
        if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) {
-               struct pt_regs *regs = ia64_task_regs(task);
+               struct pt_regs *regs = task_pt_regs(task);
 
                BUG_ON(ctx->ctx_smpl_hdr);
 
@@ -6161,7 +6164,7 @@ pfm_load_regs (struct task_struct *task)
                /*
                 * will replay the PMU interrupt
                 */
-               if (need_irq_resend) hw_resend_irq(NULL, IA64_PERFMON_VECTOR);
+               if (need_irq_resend) ia64_resend_irq(IA64_PERFMON_VECTOR);
 
                pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++;
        }
@@ -6301,7 +6304,7 @@ pfm_load_regs (struct task_struct *task)
                /*
                 * will replay the PMU interrupt
                 */
-               if (need_irq_resend) hw_resend_irq(NULL, IA64_PERFMON_VECTOR);
+               if (need_irq_resend) ia64_resend_irq(IA64_PERFMON_VECTOR);
 
                pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++;
        }
@@ -6436,7 +6439,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
 
 static struct irqaction perfmon_irqaction = {
        .handler = pfm_interrupt_handler,
-       .flags   = SA_INTERRUPT,
+       .flags   = IRQF_DISABLED,
        .name    = "perfmon"
 };
 
@@ -6445,7 +6448,7 @@ pfm_alt_save_pmu_state(void *data)
 {
        struct pt_regs *regs;
 
-       regs = ia64_task_regs(current);
+       regs = task_pt_regs(current);
 
        DPRINT(("called\n"));
 
@@ -6471,7 +6474,7 @@ pfm_alt_restore_pmu_state(void *data)
 {
        struct pt_regs *regs;
 
-       regs = ia64_task_regs(current);
+       regs = task_pt_regs(current);
 
        DPRINT(("called\n"));
 
@@ -6718,6 +6721,7 @@ __initcall(pfm_init);
 void
 pfm_init_percpu (void)
 {
+       static int first_time=1;
        /*
         * make sure no measurement is active
         * (may inherit programmed PMCs from EFI).
@@ -6730,8 +6734,10 @@ pfm_init_percpu (void)
         */
        pfm_unfreeze_pmu();
 
-       if (smp_processor_id() == 0)
+       if (first_time) {
                register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
+               first_time=0;
+       }
 
        ia64_setreg(_IA64_REG_CR_PMV, IA64_PERFMON_VECTOR);
        ia64_srlz_d();
@@ -6753,7 +6759,7 @@ dump_pmu_state(const char *from)
        local_irq_save(flags);
 
        this_cpu = smp_processor_id();
-       regs     = ia64_task_regs(current);
+       regs     = task_pt_regs(current);
        info     = PFM_CPUINFO_GET();
        dcr      = ia64_getreg(_IA64_REG_CR_DCR);