aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/chips/smsc47m1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/chips/smsc47m1.c')
-rw-r--r--drivers/i2c/chips/smsc47m1.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
index 8d22390378d79..0e12ca3694131 100644
--- a/drivers/i2c/chips/smsc47m1.c
+++ b/drivers/i2c/chips/smsc47m1.c
@@ -195,16 +195,20 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
{
struct i2c_client *client = to_i2c_client(dev);
struct smsc47m1_data *data = i2c_get_clientdata(client);
+ long rpmdiv, val = simple_strtol(buf, NULL, 10);
- long rpmdiv = simple_strtol(buf, NULL, 10)
- * DIV_FROM_REG(data->fan_div[nr]);
+ down(&data->update_lock);
+ rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]);
- if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040)
+ if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) {
+ up(&data->update_lock);
return -EINVAL;
+ }
data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
data->fan_preload[nr]);
+ up(&data->update_lock);
return count;
}
@@ -224,12 +228,16 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
if (new_div == old_div) /* No change */
return count;
+
+ down(&data->update_lock);
switch (new_div) {
case 1: data->fan_div[nr] = 0; break;
case 2: data->fan_div[nr] = 1; break;
case 4: data->fan_div[nr] = 2; break;
case 8: data->fan_div[nr] = 3; break;
- default: return -EINVAL;
+ default:
+ up(&data->update_lock);
+ return -EINVAL;
}
tmp = smsc47m1_read_value(client, SMSC47M1_REG_FANDIV) & 0x0F;
@@ -242,6 +250,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191);
smsc47m1_write_value(client, SMSC47M1_REG_FAN_PRELOAD(nr),
data->fan_preload[nr]);
+ up(&data->update_lock);
return count;
}
@@ -257,11 +266,13 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
if (val < 0 || val > 255)
return -EINVAL;
+ down(&data->update_lock);
data->pwm[nr] &= 0x81; /* Preserve additional bits */
data->pwm[nr] |= PWM_TO_REG(val);
-
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
data->pwm[nr]);
+ up(&data->update_lock);
+
return count;
}
@@ -276,11 +287,12 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
if (val != 0 && val != 1)
return -EINVAL;
+ down(&data->update_lock);
data->pwm[nr] &= 0xFE; /* preserve the other bits */
data->pwm[nr] |= !val;
-
smsc47m1_write_value(client, SMSC47M1_REG_PWM(nr),
data->pwm[nr]);
+ up(&data->update_lock);
return count;
}