Thread (9 messages) 9 messages, 3 authors, 2017-06-15

[PATCH v5 3/3] perf: cavium: Support transmit-link PMU counters

From: mark.rutland@arm.com (Mark Rutland)
Date: 2017-06-02 16:40:21
Also in: lkml

On Wed, May 17, 2017 at 10:31:22AM +0200, Jan Glauber wrote:
quoted hunk ↗ jump to hunk
Add support for the transmit-link (TLK) PMU counters found
on Caviums SOCs with an interconnect.

Signed-off-by: Jan Glauber <redacted>
---
 drivers/edac/thunderx_edac.c    |   7 ++
 drivers/perf/cavium_pmu.c       | 223 +++++++++++++++++++++++++++++++++++++++-
 include/linux/perf/cavium_pmu.h |   1 +
 3 files changed, 230 insertions(+), 1 deletion(-)
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c
index 8de4faf..d3da6d3 100644
--- a/drivers/edac/thunderx_edac.c
+++ b/drivers/edac/thunderx_edac.c
@@ -1496,6 +1496,10 @@ static int thunderx_ocx_probe(struct pci_dev *pdev,
 
 	writeq(OCX_COM_INT_ENA_ALL, ocx->regs + OCX_COM_INT_ENA_W1S);
 
+	if (IS_ENABLED(CONFIG_CAVIUM_PMU))
+		ocx->pmu_data = cvm_pmu_probe(pdev, ocx->regs,
+					      CVM_PMU_TLK);
+
 	return 0;
 err_free:
 	edac_device_free_ctl_info(edac_dev);
@@ -1509,6 +1513,9 @@ static void thunderx_ocx_remove(struct pci_dev *pdev)
 	struct thunderx_ocx *ocx = edac_dev->pvt_info;
 	int i;
 
+	if (IS_ENABLED(CONFIG_CAVIUM_PMU))
+		cvm_pmu_remove(pdev, ocx->pmu_data, CVM_PMU_TLK);
+
As with the prior patch, I don't think we can handle the PMU like this.


[...]
+static int cvm_pmu_tlk_add(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return cvm_pmu_add(event, flags, TLK_STAT_CTL_OFFSET,
+			   TLK_STAT_OFFSET + hwc->config * 8);
+}
+static void *cvm_pmu_tlk_probe_unit(struct pci_dev *pdev, void __iomem *regs,
+				    int nr)
+{
+	struct cvm_pmu_dev *tlk;
+	int ret = -ENOMEM;
+	char name[12];
+
+	tlk = kzalloc(sizeof(*tlk), GFP_KERNEL);
+	if (!tlk)
+		goto fail_nomem;
+
+	memset(name, 0, 12);
+	snprintf(name, 12, "ocx_tlk%d", nr);
Please kasprintf() the name and pass it to perf_pmu_register().

AFAICT, pmu::name is a char *, and perf_pmu_register() doesn't make a copy, so
this isn't safe.
+
+	list_add(&tlk->entry, &cvm_pmu_tlks);
As withthe prio patch, please add the element to the list after
handling the failure cases.
+
+	tlk->pdev = pdev;
+	tlk->map = regs + TLK_START_ADDR + nr * TLK_UNIT_OFFSET;
+	tlk->num_counters = ARRAY_SIZE(cvm_pmu_tlk_events_attr) - 1;
+	tlk->pmu = (struct pmu) {
+		.name		= name,
+		.task_ctx_nr    = perf_invalid_context,
+		.pmu_enable	= cvm_pmu_tlk_enable_pmu,
+		.pmu_disable	= cvm_pmu_tlk_disable_pmu,
+		.event_init	= cvm_pmu_event_init,
+		.add		= cvm_pmu_tlk_add,
+		.del		= cvm_pmu_del,
+		.start		= cvm_pmu_start,
+		.stop		= cvm_pmu_stop,
+		.read		= cvm_pmu_read,
+		.attr_groups	= cvm_pmu_tlk_attr_groups,
+	};
+
+	cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CVM_ONLINE,
+					 &tlk->cpuhp_node);
+
+	/*
+	 * perf PMU is CPU dependent so pick a random CPU and migrate away
+	 * if it goes offline.
+	 */
+	cpumask_set_cpu(smp_processor_id(), &tlk->active_mask);
+
+	ret = perf_pmu_register(&tlk->pmu, tlk->pmu.name, -1);
+	if (ret)
+		goto fail_hp;
+
+	tlk->event_valid = cvm_pmu_tlk_event_valid;
+	return tlk;
+
+fail_hp:
+	cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_CVM_ONLINE,
+				    &tlk->cpuhp_node);
+	kfree(tlk);
+fail_nomem:
+	return ERR_PTR(ret);
+}
Thanks,
Mark.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help