@@ -102,6 +102,7 @@ struct arm_ni_unit {
struct arm_ni_cd {
void __iomem *pmu_base;
u16 id;
+ bool pmu_registered;
int num_units;
int irq;
int cpu;
@@ -571,6 +572,8 @@ static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_s
err = perf_pmu_register(&cd->pmu, name, -1);
if (err)
cpuhp_state_remove_instance_nocalls(arm_ni_hp_state, &cd->cpuhp_node);
+ else
+ cd->pmu_registered = true;
return err;
}
@@ -593,6 +596,7 @@ static int arm_ni_probe(struct platform_device *pdev)
void __iomem *base;
static atomic_t id;
int num_cds;
+ int ret;
u32 reg, part;
/*
@@ -651,18 +655,29 @@ static int arm_ni_probe(struct platform_device *pdev)
reg = readl_relaxed(vd.base + NI_CHILD_PTR(p));
arm_ni_probe_domain(base + reg, &pd);
for (int c = 0; c < pd.num_components; c++) {
- int ret;
-
reg = readl_relaxed(pd.base + NI_CHILD_PTR(c));
arm_ni_probe_domain(base + reg, &cd);
ret = arm_ni_init_cd(ni, &cd, res->start);
if (ret)
- return ret;
+ goto init_cd_cleanup;
}
}
}
return 0;
+
+init_cd_cleanup:
+ for (int i = 0; i < ni->num_cds; i++) {
+ struct arm_ni_cd *cd = ni->cds + i;
+
+ if (!cd->pmu_base)
+ continue;
+
+ if (cd->pmu_registered)
+ perf_pmu_unregister(&cd->pmu);
+ }
+
+ return ret;
}
static void arm_ni_remove(struct platform_device *pdev)