Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 327339
b: refs/heads/master
c: 7a37a0b
h: refs/heads/master
i:
  327337: 6c0ac07
  327335: 40e5f73
v: v3
  • Loading branch information
David S. Miller committed Aug 19, 2012
1 parent 77441aa commit f98a09c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 24 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b4f061a4b8cbf947de4fa816a1cfc53960da218e
refs/heads/master: 7a37a0b8f8df0872932cf8373b21b5e14a92a794
98 changes: 75 additions & 23 deletions trunk/arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,18 +710,10 @@ static int sparc_perf_event_set_period(struct perf_event *event,
return ret;
}

/* If performance event entries have been added, move existing
* events around (if necessary) and then assign new entries to
* counters.
*/
static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
static void read_in_all_counters(struct cpu_hw_events *cpuc)
{
int i;

if (!cpuc->n_added)
goto out;

/* Read in the counters which are moving. */
for (i = 0; i < cpuc->n_events; i++) {
struct perf_event *cp = cpuc->event[i];

Expand All @@ -732,6 +724,20 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
cpuc->current_idx[i] = PIC_NO_INDEX;
}
}
}

/* On this PMU all PICs are programmed using a single PCR. Calculate
* the combined control register value.
*
* For such chips we require that all of the events have the same
* configuration, so just fetch the settings from the first entry.
*/
static void calculate_single_pcr(struct cpu_hw_events *cpuc)
{
int i;

if (!cpuc->n_added)
goto out;

/* Assign to counters all unassigned events. */
for (i = 0; i < cpuc->n_events; i++) {
Expand All @@ -747,37 +753,83 @@ static u64 maybe_change_configuration(struct cpu_hw_events *cpuc, u64 pcr)
cpuc->current_idx[i] = idx;

enc = perf_event_get_enc(cpuc->events[i]);
pcr &= ~mask_for_index(idx);
cpuc->pcr[0] &= ~mask_for_index(idx);
if (hwc->state & PERF_HES_STOPPED)
pcr |= nop_for_index(idx);
cpuc->pcr[0] |= nop_for_index(idx);
else
pcr |= event_encoding(enc, idx);
cpuc->pcr[0] |= event_encoding(enc, idx);
}
out:
return pcr;
cpuc->pcr[0] |= cpuc->event[0]->hw.config_base;
}

/* On this PMU each PIC has it's own PCR control register. */
static void calculate_multiple_pcrs(struct cpu_hw_events *cpuc)
{
int i;

if (!cpuc->n_added)
goto out;

for (i = 0; i < cpuc->n_events; i++) {
struct perf_event *cp = cpuc->event[i];
struct hw_perf_event *hwc = &cp->hw;
int idx = hwc->idx;
u64 enc;

if (cpuc->current_idx[i] != PIC_NO_INDEX)
continue;

sparc_perf_event_set_period(cp, hwc, idx);
cpuc->current_idx[i] = idx;

enc = perf_event_get_enc(cpuc->events[i]);
cpuc->pcr[idx] &= ~mask_for_index(idx);
if (hwc->state & PERF_HES_STOPPED)
cpuc->pcr[idx] |= nop_for_index(idx);
else
cpuc->pcr[idx] |= event_encoding(enc, idx);
}
out:
for (i = 0; i < cpuc->n_events; i++) {
struct perf_event *cp = cpuc->event[i];
int idx = cp->hw.idx;

cpuc->pcr[idx] |= cp->hw.config_base;
}
}

/* If performance event entries have been added, move existing events
* around (if necessary) and then assign new entries to counters.
*/
static void update_pcrs_for_enable(struct cpu_hw_events *cpuc)
{
if (cpuc->n_added)
read_in_all_counters(cpuc);

if (sparc_pmu->num_pcrs == 1) {
calculate_single_pcr(cpuc);
} else {
calculate_multiple_pcrs(cpuc);
}
}

static void sparc_pmu_enable(struct pmu *pmu)
{
struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
int i;

if (cpuc->enabled)
return;

cpuc->enabled = 1;
barrier();

if (cpuc->n_events) {
u64 pcr = maybe_change_configuration(cpuc, cpuc->pcr[0]);

/* We require that all of the events have the same
* configuration, so just fetch the settings from the
* first entry.
*/
cpuc->pcr[0] = pcr | cpuc->event[0]->hw.config_base;
}
if (cpuc->n_events)
update_pcrs_for_enable(cpuc);

pcr_ops->write_pcr(0, cpuc->pcr[0]);
for (i = 0; i < sparc_pmu->num_pcrs; i++)
pcr_ops->write_pcr(i, cpuc->pcr[i]);
}

static void sparc_pmu_disable(struct pmu *pmu)
Expand Down

0 comments on commit f98a09c

Please sign in to comment.