Commit c7c17c2779075e675cb3c7fe2ecde67e226771fb
1 parent
7466bd3caa
Exists in
master
and in
7 other branches
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 | } |