Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

Commit

Permalink
perf: arm_cmn: improve and make it work on 2P.
Browse files Browse the repository at this point in the history
There are following fixes:
1. If DTC node was discovered before other nodes, the old
code would register pmu events before discovery finish
which causing missing events in pmu sys tree.
2. CPU hotplug state needs to be initialized per driver,
not per instance.
3. Use ACPI UID to create unique name for each instance.

Signed-off-by: Tuan Phan <[email protected]>
  • Loading branch information
tphan-ampere committed Apr 21, 2020
1 parent 19a1b38 commit c6f079f
Showing 1 changed file with 78 additions and 22 deletions.
100 changes: 78 additions & 22 deletions drivers/perf/arm-cmn.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@
//TODO: Is it worth probing dt_dbg_id.num_pmucntr?
#define CMN_DT_NUM_COUNTERS 8


enum cmn_node_type {
CMN_TYPE_INVALID,
CMN_TYPE_DVM,
Expand All @@ -126,6 +125,7 @@ enum cmn_node_type {
struct arm_cmn {
struct device *dev;
void __iomem *base;
void __iomem *dtc_base;

u8 mesh_x;
u8 mesh_y;
Expand Down Expand Up @@ -170,6 +170,9 @@ struct arm_cmn_dtc {

#define to_cmn_dtc(x) container_of(x, struct arm_cmn_dtc, pmu)

/* Keep track of our dynamic hotplug state */
static enum cpuhp_state arm_cmn_cpuhp_state;

struct arm_cmn_event_attr {
struct device_attribute attr;
enum cmn_node_type type;
Expand Down Expand Up @@ -765,20 +768,28 @@ static irqreturn_t arm_cmn_irq_handler(int irq, void *dev_id)
return res;
}

static int arm_cmn_init_pmu(struct arm_cmn *cmn, void __iomem *base, int id)
static int arm_cmn_init_pmu(struct arm_cmn *cmn)
{
struct platform_device *pdev = to_platform_device(cmn->dev);
struct arm_cmn_dtc *dtc;
unsigned long long value;
acpi_handle handle;
acpi_status status;
const char *name;
int irq, err;

if (!cmn->dtc_base) {
dev_err(cmn->dev, "no DTC found\n");
return -ENODEV;
}

dtc = devm_kzalloc(cmn->dev, sizeof(*dtc), GFP_KERNEL);
if (!dtc)
return -ENOMEM;

irq = platform_get_irq(pdev, id);
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(cmn->dev, "missing IRQ for DTC %d\n", id);
dev_err(cmn->dev, "missing IRQ for DTC\n");
return -EINVAL;
}

Expand All @@ -788,8 +799,10 @@ static int arm_cmn_init_pmu(struct arm_cmn *cmn, void __iomem *base, int id)
if (err)
return err;

platform_set_drvdata(pdev, dtc);

dtc->cmn = cmn;
dtc->base = base;
dtc->base = cmn->dtc_base;
dtc->cpu = get_cpu();
dtc->pmu = (struct pmu) {
.attr_groups = arm_cmn_attr_groups,
Expand All @@ -804,21 +817,35 @@ static int arm_cmn_init_pmu(struct arm_cmn *cmn, void __iomem *base, int id)
.read = arm_cmn_event_read,
};

if (id == 0) {
name = "arm_cmn";
handle = ACPI_HANDLE(cmn->dev);
if (handle) {
status = acpi_evaluate_integer(handle, METHOD_NAME__UID, NULL,
&value);
if (ACPI_FAILURE(status)) {
dev_err(cmn->dev,
"Failed to evaluate _UID (0x%x)\n", status);
return -ENODEV;
}

name = devm_kasprintf(cmn->dev, GFP_KERNEL, "arm_cmn_%d",
(unsigned int)value);
} else {
name = devm_kasprintf(cmn->dev, GFP_KERNEL, "arm_cmn_%d", id);
if (!name)
return -ENOMEM;
/* FIXME: multiple instance if no ACPI? */
name = "arm_cmn";
}

cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CMN_ONLINE,
&dtc->cpuhp_node);
put_cpu();

writel_relaxed(CMN_DT_PMCR_PMU_EN, base + CMN_DT_PMCR);
writel_relaxed(CMN_DT_PMCR_PMU_EN, dtc->base + CMN_DT_PMCR);

err = perf_pmu_register(&dtc->pmu, name, -1);
if (err)
cpuhp_state_remove_instance(arm_cmn_cpuhp_state,
&dtc->cpuhp_node);

return perf_pmu_register(&dtc->pmu, name, -1);
return err;
}

static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset, int lvl)
Expand Down Expand Up @@ -884,8 +911,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset, int lv
"multiple DTCs not supported; events outside domain 0 will not be counted correctly\n");
return 0;
}
// FIXME: node_logid is apparently not a nice simple index
return arm_cmn_init_pmu(cmn, region, node_logid);
cmn->dtc_base = region;
return 0;
/* These guys have PMU events */
case CMN_TYPE_DVM:
case CMN_TYPE_HNI:
Expand All @@ -895,6 +922,10 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset, int lv
case CMN_TYPE_RND:
case CMN_TYPE_CXRA:
case CMN_TYPE_CXHA:
if (node_type == CMN_TYPE_RND) {
/* RND uses the same event type with RNI */
node_type = CMN_TYPE_RNI;
}
node = &cmn->dns[cmn->num_dns++];
break;
/* Nothing to see here */
Expand Down Expand Up @@ -1030,7 +1061,6 @@ static int arm_cmn_probe(struct platform_device *pdev)
return -ENOMEM;

cmn->dev = &pdev->dev;
platform_set_drvdata(pdev, cmn);

if (has_acpi_companion(cmn->dev))
rootnode = arm_cmn_acpi_probe(pdev, cmn);
Expand All @@ -1045,17 +1075,16 @@ static int arm_cmn_probe(struct platform_device *pdev)

arm_cmn_mesh_fixup(cmn);

return cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CMN_ONLINE,
"perf/arm/cmn:online", NULL,
arm_cmn_pmu_offline_cpu);
return arm_cmn_init_pmu(cmn);
}

static int arm_cmn_remove(struct platform_device *pdev)
{
//TODO: What's the neatest way to find the DTCs and clean them up?

cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_CMN_ONLINE);
struct arm_cmn_dtc *dtc = platform_get_drvdata(pdev);

//TODO: What's the neatest way to find the DTCs and clean them up?
cpuhp_state_remove_instance(arm_cmn_cpuhp_state,
&dtc->cpuhp_node);
return 0;
}

Expand All @@ -1082,7 +1111,34 @@ static struct platform_driver arm_cmn_driver = {
.probe = arm_cmn_probe,
.remove = arm_cmn_remove,
};
module_platform_driver(arm_cmn_driver);

static int __init arm_cmn_init(void)
{
int ret;

ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CMN_ONLINE,
"perf/arm/cmn:online", NULL,
arm_cmn_pmu_offline_cpu);
if (ret < 0)
return ret;

arm_cmn_cpuhp_state = ret;

ret = platform_driver_register(&arm_cmn_driver);
if (ret)
cpuhp_remove_multi_state(arm_cmn_cpuhp_state);

return ret;
}

static void __exit arm_cmn_exit(void)
{
platform_driver_unregister(&arm_cmn_driver);
cpuhp_remove_multi_state(arm_cmn_cpuhp_state);
}

module_init(arm_cmn_init);
module_exit(arm_cmn_exit);

MODULE_AUTHOR("Robin Murphy <[email protected]>");
MODULE_DESCRIPTION("Arm CMN-600 PMU driver");
Expand Down

0 comments on commit c6f079f

Please sign in to comment.