powerpc/perf: Rearrange memory freeing in imc init
When any of the IMC (In-Memory Collection counter) devices fail to initialize, imc_common_mem_free() frees set of memory. In doing so, pmu_ptr pointer is also freed. But pmu_ptr pointer is used in subsequent function (imc_common_cpuhp_mem_free()) which is wrong. Patch here reorders the code to avoid such access. Also free the memory which is dynamically allocated during imc initialization, wherever required. Signed-off-by: Anju T Sudhakar <anju@linux.vnet.ibm.com> Reviewed-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
589b1f7e4b
commit
cb094fa5af
|
@ -1153,7 +1153,7 @@ static void cleanup_all_core_imc_memory(void)
|
||||||
/* mem_info will never be NULL */
|
/* mem_info will never be NULL */
|
||||||
for (i = 0; i < nr_cores; i++) {
|
for (i = 0; i < nr_cores; i++) {
|
||||||
if (ptr[i].vbase)
|
if (ptr[i].vbase)
|
||||||
free_pages((u64)ptr->vbase, get_order(size));
|
free_pages((u64)ptr[i].vbase, get_order(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(ptr);
|
kfree(ptr);
|
||||||
|
@ -1191,7 +1191,6 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
|
||||||
if (pmu_ptr->attr_groups[IMC_EVENT_ATTR])
|
if (pmu_ptr->attr_groups[IMC_EVENT_ATTR])
|
||||||
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
|
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs);
|
||||||
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
|
kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]);
|
||||||
kfree(pmu_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1208,6 +1207,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
|
||||||
cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
|
cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
|
||||||
kfree(nest_imc_refc);
|
kfree(nest_imc_refc);
|
||||||
kfree(per_nest_pmu_arr);
|
kfree(per_nest_pmu_arr);
|
||||||
|
per_nest_pmu_arr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nest_pmus > 0)
|
if (nest_pmus > 0)
|
||||||
|
@ -1319,10 +1319,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = imc_mem_init(pmu_ptr, parent, pmu_idx);
|
ret = imc_mem_init(pmu_ptr, parent, pmu_idx);
|
||||||
if (ret) {
|
if (ret)
|
||||||
imc_common_mem_free(pmu_ptr);
|
goto err_free_mem;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pmu_ptr->domain) {
|
switch (pmu_ptr->domain) {
|
||||||
case IMC_DOMAIN_NEST:
|
case IMC_DOMAIN_NEST:
|
||||||
|
@ -1337,7 +1335,9 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
ret = init_nest_pmu_ref();
|
ret = init_nest_pmu_ref();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
mutex_unlock(&nest_init_lock);
|
mutex_unlock(&nest_init_lock);
|
||||||
goto err_free;
|
kfree(per_nest_pmu_arr);
|
||||||
|
per_nest_pmu_arr = NULL;
|
||||||
|
goto err_free_mem;
|
||||||
}
|
}
|
||||||
/* Register for cpu hotplug notification. */
|
/* Register for cpu hotplug notification. */
|
||||||
ret = nest_pmu_cpumask_init();
|
ret = nest_pmu_cpumask_init();
|
||||||
|
@ -1345,7 +1345,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
mutex_unlock(&nest_init_lock);
|
mutex_unlock(&nest_init_lock);
|
||||||
kfree(nest_imc_refc);
|
kfree(nest_imc_refc);
|
||||||
kfree(per_nest_pmu_arr);
|
kfree(per_nest_pmu_arr);
|
||||||
goto err_free;
|
per_nest_pmu_arr = NULL;
|
||||||
|
goto err_free_mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nest_pmus++;
|
nest_pmus++;
|
||||||
|
@ -1355,7 +1356,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
ret = core_imc_pmu_cpumask_init();
|
ret = core_imc_pmu_cpumask_init();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
cleanup_all_core_imc_memory();
|
cleanup_all_core_imc_memory();
|
||||||
return ret;
|
goto err_free_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1363,7 +1364,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
ret = thread_imc_cpu_init();
|
ret = thread_imc_cpu_init();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
cleanup_all_thread_imc_memory();
|
cleanup_all_thread_imc_memory();
|
||||||
return ret;
|
goto err_free_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1373,23 +1374,24 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
|
||||||
|
|
||||||
ret = update_events_in_group(parent, pmu_ptr);
|
ret = update_events_in_group(parent, pmu_ptr);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free_cpuhp_mem;
|
||||||
|
|
||||||
ret = update_pmu_ops(pmu_ptr);
|
ret = update_pmu_ops(pmu_ptr);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free_cpuhp_mem;
|
||||||
|
|
||||||
ret = perf_pmu_register(&pmu_ptr->pmu, pmu_ptr->pmu.name, -1);
|
ret = perf_pmu_register(&pmu_ptr->pmu, pmu_ptr->pmu.name, -1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_free;
|
goto err_free_cpuhp_mem;
|
||||||
|
|
||||||
pr_info("%s performance monitor hardware support registered\n",
|
pr_info("%s performance monitor hardware support registered\n",
|
||||||
pmu_ptr->pmu.name);
|
pmu_ptr->pmu.name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_free:
|
err_free_cpuhp_mem:
|
||||||
imc_common_mem_free(pmu_ptr);
|
|
||||||
imc_common_cpuhp_mem_free(pmu_ptr);
|
imc_common_cpuhp_mem_free(pmu_ptr);
|
||||||
|
err_free_mem:
|
||||||
|
imc_common_mem_free(pmu_ptr);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,10 @@ static int imc_get_mem_addr_nest(struct device_node *node,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL);
|
chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL);
|
||||||
if (!chipid_arr)
|
if (!chipid_arr) {
|
||||||
|
kfree(base_addr_arr);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips))
|
if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -143,7 +145,6 @@ static int imc_get_mem_addr_nest(struct device_node *node,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
kfree(pmu_ptr->mem_info);
|
|
||||||
kfree(base_addr_arr);
|
kfree(base_addr_arr);
|
||||||
kfree(chipid_arr);
|
kfree(chipid_arr);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -183,8 +184,14 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
|
||||||
|
|
||||||
/* Function to register IMC pmu */
|
/* Function to register IMC pmu */
|
||||||
ret = init_imc_pmu(parent, pmu_ptr, pmu_index);
|
ret = init_imc_pmu(parent, pmu_ptr, pmu_index);
|
||||||
if (ret)
|
if (ret) {
|
||||||
pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name);
|
pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name);
|
||||||
|
kfree(pmu_ptr->pmu.name);
|
||||||
|
if (pmu_ptr->domain == IMC_DOMAIN_NEST)
|
||||||
|
kfree(pmu_ptr->mem_info);
|
||||||
|
kfree(pmu_ptr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue