Skip to content

Commit 9b1ac04

Browse files
kjain101mpe
authored andcommitted
powerpc/papr_scm: Fix nvdimm event mappings
Commit 4c08d4b ("powerpc/papr_scm: Add perf interface support") added performance monitoring support for papr-scm nvdimm devices via perf interface. Commit also added an array in papr_scm_priv structure called "nvdimm_events_map", which got filled based on the result of H_SCM_PERFORMANCE_STATS hcall. Currently there is an assumption that the order of events in the stats buffer, returned by the hypervisor is same. And order also happens to matches with the events specified in nvdimm driver code. But this assumption is not documented in Power Architecture Platform Requirements (PAPR) document. Although the order of events happens to be same on current generation od system, but it might not be true in future generation systems. Fix the issue, by adding a static mapping for nvdimm events to corresponding stat-id, and removing the dynamic map from papr_scm_priv structure. Also remove the function papr_scm_pmu_check_events from papr_scm.c file, as we no longer need to copy stat-ids dynamically. Fixes: 4c08d4b ("powerpc/papr_scm: Add perf interface support") Reported-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> Signed-off-by: Kajol Jain <kjain@linux.ibm.com> Reviewed-by: Vaibhav Jain <vaibhav@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220804074852.55157-1-kjain@linux.ibm.com
1 parent 1c23f9e commit 9b1ac04

File tree

1 file changed

+27
-61
lines changed

1 file changed

+27
-61
lines changed

arch/powerpc/platforms/pseries/papr_scm.c

Lines changed: 27 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,6 @@ struct papr_scm_priv {
124124

125125
/* The bits which needs to be overridden */
126126
u64 health_bitmap_inject_mask;
127-
128-
/* array to have event_code and stat_id mappings */
129-
u8 *nvdimm_events_map;
130127
};
131128

132129
static int papr_scm_pmem_flush(struct nd_region *nd_region,
@@ -350,18 +347,41 @@ static ssize_t drc_pmem_query_stats(struct papr_scm_priv *p,
350347
#ifdef CONFIG_PERF_EVENTS
351348
#define to_nvdimm_pmu(_pmu) container_of(_pmu, struct nvdimm_pmu, pmu)
352349

350+
static const char * const nvdimm_events_map[] = {
351+
[1] = "CtlResCt",
352+
[2] = "CtlResTm",
353+
[3] = "PonSecs ",
354+
[4] = "MemLife ",
355+
[5] = "CritRscU",
356+
[6] = "HostLCnt",
357+
[7] = "HostSCnt",
358+
[8] = "HostSDur",
359+
[9] = "HostLDur",
360+
[10] = "MedRCnt ",
361+
[11] = "MedWCnt ",
362+
[12] = "MedRDur ",
363+
[13] = "MedWDur ",
364+
[14] = "CchRHCnt",
365+
[15] = "CchWHCnt",
366+
[16] = "FastWCnt",
367+
};
368+
353369
static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev, u64 *count)
354370
{
355371
struct papr_scm_perf_stat *stat;
356372
struct papr_scm_perf_stats *stats;
357373
struct papr_scm_priv *p = dev_get_drvdata(dev);
358374
int rc, size;
359375

376+
/* Invalid eventcode */
377+
if (event->attr.config == 0 || event->attr.config >= ARRAY_SIZE(nvdimm_events_map))
378+
return -EINVAL;
379+
360380
/* Allocate request buffer enough to hold single performance stat */
361381
size = sizeof(struct papr_scm_perf_stats) +
362382
sizeof(struct papr_scm_perf_stat);
363383

364-
if (!p || !p->nvdimm_events_map)
384+
if (!p)
365385
return -EINVAL;
366386

367387
stats = kzalloc(size, GFP_KERNEL);
@@ -370,7 +390,7 @@ static int papr_scm_pmu_get_value(struct perf_event *event, struct device *dev,
370390

371391
stat = &stats->scm_statistic[0];
372392
memcpy(&stat->stat_id,
373-
&p->nvdimm_events_map[event->attr.config * sizeof(stat->stat_id)],
393+
nvdimm_events_map[event->attr.config],
374394
sizeof(stat->stat_id));
375395
stat->stat_val = 0;
376396

@@ -458,56 +478,6 @@ static void papr_scm_pmu_del(struct perf_event *event, int flags)
458478
papr_scm_pmu_read(event);
459479
}
460480

461-
static int papr_scm_pmu_check_events(struct papr_scm_priv *p, struct nvdimm_pmu *nd_pmu)
462-
{
463-
struct papr_scm_perf_stat *stat;
464-
struct papr_scm_perf_stats *stats;
465-
u32 available_events;
466-
int index, rc = 0;
467-
468-
if (!p->stat_buffer_len)
469-
return -ENOENT;
470-
471-
available_events = (p->stat_buffer_len - sizeof(struct papr_scm_perf_stats))
472-
/ sizeof(struct papr_scm_perf_stat);
473-
if (available_events == 0)
474-
return -EOPNOTSUPP;
475-
476-
/* Allocate the buffer for phyp where stats are written */
477-
stats = kzalloc(p->stat_buffer_len, GFP_KERNEL);
478-
if (!stats) {
479-
rc = -ENOMEM;
480-
return rc;
481-
}
482-
483-
/* Called to get list of events supported */
484-
rc = drc_pmem_query_stats(p, stats, 0);
485-
if (rc)
486-
goto out;
487-
488-
/*
489-
* Allocate memory and populate nvdimm_event_map.
490-
* Allocate an extra element for NULL entry
491-
*/
492-
p->nvdimm_events_map = kcalloc(available_events + 1,
493-
sizeof(stat->stat_id),
494-
GFP_KERNEL);
495-
if (!p->nvdimm_events_map) {
496-
rc = -ENOMEM;
497-
goto out;
498-
}
499-
500-
/* Copy all stat_ids to event map */
501-
for (index = 0, stat = stats->scm_statistic;
502-
index < available_events; index++, ++stat) {
503-
memcpy(&p->nvdimm_events_map[index * sizeof(stat->stat_id)],
504-
&stat->stat_id, sizeof(stat->stat_id));
505-
}
506-
out:
507-
kfree(stats);
508-
return rc;
509-
}
510-
511481
static void papr_scm_pmu_register(struct papr_scm_priv *p)
512482
{
513483
struct nvdimm_pmu *nd_pmu;
@@ -519,8 +489,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
519489
goto pmu_err_print;
520490
}
521491

522-
rc = papr_scm_pmu_check_events(p, nd_pmu);
523-
if (rc)
492+
if (!p->stat_buffer_len)
524493
goto pmu_check_events_err;
525494

526495
nd_pmu->pmu.task_ctx_nr = perf_invalid_context;
@@ -539,7 +508,7 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
539508

540509
rc = register_nvdimm_pmu(nd_pmu, p->pdev);
541510
if (rc)
542-
goto pmu_register_err;
511+
goto pmu_check_events_err;
543512

544513
/*
545514
* Set archdata.priv value to nvdimm_pmu structure, to handle the
@@ -548,8 +517,6 @@ static void papr_scm_pmu_register(struct papr_scm_priv *p)
548517
p->pdev->archdata.priv = nd_pmu;
549518
return;
550519

551-
pmu_register_err:
552-
kfree(p->nvdimm_events_map);
553520
pmu_check_events_err:
554521
kfree(nd_pmu);
555522
pmu_err_print:
@@ -1560,7 +1527,6 @@ static int papr_scm_remove(struct platform_device *pdev)
15601527
unregister_nvdimm_pmu(pdev->archdata.priv);
15611528

15621529
pdev->archdata.priv = NULL;
1563-
kfree(p->nvdimm_events_map);
15641530
kfree(p->bus_desc.provider_name);
15651531
kfree(p);
15661532

0 commit comments

Comments
 (0)