diff options
author | Yuan Mu <ymu@winbond.com.tw> | 2006-06-04 14:18:45 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-22 14:10:34 -0400 |
commit | bed730821b74be4c7d135098842219473f7c8f2c (patch) | |
tree | 8cc046bc9b7415c5036322de29d754dd5bc97be5 | |
parent | 53e2761bb2e4ed58913c266ad13e8c10692aec1e (diff) |
[PATCH] w83792d: Add missing data access locks
Add missing data lock in w83792d driver to avoid unexpected
data change.
Signed-off-by: Yuan Mu <ymu@winbond.com.tw>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/hwmon/w83792d.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 6cdef18b1b27..4ef884c216e2 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -372,8 +372,10 @@ static ssize_t store_in_##reg (struct device *dev, \ | |||
372 | u32 val; \ | 372 | u32 val; \ |
373 | \ | 373 | \ |
374 | val = simple_strtoul(buf, NULL, 10); \ | 374 | val = simple_strtoul(buf, NULL, 10); \ |
375 | mutex_lock(&data->update_lock); \ | ||
375 | data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \ | 376 | data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \ |
376 | w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \ | 377 | w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \ |
378 | mutex_unlock(&data->update_lock); \ | ||
377 | \ | 379 | \ |
378 | return count; \ | 380 | return count; \ |
379 | } | 381 | } |
@@ -440,9 +442,11 @@ store_fan_min(struct device *dev, struct device_attribute *attr, | |||
440 | u32 val; | 442 | u32 val; |
441 | 443 | ||
442 | val = simple_strtoul(buf, NULL, 10); | 444 | val = simple_strtoul(buf, NULL, 10); |
445 | mutex_lock(&data->update_lock); | ||
443 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); | 446 | data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); |
444 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], | 447 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], |
445 | data->fan_min[nr]); | 448 | data->fan_min[nr]); |
449 | mutex_unlock(&data->update_lock); | ||
446 | 450 | ||
447 | return count; | 451 | return count; |
448 | } | 452 | } |
@@ -475,6 +479,7 @@ store_fan_div(struct device *dev, struct device_attribute *attr, | |||
475 | u8 tmp_fan_div; | 479 | u8 tmp_fan_div; |
476 | 480 | ||
477 | /* Save fan_min */ | 481 | /* Save fan_min */ |
482 | mutex_lock(&data->update_lock); | ||
478 | min = FAN_FROM_REG(data->fan_min[nr], | 483 | min = FAN_FROM_REG(data->fan_min[nr], |
479 | DIV_FROM_REG(data->fan_div[nr])); | 484 | DIV_FROM_REG(data->fan_div[nr])); |
480 | 485 | ||
@@ -490,6 +495,7 @@ store_fan_div(struct device *dev, struct device_attribute *attr, | |||
490 | /* Restore fan_min */ | 495 | /* Restore fan_min */ |
491 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); | 496 | data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); |
492 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); | 497 | w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); |
498 | mutex_unlock(&data->update_lock); | ||
493 | 499 | ||
494 | return count; | 500 | return count; |
495 | } | 501 | } |
@@ -544,10 +550,11 @@ static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, | |||
544 | s32 val; | 550 | s32 val; |
545 | 551 | ||
546 | val = simple_strtol(buf, NULL, 10); | 552 | val = simple_strtol(buf, NULL, 10); |
547 | 553 | mutex_lock(&data->update_lock); | |
548 | data->temp1[nr] = TEMP1_TO_REG(val); | 554 | data->temp1[nr] = TEMP1_TO_REG(val); |
549 | w83792d_write_value(client, W83792D_REG_TEMP1[nr], | 555 | w83792d_write_value(client, W83792D_REG_TEMP1[nr], |
550 | data->temp1[nr]); | 556 | data->temp1[nr]); |
557 | mutex_unlock(&data->update_lock); | ||
551 | 558 | ||
552 | return count; | 559 | return count; |
553 | } | 560 | } |
@@ -577,13 +584,14 @@ static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, | |||
577 | s32 val; | 584 | s32 val; |
578 | 585 | ||
579 | val = simple_strtol(buf, NULL, 10); | 586 | val = simple_strtol(buf, NULL, 10); |
580 | 587 | mutex_lock(&data->update_lock); | |
581 | data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); | 588 | data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); |
582 | data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); | 589 | data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); |
583 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], | 590 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], |
584 | data->temp_add[nr][index]); | 591 | data->temp_add[nr][index]); |
585 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], | 592 | w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], |
586 | data->temp_add[nr][index+1]); | 593 | data->temp_add[nr][index+1]); |
594 | mutex_unlock(&data->update_lock); | ||
587 | 595 | ||
588 | return count; | 596 | return count; |
589 | } | 597 | } |
@@ -682,6 +690,10 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, | |||
682 | u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; | 690 | u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; |
683 | 691 | ||
684 | val = simple_strtoul(buf, NULL, 10); | 692 | val = simple_strtoul(buf, NULL, 10); |
693 | if (val < 1 || val > 3) | ||
694 | return -EINVAL; | ||
695 | |||
696 | mutex_lock(&data->update_lock); | ||
685 | switch (val) { | 697 | switch (val) { |
686 | case 1: | 698 | case 1: |
687 | data->pwmenable[nr] = 0; /* manual mode */ | 699 | data->pwmenable[nr] = 0; /* manual mode */ |
@@ -692,8 +704,6 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, | |||
692 | case 3: | 704 | case 3: |
693 | data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ | 705 | data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ |
694 | break; | 706 | break; |
695 | default: | ||
696 | return -EINVAL; | ||
697 | } | 707 | } |
698 | cfg1_tmp = data->pwmenable[0]; | 708 | cfg1_tmp = data->pwmenable[0]; |
699 | cfg2_tmp = (data->pwmenable[1]) << 2; | 709 | cfg2_tmp = (data->pwmenable[1]) << 2; |
@@ -701,6 +711,7 @@ store_pwmenable(struct device *dev, struct device_attribute *attr, | |||
701 | cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0; | 711 | cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0; |
702 | fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; | 712 | fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; |
703 | w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); | 713 | w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); |
714 | mutex_unlock(&data->update_lock); | ||
704 | 715 | ||
705 | return count; | 716 | return count; |
706 | } | 717 | } |
@@ -794,12 +805,13 @@ store_chassis_clear(struct device *dev, struct device_attribute *attr, | |||
794 | u8 temp1 = 0, temp2 = 0; | 805 | u8 temp1 = 0, temp2 = 0; |
795 | 806 | ||
796 | val = simple_strtoul(buf, NULL, 10); | 807 | val = simple_strtoul(buf, NULL, 10); |
797 | 808 | mutex_lock(&data->update_lock); | |
798 | data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); | 809 | data->chassis_clear = SENSORS_LIMIT(val, 0 ,1); |
799 | temp1 = ((data->chassis_clear) << 7) & 0x80; | 810 | temp1 = ((data->chassis_clear) << 7) & 0x80; |
800 | temp2 = w83792d_read_value(client, | 811 | temp2 = w83792d_read_value(client, |
801 | W83792D_REG_CHASSIS_CLR) & 0x7f; | 812 | W83792D_REG_CHASSIS_CLR) & 0x7f; |
802 | w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); | 813 | w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); |
814 | mutex_unlock(&data->update_lock); | ||
803 | 815 | ||
804 | return count; | 816 | return count; |
805 | } | 817 | } |
@@ -832,10 +844,12 @@ store_thermal_cruise(struct device *dev, struct device_attribute *attr, | |||
832 | val = simple_strtoul(buf, NULL, 10); | 844 | val = simple_strtoul(buf, NULL, 10); |
833 | target_tmp = val; | 845 | target_tmp = val; |
834 | target_tmp = target_tmp & 0x7f; | 846 | target_tmp = target_tmp & 0x7f; |
847 | mutex_lock(&data->update_lock); | ||
835 | target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80; | 848 | target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80; |
836 | data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); | 849 | data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); |
837 | w83792d_write_value(client, W83792D_REG_THERMAL[nr], | 850 | w83792d_write_value(client, W83792D_REG_THERMAL[nr], |
838 | (data->thermal_cruise[nr]) | target_mask); | 851 | (data->thermal_cruise[nr]) | target_mask); |
852 | mutex_unlock(&data->update_lock); | ||
839 | 853 | ||
840 | return count; | 854 | return count; |
841 | } | 855 | } |
@@ -872,6 +886,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr, | |||
872 | u8 tol_tmp, tol_mask; | 886 | u8 tol_tmp, tol_mask; |
873 | 887 | ||
874 | val = simple_strtoul(buf, NULL, 10); | 888 | val = simple_strtoul(buf, NULL, 10); |
889 | mutex_lock(&data->update_lock); | ||
875 | tol_mask = w83792d_read_value(client, | 890 | tol_mask = w83792d_read_value(client, |
876 | W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); | 891 | W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); |
877 | tol_tmp = SENSORS_LIMIT(val, 0, 15); | 892 | tol_tmp = SENSORS_LIMIT(val, 0, 15); |
@@ -882,6 +897,7 @@ store_tolerance(struct device *dev, struct device_attribute *attr, | |||
882 | } | 897 | } |
883 | w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], | 898 | w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], |
884 | tol_mask | tol_tmp); | 899 | tol_mask | tol_tmp); |
900 | mutex_unlock(&data->update_lock); | ||
885 | 901 | ||
886 | return count; | 902 | return count; |
887 | } | 903 | } |
@@ -920,11 +936,13 @@ store_sf2_point(struct device *dev, struct device_attribute *attr, | |||
920 | u8 mask_tmp = 0; | 936 | u8 mask_tmp = 0; |
921 | 937 | ||
922 | val = simple_strtoul(buf, NULL, 10); | 938 | val = simple_strtoul(buf, NULL, 10); |
939 | mutex_lock(&data->update_lock); | ||
923 | data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); | 940 | data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); |
924 | mask_tmp = w83792d_read_value(client, | 941 | mask_tmp = w83792d_read_value(client, |
925 | W83792D_REG_POINTS[index][nr]) & 0x80; | 942 | W83792D_REG_POINTS[index][nr]) & 0x80; |
926 | w83792d_write_value(client, W83792D_REG_POINTS[index][nr], | 943 | w83792d_write_value(client, W83792D_REG_POINTS[index][nr], |
927 | mask_tmp|data->sf2_points[index][nr]); | 944 | mask_tmp|data->sf2_points[index][nr]); |
945 | mutex_unlock(&data->update_lock); | ||
928 | 946 | ||
929 | return count; | 947 | return count; |
930 | } | 948 | } |
@@ -984,6 +1002,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, | |||
984 | u8 mask_tmp=0, level_tmp=0; | 1002 | u8 mask_tmp=0, level_tmp=0; |
985 | 1003 | ||
986 | val = simple_strtoul(buf, NULL, 10); | 1004 | val = simple_strtoul(buf, NULL, 10); |
1005 | mutex_lock(&data->update_lock); | ||
987 | data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); | 1006 | data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); |
988 | mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) | 1007 | mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) |
989 | & ((nr==3) ? 0xf0 : 0x0f); | 1008 | & ((nr==3) ? 0xf0 : 0x0f); |
@@ -993,6 +1012,7 @@ store_sf2_level(struct device *dev, struct device_attribute *attr, | |||
993 | level_tmp = data->sf2_levels[index][nr] << 4; | 1012 | level_tmp = data->sf2_levels[index][nr] << 4; |
994 | } | 1013 | } |
995 | w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp); | 1014 | w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp); |
1015 | mutex_unlock(&data->update_lock); | ||
996 | 1016 | ||
997 | return count; | 1017 | return count; |
998 | } | 1018 | } |