aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-01-04 18:31:10 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-04 18:31:10 -0500
commitc7c17c2779075e675cb3c7fe2ecde67e226771fb (patch)
tree680ab98f6f9b2275b7140f73a3c3a842062a7e93
parent7466bd3caab6bd1d0095de957affbacd02ca58a7 (diff)
bbc_envctrl: Clean up properly if kthread_run() fails.
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 <pat@computer-refuge.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/sbus/char/bbc_envctrl.c64
1 files changed, 38 insertions, 26 deletions
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 7c815d3327f7..28d86f9df83c 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
522 set_fan_speeds(fp); 522 set_fan_speeds(fp);
523} 523}
524 524
525static void destroy_one_temp(struct bbc_cpu_temperature *tp)
526{
527 bbc_i2c_detach(tp->client);
528 kfree(tp);
529}
530
531static void destroy_all_temps(struct bbc_i2c_bus *bp)
532{
533 struct bbc_cpu_temperature *tp, *tpos;
534
535 list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
536 list_del(&tp->bp_list);
537 list_del(&tp->glob_list);
538 destroy_one_temp(tp);
539 }
540}
541
542static void destroy_one_fan(struct bbc_fan_control *fp)
543{
544 bbc_i2c_detach(fp->client);
545 kfree(fp);
546}
547
548static void destroy_all_fans(struct bbc_i2c_bus *bp)
549{
550 struct bbc_fan_control *fp, *fpos;
551
552 list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
553 list_del(&fp->bp_list);
554 list_del(&fp->glob_list);
555 destroy_one_fan(fp);
556 }
557}
558
525int bbc_envctrl_init(struct bbc_i2c_bus *bp) 559int bbc_envctrl_init(struct bbc_i2c_bus *bp)
526{ 560{
527 struct of_device *op; 561 struct of_device *op;
@@ -541,6 +575,8 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
541 int err = PTR_ERR(kenvctrld_task); 575 int err = PTR_ERR(kenvctrld_task);
542 576
543 kenvctrld_task = NULL; 577 kenvctrld_task = NULL;
578 destroy_all_temps(bp);
579 destroy_all_fans(bp);
544 return err; 580 return err;
545 } 581 }
546 } 582 }
@@ -548,35 +584,11 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
548 return 0; 584 return 0;
549} 585}
550 586
551static void destroy_one_temp(struct bbc_cpu_temperature *tp)
552{
553 bbc_i2c_detach(tp->client);
554 kfree(tp);
555}
556
557static void destroy_one_fan(struct bbc_fan_control *fp)
558{
559 bbc_i2c_detach(fp->client);
560 kfree(fp);
561}
562
563void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) 587void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
564{ 588{
565 struct bbc_cpu_temperature *tp, *tpos;
566 struct bbc_fan_control *fp, *fpos;
567
568 if (kenvctrld_task) 589 if (kenvctrld_task)
569 kthread_stop(kenvctrld_task); 590 kthread_stop(kenvctrld_task);
570 591
571 list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { 592 destroy_all_temps(bp);
572 list_del(&tp->bp_list); 593 destroy_all_fans(bp);
573 list_del(&tp->glob_list);
574 destroy_one_temp(tp);
575 }
576
577 list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
578 list_del(&fp->bp_list);
579 list_del(&fp->glob_list);
580 destroy_one_fan(fp);
581 }
582} 594}