Subject: OProfile fix call to kzalloc From: Bob Nelson Fix OProfile kernel module to check pointer returned from kzalloc for success/failure. Eliminated unnecessary cast. Added some better error handling and cleanup in the related area of the code. Signed-off-by: Bob Nelson Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/oprofile/cell/pr_util.h =================================================================== --- linux-2.6.orig/arch/powerpc/oprofile/cell/pr_util.h +++ linux-2.6/arch/powerpc/oprofile/cell/pr_util.h @@ -70,7 +70,7 @@ void vma_map_free(struct vma_to_fileoffs * Entry point for SPU profiling. * cycles_reset is the SPU_CYCLES count value specified by the user. */ -void start_spu_profiling(unsigned int cycles_reset); +int start_spu_profiling(unsigned int cycles_reset); void stop_spu_profiling(void); Index: linux-2.6/arch/powerpc/oprofile/cell/spu_profiler.c =================================================================== --- linux-2.6.orig/arch/powerpc/oprofile/cell/spu_profiler.c +++ linux-2.6/arch/powerpc/oprofile/cell/spu_profiler.c @@ -192,23 +192,27 @@ static struct hrtimer timer; * cycles_reset is the count value specified by the user when * setting up OProfile to count SPU_CYCLES. */ -void start_spu_profiling(unsigned int cycles_reset) { +int start_spu_profiling(unsigned int cycles_reset) { ktime_t kt; - pr_debug("timer resolution: %lu\n", - TICK_NSEC); + pr_debug("timer resolution: %lu\n", TICK_NSEC); kt = ktime_set(0, profiling_interval); hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); timer.expires = kt; timer.function = profile_spus; /* Allocate arrays for collecting SPU PC samples */ - samples = (u32 *) kzalloc(SPUS_PER_NODE * - TRACE_ARRAY_SIZE * sizeof(u32), GFP_KERNEL); + samples = kzalloc(SPUS_PER_NODE * + TRACE_ARRAY_SIZE * sizeof(u32), GFP_KERNEL); + + if (!samples) + return -ENOMEM; spu_prof_running = 1; hrtimer_start(&timer, kt, HRTIMER_MODE_REL); + + return 0; } void stop_spu_profiling(void) Index: linux-2.6/arch/powerpc/oprofile/op_model_cell.c =================================================================== --- linux-2.6.orig/arch/powerpc/oprofile/op_model_cell.c +++ linux-2.6/arch/powerpc/oprofile/op_model_cell.c @@ -40,6 +40,8 @@ #include "../platforms/cell/cbe_regs.h" #include "cell/pr_util.h" +static void cell_global_stop_spu(void); + /* * spu_cycle_reset is the number of cycles between samples. * This variable is used for SPU profiling and should ONLY be set @@ -876,7 +878,7 @@ static struct notifier_block cpu_freq_no static int cell_global_start_spu(struct op_counter_config *ctr) { - int subfunc, rtn_value; + int subfunc; unsigned int lfsr_value; int cpu; int ret; @@ -939,23 +941,27 @@ static int cell_global_start_spu(struct subfunc = 2; /* 2 - activate SPU tracing, 3 - deactivate */ /* start profiling */ - rtn_value = rtas_call(spu_rtas_token, 3, 1, NULL, subfunc, + ret = rtas_call(spu_rtas_token, 3, 1, NULL, subfunc, cbe_cpu_to_node(cpu), lfsr_value); - if (unlikely(rtn_value != 0)) { + if (unlikely(ret != 0)) { printk(KERN_ERR "%s: rtas call ibm,cbe-spu-perftools failed, return = %d\n", - __FUNCTION__, rtn_value); + __FUNCTION__, ret); rtas_error = -EIO; goto out; } } - start_spu_profiling(spu_cycle_reset); + rtas_error = start_spu_profiling(spu_cycle_reset); + if (rtas_error) + goto out_stop; oprofile_running = 1; return 0; +out_stop: + cell_global_stop_spu(); /* clean up the PMU/debug bus */ out: return rtas_error; }