diff options
author | Jean Delvare <khali@linux-fr.org> | 2010-01-30 23:00:30 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2010-02-03 01:39:49 -0500 |
commit | 33a470f6d5e1879c26f16f6b34dc09f82d44f6e9 (patch) | |
tree | fc3111cc16b918e9a5f643118653f8b163184a24 /drivers/macintosh/therm_adt746x.c | |
parent | 119ea10947cc1402abbf9d6200815b0606536906 (diff) |
macintosh/therm_adt746x: Fix sysfs attributes lifetime
Looking at drivers/macintosh/therm_adt746x.c, the sysfs files are
created in thermostat_init() and removed in thermostat_exit(), which
are the driver's init and exit functions. These files are backed-up by
a per-device structure, so it looks like the wrong thing to do: the
sysfs files have a lifetime longer than the data structure that is
backing it up.
I think that sysfs files creation should be moved to the end of
probe_thermostat() and sysfs files removal should be moved to the
beginning of remove_thermostat().
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Tested-by: Christian Kujau <lists@nerdbynature.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Colin Leroy <colin@colino.net>
Cc: stable@kernel.org
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/macintosh/therm_adt746x.c')
-rw-r--r-- | drivers/macintosh/therm_adt746x.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 5ff47ba7f2d0..58809b0510f9 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c | |||
@@ -90,6 +90,8 @@ static struct task_struct *thread_therm = NULL; | |||
90 | 90 | ||
91 | static void write_both_fan_speed(struct thermostat *th, int speed); | 91 | static void write_both_fan_speed(struct thermostat *th, int speed); |
92 | static void write_fan_speed(struct thermostat *th, int speed, int fan); | 92 | static void write_fan_speed(struct thermostat *th, int speed, int fan); |
93 | static void thermostat_create_files(void); | ||
94 | static void thermostat_remove_files(void); | ||
93 | 95 | ||
94 | static int | 96 | static int |
95 | write_reg(struct thermostat* th, int reg, u8 data) | 97 | write_reg(struct thermostat* th, int reg, u8 data) |
@@ -161,6 +163,8 @@ remove_thermostat(struct i2c_client *client) | |||
161 | struct thermostat *th = i2c_get_clientdata(client); | 163 | struct thermostat *th = i2c_get_clientdata(client); |
162 | int i; | 164 | int i; |
163 | 165 | ||
166 | thermostat_remove_files(); | ||
167 | |||
164 | if (thread_therm != NULL) { | 168 | if (thread_therm != NULL) { |
165 | kthread_stop(thread_therm); | 169 | kthread_stop(thread_therm); |
166 | } | 170 | } |
@@ -449,6 +453,8 @@ static int probe_thermostat(struct i2c_client *client, | |||
449 | return -ENOMEM; | 453 | return -ENOMEM; |
450 | } | 454 | } |
451 | 455 | ||
456 | thermostat_create_files(); | ||
457 | |||
452 | return 0; | 458 | return 0; |
453 | } | 459 | } |
454 | 460 | ||
@@ -566,7 +572,6 @@ thermostat_init(void) | |||
566 | struct device_node* np; | 572 | struct device_node* np; |
567 | const u32 *prop; | 573 | const u32 *prop; |
568 | int i = 0, offset = 0; | 574 | int i = 0, offset = 0; |
569 | int err; | ||
570 | 575 | ||
571 | np = of_find_node_by_name(NULL, "fan"); | 576 | np = of_find_node_by_name(NULL, "fan"); |
572 | if (!np) | 577 | if (!np) |
@@ -633,6 +638,17 @@ thermostat_init(void) | |||
633 | return -ENODEV; | 638 | return -ENODEV; |
634 | } | 639 | } |
635 | 640 | ||
641 | #ifndef CONFIG_I2C_POWERMAC | ||
642 | request_module("i2c-powermac"); | ||
643 | #endif | ||
644 | |||
645 | return i2c_add_driver(&thermostat_driver); | ||
646 | } | ||
647 | |||
648 | static void thermostat_create_files(void) | ||
649 | { | ||
650 | int err; | ||
651 | |||
636 | err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); | 652 | err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); |
637 | err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); | 653 | err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); |
638 | err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); | 654 | err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); |
@@ -647,16 +663,9 @@ thermostat_init(void) | |||
647 | if (err) | 663 | if (err) |
648 | printk(KERN_WARNING | 664 | printk(KERN_WARNING |
649 | "Failed to create tempertaure attribute file(s).\n"); | 665 | "Failed to create tempertaure attribute file(s).\n"); |
650 | |||
651 | #ifndef CONFIG_I2C_POWERMAC | ||
652 | request_module("i2c-powermac"); | ||
653 | #endif | ||
654 | |||
655 | return i2c_add_driver(&thermostat_driver); | ||
656 | } | 666 | } |
657 | 667 | ||
658 | static void __exit | 668 | static void thermostat_remove_files(void) |
659 | thermostat_exit(void) | ||
660 | { | 669 | { |
661 | if (of_dev) { | 670 | if (of_dev) { |
662 | device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); | 671 | device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); |
@@ -673,9 +682,14 @@ thermostat_exit(void) | |||
673 | device_remove_file(&of_dev->dev, | 682 | device_remove_file(&of_dev->dev, |
674 | &dev_attr_sensor2_fan_speed); | 683 | &dev_attr_sensor2_fan_speed); |
675 | 684 | ||
676 | of_device_unregister(of_dev); | ||
677 | } | 685 | } |
686 | } | ||
687 | |||
688 | static void __exit | ||
689 | thermostat_exit(void) | ||
690 | { | ||
678 | i2c_del_driver(&thermostat_driver); | 691 | i2c_del_driver(&thermostat_driver); |
692 | of_device_unregister(of_dev); | ||
679 | } | 693 | } |
680 | 694 | ||
681 | module_init(thermostat_init); | 695 | module_init(thermostat_init); |