]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
authorIngo Molnar <mingo@elte.hu>
Wed, 15 Sep 2010 08:27:31 +0000 (10:27 +0200)
committerIngo Molnar <mingo@elte.hu>
Wed, 15 Sep 2010 08:27:31 +0000 (10:27 +0200)
1  2 
arch/alpha/kernel/perf_event.c
arch/arm/kernel/perf_event.c
kernel/sched.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
net/core/dev.c
net/core/skbuff.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index 9bb8c024080cf343b122c477375c3c89a06649fa,85d8e4f58c83ce612269162b9635bd49059c39dd..a25fe9eb47397dd8c0ba0116fd11743f28966844
@@@ -241,20 -241,20 +241,20 @@@ static inline unsigned long alpha_read_
  static int alpha_perf_event_set_period(struct perf_event *event,
                                struct hw_perf_event *hwc, int idx)
  {
-       long left = atomic64_read(&hwc->period_left);
+       long left = local64_read(&hwc->period_left);
        long period = hwc->sample_period;
        int ret = 0;
  
        if (unlikely(left <= -period)) {
                left = period;
-               atomic64_set(&hwc->period_left, left);
+               local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                ret = 1;
        }
  
        if (unlikely(left <= 0)) {
                left += period;
-               atomic64_set(&hwc->period_left, left);
+               local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                ret = 1;
        }
        if (left > (long)alpha_pmu->pmc_max_period[idx])
                left = alpha_pmu->pmc_max_period[idx];
  
-       atomic64_set(&hwc->prev_count, (unsigned long)(-left));
+       local64_set(&hwc->prev_count, (unsigned long)(-left));
  
        alpha_write_pmc(idx, (unsigned long)(-left));
  
@@@ -300,14 -300,14 +300,14 @@@ static unsigned long alpha_perf_event_u
        long delta;
  
  again:
-       prev_raw_count = atomic64_read(&hwc->prev_count);
+       prev_raw_count = local64_read(&hwc->prev_count);
        new_raw_count = alpha_read_pmc(idx);
  
-       if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
+       if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
                             new_raw_count) != prev_raw_count)
                goto again;
  
 -      delta = (new_raw_count  - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
 +      delta = (new_raw_count - (prev_raw_count & alpha_pmu->pmc_count_mask[idx])) + ovf;
  
        /* It is possible on very rare occasions that the PMC has overflowed
         * but the interrupt is yet to come.  Detect and fix this situation.
                delta += alpha_pmu->pmc_max_period[idx] + 1;
        }
  
-       atomic64_add(delta, &event->count);
-       atomic64_sub(delta, &hwc->period_left);
+       local64_add(delta, &event->count);
+       local64_sub(delta, &hwc->period_left);
  
        return new_raw_count;
  }
@@@ -402,13 -402,14 +402,13 @@@ static void maybe_change_configuration(
                struct hw_perf_event *hwc = &pe->hw;
                int idx = hwc->idx;
  
 -              if (cpuc->current_idx[j] != PMC_NO_INDEX) {
 -                      cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
 -                      continue;
 +              if (cpuc->current_idx[j] == PMC_NO_INDEX) {
 +                      alpha_perf_event_set_period(pe, hwc, idx);
 +                      cpuc->current_idx[j] = idx;
                }
  
 -              alpha_perf_event_set_period(pe, hwc, idx);
 -              cpuc->current_idx[j] = idx;
 -              cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
 +              if (!(hwc->state & PERF_HES_STOPPED))
 +                      cpuc->idx_mask |= (1<<cpuc->current_idx[j]);
        }
        cpuc->config = cpuc->event[0]->hw.config_base;
  }
   *  - this function is called from outside this module via the pmu struct
   *    returned from perf event initialisation.
   */
 -static int alpha_pmu_enable(struct perf_event *event)
 +static int alpha_pmu_add(struct perf_event *event, int flags)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        int n0;
         * nevertheless we disable the PMCs first to enable a potential
         * final PMI to occur before we disable interrupts.
         */
 -      perf_disable();
 +      perf_pmu_disable(event->pmu);
        local_irq_save(flags);
  
        /* Default to error to be returned */
                }
        }
  
 +      hwc->state = PERF_HES_UPTODATE;
 +      if (!(flags & PERF_EF_START))
 +              hwc->state |= PERF_HES_STOPPED;
 +
        local_irq_restore(flags);
 -      perf_enable();
 +      perf_pmu_enable(event->pmu);
  
        return ret;
  }
   *  - this function is called from outside this module via the pmu struct
   *    returned from perf event initialisation.
   */
 -static void alpha_pmu_disable(struct perf_event *event)
 +static void alpha_pmu_del(struct perf_event *event, int flags)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        unsigned long flags;
        int j;
  
 -      perf_disable();
 +      perf_pmu_disable(event->pmu);
        local_irq_save(flags);
  
        for (j = 0; j < cpuc->n_events; j++) {
        }
  
        local_irq_restore(flags);
 -      perf_enable();
 +      perf_pmu_enable(event->pmu);
  }
  
  
@@@ -517,44 -514,13 +517,44 @@@ static void alpha_pmu_read(struct perf_
  }
  
  
 -static void alpha_pmu_unthrottle(struct perf_event *event)
 +static void alpha_pmu_stop(struct perf_event *event, int flags)
 +{
 +      struct hw_perf_event *hwc = &event->hw;
 +      struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 +
 +      if (!(hwc->state & PERF_HES_STOPPED)) {
 +              cpuc->idx_mask &= !(1UL<<hwc->idx);
 +              hwc->state |= PERF_HES_STOPPED;
 +      }
 +
 +      if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
 +              alpha_perf_event_update(event, hwc, hwc->idx, 0);
 +              hwc->state |= PERF_HES_UPTODATE;
 +      }
 +
 +      if (cpuc->enabled)
 +              wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
 +}
 +
 +
 +static void alpha_pmu_start(struct perf_event *event, int flags)
  {
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
  
 +      if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
 +              return;
 +
 +      if (flags & PERF_EF_RELOAD) {
 +              WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
 +              alpha_perf_event_set_period(event, hwc, hwc->idx);
 +      }
 +
 +      hwc->state = 0;
 +
        cpuc->idx_mask |= 1UL<<hwc->idx;
 -      wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
 +      if (cpuc->enabled)
 +              wrperfmon(PERFMON_CMD_ENABLE, (1UL<<hwc->idx));
  }
  
  
@@@ -670,42 -636,45 +670,42 @@@ static int __hw_perf_event_init(struct 
        if (!hwc->sample_period) {
                hwc->sample_period = alpha_pmu->pmc_max_period[0];
                hwc->last_period = hwc->sample_period;
-               atomic64_set(&hwc->period_left, hwc->sample_period);
+               local64_set(&hwc->period_left, hwc->sample_period);
        }
  
        return 0;
  }
  
 -static const struct pmu pmu = {
 -      .enable         = alpha_pmu_enable,
 -      .disable        = alpha_pmu_disable,
 -      .read           = alpha_pmu_read,
 -      .unthrottle     = alpha_pmu_unthrottle,
 -};
 -
 -
  /*
   * Main entry point to initialise a HW performance event.
   */
 -const struct pmu *hw_perf_event_init(struct perf_event *event)
 +static int alpha_pmu_event_init(struct perf_event *event)
  {
        int err;
  
 +      switch (event->attr.type) {
 +      case PERF_TYPE_RAW:
 +      case PERF_TYPE_HARDWARE:
 +      case PERF_TYPE_HW_CACHE:
 +              break;
 +
 +      default:
 +              return -ENOENT;
 +      }
 +
        if (!alpha_pmu)
 -              return ERR_PTR(-ENODEV);
 +              return -ENODEV;
  
        /* Do the real initialisation work. */
        err = __hw_perf_event_init(event);
  
 -      if (err)
 -              return ERR_PTR(err);
 -
 -      return &pmu;
 +      return err;
  }
  
 -
 -
  /*
   * Main entry point - enable HW performance counters.
   */
 -void hw_perf_enable(void)
 +static void alpha_pmu_enable(struct pmu *pmu)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
  
   * Main entry point - disable HW performance counters.
   */
  
 -void hw_perf_disable(void)
 +static void alpha_pmu_disable(struct pmu *pmu)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
  
        wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
  }
  
 +static struct pmu pmu = {
 +      .pmu_enable     = alpha_pmu_enable,
 +      .pmu_disable    = alpha_pmu_disable,
 +      .event_init     = alpha_pmu_event_init,
 +      .add            = alpha_pmu_add,
 +      .del            = alpha_pmu_del,
 +      .start          = alpha_pmu_start,
 +      .stop           = alpha_pmu_stop,
 +      .read           = alpha_pmu_read,
 +};
 +
  
  /*
   * Main entry point - don't know when this is called but it
@@@ -808,7 -766,7 +808,7 @@@ static void alpha_perf_event_irq_handle
        wrperfmon(PERFMON_CMD_DISABLE, cpuc->idx_mask);
  
        /* la_ptr is the counter that overflowed. */
 -      if (unlikely(la_ptr >= perf_max_events)) {
 +      if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
                /* This should never occur! */
                irq_err_count++;
                pr_warning("PMI: silly index %ld\n", la_ptr);
@@@ -879,7 -837,6 +879,7 @@@ void __init init_hw_perf_events(void
  
        /* And set up PMU specification */
        alpha_pmu = &ev67_pmu;
 -      perf_max_events = alpha_pmu->num_pmcs;
 +
 +      perf_pmu_register(&pmu);
  }
  
index 45d6a35217c1846f570f72684f4b8fbfe352c2b9,ecbb0288e5dd95c80b420635dffee6ef600f86a8..ad19c276b10fa1b5d7f82a8f5c2169560d9ebdd0
@@@ -221,56 -221,46 +221,56 @@@ again
  }
  
  static void
 -armpmu_disable(struct perf_event *event)
 +armpmu_read(struct perf_event *event)
  {
 -      struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
 -      int idx = hwc->idx;
 -
 -      WARN_ON(idx < 0);
 -
 -      clear_bit(idx, cpuc->active_mask);
 -      armpmu->disable(hwc, idx);
 -
 -      barrier();
  
 -      armpmu_event_update(event, hwc, idx);
 -      cpuc->events[idx] = NULL;
 -      clear_bit(idx, cpuc->used_mask);
 +      /* Don't read disabled counters! */
 +      if (hwc->idx < 0)
 +              return;
  
 -      perf_event_update_userpage(event);
 +      armpmu_event_update(event, hwc, hwc->idx);
  }
  
  static void
 -armpmu_read(struct perf_event *event)
 +armpmu_stop(struct perf_event *event, int flags)
  {
        struct hw_perf_event *hwc = &event->hw;
  
 -      /* Don't read disabled counters! */
 -      if (hwc->idx < 0)
 +      if (!armpmu)
                return;
  
 -      armpmu_event_update(event, hwc, hwc->idx);
 +      /*
 +       * ARM pmu always has to update the counter, so ignore
 +       * PERF_EF_UPDATE, see comments in armpmu_start().
 +       */
 +      if (!(hwc->state & PERF_HES_STOPPED)) {
 +              armpmu->disable(hwc, hwc->idx);
 +              barrier(); /* why? */
 +              armpmu_event_update(event, hwc, hwc->idx);
 +              hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 +      }
  }
  
  static void
 -armpmu_unthrottle(struct perf_event *event)
 +armpmu_start(struct perf_event *event, int flags)
  {
        struct hw_perf_event *hwc = &event->hw;
  
 +      if (!armpmu)
 +              return;
 +
 +      /*
 +       * ARM pmu always has to reprogram the period, so ignore
 +       * PERF_EF_RELOAD, see the comment below.
 +       */
 +      if (flags & PERF_EF_RELOAD)
 +              WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
 +
 +      hwc->state = 0;
        /*
         * Set the period again. Some counters can't be stopped, so when we
 -       * were throttled we simply disabled the IRQ source and the counter
 +       * were stopped we simply disabled the IRQ source and the counter
         * may have been left counting. If we don't do this step then we may
         * get an interrupt too soon or *way* too late if the overflow has
         * happened since disabling.
        armpmu->enable(hwc, hwc->idx);
  }
  
 +static void
 +armpmu_del(struct perf_event *event, int flags)
 +{
 +      struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 +      struct hw_perf_event *hwc = &event->hw;
 +      int idx = hwc->idx;
 +
 +      WARN_ON(idx < 0);
 +
 +      clear_bit(idx, cpuc->active_mask);
 +      armpmu_stop(event, PERF_EF_UPDATE);
 +      cpuc->events[idx] = NULL;
 +      clear_bit(idx, cpuc->used_mask);
 +
 +      perf_event_update_userpage(event);
 +}
 +
  static int
 -armpmu_enable(struct perf_event *event)
 +armpmu_add(struct perf_event *event, int flags)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        int idx;
        int err = 0;
  
 +      perf_pmu_disable(event->pmu);
 +
        /* If we don't have a space for the counter then finish early. */
        idx = armpmu->get_event_idx(cpuc, hwc);
        if (idx < 0) {
        cpuc->events[idx] = event;
        set_bit(idx, cpuc->active_mask);
  
 -      /* Set the period for the event. */
 -      armpmu_event_set_period(event, hwc, idx);
 -
 -      /* Enable the event. */
 -      armpmu->enable(hwc, idx);
 +      hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
 +      if (flags & PERF_EF_START)
 +              armpmu_start(event, PERF_EF_RELOAD);
  
        /* Propagate our changes to the userspace mapping. */
        perf_event_update_userpage(event);
  
  out:
 +      perf_pmu_enable(event->pmu);
        return err;
  }
  
 -static struct pmu pmu = {
 -      .enable     = armpmu_enable,
 -      .disable    = armpmu_disable,
 -      .unthrottle = armpmu_unthrottle,
 -      .read       = armpmu_read,
 -};
 +static struct pmu pmu;
  
  static int
  validate_event(struct cpu_hw_events *cpuc,
  {
        struct hw_perf_event fake_event = event->hw;
  
-       if (event->pmu && event->pmu != &pmu)
-               return 0;
+       if (event->pmu != &pmu || event->state <= PERF_EVENT_STATE_OFF)
+               return 1;
  
        return armpmu->get_event_idx(cpuc, &fake_event) >= 0;
  }
@@@ -514,29 -491,20 +514,29 @@@ __hw_perf_event_init(struct perf_event 
        return err;
  }
  
 -const struct pmu *
 -hw_perf_event_init(struct perf_event *event)
 +static int armpmu_event_init(struct perf_event *event)
  {
        int err = 0;
  
 +      switch (event->attr.type) {
 +      case PERF_TYPE_RAW:
 +      case PERF_TYPE_HARDWARE:
 +      case PERF_TYPE_HW_CACHE:
 +              break;
 +
 +      default:
 +              return -ENOENT;
 +      }
 +
        if (!armpmu)
 -              return ERR_PTR(-ENODEV);
 +              return -ENODEV;
  
        event->destroy = hw_perf_event_destroy;
  
        if (!atomic_inc_not_zero(&active_events)) {
 -              if (atomic_read(&active_events) > perf_max_events) {
 +              if (atomic_read(&active_events) > armpmu.num_events) {
                        atomic_dec(&active_events);
 -                      return ERR_PTR(-ENOSPC);
 +                      return -ENOSPC;
                }
  
                mutex_lock(&pmu_reserve_mutex);
        }
  
        if (err)
 -              return ERR_PTR(err);
 +              return err;
  
        err = __hw_perf_event_init(event);
        if (err)
                hw_perf_event_destroy(event);
  
 -      return err ? ERR_PTR(err) : &pmu;
 +      return err;
  }
  
 -void
 -hw_perf_enable(void)
 +static void armpmu_enable(struct pmu *pmu)
  {
        /* Enable all of the perf events on hardware. */
        int idx;
        armpmu->start();
  }
  
 -void
 -hw_perf_disable(void)
 +static void armpmu_disable(struct pmu *pmu)
  {
        if (armpmu)
                armpmu->stop();
  }
  
 +static struct pmu pmu = {
 +      .pmu_enable     = armpmu_enable,
 +      .pmu_disable    = armpmu_disable,
 +      .event_init     = armpmu_event_init,
 +      .add            = armpmu_add,
 +      .del            = armpmu_del,
 +      .start          = armpmu_start,
 +      .stop           = armpmu_stop,
 +      .read           = armpmu_read,
 +};
 +
  /*
   * ARMv6 Performance counter handling code.
   *
@@@ -1082,8 -1041,8 +1082,8 @@@ armv6pmu_handle_irq(int irq_num
        /*
         * Handle the pending perf events.
         *
-        * Note: this call *must* be run with interrupts enabled. For
-        * platforms that can have the PMU interrupts raised as a PMI, this
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
        perf_event_do_pending();
@@@ -2058,8 -2017,8 +2058,8 @@@ static irqreturn_t armv7pmu_handle_irq(
        /*
         * Handle the pending perf events.
         *
-        * Note: this call *must* be run with interrupts enabled. For
-        * platforms that can have the PMU interrupts raised as a PMI, this
+        * Note: this call *must* be run with interrupts disabled. For
+        * platforms that can have the PMU interrupts raised as an NMI, this
         * will not work.
         */
        perf_event_do_pending();
@@@ -2974,12 -2933,14 +2974,12 @@@ init_hw_perf_events(void
                        armpmu = &armv6pmu;
                        memcpy(armpmu_perf_cache_map, armv6_perf_cache_map,
                                        sizeof(armv6_perf_cache_map));
 -                      perf_max_events = armv6pmu.num_events;
                        break;
                case 0xB020:    /* ARM11mpcore */
                        armpmu = &armv6mpcore_pmu;
                        memcpy(armpmu_perf_cache_map,
                               armv6mpcore_perf_cache_map,
                               sizeof(armv6mpcore_perf_cache_map));
 -                      perf_max_events = armv6mpcore_pmu.num_events;
                        break;
                case 0xC080:    /* Cortex-A8 */
                        armv7pmu.id = ARM_PERF_PMU_ID_CA8;
                        /* Reset PMNC and read the nb of CNTx counters
                            supported */
                        armv7pmu.num_events = armv7_reset_read_pmnc();
 -                      perf_max_events = armv7pmu.num_events;
                        break;
                case 0xC090:    /* Cortex-A9 */
                        armv7pmu.id = ARM_PERF_PMU_ID_CA9;
                        /* Reset PMNC and read the nb of CNTx counters
                            supported */
                        armv7pmu.num_events = armv7_reset_read_pmnc();
 -                      perf_max_events = armv7pmu.num_events;
                        break;
                }
        /* Intel CPUs [xscale]. */
                        armpmu = &xscale1pmu;
                        memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
                                        sizeof(xscale_perf_cache_map));
 -                      perf_max_events = xscale1pmu.num_events;
                        break;
                case 2:
                        armpmu = &xscale2pmu;
                        memcpy(armpmu_perf_cache_map, xscale_perf_cache_map,
                                        sizeof(xscale_perf_cache_map));
 -                      perf_max_events = xscale2pmu.num_events;
                        break;
                }
        }
                                arm_pmu_names[armpmu->id], armpmu->num_events);
        } else {
                pr_info("no hardware support available\n");
 -              perf_max_events = -1;
        }
  
 +      perf_pmu_register(&pmu);
 +
        return 0;
  }
  arch_initcall(init_hw_perf_events);
  /*
   * Callchain handling code.
   */
 -static inline void
 -callchain_store(struct perf_callchain_entry *entry,
 -              u64 ip)
 -{
 -      if (entry->nr < PERF_MAX_STACK_DEPTH)
 -              entry->ip[entry->nr++] = ip;
 -}
  
  /*
   * The registers we're interested in are at the end of the variable
@@@ -3068,7 -3039,7 +3068,7 @@@ user_backtrace(struct frame_tail *tail
        if (__copy_from_user_inatomic(&buftail, tail, sizeof(buftail)))
                return NULL;
  
 -      callchain_store(entry, buftail.lr);
 +      perf_callchain_store(entry, buftail.lr);
  
        /*
         * Frame pointers should strictly progress back up the stack
        return buftail.fp - 1;
  }
  
 -static void
 -perf_callchain_user(struct pt_regs *regs,
 -                  struct perf_callchain_entry *entry)
 +void
 +perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
  {
        struct frame_tail *tail;
  
 -      callchain_store(entry, PERF_CONTEXT_USER);
 -
 -      if (!user_mode(regs))
 -              regs = task_pt_regs(current);
  
        tail = (struct frame_tail *)regs->ARM_fp - 1;
  
@@@ -3102,18 -3078,56 +3102,18 @@@ callchain_trace(struct stackframe *fr
                void *data)
  {
        struct perf_callchain_entry *entry = data;
 -      callchain_store(entry, fr->pc);
 +      perf_callchain_store(entry, fr->pc);
        return 0;
  }
  
 -static void
 -perf_callchain_kernel(struct pt_regs *regs,
 -                    struct perf_callchain_entry *entry)
 +void
 +perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
  {
        struct stackframe fr;
  
 -      callchain_store(entry, PERF_CONTEXT_KERNEL);
        fr.fp = regs->ARM_fp;
        fr.sp = regs->ARM_sp;
        fr.lr = regs->ARM_lr;
        fr.pc = regs->ARM_pc;
        walk_stackframe(&fr, callchain_trace, entry);
  }
 -
 -static void
 -perf_do_callchain(struct pt_regs *regs,
 -                struct perf_callchain_entry *entry)
 -{
 -      int is_user;
 -
 -      if (!regs)
 -              return;
 -
 -      is_user = user_mode(regs);
 -
 -      if (!current || !current->pid)
 -              return;
 -
 -      if (is_user && current->state != TASK_RUNNING)
 -              return;
 -
 -      if (!is_user)
 -              perf_callchain_kernel(regs, entry);
 -
 -      if (current->mm)
 -              perf_callchain_user(regs, entry);
 -}
 -
 -static DEFINE_PER_CPU(struct perf_callchain_entry, pmc_irq_entry);
 -
 -struct perf_callchain_entry *
 -perf_callchain(struct pt_regs *regs)
 -{
 -      struct perf_callchain_entry *entry = &__get_cpu_var(pmc_irq_entry);
 -
 -      entry->nr = 0;
 -      perf_do_callchain(regs, entry);
 -      return entry;
 -}
diff --combined kernel/sched.c
index 66a02ba83c0192c7f9f5d10515305d8be6ae3ccd,ed09d4f2a69c5b4c1412d350c7c834a655732f2a..1c3ea7a55b7ba092dd35500b198e206ebc75a907
@@@ -1294,6 -1294,10 +1294,10 @@@ static void resched_task(struct task_st
  static void sched_rt_avg_update(struct rq *rq, u64 rt_delta)
  {
  }
+ static void sched_avg_update(struct rq *rq)
+ {
+ }
  #endif /* CONFIG_SMP */
  
  #if BITS_PER_LONG == 32
@@@ -3182,6 -3186,8 +3186,8 @@@ static void update_cpu_load(struct rq *
  
                this_rq->cpu_load[i] = (old_load * (scale - 1) + new_load) >> i;
        }
+       sched_avg_update(this_rq);
  }
  
  static void update_cpu_load_active(struct rq *this_rq)
@@@ -3578,6 -3584,8 +3584,6 @@@ void scheduler_tick(void
        curr->sched_class->task_tick(rq, curr, 0);
        raw_spin_unlock(&rq->lock);
  
 -      perf_event_task_tick(curr);
 -
  #ifdef CONFIG_SMP
        rq->idle_at_tick = idle_cpu(cpu);
        trigger_load_balance(rq, cpu);
diff --combined kernel/trace/ftrace.c
index 20aff3f1c71993eaa1c8ec10eaa47479ea179877,1884cf5bc110a475e350255cf353b62845296313..65fb077ea79c147c21d6a8a4890a2ec6d17712bc
@@@ -884,8 -884,10 +884,8 @@@ enum 
        FTRACE_ENABLE_CALLS             = (1 << 0),
        FTRACE_DISABLE_CALLS            = (1 << 1),
        FTRACE_UPDATE_TRACE_FUNC        = (1 << 2),
 -      FTRACE_ENABLE_MCOUNT            = (1 << 3),
 -      FTRACE_DISABLE_MCOUNT           = (1 << 4),
 -      FTRACE_START_FUNC_RET           = (1 << 5),
 -      FTRACE_STOP_FUNC_RET            = (1 << 6),
 +      FTRACE_START_FUNC_RET           = (1 << 3),
 +      FTRACE_STOP_FUNC_RET            = (1 << 4),
  };
  
  static int ftrace_filtered;
@@@ -1224,6 -1226,8 +1224,6 @@@ static void ftrace_shutdown(int command
  
  static void ftrace_startup_sysctl(void)
  {
 -      int command = FTRACE_ENABLE_MCOUNT;
 -
        if (unlikely(ftrace_disabled))
                return;
  
        saved_ftrace_func = NULL;
        /* ftrace_start_up is true if we want ftrace running */
        if (ftrace_start_up)
 -              command |= FTRACE_ENABLE_CALLS;
 -
 -      ftrace_run_update_code(command);
 +              ftrace_run_update_code(FTRACE_ENABLE_CALLS);
  }
  
  static void ftrace_shutdown_sysctl(void)
  {
 -      int command = FTRACE_DISABLE_MCOUNT;
 -
        if (unlikely(ftrace_disabled))
                return;
  
        /* ftrace_start_up is true if ftrace is running */
        if (ftrace_start_up)
 -              command |= FTRACE_DISABLE_CALLS;
 -
 -      ftrace_run_update_code(command);
 +              ftrace_run_update_code(FTRACE_DISABLE_CALLS);
  }
  
  static cycle_t                ftrace_update_time;
@@@ -1358,24 -1368,29 +1358,29 @@@ enum 
  #define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
  
  struct ftrace_iterator {
-       struct ftrace_page      *pg;
-       int                     hidx;
-       int                     idx;
-       unsigned                flags;
-       struct trace_parser     parser;
+       loff_t                          pos;
+       loff_t                          func_pos;
+       struct ftrace_page              *pg;
+       struct dyn_ftrace               *func;
+       struct ftrace_func_probe        *probe;
+       struct trace_parser             parser;
+       int                             hidx;
+       int                             idx;
+       unsigned                        flags;
  };
  
  static void *
- t_hash_next(struct seq_file *m, void *v, loff_t *pos)
+ t_hash_next(struct seq_file *m, loff_t *pos)
  {
        struct ftrace_iterator *iter = m->private;
-       struct hlist_node *hnd = v;
+       struct hlist_node *hnd = NULL;
        struct hlist_head *hhd;
  
-       WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
        (*pos)++;
+       iter->pos = *pos;
  
+       if (iter->probe)
+               hnd = &iter->probe->node;
   retry:
        if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
                return NULL;
                }
        }
  
-       return hnd;
+       if (WARN_ON_ONCE(!hnd))
+               return NULL;
+       iter->probe = hlist_entry(hnd, struct ftrace_func_probe, node);
+       return iter;
  }
  
  static void *t_hash_start(struct seq_file *m, loff_t *pos)
        void *p = NULL;
        loff_t l;
  
-       if (!(iter->flags & FTRACE_ITER_HASH))
-               *pos = 0;
-       iter->flags |= FTRACE_ITER_HASH;
+       if (iter->func_pos > *pos)
+               return NULL;
  
        iter->hidx = 0;
-       for (l = 0; l <= *pos; ) {
-               p = t_hash_next(m, p, &l);
+       for (l = 0; l <= (*pos - iter->func_pos); ) {
+               p = t_hash_next(m, &l);
                if (!p)
                        break;
        }
-       return p;
+       if (!p)
+               return NULL;
+       /* Only set this if we have an item */
+       iter->flags |= FTRACE_ITER_HASH;
+       return iter;
  }
  
- static int t_hash_show(struct seq_file *m, void *v)
+ static int
+ t_hash_show(struct seq_file *m, struct ftrace_iterator *iter)
  {
        struct ftrace_func_probe *rec;
-       struct hlist_node *hnd = v;
  
-       rec = hlist_entry(hnd, struct ftrace_func_probe, node);
+       rec = iter->probe;
+       if (WARN_ON_ONCE(!rec))
+               return -EIO;
  
        if (rec->ops->print)
                return rec->ops->print(m, rec->ip, rec->ops, rec->data);
@@@ -1447,12 -1473,13 +1463,13 @@@ t_next(struct seq_file *m, void *v, lof
        struct dyn_ftrace *rec = NULL;
  
        if (iter->flags & FTRACE_ITER_HASH)
-               return t_hash_next(m, v, pos);
+               return t_hash_next(m, pos);
  
        (*pos)++;
+       iter->pos = *pos;
  
        if (iter->flags & FTRACE_ITER_PRINTALL)
-               return NULL;
+               return t_hash_start(m, pos);
  
   retry:
        if (iter->idx >= iter->pg->index) {
                }
        }
  
-       return rec;
+       if (!rec)
+               return t_hash_start(m, pos);
+       iter->func_pos = *pos;
+       iter->func = rec;
+       return iter;
+ }
+ static void reset_iter_read(struct ftrace_iterator *iter)
+ {
+       iter->pos = 0;
+       iter->func_pos = 0;
+       iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH);
  }
  
  static void *t_start(struct seq_file *m, loff_t *pos)
        loff_t l;
  
        mutex_lock(&ftrace_lock);
+       /*
+        * If an lseek was done, then reset and start from beginning.
+        */
+       if (*pos < iter->pos)
+               reset_iter_read(iter);
        /*
         * For set_ftrace_filter reading, if we have the filter
         * off, we can short cut and just print out that all
                if (*pos > 0)
                        return t_hash_start(m, pos);
                iter->flags |= FTRACE_ITER_PRINTALL;
+               /* reset in case of seek/pread */
+               iter->flags &= ~FTRACE_ITER_HASH;
                return iter;
        }
  
        if (iter->flags & FTRACE_ITER_HASH)
                return t_hash_start(m, pos);
  
+       /*
+        * Unfortunately, we need to restart at ftrace_pages_start
+        * every time we let go of the ftrace_mutex. This is because
+        * those pointers can change without the lock.
+        */
        iter->pg = ftrace_pages_start;
        iter->idx = 0;
        for (l = 0; l <= *pos; ) {
                        break;
        }
  
-       if (!p && iter->flags & FTRACE_ITER_FILTER)
-               return t_hash_start(m, pos);
+       if (!p) {
+               if (iter->flags & FTRACE_ITER_FILTER)
+                       return t_hash_start(m, pos);
  
-       return p;
+               return NULL;
+       }
+       return iter;
  }
  
  static void t_stop(struct seq_file *m, void *p)
  static int t_show(struct seq_file *m, void *v)
  {
        struct ftrace_iterator *iter = m->private;
-       struct dyn_ftrace *rec = v;
+       struct dyn_ftrace *rec;
  
        if (iter->flags & FTRACE_ITER_HASH)
-               return t_hash_show(m, v);
+               return t_hash_show(m, iter);
  
        if (iter->flags & FTRACE_ITER_PRINTALL) {
                seq_printf(m, "#### all functions enabled ####\n");
                return 0;
        }
  
+       rec = iter->func;
        if (!rec)
                return 0;
  
@@@ -2406,7 -2465,7 +2455,7 @@@ static const struct file_operations ftr
        .open = ftrace_filter_open,
        .read = seq_read,
        .write = ftrace_filter_write,
-       .llseek = no_llseek,
+       .llseek = ftrace_regex_lseek,
        .release = ftrace_filter_release,
  };
  
index ef27017caa56dc7fa9b08f38549354376927b417,492197e2f86cda2792603186b59ad3fdd17c448d..4e2f03410377af2ee6f0fb46a7102e1ae76eba0c
@@@ -2606,19 -2606,6 +2606,19 @@@ void ring_buffer_record_enable_cpu(stru
  }
  EXPORT_SYMBOL_GPL(ring_buffer_record_enable_cpu);
  
 +/*
 + * The total entries in the ring buffer is the running counter
 + * of entries entered into the ring buffer, minus the sum of
 + * the entries read from the ring buffer and the number of
 + * entries that were overwritten.
 + */
 +static inline unsigned long
 +rb_num_of_entries(struct ring_buffer_per_cpu *cpu_buffer)
 +{
 +      return local_read(&cpu_buffer->entries) -
 +              (local_read(&cpu_buffer->overrun) + cpu_buffer->read);
 +}
 +
  /**
   * ring_buffer_entries_cpu - get the number of entries in a cpu buffer
   * @buffer: The ring buffer
  unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu)
  {
        struct ring_buffer_per_cpu *cpu_buffer;
 -      unsigned long ret;
  
        if (!cpumask_test_cpu(cpu, buffer->cpumask))
                return 0;
  
        cpu_buffer = buffer->buffers[cpu];
 -      ret = (local_read(&cpu_buffer->entries) - local_read(&cpu_buffer->overrun))
 -              - cpu_buffer->read;
  
 -      return ret;
 +      return rb_num_of_entries(cpu_buffer);
  }
  EXPORT_SYMBOL_GPL(ring_buffer_entries_cpu);
  
@@@ -2694,7 -2684,8 +2694,7 @@@ unsigned long ring_buffer_entries(struc
        /* if you care about this being correct, lock the buffer */
        for_each_buffer_cpu(buffer, cpu) {
                cpu_buffer = buffer->buffers[cpu];
 -              entries += (local_read(&cpu_buffer->entries) -
 -                          local_read(&cpu_buffer->overrun)) - cpu_buffer->read;
 +              entries += rb_num_of_entries(cpu_buffer);
        }
  
        return entries;
@@@ -2994,13 -2985,11 +2994,11 @@@ static void rb_advance_reader(struct ri
  
  static void rb_advance_iter(struct ring_buffer_iter *iter)
  {
-       struct ring_buffer *buffer;
        struct ring_buffer_per_cpu *cpu_buffer;
        struct ring_buffer_event *event;
        unsigned length;
  
        cpu_buffer = iter->cpu_buffer;
-       buffer = cpu_buffer->buffer;
  
        /*
         * Check if we are at the end of the buffer.
diff --combined net/core/dev.c
index 2308cce480483c0df4c93ea61b21b98b8fb8754d,b9b22a3c4c8fa36ea3412e22a816d0c738562831..561ee3a86525aef6641b47a52c59dc73510ec829
  #include <linux/jhash.h>
  #include <linux/random.h>
  #include <trace/events/napi.h>
 +#include <trace/events/net.h>
 +#include <trace/events/skb.h>
  #include <linux/pci.h>
  
  #include "net-sysfs.h"
@@@ -1980,7 -1978,6 +1980,7 @@@ int dev_hard_start_xmit(struct sk_buff 
                }
  
                rc = ops->ndo_start_xmit(skb, dev);
 +              trace_net_dev_xmit(skb, rc);
                if (rc == NETDEV_TX_OK)
                        txq_trans_update(txq);
                return rc;
@@@ -2001,7 -1998,6 +2001,7 @@@ gso
                        skb_dst_drop(nskb);
  
                rc = ops->ndo_start_xmit(nskb, dev);
 +              trace_net_dev_xmit(nskb, rc);
                if (unlikely(rc != NETDEV_TX_OK)) {
                        if (rc & ~NETDEV_TX_MASK)
                                goto out_kfree_gso_skb;
@@@ -2062,16 -2058,16 +2062,16 @@@ static struct netdev_queue *dev_pick_tx
                                        struct sk_buff *skb)
  {
        int queue_index;
-       struct sock *sk = skb->sk;
+       const struct net_device_ops *ops = dev->netdev_ops;
  
-       queue_index = sk_tx_queue_get(sk);
-       if (queue_index < 0) {
-               const struct net_device_ops *ops = dev->netdev_ops;
+       if (ops->ndo_select_queue) {
+               queue_index = ops->ndo_select_queue(dev, skb);
+               queue_index = dev_cap_txqueue(dev, queue_index);
+       } else {
+               struct sock *sk = skb->sk;
+               queue_index = sk_tx_queue_get(sk);
+               if (queue_index < 0) {
  
-               if (ops->ndo_select_queue) {
-                       queue_index = ops->ndo_select_queue(dev, skb);
-                       queue_index = dev_cap_txqueue(dev, queue_index);
-               } else {
                        queue_index = 0;
                        if (dev->real_num_tx_queues > 1)
                                queue_index = skb_tx_hash(dev, skb);
@@@ -2190,7 -2186,6 +2190,7 @@@ int dev_queue_xmit(struct sk_buff *skb
  #ifdef CONFIG_NET_CLS_ACT
        skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_EGRESS);
  #endif
 +      trace_net_dev_queue(skb);
        if (q->enqueue) {
                rc = __dev_xmit_skb(skb, q, dev, txq);
                goto out;
@@@ -2517,7 -2512,6 +2517,7 @@@ int netif_rx(struct sk_buff *skb
        if (netdev_tstamp_prequeue)
                net_timestamp_check(skb);
  
 +      trace_netif_rx(skb);
  #ifdef CONFIG_RPS
        {
                struct rps_dev_flow voidflow, *rflow = &voidflow;
@@@ -2577,7 -2571,6 +2577,7 @@@ static void net_tx_action(struct softir
                        clist = clist->next;
  
                        WARN_ON(atomic_read(&skb->users));
 +                      trace_kfree_skb(skb, net_tx_action);
                        __kfree_skb(skb);
                }
        }
@@@ -2835,7 -2828,6 +2835,7 @@@ static int __netif_receive_skb(struct s
        if (!netdev_tstamp_prequeue)
                net_timestamp_check(skb);
  
 +      trace_netif_receive_skb(skb);
        if (vlan_tx_tag_present(skb) && vlan_hwaccel_do_receive(skb))
                return NET_RX_SUCCESS;
  
diff --combined net/core/skbuff.c
index 12e61e351d0e2678d6cd4e330129cc353cd55915,c83b421341c01b4a1de702e42d3380fac2f0aa2b..56ba3c4e4761c6584375a8acf45022bc5c40d6e8
@@@ -466,7 -466,6 +466,7 @@@ void consume_skb(struct sk_buff *skb
                smp_rmb();
        else if (likely(!atomic_dec_and_test(&skb->users)))
                return;
 +      trace_consume_skb(skb);
        __kfree_skb(skb);
  }
  EXPORT_SYMBOL(consume_skb);
@@@ -2574,6 -2573,10 +2574,10 @@@ struct sk_buff *skb_segment(struct sk_b
                __copy_skb_header(nskb, skb);
                nskb->mac_len = skb->mac_len;
  
+               /* nskb and skb might have different headroom */
+               if (nskb->ip_summed == CHECKSUM_PARTIAL)
+                       nskb->csum_start += skb_headroom(nskb) - headroom;
                skb_reset_mac_header(nskb);
                skb_set_network_header(nskb, skb->mac_len);
                nskb->transport_header = (nskb->network_header +
@@@ -2704,7 -2707,7 +2708,7 @@@ int skb_gro_receive(struct sk_buff **he
                return -E2BIG;
  
        headroom = skb_headroom(p);
-       nskb = netdev_alloc_skb(p->dev, headroom + skb_gro_offset(p));
+       nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
        if (unlikely(!nskb))
                return -ENOMEM;
  
diff --combined tools/perf/util/symbol.c
index a08e1cbcbbbd5603cea99f7141ea940b17bf3b7c,b2f5ae97f33dded1cdaba3e843ab2df888515777..b39f499e575a604198bf1bb11d11d6280a091548
@@@ -388,20 -388,6 +388,20 @@@ size_t dso__fprintf_buildid(struct dso 
        return fprintf(fp, "%s", sbuild_id);
  }
  
 +size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp)
 +{
 +      size_t ret = 0;
 +      struct rb_node *nd;
 +      struct symbol_name_rb_node *pos;
 +
 +      for (nd = rb_first(&self->symbol_names[type]); nd; nd = rb_next(nd)) {
 +              pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
 +              fprintf(fp, "%s\n", pos->sym.name);
 +      }
 +
 +      return ret;
 +}
 +
  size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
  {
        struct rb_node *nd;
@@@ -2282,6 -2268,9 +2282,9 @@@ static int setup_list(struct strlist **
  
  int symbol__init(void)
  {
+       if (symbol_conf.initialized)
+               return 0;
        elf_version(EV_CURRENT);
        if (symbol_conf.sort_by_name)
                symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
                       symbol_conf.sym_list_str, "symbol") < 0)
                goto out_free_comm_list;
  
+       symbol_conf.initialized = true;
        return 0;
  
  out_free_dso_list:
@@@ -2318,11 -2308,14 +2322,14 @@@ out_free_comm_list
  
  void symbol__exit(void)
  {
+       if (!symbol_conf.initialized)
+               return;
        strlist__delete(symbol_conf.sym_list);
        strlist__delete(symbol_conf.dso_list);
        strlist__delete(symbol_conf.comm_list);
        vmlinux_path__exit();
        symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
+       symbol_conf.initialized = false;
  }
  
  int machines__create_kernel_maps(struct rb_root *self, pid_t pid)
diff --combined tools/perf/util/symbol.h
index 0a2c460b6d81f009223b7ff1ecfc9c25054ccf22,ea95c2756f05e73d09f6868f24b174ed1221f59a..038f2201ee09579ca3f460d9f59576770ea477d2
@@@ -69,7 -69,8 +69,8 @@@ struct symbol_conf 
                        show_nr_samples,
                        use_callchain,
                        exclude_other,
-                       show_cpu_utilization;
+                       show_cpu_utilization,
+                       initialized;
        const char      *vmlinux_name,
                        *source_prefix,
                        *field_sep;
@@@ -181,7 -182,6 +182,7 @@@ size_t machines__fprintf_dsos(struct rb
  size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits);
  
  size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
 +size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp);
  size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
  
  enum dso_origin {