Skip to content

Commit

Permalink
bbc_envctrl: Clean up properly if kthread_run() fails.
Browse files Browse the repository at this point in the history
In bbc_envctrl_init() we have to unlink the fan and temp instances
from the lists because our caller is going to free up the 'bp' object
if we return an error.

We can't rely upon bbc_envctrl_cleanup() to do this work for us in
this case.

Reported-by: Patrick Finnegan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jan 4, 2010
1 parent 7466bd3 commit c7c17c2
Showing 1 changed file with 38 additions and 26 deletions.
64 changes: 38 additions & 26 deletions drivers/sbus/char/bbc_envctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
set_fan_speeds(fp);
}

static void destroy_one_temp(struct bbc_cpu_temperature *tp)
{
bbc_i2c_detach(tp->client);
kfree(tp);
}

static void destroy_all_temps(struct bbc_i2c_bus *bp)
{
struct bbc_cpu_temperature *tp, *tpos;

list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
list_del(&tp->bp_list);
list_del(&tp->glob_list);
destroy_one_temp(tp);
}
}

static void destroy_one_fan(struct bbc_fan_control *fp)
{
bbc_i2c_detach(fp->client);
kfree(fp);
}

static void destroy_all_fans(struct bbc_i2c_bus *bp)
{
struct bbc_fan_control *fp, *fpos;

list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
list_del(&fp->bp_list);
list_del(&fp->glob_list);
destroy_one_fan(fp);
}
}

int bbc_envctrl_init(struct bbc_i2c_bus *bp)
{
struct of_device *op;
Expand All @@ -541,42 +575,20 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
int err = PTR_ERR(kenvctrld_task);

kenvctrld_task = NULL;
destroy_all_temps(bp);
destroy_all_fans(bp);
return err;
}
}

return 0;
}

static void destroy_one_temp(struct bbc_cpu_temperature *tp)
{
bbc_i2c_detach(tp->client);
kfree(tp);
}

static void destroy_one_fan(struct bbc_fan_control *fp)
{
bbc_i2c_detach(fp->client);
kfree(fp);
}

void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
{
struct bbc_cpu_temperature *tp, *tpos;
struct bbc_fan_control *fp, *fpos;

if (kenvctrld_task)
kthread_stop(kenvctrld_task);

list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
list_del(&tp->bp_list);
list_del(&tp->glob_list);
destroy_one_temp(tp);
}

list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
list_del(&fp->bp_list);
list_del(&fp->glob_list);
destroy_one_fan(fp);
}
destroy_all_temps(bp);
destroy_all_fans(bp);
}

0 comments on commit c7c17c2

Please sign in to comment.