summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Gupta <sumitg@nvidia.com>2021-03-24 10:11:56 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2021-05-25 10:24:23 -0400
commit2c40a6bc48f6701fe44cb7edadca26f6a40892da (patch)
treefffbb849a9053acfb87b53d6e260fd45d66a26fc
parent6fcc5021a8f8eaef1a2a8e2c342728d1a6ff35d0 (diff)
pwm: fan: fix deadlock due to incorrect locking
Bug 3227296 Bug 200695596 Bug 200728417 Signed-off-by: Sumit Gupta <sumitg@nvidia.com> Change-Id: Ib64915556d285bd798e95da81a261eb2c16b4dab Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2503884 Reviewed-by: svcacv <svcacv@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: Bibek Basu <bbasu@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/thermal/pwm_fan.c67
-rw-r--r--include/linux/therm_est.h4
2 files changed, 47 insertions, 24 deletions
diff --git a/drivers/thermal/pwm_fan.c b/drivers/thermal/pwm_fan.c
index 35a09a108..2deb7abf5 100644
--- a/drivers/thermal/pwm_fan.c
+++ b/drivers/thermal/pwm_fan.c
@@ -114,8 +114,7 @@ static void fan_validate_target_rpm(struct fan_dev_data *fan_data)
114 fan_data->next_target_pwm); 114 fan_data->next_target_pwm);
115 115
116 fan_data->fan_rpm_in_limits = false; 116 fan_data->fan_rpm_in_limits = false;
117 cancel_delayed_work(&fan_data->fan_ramp_rpm_work); 117 cancel_delayed_work_sync(&fan_data->fan_ramp_rpm_work);
118 mutex_unlock(&fan_data->fan_state_lock);
119 queue_delayed_work(fan_data->workqueue, 118 queue_delayed_work(fan_data->workqueue,
120 &fan_data->fan_ramp_rpm_work, 119 &fan_data->fan_ramp_rpm_work,
121 msecs_to_jiffies(fan_data->fan_ramp_time_ms)); 120 msecs_to_jiffies(fan_data->fan_ramp_time_ms));
@@ -126,12 +125,8 @@ static void fan_update_target_pwm(struct fan_dev_data *fan_data, int val)
126 if (fan_data) { 125 if (fan_data) {
127 fan_data->next_target_pwm = min(val, fan_data->fan_cap_pwm); 126 fan_data->next_target_pwm = min(val, fan_data->fan_cap_pwm);
128 127
129 /* If a new pwm update request, reset the lock sequence */
130 if (mutex_is_locked(&fan_data->pwm_set))
131 mutex_unlock(&fan_data->pwm_set);
132 mutex_lock(&fan_data->pwm_set);
133 if (fan_data->next_target_pwm != fan_data->fan_cur_pwm) { 128 if (fan_data->next_target_pwm != fan_data->fan_cur_pwm) {
134 cancel_delayed_work(&fan_data->fan_ramp_pwm_work); 129 cancel_delayed_work_sync(&fan_data->fan_ramp_pwm_work);
135 queue_delayed_work(fan_data->workqueue, 130 queue_delayed_work(fan_data->workqueue,
136 &fan_data->fan_ramp_pwm_work, 131 &fan_data->fan_ramp_pwm_work,
137 msecs_to_jiffies(fan_data->step_time)); 132 msecs_to_jiffies(fan_data->step_time));
@@ -659,16 +654,19 @@ static void fan_ramping_rpm_work_func(struct work_struct *work)
659 struct fan_dev_data, 654 struct fan_dev_data,
660 fan_ramp_rpm_work); 655 fan_ramp_rpm_work);
661 656
662 /* 657 time_off = fan_data->rpm_invalid_retry_delay;
663 * If mutex is locked, preempt. Only after pwm work function is done 658 if (!wait_for_completion_timeout(&fan_data->pwm_set,
664 * with its execution, rpm work function should start. 659 msecs_to_jiffies(10000))) {
665 */ 660 dev_info(fan_data->dev, "pwm_set completion timedout\n");
666 if (mutex_is_locked((&fan_data->pwm_set))) { 661 return;
667 time_off = fan_data->fan_ramp_time_ms;
668 goto reschedule;
669 } 662 }
670 663
671 mutex_lock(&fan_data->fan_state_lock); 664 if (!mutex_trylock(&fan_data->fan_state_lock)) {
665 queue_delayed_work(fan_data->workqueue,
666 &fan_data->fan_ramp_rpm_work,
667 msecs_to_jiffies(fan_data->step_time + time_off));
668 return;
669 }
672 670
673 if (!fan_data->fan_temp_control_flag) 671 if (!fan_data->fan_temp_control_flag)
674 goto unlock_mutex; 672 goto unlock_mutex;
@@ -788,13 +786,30 @@ static void fan_ramping_pwm_work_func(struct work_struct *work)
788{ 786{
789 int rru, rrd, err; 787 int rru, rrd, err;
790 int cur_pwm, next_pwm; 788 int cur_pwm, next_pwm;
789 int time_off;
791 struct delayed_work *dwork = container_of(work, struct delayed_work, 790 struct delayed_work *dwork = container_of(work, struct delayed_work,
792 work); 791 work);
793 struct fan_dev_data *fan_data = container_of(dwork, struct 792 struct fan_dev_data *fan_data = container_of(dwork, struct
794 fan_dev_data, 793 fan_dev_data,
795 fan_ramp_pwm_work); 794 fan_ramp_pwm_work);
796 795
797 mutex_lock(&fan_data->fan_state_lock); 796 time_off = fan_data->rpm_invalid_retry_delay;
797 if (!mutex_trylock(&fan_data->fan_state_lock)) {
798 if (fan_data->pwm_tach_dev)
799 cancel_delayed_work_sync(&fan_data->fan_ramp_rpm_work);
800
801 queue_delayed_work(fan_data->workqueue,
802 &(fan_data->fan_ramp_pwm_work),
803 msecs_to_jiffies(fan_data->step_time));
804
805 if (fan_data->pwm_tach_dev)
806 queue_delayed_work(fan_data->workqueue,
807 &fan_data->fan_ramp_rpm_work,
808 msecs_to_jiffies(fan_data->step_time + time_off));
809 return;
810 }
811
812 reinit_completion(&fan_data->pwm_set);
798 813
799 cur_pwm = fan_data->fan_cur_pwm; 814 cur_pwm = fan_data->fan_cur_pwm;
800 rru = fan_get_pwm_rru(cur_pwm, fan_data); 815 rru = fan_get_pwm_rru(cur_pwm, fan_data);
@@ -841,12 +856,21 @@ static void fan_ramping_pwm_work_func(struct work_struct *work)
841 856
842 set_pwm_duty_cycle(next_pwm, fan_data); 857 set_pwm_duty_cycle(next_pwm, fan_data);
843 fan_data->fan_cur_pwm = next_pwm; 858 fan_data->fan_cur_pwm = next_pwm;
844 if (fan_data->next_target_pwm != next_pwm) 859 if (fan_data->next_target_pwm != next_pwm) {
860 if (fan_data->pwm_tach_dev)
861 cancel_delayed_work_sync(&fan_data->fan_ramp_rpm_work);
862
845 queue_delayed_work(fan_data->workqueue, 863 queue_delayed_work(fan_data->workqueue,
846 &(fan_data->fan_ramp_pwm_work), 864 &(fan_data->fan_ramp_pwm_work),
847 msecs_to_jiffies(fan_data->step_time)); 865 msecs_to_jiffies(fan_data->step_time));
866
867 if (fan_data->pwm_tach_dev)
868 queue_delayed_work(fan_data->workqueue,
869 &fan_data->fan_ramp_rpm_work,
870 msecs_to_jiffies(fan_data->step_time + time_off));
871 }
848 else 872 else
849 mutex_unlock(&fan_data->pwm_set); 873 complete(&fan_data->pwm_set);
850 874
851 mutex_unlock(&fan_data->fan_state_lock); 875 mutex_unlock(&fan_data->fan_state_lock);
852} 876}
@@ -1529,7 +1553,7 @@ static int pwm_fan_probe(struct platform_device *pdev)
1529 } 1553 }
1530 1554
1531 mutex_init(&fan_data->fan_state_lock); 1555 mutex_init(&fan_data->fan_state_lock);
1532 mutex_init(&fan_data->pwm_set); 1556 init_completion(&fan_data->pwm_set);
1533 spin_lock_init(&fan_data->irq_lock); 1557 spin_lock_init(&fan_data->irq_lock);
1534 1558
1535 fan_data->workqueue = alloc_workqueue(dev_name(&pdev->dev), 1559 fan_data->workqueue = alloc_workqueue(dev_name(&pdev->dev),
@@ -1873,10 +1897,10 @@ static int pwm_fan_resume(struct platform_device *pdev)
1873{ 1897{
1874 struct fan_dev_data *fan_data = platform_get_drvdata(pdev); 1898 struct fan_dev_data *fan_data = platform_get_drvdata(pdev);
1875 1899
1876 mutex_lock(&fan_data->fan_state_lock);
1877
1878 gpio_free(fan_data->pwm_gpio); 1900 gpio_free(fan_data->pwm_gpio);
1879 1901
1902 reinit_completion(&fan_data->pwm_set);
1903
1880 queue_delayed_work(fan_data->workqueue, 1904 queue_delayed_work(fan_data->workqueue,
1881 &fan_data->fan_ramp_pwm_work, 1905 &fan_data->fan_ramp_pwm_work,
1882 msecs_to_jiffies(fan_data->step_time)); 1906 msecs_to_jiffies(fan_data->step_time));
@@ -1886,7 +1910,6 @@ static int pwm_fan_resume(struct platform_device *pdev)
1886 msecs_to_jiffies(fan_data->step_time)); 1910 msecs_to_jiffies(fan_data->step_time));
1887 1911
1888 fan_data->fan_temp_control_flag = 1; 1912 fan_data->fan_temp_control_flag = 1;
1889 mutex_unlock(&fan_data->fan_state_lock);
1890 return 0; 1913 return 0;
1891} 1914}
1892#endif 1915#endif
diff --git a/include/linux/therm_est.h b/include/linux/therm_est.h
index 85284a5fe..5c5d916ce 100644
--- a/include/linux/therm_est.h
+++ b/include/linux/therm_est.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * include/linux/therm_est.h 2 * include/linux/therm_est.h
3 * 3 *
4 * Copyright (c) 2010-2020, NVIDIA CORPORATION. All rights reserved. 4 * Copyright (c) 2010-2021, NVIDIA CORPORATION. All rights reserved.
5 * 5 *
6 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and 7 * License version 2, as published by the Free Software Foundation, and
@@ -187,7 +187,7 @@ struct fan_dev_data {
187 struct delayed_work fan_ramp_pwm_work; 187 struct delayed_work fan_ramp_pwm_work;
188 struct delayed_work fan_ramp_rpm_work; 188 struct delayed_work fan_ramp_rpm_work;
189 struct device *pwm_tach_dev; 189 struct device *pwm_tach_dev;
190 struct mutex pwm_set; 190 struct completion pwm_set;
191 bool fan_rpm_in_limits; 191 bool fan_rpm_in_limits;
192 int rpm_valid_retry_delay; 192 int rpm_valid_retry_delay;
193 int rpm_invalid_retry_delay; 193 int rpm_invalid_retry_delay;