Commit cb094fa5 authored by Anju T Sudhakar's avatar Anju T Sudhakar Committed by Michael Ellerman

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: default avatarAnju T Sudhakar <anju@linux.vnet.ibm.com>
Reviewed-by: default avatarMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 589b1f7e
...@@ -1153,7 +1153,7 @@ static void cleanup_all_core_imc_memory(void) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment