diff options
author | Jinyoung Park <jinyoungp@nvidia.com> | 2013-09-30 12:33:38 +0900 |
---|---|---|
committer | Harry Hong <hhong@nvidia.com> | 2014-01-12 16:45:35 -0800 |
commit | 85ba3c70fd78cfb674ca557180325d8ca790a24e (patch) | |
tree | 4e0601653d9e5edaa5d599e321782b715b7f26db /drivers | |
parent | aec358d727fcfec2702b828f0540a5fa8413f3e7 (diff) |
misc: therm_est: Robustify history management
Added below things to prevent bad temp estimation by wrong history management.
- Set current temp estimation with 25C if history initialization is failed.
- Store last temp as current history if temp reading is failed.
Bug 1375775
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/280251
(cherry picked from commit d498f2502ba9135bfaf137aecfd2576f39b88463)
Change-Id: If97275cc3ba36914b43afc2b98ba3163e2ac8255
Signed-off-by: Jinyoung Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/353272
Reviewed-by: Harry Hong <hhong@nvidia.com>
Tested-by: Harry Hong <hhong@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/therm_est.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/misc/therm_est.c b/drivers/misc/therm_est.c index 2aa725eee17e..5918d240c962 100644 --- a/drivers/misc/therm_est.c +++ b/drivers/misc/therm_est.c @@ -72,8 +72,12 @@ struct therm_estimator { #define TIMER_TRIP_STATE_UP BIT(2) #define TIMER_TRIP_STATE_DOWN BIT(3) +#define HIST_UNINIT -1 +#define DEFAULT_TEMP 25000 + static int __get_trip_temp(struct thermal_zone_device *thz, int trip, long *temp); +static int therm_est_init_history(struct therm_estimator *est); static struct therm_est_timer_trip_info * __find_timer_trip(struct therm_estimator *est, int trip) @@ -112,9 +116,8 @@ static int therm_est_subdev_get_temp(void *data, long *temp) struct thermal_zone_device *thz; thz = thermal_zone_device_find(data, therm_est_subdev_match); - if (!thz || thz->ops->get_temp(thz, temp)) - *temp = 25000; + return -ENXIO; return 0; } @@ -247,9 +250,16 @@ static void therm_est_work_func(struct work_struct *work) struct therm_estimator, therm_est_work); + if ((est->ntemp == HIST_UNINIT) && therm_est_init_history(est)) { + est->cur_temp = DEFAULT_TEMP; + goto out; + } + for (i = 0; i < est->ndevs; i++) { - if (therm_est_subdev_get_temp(est->devs[i].dev_data, &temp)) - continue; + if (therm_est_subdev_get_temp(est->devs[i].dev_data, &temp)) { + index = (est->ntemp > 0) ? (est->ntemp - 1) : 0; + temp = est->devs[i].hist[(index % HIST_LEN)]; + } est->devs[i].hist[(est->ntemp % HIST_LEN)] = temp; } @@ -264,6 +274,7 @@ static void therm_est_work_func(struct work_struct *work) est->cur_temp = sum / 100 + est->toffset; est->ntemp++; +out: if (est->thz && ((est->cur_temp < est->low_limit) || (est->cur_temp >= est->high_limit))) { thermal_zone_device_update(est->thz); @@ -653,16 +664,19 @@ static int therm_est_init_history(struct therm_estimator *est) int i, j; struct therm_est_subdevice *dev; long temp; + int ret; for (i = 0; i < est->ndevs; i++) { dev = &est->devs[i]; - if (therm_est_subdev_get_temp(dev->dev_data, &temp)) - return -EINVAL; + ret = therm_est_subdev_get_temp(dev->dev_data, &temp); + if (ret < 0) + return ret; for (j = 0; j < HIST_LEN; j++) dev->hist[j] = temp; } + est->ntemp = 0; return 0; } @@ -684,7 +698,7 @@ static int therm_est_pm_notify(struct notifier_block *nb, case PM_POST_SUSPEND: est->low_limit = 0; est->high_limit = 0; - therm_est_init_history(est); + est->ntemp = HIST_UNINIT; therm_est_init_timer_trips(est); queue_delayed_work(est->workqueue, &est->therm_est_work, @@ -972,9 +986,8 @@ static int __devinit therm_est_probe(struct platform_device *pdev) est->polling_period = data->polling_period; est->tc1 = data->tc1; est->tc2 = data->tc2; - - /* initialize history */ - therm_est_init_history(est); + est->cur_temp = DEFAULT_TEMP; + est->ntemp = HIST_UNINIT; /* initialize timer trips */ est->num_timer_trips = data->num_timer_trips; |