]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
authorDavid S. Miller <davem@davemloft.net>
Sat, 26 Jun 2010 17:27:00 +0000 (10:27 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sat, 26 Jun 2010 17:27:00 +0000 (10:27 -0700)
1  2 
arch/sparc/kernel/perf_event.c

index 2e1698332b6deca72d2718df3ce12a332dafa908,0ec92c8861dd3a68fe0465b71ccf8007ad6e40a7..44faabc3c02c920bba1b9f12272d1a907895161e
@@@ -92,6 -92,8 +92,8 @@@ struct cpu_hw_events 
  
        /* Enabled/disable state.  */
        int                     enabled;
+       unsigned int            group_flag;
  };
  DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, };
  
@@@ -655,7 -657,6 +657,7 @@@ static u64 maybe_change_configuration(s
                cpuc->current_idx[i] = idx;
  
                enc = perf_event_get_enc(cpuc->events[i]);
 +              pcr &= ~mask_for_index(idx);
                pcr |= event_encoding(enc, idx);
        }
  out:
@@@ -982,53 -983,6 +984,6 @@@ static int collect_events(struct perf_e
        return n;
  }
  
- static void event_sched_in(struct perf_event *event)
- {
-       event->state = PERF_EVENT_STATE_ACTIVE;
-       event->oncpu = smp_processor_id();
-       event->tstamp_running += event->ctx->time - event->tstamp_stopped;
-       if (is_software_event(event))
-               event->pmu->enable(event);
- }
- int hw_perf_group_sched_in(struct perf_event *group_leader,
-                          struct perf_cpu_context *cpuctx,
-                          struct perf_event_context *ctx)
- {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
-       struct perf_event *sub;
-       int n0, n;
-       if (!sparc_pmu)
-               return 0;
-       n0 = cpuc->n_events;
-       n = collect_events(group_leader, perf_max_events - n0,
-                          &cpuc->event[n0], &cpuc->events[n0],
-                          &cpuc->current_idx[n0]);
-       if (n < 0)
-               return -EAGAIN;
-       if (check_excludes(cpuc->event, n0, n))
-               return -EINVAL;
-       if (sparc_check_constraints(cpuc->event, cpuc->events, n + n0))
-               return -EAGAIN;
-       cpuc->n_events = n0 + n;
-       cpuc->n_added += n;
-       cpuctx->active_oncpu += n;
-       n = 1;
-       event_sched_in(group_leader);
-       list_for_each_entry(sub, &group_leader->sibling_list, group_entry) {
-               if (sub->state != PERF_EVENT_STATE_OFF) {
-                       event_sched_in(sub);
-                       n++;
-               }
-       }
-       ctx->nr_active += n;
-       return 1;
- }
  static int sparc_pmu_enable(struct perf_event *event)
  {
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        cpuc->events[n0] = event->hw.event_base;
        cpuc->current_idx[n0] = PIC_NO_INDEX;
  
+       /*
+        * If group events scheduling transaction was started,
+        * skip the schedulability test here, it will be peformed
+        * at commit time(->commit_txn) as a whole
+        */
+       if (cpuc->group_flag & PERF_EVENT_TXN_STARTED)
+               goto nocheck;
        if (check_excludes(cpuc->event, n0, 1))
                goto out;
        if (sparc_check_constraints(cpuc->event, cpuc->events, n0 + 1))
                goto out;
  
+ nocheck:
        cpuc->n_events++;
        cpuc->n_added++;
  
@@@ -1130,11 -1093,61 +1094,61 @@@ static int __hw_perf_event_init(struct 
        return 0;
  }
  
+ /*
+  * Start group events scheduling transaction
+  * Set the flag to make pmu::enable() not perform the
+  * schedulability test, it will be performed at commit time
+  */
+ static void sparc_pmu_start_txn(const struct pmu *pmu)
+ {
+       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+       cpuhw->group_flag |= PERF_EVENT_TXN_STARTED;
+ }
+ /*
+  * Stop group events scheduling transaction
+  * Clear the flag and pmu::enable() will perform the
+  * schedulability test.
+  */
+ static void sparc_pmu_cancel_txn(const struct pmu *pmu)
+ {
+       struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
+       cpuhw->group_flag &= ~PERF_EVENT_TXN_STARTED;
+ }
+ /*
+  * Commit group events scheduling transaction
+  * Perform the group schedulability test as a whole
+  * Return 0 if success
+  */
+ static int sparc_pmu_commit_txn(const struct pmu *pmu)
+ {
+       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+       int n;
+       if (!sparc_pmu)
+               return -EINVAL;
+       cpuc = &__get_cpu_var(cpu_hw_events);
+       n = cpuc->n_events;
+       if (check_excludes(cpuc->event, 0, n))
+               return -EINVAL;
+       if (sparc_check_constraints(cpuc->event, cpuc->events, n))
+               return -EAGAIN;
+       return 0;
+ }
  static const struct pmu pmu = {
        .enable         = sparc_pmu_enable,
        .disable        = sparc_pmu_disable,
        .read           = sparc_pmu_read,
        .unthrottle     = sparc_pmu_unthrottle,
+       .start_txn      = sparc_pmu_start_txn,
+       .cancel_txn     = sparc_pmu_cancel_txn,
+       .commit_txn     = sparc_pmu_commit_txn,
  };
  
  const struct pmu *hw_perf_event_init(struct perf_event *event)