aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/amc6821.c
diff options
context:
space:
mode:
authorAxel Lin <axel.lin@ingics.com>2014-07-30 21:43:19 -0400
committerGuenter Roeck <linux@roeck-us.net>2014-07-31 00:42:37 -0400
commitcf44819c98db11163f58f08b822d626c7a8f5188 (patch)
tree68af0f6580a73753e5c43bc51ba46a87aaa1a18b /drivers/hwmon/amc6821.c
parent1074d683a51f1aded3562add9ef313e75d557327 (diff)
hwmon: (amc6821) Fix possible race condition bug
Ensure mutex lock protects the read-modify-write period to prevent possible race condition bug. In additional, update data->valid should also be protected by the mutex lock. Signed-off-by: Axel Lin <axel.lin@ingics.com> Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/amc6821.c')
-rw-r--r--drivers/hwmon/amc6821.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
index 9f2be3dd28f3..8a67ec6279a4 100644
--- a/drivers/hwmon/amc6821.c
+++ b/drivers/hwmon/amc6821.c
@@ -360,11 +360,13 @@ static ssize_t set_pwm1_enable(
360 if (config) 360 if (config)
361 return config; 361 return config;
362 362
363 mutex_lock(&data->update_lock);
363 config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); 364 config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1);
364 if (config < 0) { 365 if (config < 0) {
365 dev_err(&client->dev, 366 dev_err(&client->dev,
366 "Error reading configuration register, aborting.\n"); 367 "Error reading configuration register, aborting.\n");
367 return config; 368 count = config;
369 goto unlock;
368 } 370 }
369 371
370 switch (val) { 372 switch (val) {
@@ -381,14 +383,15 @@ static ssize_t set_pwm1_enable(
381 config |= AMC6821_CONF1_FDRC1; 383 config |= AMC6821_CONF1_FDRC1;
382 break; 384 break;
383 default: 385 default:
384 return -EINVAL; 386 count = -EINVAL;
387 goto unlock;
385 } 388 }
386 mutex_lock(&data->update_lock);
387 if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { 389 if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) {
388 dev_err(&client->dev, 390 dev_err(&client->dev,
389 "Configuration register write error, aborting.\n"); 391 "Configuration register write error, aborting.\n");
390 count = -EIO; 392 count = -EIO;
391 } 393 }
394unlock:
392 mutex_unlock(&data->update_lock); 395 mutex_unlock(&data->update_lock);
393 return count; 396 return count;
394} 397}
@@ -493,8 +496,9 @@ static ssize_t set_temp_auto_point_temp(
493 return -EINVAL; 496 return -EINVAL;
494 } 497 }
495 498
496 data->valid = 0;
497 mutex_lock(&data->update_lock); 499 mutex_lock(&data->update_lock);
500 data->valid = 0;
501
498 switch (ix) { 502 switch (ix) {
499 case 0: 503 case 0:
500 ptemp[0] = clamp_val(val / 1000, 0, 504 ptemp[0] = clamp_val(val / 1000, 0,
@@ -658,13 +662,14 @@ static ssize_t set_fan1_div(
658 if (config) 662 if (config)
659 return config; 663 return config;
660 664
665 mutex_lock(&data->update_lock);
661 config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); 666 config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4);
662 if (config < 0) { 667 if (config < 0) {
663 dev_err(&client->dev, 668 dev_err(&client->dev,
664 "Error reading configuration register, aborting.\n"); 669 "Error reading configuration register, aborting.\n");
665 return config; 670 count = config;
671 goto EXIT;
666 } 672 }
667 mutex_lock(&data->update_lock);
668 switch (val) { 673 switch (val) {
669 case 2: 674 case 2:
670 config &= ~AMC6821_CONF4_PSPR; 675 config &= ~AMC6821_CONF4_PSPR;