Commit 9aae1780 authored by Kan Liang's avatar Kan Liang Committed by Ingo Molnar

perf/x86/intel/uncore: Clean up client IMC uncore

The counters in client IMC uncore are free running counters, not fixed
counters. It should be corrected. The new infrastructure for free
running counter should be applied.

Introducing a new type SNB_PCI_UNCORE_IMC_DATA for client IMC free
running counters.

Keeping the customized event_init() function to be compatible with old
event encoding.

Clean up other customized event_*() functions.
Signed-off-by: default avatarKan Liang <kan.liang@intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: acme@kernel.org
Cc: eranian@google.com
Link: http://lkml.kernel.org/r/1525371913-10597-8-git-send-email-kan.liang@intel.comSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 5a6c9d94
...@@ -285,6 +285,15 @@ static struct uncore_event_desc snb_uncore_imc_events[] = { ...@@ -285,6 +285,15 @@ static struct uncore_event_desc snb_uncore_imc_events[] = {
#define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE 0x5054 #define SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE 0x5054
#define SNB_UNCORE_PCI_IMC_CTR_BASE SNB_UNCORE_PCI_IMC_DATA_READS_BASE #define SNB_UNCORE_PCI_IMC_CTR_BASE SNB_UNCORE_PCI_IMC_DATA_READS_BASE
enum perf_snb_uncore_imc_freerunning_types {
SNB_PCI_UNCORE_IMC_DATA = 0,
SNB_PCI_UNCORE_IMC_FREERUNNING_TYPE_MAX,
};
static struct freerunning_counters snb_uncore_imc_freerunning[] = {
[SNB_PCI_UNCORE_IMC_DATA] = { SNB_UNCORE_PCI_IMC_DATA_READS_BASE, 0x4, 0x0, 2, 32 },
};
static struct attribute *snb_uncore_imc_formats_attr[] = { static struct attribute *snb_uncore_imc_formats_attr[] = {
&format_attr_event.attr, &format_attr_event.attr,
NULL, NULL,
...@@ -341,9 +350,8 @@ static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf ...@@ -341,9 +350,8 @@ static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf
} }
/* /*
* custom event_init() function because we define our own fixed, free * Keep the custom event_init() function compatible with old event
* running counters, so we do not want to conflict with generic uncore * encoding for free running counters.
* logic. Also simplifies processing
*/ */
static int snb_uncore_imc_event_init(struct perf_event *event) static int snb_uncore_imc_event_init(struct perf_event *event)
{ {
...@@ -405,11 +413,11 @@ static int snb_uncore_imc_event_init(struct perf_event *event) ...@@ -405,11 +413,11 @@ static int snb_uncore_imc_event_init(struct perf_event *event)
switch (cfg) { switch (cfg) {
case SNB_UNCORE_PCI_IMC_DATA_READS: case SNB_UNCORE_PCI_IMC_DATA_READS:
base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE; base = SNB_UNCORE_PCI_IMC_DATA_READS_BASE;
idx = UNCORE_PMC_IDX_FIXED; idx = UNCORE_PMC_IDX_FREERUNNING;
break; break;
case SNB_UNCORE_PCI_IMC_DATA_WRITES: case SNB_UNCORE_PCI_IMC_DATA_WRITES:
base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE; base = SNB_UNCORE_PCI_IMC_DATA_WRITES_BASE;
idx = UNCORE_PMC_IDX_FIXED + 1; idx = UNCORE_PMC_IDX_FREERUNNING;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -430,104 +438,6 @@ static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_ev ...@@ -430,104 +438,6 @@ static int snb_uncore_imc_hw_config(struct intel_uncore_box *box, struct perf_ev
return 0; return 0;
} }
static void snb_uncore_imc_event_start(struct perf_event *event, int flags)
{
struct intel_uncore_box *box = uncore_event_to_box(event);
u64 count;
if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
return;
event->hw.state = 0;
box->n_active++;
list_add_tail(&event->active_entry, &box->active_list);
count = snb_uncore_imc_read_counter(box, event);
local64_set(&event->hw.prev_count, count);
if (box->n_active == 1)
uncore_pmu_start_hrtimer(box);
}
static void snb_uncore_imc_event_read(struct perf_event *event)
{
struct intel_uncore_box *box = uncore_event_to_box(event);
u64 prev_count, new_count, delta;
int shift;
/*
* There are two free running counters in IMC.
* The index for the second one is hardcoded to
* UNCORE_PMC_IDX_FIXED + 1.
*/
if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
shift = 64 - uncore_fixed_ctr_bits(box);
else
shift = 64 - uncore_perf_ctr_bits(box);
/* the hrtimer might modify the previous event value */
again:
prev_count = local64_read(&event->hw.prev_count);
new_count = uncore_read_counter(box, event);
if (local64_xchg(&event->hw.prev_count, new_count) != prev_count)
goto again;
delta = (new_count << shift) - (prev_count << shift);
delta >>= shift;
local64_add(delta, &event->count);
}
static void snb_uncore_imc_event_stop(struct perf_event *event, int flags)
{
struct intel_uncore_box *box = uncore_event_to_box(event);
struct hw_perf_event *hwc = &event->hw;
if (!(hwc->state & PERF_HES_STOPPED)) {
box->n_active--;
WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
hwc->state |= PERF_HES_STOPPED;
list_del(&event->active_entry);
if (box->n_active == 0)
uncore_pmu_cancel_hrtimer(box);
}
if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
/*
* Drain the remaining delta count out of a event
* that we are disabling:
*/
snb_uncore_imc_event_read(event);
hwc->state |= PERF_HES_UPTODATE;
}
}
static int snb_uncore_imc_event_add(struct perf_event *event, int flags)
{
struct intel_uncore_box *box = uncore_event_to_box(event);
struct hw_perf_event *hwc = &event->hw;
if (!box)
return -ENODEV;
hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
if (!(flags & PERF_EF_START))
hwc->state |= PERF_HES_ARCH;
snb_uncore_imc_event_start(event, 0);
return 0;
}
static void snb_uncore_imc_event_del(struct perf_event *event, int flags)
{
snb_uncore_imc_event_stop(event, PERF_EF_UPDATE);
}
int snb_pci2phy_map_init(int devid) int snb_pci2phy_map_init(int devid)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
...@@ -559,11 +469,11 @@ int snb_pci2phy_map_init(int devid) ...@@ -559,11 +469,11 @@ int snb_pci2phy_map_init(int devid)
static struct pmu snb_uncore_imc_pmu = { static struct pmu snb_uncore_imc_pmu = {
.task_ctx_nr = perf_invalid_context, .task_ctx_nr = perf_invalid_context,
.event_init = snb_uncore_imc_event_init, .event_init = snb_uncore_imc_event_init,
.add = snb_uncore_imc_event_add, .add = uncore_pmu_event_add,
.del = snb_uncore_imc_event_del, .del = uncore_pmu_event_del,
.start = snb_uncore_imc_event_start, .start = uncore_pmu_event_start,
.stop = snb_uncore_imc_event_stop, .stop = uncore_pmu_event_stop,
.read = snb_uncore_imc_event_read, .read = uncore_pmu_event_read,
}; };
static struct intel_uncore_ops snb_uncore_imc_ops = { static struct intel_uncore_ops snb_uncore_imc_ops = {
...@@ -581,12 +491,10 @@ static struct intel_uncore_type snb_uncore_imc = { ...@@ -581,12 +491,10 @@ static struct intel_uncore_type snb_uncore_imc = {
.name = "imc", .name = "imc",
.num_counters = 2, .num_counters = 2,
.num_boxes = 1, .num_boxes = 1,
.fixed_ctr_bits = 32, .num_freerunning_types = SNB_PCI_UNCORE_IMC_FREERUNNING_TYPE_MAX,
.fixed_ctr = SNB_UNCORE_PCI_IMC_CTR_BASE, .freerunning = snb_uncore_imc_freerunning,
.event_descs = snb_uncore_imc_events, .event_descs = snb_uncore_imc_events,
.format_group = &snb_uncore_imc_format_group, .format_group = &snb_uncore_imc_format_group,
.perf_ctr = SNB_UNCORE_PCI_IMC_DATA_READS_BASE,
.event_mask = SNB_UNCORE_PCI_IMC_EVENT_MASK,
.ops = &snb_uncore_imc_ops, .ops = &snb_uncore_imc_ops,
.pmu = &snb_uncore_imc_pmu, .pmu = &snb_uncore_imc_pmu,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment