[Cbe-oss-dev] [PATCH] OProfile fix call to kzalloc
Bob Nelson
rrnelson at linux.vnet.ibm.com
Sat Jun 23 04:36:31 EST 2007
Ok, try again without any Windows programs involved this time...
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 <rrnelson at us.ibm.com
Index: linux-2.6.21-rc7/arch/powerpc/oprofile/cell/pr_util.h
===================================================================
--- linux-2.6.21-rc7.orig/arch/powerpc/oprofile/cell/pr_util.h
+++ linux-2.6.21-rc7/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.21-rc7/arch/powerpc/oprofile/cell/spu_profiler.c
===================================================================
--- linux-2.6.21-rc7.orig/arch/powerpc/oprofile/cell/spu_profiler.c
+++ linux-2.6.21-rc7/arch/powerpc/oprofile/cell/spu_profiler.c
@@ -22,7 +22,7 @@
#define TRACE_ARRAY_SIZE 1024
#define SCALE_SHIFT 14
-static u32 * samples;
+static u32 * samples = 0;
static int spu_prof_running = 0;
static unsigned int profiling_interval = 0;
@@ -192,9 +192,10 @@ 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;
+ int ret = 0;
pr_debug("timer resolution: %lu\n",
TICK_NSEC);
@@ -204,17 +205,25 @@ void start_spu_profiling(unsigned int cy
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);
- spu_prof_running = 1;
- hrtimer_start(&timer, kt, HRTIMER_MODE_REL);
+ if (unlikely(samples == 0)) {
+ ret = -ENOMEM;
+ } else {
+ spu_prof_running = 1;
+ hrtimer_start(&timer, kt, HRTIMER_MODE_REL);
+ }
+
+ return ret;
}
void stop_spu_profiling(void)
{
spu_prof_running = 0;
hrtimer_cancel(&timer);
- kfree(samples);
+ if (samples != 0) {
+ kfree(samples);
+ }
pr_debug("SPU_PROF: stop_spu_profiling issued\n");
}
Index: linux-2.6.21-rc7/arch/powerpc/oprofile/op_model_cell.c
===================================================================
--- linux-2.6.21-rc7.orig/arch/powerpc/oprofile/op_model_cell.c
+++ linux-2.6.21-rc7/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,19 +941,24 @@ 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);
+ ret = start_spu_profiling(spu_cycle_reset);
+ if (unlikely(ret != 0)) {
+ cell_global_stop_spu(); /* clean up the PMU/debug bus */
+ rtas_error = ret;
+ goto out;
+ }
oprofile_running = 1;
return 0;
More information about the cbe-oss-dev
mailing list