static int therm_est_get_trip_temp(struct thermal_zone_device *thz, int trip, unsigned long *temp) { struct therm_estimator *est = thz->devdata; struct therm_est_timer_trip_info *timer_info; int ret; ret = __get_trip_temp(thz, trip, temp); if (ret & (TIMER_TRIP_STATE_START | TIMER_TRIP_STATE_DOWN)) { timer_info = __find_timer_trip(est, trip); mutex_lock(&est->timer_trip_lock); timer_info->last_tripped = ktime_to_ms(ktime_get()); if (ret & TIMER_TRIP_STATE_START) { timer_info->cur = TIMER_TRIP_INACTIVE + 1; } else if (ret & TIMER_TRIP_STATE_DOWN) { if (--timer_info->cur < TIMER_TRIP_INACTIVE) timer_info->cur = TIMER_TRIP_INACTIVE; } mutex_unlock(&est->timer_trip_lock); /* Update limits, because trip temp was changed by timer trip * changing. */ therm_est_update_limits(est); } return 0; }
static int therm_est_set_trip_temp(struct thermal_zone_device *thz, int trip, unsigned long temp) { struct therm_estimator *est = thz->devdata; est->trips[trip].trip_temp = temp; /* Update limits, because trip temp was changed. */ therm_est_update_limits(est); return 0; }
static void therm_est_timer_trip_work_func(struct work_struct *work) { struct therm_estimator *est = container_of(work, struct therm_estimator, timer_trip_work.work); struct thermal_trip_info *trip_state; struct therm_est_timer_trip_info *timer_info; s64 now, delay; int timer_trip_state, i; mutex_lock(&est->timer_trip_lock); timer_trip_state = TIMER_TRIP_STATE_NONE; now = ktime_to_ms(ktime_get()); for (i = 0; i < est->num_timer_trips; i++) { timer_info = &est->timer_trips[i]; trip_state = &est->trips[timer_info->trip]; pr_debug("%s: i %d, trip %d, tripped %d, cur %d\n", __func__, i, timer_info->trip, trip_state->tripped, timer_info->cur); if ((timer_info->cur == TIMER_TRIP_INACTIVE) || (__get_timer_trip_delay(timer_info, now, &delay) < 0)) continue; if (delay <= 0) { /* Timer on this trip has expired. */ if (timer_info->cur + 1 < timer_info->num_timers) { timer_info->last_tripped = now; timer_info->cur++; timer_trip_state |= TIMER_TRIP_STATE_UP; } } /* If delay > 0, timer on this trip has not yet expired. * So need to restart timer with remaining delay. */ timer_trip_state |= TIMER_TRIP_STATE_START; pr_debug("%s: new_cur %d, delay %lld, timer_trip_state 0x%x\n", __func__, timer_info->cur, delay, timer_trip_state); } mutex_unlock(&est->timer_trip_lock); if (timer_trip_state & (TIMER_TRIP_STATE_START | TIMER_TRIP_STATE_UP)) { therm_est_update_timer_trips(est); therm_est_update_limits(est); } }
static void therm_est_work_func(struct work_struct *work) { int i, j, index, sum = 0; long temp; struct delayed_work *dwork = container_of(work, struct delayed_work, work); struct therm_estimator *est = container_of(dwork, 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)) { 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; } for (i = 0; i < est->ndevs; i++) { for (j = 0; j < HIST_LEN; j++) { index = (est->ntemp - j + HIST_LEN) % HIST_LEN; sum += est->devs[i].hist[index] * est->devs[i].coeffs[j]; } } 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); therm_est_update_timer_trips(est); therm_est_update_limits(est); } queue_delayed_work(est->workqueue, &est->therm_est_work, msecs_to_jiffies(est->polling_period)); }