Commit 6a82e23f authored by Thomas Richter's avatar Thomas Richter Committed by Vasily Gorbik

s390/cpumf: Adjust registration of s390 PMU device drivers

Linux-next commit titled "perf/core: Optimize perf_init_event()"
changed the semantics of PMU device driver registration.
It was done to speed up the lookup/handling of PMU device driver
specific events. It also enforces that only one PMU device
driver will be registered of type PERF_EVENT_RAW.

This change added these line in function perf_pmu_register():

  ...
  +       ret = idr_alloc(&pmu_idr, pmu, max, 0, GFP_KERNEL);
  +       if (ret < 0)
                goto free_pdc;
  +
  +       WARN_ON(type >= 0 && ret != type);

The warn_on generates a message. We have 3 PMU device drivers,
each registered as type PERF_TYPE_RAW.
The cf_diag device driver (arch/s390/kernel/perf_cpumf_cf_diag.c)
always hits the WARN_ON because it is the second PMU device driver
(after sampling device driver arch/s390/kernel/perf_cpumf_sf.c)
which is registered as type 4 (PERF_TYPE_RAW).
So when the sampling device driver is registered, ret has value 4.
When cf_diag device driver is registered with type 4,
ret has value of 5 and WARN_ON fires.

Adjust the PMU device drivers for s390 to support the new
semantics required by perf_pmu_register().
Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 72a81ad9
...@@ -199,7 +199,7 @@ static const int cpumf_generic_events_user[] = { ...@@ -199,7 +199,7 @@ static const int cpumf_generic_events_user[] = {
[PERF_COUNT_HW_BUS_CYCLES] = -1, [PERF_COUNT_HW_BUS_CYCLES] = -1,
}; };
static int __hw_perf_event_init(struct perf_event *event) static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
{ {
struct perf_event_attr *attr = &event->attr; struct perf_event_attr *attr = &event->attr;
struct hw_perf_event *hwc = &event->hw; struct hw_perf_event *hwc = &event->hw;
...@@ -207,7 +207,7 @@ static int __hw_perf_event_init(struct perf_event *event) ...@@ -207,7 +207,7 @@ static int __hw_perf_event_init(struct perf_event *event)
int err = 0; int err = 0;
u64 ev; u64 ev;
switch (attr->type) { switch (type) {
case PERF_TYPE_RAW: case PERF_TYPE_RAW:
/* Raw events are used to access counters directly, /* Raw events are used to access counters directly,
* hence do not permit excludes */ * hence do not permit excludes */
...@@ -294,17 +294,16 @@ static int __hw_perf_event_init(struct perf_event *event) ...@@ -294,17 +294,16 @@ static int __hw_perf_event_init(struct perf_event *event)
static int cpumf_pmu_event_init(struct perf_event *event) static int cpumf_pmu_event_init(struct perf_event *event)
{ {
unsigned int type = event->attr.type;
int err; int err;
switch (event->attr.type) { if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_RAW)
case PERF_TYPE_HARDWARE: err = __hw_perf_event_init(event, type);
case PERF_TYPE_HW_CACHE: else if (event->pmu->type == type)
case PERF_TYPE_RAW: /* Registered as unknown PMU */
err = __hw_perf_event_init(event); err = __hw_perf_event_init(event, PERF_TYPE_RAW);
break; else
default:
return -ENOENT; return -ENOENT;
}
if (unlikely(err) && event->destroy) if (unlikely(err) && event->destroy)
event->destroy(event); event->destroy(event);
...@@ -553,7 +552,7 @@ static int __init cpumf_pmu_init(void) ...@@ -553,7 +552,7 @@ static int __init cpumf_pmu_init(void)
return -ENODEV; return -ENODEV;
cpumf_pmu.attr_groups = cpumf_cf_event_group(); cpumf_pmu.attr_groups = cpumf_cf_event_group();
rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW); rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", -1);
if (rc) if (rc)
pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc); pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
return rc; return rc;
......
...@@ -243,13 +243,13 @@ static int cf_diag_event_init(struct perf_event *event) ...@@ -243,13 +243,13 @@ static int cf_diag_event_init(struct perf_event *event)
int err = -ENOENT; int err = -ENOENT;
debug_sprintf_event(cf_diag_dbg, 5, debug_sprintf_event(cf_diag_dbg, 5,
"%s event %p cpu %d config %#llx " "%s event %p cpu %d config %#llx type:%u "
"sample_type %#llx cf_diag_events %d\n", __func__, "sample_type %#llx cf_diag_events %d\n", __func__,
event, event->cpu, attr->config, attr->sample_type, event, event->cpu, attr->config, event->pmu->type,
atomic_read(&cf_diag_events)); attr->sample_type, atomic_read(&cf_diag_events));
if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG || if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
event->attr.type != PERF_TYPE_RAW) event->attr.type != event->pmu->type)
goto out; goto out;
/* Raw events are used to access counters directly, /* Raw events are used to access counters directly,
...@@ -693,7 +693,7 @@ static int __init cf_diag_init(void) ...@@ -693,7 +693,7 @@ static int __init cf_diag_init(void)
} }
debug_register_view(cf_diag_dbg, &debug_sprintf_view); debug_register_view(cf_diag_dbg, &debug_sprintf_view);
rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", PERF_TYPE_RAW); rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", -1);
if (rc) { if (rc) {
debug_unregister_view(cf_diag_dbg, &debug_sprintf_view); debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
debug_unregister(cf_diag_dbg); debug_unregister(cf_diag_dbg);
......
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