Commit c7c17c2779075e675cb3c7fe2ecde67e226771fb

Authored by David S. Miller
1 parent 7466bd3caa

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>

Showing 1 changed file with 38 additions and 26 deletions Side-by-side Diff

drivers/sbus/char/bbc_envctrl.c
... ... @@ -522,6 +522,40 @@
522 522 set_fan_speeds(fp);
523 523 }
524 524  
  525 +static void destroy_one_temp(struct bbc_cpu_temperature *tp)
  526 +{
  527 + bbc_i2c_detach(tp->client);
  528 + kfree(tp);
  529 +}
  530 +
  531 +static 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 +
  542 +static void destroy_one_fan(struct bbc_fan_control *fp)
  543 +{
  544 + bbc_i2c_detach(fp->client);
  545 + kfree(fp);
  546 +}
  547 +
  548 +static 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 +
525 559 int bbc_envctrl_init(struct bbc_i2c_bus *bp)
526 560 {
527 561 struct of_device *op;
... ... @@ -541,6 +575,8 @@
541 575 int err = PTR_ERR(kenvctrld_task);
542 576  
543 577 kenvctrld_task = NULL;
  578 + destroy_all_temps(bp);
  579 + destroy_all_fans(bp);
544 580 return err;
545 581 }
546 582 }
547 583  
548 584  
... ... @@ -548,36 +584,12 @@
548 584 return 0;
549 585 }
550 586  
551   -static void destroy_one_temp(struct bbc_cpu_temperature *tp)
552   -{
553   - bbc_i2c_detach(tp->client);
554   - kfree(tp);
555   -}
556   -
557   -static void destroy_one_fan(struct bbc_fan_control *fp)
558   -{
559   - bbc_i2c_detach(fp->client);
560   - kfree(fp);
561   -}
562   -
563 587 void 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 589 if (kenvctrld_task)
569 590 kthread_stop(kenvctrld_task);
570 591  
571   - list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
572   - list_del(&tp->bp_list);
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   - }
  592 + destroy_all_temps(bp);
  593 + destroy_all_fans(bp);
582 594 }