Skip to content

Commit

Permalink
i8k: Convert to use to hwmon_device_register_with_groups hwmon API
Browse files Browse the repository at this point in the history
Simplify code and fix race condition caused by registering
hwmon device prior to creating sysfs attributes.

Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Guenter Roeck authored and Greg Kroah-Hartman committed Dec 19, 2013
1 parent 12186f5 commit 82ba1d3
Showing 1 changed file with 54 additions and 78 deletions.
132 changes: 54 additions & 78 deletions drivers/char/i8k.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@
static DEFINE_MUTEX(i8k_mutex);
static char bios_version[4];
static struct device *i8k_hwmon_dev;
static u32 i8k_hwmon_flags;

#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
#define I8K_HWMON_HAVE_FAN1 (1 << 1)
#define I8K_HWMON_HAVE_FAN2 (1 << 2)

MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
Expand Down Expand Up @@ -502,8 +507,7 @@ static ssize_t i8k_hwmon_show_label(struct device *dev,
struct device_attribute *devattr,
char *buf)
{
static const char *labels[4] = {
"i8k",
static const char *labels[3] = {
"CPU",
"Left Fan",
"Right Fan",
Expand All @@ -518,100 +522,72 @@ static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
I8K_FAN_LEFT);
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
I8K_FAN_RIGHT);
static SENSOR_DEVICE_ATTR(name, S_IRUGO, i8k_hwmon_show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1);
static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2);
static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 3);
static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1);
static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2);

static struct attribute *i8k_attrs[] = {
&dev_attr_temp1_input.attr, /* 0 */
&sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */
&sensor_dev_attr_fan1_input.dev_attr.attr, /* 2 */
&sensor_dev_attr_fan1_label.dev_attr.attr, /* 3 */
&sensor_dev_attr_fan2_input.dev_attr.attr, /* 4 */
&sensor_dev_attr_fan2_label.dev_attr.attr, /* 5 */
NULL
};

static void i8k_hwmon_remove_files(struct device *dev)
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
device_remove_file(dev, &dev_attr_temp1_input);
device_remove_file(dev, &sensor_dev_attr_fan1_input.dev_attr);
device_remove_file(dev, &sensor_dev_attr_fan2_input.dev_attr);
device_remove_file(dev, &sensor_dev_attr_temp1_label.dev_attr);
device_remove_file(dev, &sensor_dev_attr_fan1_label.dev_attr);
device_remove_file(dev, &sensor_dev_attr_fan2_label.dev_attr);
device_remove_file(dev, &sensor_dev_attr_name.dev_attr);
if ((index == 0 || index == 1) &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
return 0;
if ((index == 2 || index == 3) &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
return 0;
if ((index == 4 || index == 5) &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
return 0;

return attr->mode;
}

static const struct attribute_group i8k_group = {
.attrs = i8k_attrs,
.is_visible = i8k_is_visible,
};
__ATTRIBUTE_GROUPS(i8k);

static int __init i8k_init_hwmon(void)
{
int err;

i8k_hwmon_dev = hwmon_device_register(NULL);
if (IS_ERR(i8k_hwmon_dev)) {
err = PTR_ERR(i8k_hwmon_dev);
i8k_hwmon_dev = NULL;
pr_err("hwmon registration failed (%d)\n", err);
return err;
}

/* Required name attribute */
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_name.dev_attr);
if (err)
goto exit_unregister;
i8k_hwmon_flags = 0;

/* CPU temperature attributes, if temperature reading is OK */
err = i8k_get_temp(0);
if (err < 0) {
dev_dbg(i8k_hwmon_dev,
"Not creating temperature attributes (%d)\n", err);
} else {
err = device_create_file(i8k_hwmon_dev, &dev_attr_temp1_input);
if (err)
goto exit_remove_files;
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_temp1_label.dev_attr);
if (err)
goto exit_remove_files;
}
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;

/* Left fan attributes, if left fan is present */
err = i8k_get_fan_status(I8K_FAN_LEFT);
if (err < 0) {
dev_dbg(i8k_hwmon_dev,
"Not creating %s fan attributes (%d)\n", "left", err);
} else {
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_fan1_input.dev_attr);
if (err)
goto exit_remove_files;
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_fan1_label.dev_attr);
if (err)
goto exit_remove_files;
}
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;

/* Right fan attributes, if right fan is present */
err = i8k_get_fan_status(I8K_FAN_RIGHT);
if (err < 0) {
dev_dbg(i8k_hwmon_dev,
"Not creating %s fan attributes (%d)\n", "right", err);
} else {
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_fan2_input.dev_attr);
if (err)
goto exit_remove_files;
err = device_create_file(i8k_hwmon_dev,
&sensor_dev_attr_fan2_label.dev_attr);
if (err)
goto exit_remove_files;
}
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;

i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "i8k", NULL,
i8k_groups);
if (IS_ERR(i8k_hwmon_dev)) {
err = PTR_ERR(i8k_hwmon_dev);
i8k_hwmon_dev = NULL;
pr_err("hwmon registration failed (%d)\n", err);
return err;
}
return 0;

exit_remove_files:
i8k_hwmon_remove_files(i8k_hwmon_dev);
exit_unregister:
hwmon_device_unregister(i8k_hwmon_dev);
return err;
}

static void __exit i8k_exit_hwmon(void)
{
i8k_hwmon_remove_files(i8k_hwmon_dev);
hwmon_device_unregister(i8k_hwmon_dev);
}

static struct dmi_system_id i8k_dmi_table[] __initdata = {
Expand Down Expand Up @@ -774,7 +750,7 @@ static int __init i8k_init(void)

static void __exit i8k_exit(void)
{
i8k_exit_hwmon();
hwmon_device_unregister(i8k_hwmon_dev);
remove_proc_entry("i8k", NULL);
}

Expand Down

0 comments on commit 82ba1d3

Please sign in to comment.