diff options
author | Axel Lin <axel.lin@ingics.com> | 2014-07-30 21:43:19 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2014-07-31 00:42:37 -0400 |
commit | cf44819c98db11163f58f08b822d626c7a8f5188 (patch) | |
tree | 68af0f6580a73753e5c43bc51ba46a87aaa1a18b /drivers/hwmon/amc6821.c | |
parent | 1074d683a51f1aded3562add9ef313e75d557327 (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.c | 17 |
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 | } |
394 | unlock: | ||
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; |