Message ID | 1346500296-25200-14-git-send-email-durgadoss.r@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On ?, 2012-09-01 at 17:21 +0530, Durgadoss R wrote: > This patch removes the throttling logic out of > thermal_sys.c; also refactors the code into smaller > functions so that are easy to read/maintain. > * Seperates the handling of critical and non-critical trips > * Re-arranges the set_polling and device_check methods, so > that all related functions are arranged in one place. > * Removes the 'do_update' and 'trip_update' method, as part > of moving the throttling logic out of thermal_sys.c > > Signed-off-by: Durgadoss R <durgadoss.r@intel.com> > --- > drivers/thermal/thermal_sys.c | 313 +++++++++++++++-------------------------- > 1 file changed, 112 insertions(+), 201 deletions(-) > > diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c > index 93672aa..086c1c9 100644 > --- a/drivers/thermal/thermal_sys.c > +++ b/drivers/thermal/thermal_sys.c > @@ -315,6 +315,118 @@ exit: > mutex_unlock(&thermal_list_lock); > } > > +static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, > + int delay) > +{ > + cancel_delayed_work(&(tz->poll_queue)); > + > + if (!delay) > + return; > + > + if (delay > 1000) > + queue_delayed_work(system_freezable_wq, &(tz->poll_queue), > + round_jiffies(msecs_to_jiffies(delay))); > + else > + queue_delayed_work(system_freezable_wq, &(tz->poll_queue), > + msecs_to_jiffies(delay)); > +} > + > +static void monitor_thermal_zone(struct thermal_zone_device *tz) > +{ > + mutex_lock(&tz->lock); > + > + if (tz->passive) > + thermal_zone_device_set_polling(tz, tz->passive_delay); > + else if (tz->polling_delay) > + thermal_zone_device_set_polling(tz, tz->polling_delay); > + else > + thermal_zone_device_set_polling(tz, 0); > + > + mutex_unlock(&tz->lock); > +} > + > +static void handle_non_critical_trips(struct thermal_zone_device *tz, > + int trip, enum thermal_trip_type trip_type) > +{ > + tz->governor->throttle(tz, trip); > +} here is the problem, we must make sure every registered thermal zone have a governor when it is running, right? then the default governor must always be built in. We can have a Kconfig option for step_wise, but we should not make it configurable by users. or we can use prompt to get the default governor at build time. say choice prompt "Default thermal governor" default THERMAL_DEFAULT_GOV_STEP_WISE help This option sets which thermal governor shall be loaded at startup. config THERMAL_DEFAULT_GOV_STEP_WISE bool "step-wise" select THERMAL_GOV_STEP_WISE help Use the thermal governor 'step-wise' as default.blabla thanks, rui > + > +static void handle_critical_trips(struct thermal_zone_device *tz, > + int trip, enum thermal_trip_type trip_type) > +{ > + long trip_temp; > + > + tz->ops->get_trip_temp(tz, trip, &trip_temp); > + > + /* If we have not crossed the trip_temp, we do not care. */ > + if (tz->temperature < trip_temp) > + return; > + > + if (tz->ops->notify) > + tz->ops->notify(tz, trip, trip_type); > + > + if (trip_type == THERMAL_TRIP_CRITICAL) { > + pr_emerg("Critical temperature reached(%d C),shutting down\n", > + tz->temperature / 1000); > + orderly_poweroff(true); > + } > +} > + > +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) > +{ > + enum thermal_trip_type type; > + > + tz->ops->get_trip_type(tz, trip, &type); > + > + if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) > + handle_critical_trips(tz, trip, type); > + else > + handle_non_critical_trips(tz, trip, type); > + /* > + * Alright, we handled this trip successfully. > + * So, start monitoring again. > + */ > + monitor_thermal_zone(tz); > +} > + > +static void update_temperature(struct thermal_zone_device *tz) > +{ > + long temp; > + int ret; > + > + mutex_lock(&tz->lock); > + > + ret = tz->ops->get_temp(tz, &temp); > + if (ret) { > + pr_warn("failed to read out thermal zone %d\n", tz->id); > + return; > + } > + > + tz->last_temperature = tz->temperature; > + tz->temperature = temp; > + > + mutex_unlock(&tz->lock); > +} > + > +void thermal_zone_device_update(struct thermal_zone_device *tz) > +{ > + int count; > + > + update_temperature(tz); > + > + for (count = 0; count < tz->trips; count++) > + handle_thermal_trip(tz, count); > +} > +EXPORT_SYMBOL(thermal_zone_device_update); > + > +static void thermal_zone_device_check(struct work_struct *work) > +{ > + struct thermal_zone_device *tz = container_of(work, struct > + thermal_zone_device, > + poll_queue.work); > + thermal_zone_device_update(tz); > +} > + > /* sys I/F for thermal zone */ > > #define to_thermal_zone(_dev) \ > @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) > } > #endif > > -static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, > - int delay) > -{ > - cancel_delayed_work(&(tz->poll_queue)); > - > - if (!delay) > - return; > - > - if (delay > 1000) > - queue_delayed_work(system_freezable_wq, &(tz->poll_queue), > - round_jiffies(msecs_to_jiffies(delay))); > - else > - queue_delayed_work(system_freezable_wq, &(tz->poll_queue), > - msecs_to_jiffies(delay)); > -} > - > -static void thermal_zone_device_check(struct work_struct *work) > -{ > - struct thermal_zone_device *tz = container_of(work, struct > - thermal_zone_device, > - poll_queue.work); > - thermal_zone_device_update(tz); > -} > - > /** > * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone > * @tz: thermal zone device > @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) > } > EXPORT_SYMBOL(thermal_cdev_update); > > -static void thermal_zone_do_update(struct thermal_zone_device *tz) > -{ > - struct thermal_instance *instance; > - > - list_for_each_entry(instance, &tz->thermal_instances, tz_node) > - thermal_cdev_update(instance->cdev); > -} > - > -/* > - * Cooling algorithm for both active and passive cooling > - * > - * 1. if the temperature is higher than a trip point, > - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling > - * state for this trip point > - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling > - * state for this trip point > - * > - * 2. if the temperature is lower than a trip point, use lower > - * cooling state for this trip point > - * > - * Note that this behaves the same as the previous passive cooling > - * algorithm. > - */ > - > -static void thermal_zone_trip_update(struct thermal_zone_device *tz, > - int trip, long temp) > -{ > - struct thermal_instance *instance; > - struct thermal_cooling_device *cdev = NULL; > - unsigned long cur_state, max_state; > - long trip_temp; > - enum thermal_trip_type trip_type; > - enum thermal_trend trend; > - > - if (trip == THERMAL_TRIPS_NONE) { > - trip_temp = tz->forced_passive; > - trip_type = THERMAL_TRIPS_NONE; > - } else { > - tz->ops->get_trip_temp(tz, trip, &trip_temp); > - tz->ops->get_trip_type(tz, trip, &trip_type); > - } > - > - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { > - /* > - * compare the current temperature and previous temperature > - * to get the thermal trend, if no special requirement > - */ > - if (tz->temperature > tz->last_temperature) > - trend = THERMAL_TREND_RAISING; > - else if (tz->temperature < tz->last_temperature) > - trend = THERMAL_TREND_DROPPING; > - else > - trend = THERMAL_TREND_STABLE; > - } > - > - if (temp >= trip_temp) { > - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { > - if (instance->trip != trip) > - continue; > - > - cdev = instance->cdev; > - > - cdev->ops->get_cur_state(cdev, &cur_state); > - cdev->ops->get_max_state(cdev, &max_state); > - > - if (trend == THERMAL_TREND_RAISING) { > - cur_state = cur_state < instance->upper ? > - (cur_state + 1) : instance->upper; > - } else if (trend == THERMAL_TREND_DROPPING) { > - cur_state = cur_state > instance->lower ? > - (cur_state - 1) : instance->lower; > - } > - > - /* activate a passive thermal instance */ > - if ((trip_type == THERMAL_TRIP_PASSIVE || > - trip_type == THERMAL_TRIPS_NONE) && > - instance->target == THERMAL_NO_TARGET) > - tz->passive++; > - > - instance->target = cur_state; > - cdev->updated = false; /* cooling device needs update */ > - } > - } else { /* below trip */ > - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { > - if (instance->trip != trip) > - continue; > - > - /* Do not use the inactive thermal instance */ > - if (instance->target == THERMAL_NO_TARGET) > - continue; > - cdev = instance->cdev; > - cdev->ops->get_cur_state(cdev, &cur_state); > - > - cur_state = cur_state > instance->lower ? > - (cur_state - 1) : THERMAL_NO_TARGET; > - > - /* deactivate a passive thermal instance */ > - if ((trip_type == THERMAL_TRIP_PASSIVE || > - trip_type == THERMAL_TRIPS_NONE) && > - cur_state == THERMAL_NO_TARGET) > - tz->passive--; > - instance->target = cur_state; > - cdev->updated = false; /* cooling device needs update */ > - } > - } > - > - return; > -} > -/** > - * thermal_zone_device_update - force an update of a thermal zone's state > - * @ttz: the thermal zone to update > - */ > - > -void thermal_zone_device_update(struct thermal_zone_device *tz) > -{ > - int count, ret = 0; > - long temp, trip_temp; > - enum thermal_trip_type trip_type; > - > - mutex_lock(&tz->lock); > - > - if (tz->ops->get_temp(tz, &temp)) { > - /* get_temp failed - retry it later */ > - pr_warn("failed to read out thermal zone %d\n", tz->id); > - goto leave; > - } > - > - tz->last_temperature = tz->temperature; > - tz->temperature = temp; > - > - for (count = 0; count < tz->trips; count++) { > - tz->ops->get_trip_type(tz, count, &trip_type); > - tz->ops->get_trip_temp(tz, count, &trip_temp); > - > - switch (trip_type) { > - case THERMAL_TRIP_CRITICAL: > - if (temp >= trip_temp) { > - if (tz->ops->notify) > - ret = tz->ops->notify(tz, count, > - trip_type); > - if (!ret) { > - pr_emerg("Critical temperature reached (%ld C), shutting down\n", > - temp/1000); > - orderly_poweroff(true); > - } > - } > - break; > - case THERMAL_TRIP_HOT: > - if (temp >= trip_temp) > - if (tz->ops->notify) > - tz->ops->notify(tz, count, trip_type); > - break; > - case THERMAL_TRIP_ACTIVE: > - thermal_zone_trip_update(tz, count, temp); > - break; > - case THERMAL_TRIP_PASSIVE: > - if (temp >= trip_temp || tz->passive) > - thermal_zone_trip_update(tz, count, temp); > - break; > - } > - } > - > - if (tz->forced_passive) > - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp); > - thermal_zone_do_update(tz); > - > -leave: > - if (tz->passive) > - thermal_zone_device_set_polling(tz, tz->passive_delay); > - else if (tz->polling_delay) > - thermal_zone_device_set_polling(tz, tz->polling_delay); > - else > - thermal_zone_device_set_polling(tz, 0); > - mutex_unlock(&tz->lock); > -} > -EXPORT_SYMBOL(thermal_zone_device_update); > - > /** > * create_trip_attrs - create attributes for trip points > * @tz: the thermal zone device -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Rui, > -----Original Message----- > From: Zhang, Rui > Sent: Monday, September 10, 2012 2:14 PM > To: R, Durgadoss > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; eduardo.valentin@ti.com > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of > thermal_sys.c [cut.] > > + > > +static void handle_non_critical_trips(struct thermal_zone_device *tz, > > + int trip, enum thermal_trip_type trip_type) > > +{ > > + tz->governor->throttle(tz, trip); > > +} > here is the problem, we must make sure every registered thermal zone > have a governor when it is running, right? Yes, agree with you. Had some thoughts here, but wanted to get your opinion before I implemented them. 1. We can make the default governor as 'user space', and make it load inside thermal_sys.c (so that every zone will always have a default governor) 2. All other governors, that are implemented in a separate .c file can be optional i.e. left to the user to select/deselect. IMO, this will make our implementation easier and cleaner. What do you think ? Thanks, Durga > > then the default governor must always be built in. > We can have a Kconfig option for step_wise, but we should not make it > configurable by users. > or we can use prompt to get the default governor at build time. say > > choice > prompt "Default thermal governor" > default THERMAL_DEFAULT_GOV_STEP_WISE > help > This option sets which thermal governor shall be loaded at > startup. > > config THERMAL_DEFAULT_GOV_STEP_WISE > bool "step-wise" > select THERMAL_GOV_STEP_WISE > help > Use the thermal governor 'step-wise' as default.blabla > > > thanks, > rui > > > + > > +static void handle_critical_trips(struct thermal_zone_device *tz, > > + int trip, enum thermal_trip_type trip_type) > > +{ > > + long trip_temp; > > + > > + tz->ops->get_trip_temp(tz, trip, &trip_temp); > > + > > + /* If we have not crossed the trip_temp, we do not care. */ > > + if (tz->temperature < trip_temp) > > + return; > > + > > + if (tz->ops->notify) > > + tz->ops->notify(tz, trip, trip_type); > > + > > + if (trip_type == THERMAL_TRIP_CRITICAL) { > > + pr_emerg("Critical temperature reached(%d C),shutting > down\n", > > + tz->temperature / 1000); > > + orderly_poweroff(true); > > + } > > +} > > + > > +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) > > +{ > > + enum thermal_trip_type type; > > + > > + tz->ops->get_trip_type(tz, trip, &type); > > + > > + if (type == THERMAL_TRIP_CRITICAL || type == > THERMAL_TRIP_HOT) > > + handle_critical_trips(tz, trip, type); > > + else > > + handle_non_critical_trips(tz, trip, type); > > + /* > > + * Alright, we handled this trip successfully. > > + * So, start monitoring again. > > + */ > > + monitor_thermal_zone(tz); > > +} > > + > > +static void update_temperature(struct thermal_zone_device *tz) > > +{ > > + long temp; > > + int ret; > > + > > + mutex_lock(&tz->lock); > > + > > + ret = tz->ops->get_temp(tz, &temp); > > + if (ret) { > > + pr_warn("failed to read out thermal zone %d\n", tz->id); > > + return; > > + } > > + > > + tz->last_temperature = tz->temperature; > > + tz->temperature = temp; > > + > > + mutex_unlock(&tz->lock); > > +} > > + > > +void thermal_zone_device_update(struct thermal_zone_device *tz) > > +{ > > + int count; > > + > > + update_temperature(tz); > > + > > + for (count = 0; count < tz->trips; count++) > > + handle_thermal_trip(tz, count); > > +} > > +EXPORT_SYMBOL(thermal_zone_device_update); > > + > > +static void thermal_zone_device_check(struct work_struct *work) > > +{ > > + struct thermal_zone_device *tz = container_of(work, struct > > + thermal_zone_device, > > + poll_queue.work); > > + thermal_zone_device_update(tz); > > +} > > + > > /* sys I/F for thermal zone */ > > > > #define to_thermal_zone(_dev) \ > > @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct > thermal_zone_device *tz) > > } > > #endif > > > > -static void thermal_zone_device_set_polling(struct thermal_zone_device > *tz, > > - int delay) > > -{ > > - cancel_delayed_work(&(tz->poll_queue)); > > - > > - if (!delay) > > - return; > > - > > - if (delay > 1000) > > - queue_delayed_work(system_freezable_wq, &(tz- > >poll_queue), > > - round_jiffies(msecs_to_jiffies(delay))); > > - else > > - queue_delayed_work(system_freezable_wq, &(tz- > >poll_queue), > > - msecs_to_jiffies(delay)); > > -} > > - > > -static void thermal_zone_device_check(struct work_struct *work) > > -{ > > - struct thermal_zone_device *tz = container_of(work, struct > > - thermal_zone_device, > > - poll_queue.work); > > - thermal_zone_device_update(tz); > > -} > > - > > /** > > * thermal_zone_bind_cooling_device - bind a cooling device to a thermal > zone > > * @tz: thermal zone device > > @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct > thermal_cooling_device *cdev) > > } > > EXPORT_SYMBOL(thermal_cdev_update); > > > > -static void thermal_zone_do_update(struct thermal_zone_device *tz) > > -{ > > - struct thermal_instance *instance; > > - > > - list_for_each_entry(instance, &tz->thermal_instances, tz_node) > > - thermal_cdev_update(instance->cdev); > > -} > > - > > -/* > > - * Cooling algorithm for both active and passive cooling > > - * > > - * 1. if the temperature is higher than a trip point, > > - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling > > - * state for this trip point > > - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling > > - * state for this trip point > > - * > > - * 2. if the temperature is lower than a trip point, use lower > > - * cooling state for this trip point > > - * > > - * Note that this behaves the same as the previous passive cooling > > - * algorithm. > > - */ > > - > > -static void thermal_zone_trip_update(struct thermal_zone_device *tz, > > - int trip, long temp) > > -{ > > - struct thermal_instance *instance; > > - struct thermal_cooling_device *cdev = NULL; > > - unsigned long cur_state, max_state; > > - long trip_temp; > > - enum thermal_trip_type trip_type; > > - enum thermal_trend trend; > > - > > - if (trip == THERMAL_TRIPS_NONE) { > > - trip_temp = tz->forced_passive; > > - trip_type = THERMAL_TRIPS_NONE; > > - } else { > > - tz->ops->get_trip_temp(tz, trip, &trip_temp); > > - tz->ops->get_trip_type(tz, trip, &trip_type); > > - } > > - > > - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { > > - /* > > - * compare the current temperature and previous > temperature > > - * to get the thermal trend, if no special requirement > > - */ > > - if (tz->temperature > tz->last_temperature) > > - trend = THERMAL_TREND_RAISING; > > - else if (tz->temperature < tz->last_temperature) > > - trend = THERMAL_TREND_DROPPING; > > - else > > - trend = THERMAL_TREND_STABLE; > > - } > > - > > - if (temp >= trip_temp) { > > - list_for_each_entry(instance, &tz->thermal_instances, > tz_node) { > > - if (instance->trip != trip) > > - continue; > > - > > - cdev = instance->cdev; > > - > > - cdev->ops->get_cur_state(cdev, &cur_state); > > - cdev->ops->get_max_state(cdev, &max_state); > > - > > - if (trend == THERMAL_TREND_RAISING) { > > - cur_state = cur_state < instance->upper ? > > - (cur_state + 1) : instance->upper; > > - } else if (trend == THERMAL_TREND_DROPPING) { > > - cur_state = cur_state > instance->lower ? > > - (cur_state - 1) : instance->lower; > > - } > > - > > - /* activate a passive thermal instance */ > > - if ((trip_type == THERMAL_TRIP_PASSIVE || > > - trip_type == THERMAL_TRIPS_NONE) && > > - instance->target == THERMAL_NO_TARGET) > > - tz->passive++; > > - > > - instance->target = cur_state; > > - cdev->updated = false; /* cooling device needs > update */ > > - } > > - } else { /* below trip */ > > - list_for_each_entry(instance, &tz->thermal_instances, > tz_node) { > > - if (instance->trip != trip) > > - continue; > > - > > - /* Do not use the inactive thermal instance */ > > - if (instance->target == THERMAL_NO_TARGET) > > - continue; > > - cdev = instance->cdev; > > - cdev->ops->get_cur_state(cdev, &cur_state); > > - > > - cur_state = cur_state > instance->lower ? > > - (cur_state - 1) : THERMAL_NO_TARGET; > > - > > - /* deactivate a passive thermal instance */ > > - if ((trip_type == THERMAL_TRIP_PASSIVE || > > - trip_type == THERMAL_TRIPS_NONE) && > > - cur_state == THERMAL_NO_TARGET) > > - tz->passive--; > > - instance->target = cur_state; > > - cdev->updated = false; /* cooling device needs > update */ > > - } > > - } > > - > > - return; > > -} > > -/** > > - * thermal_zone_device_update - force an update of a thermal zone's > state > > - * @ttz: the thermal zone to update > > - */ > > - > > -void thermal_zone_device_update(struct thermal_zone_device *tz) > > -{ > > - int count, ret = 0; > > - long temp, trip_temp; > > - enum thermal_trip_type trip_type; > > - > > - mutex_lock(&tz->lock); > > - > > - if (tz->ops->get_temp(tz, &temp)) { > > - /* get_temp failed - retry it later */ > > - pr_warn("failed to read out thermal zone %d\n", tz->id); > > - goto leave; > > - } > > - > > - tz->last_temperature = tz->temperature; > > - tz->temperature = temp; > > - > > - for (count = 0; count < tz->trips; count++) { > > - tz->ops->get_trip_type(tz, count, &trip_type); > > - tz->ops->get_trip_temp(tz, count, &trip_temp); > > - > > - switch (trip_type) { > > - case THERMAL_TRIP_CRITICAL: > > - if (temp >= trip_temp) { > > - if (tz->ops->notify) > > - ret = tz->ops->notify(tz, count, > > - trip_type); > > - if (!ret) { > > - pr_emerg("Critical temperature > reached (%ld C), shutting down\n", > > - temp/1000); > > - orderly_poweroff(true); > > - } > > - } > > - break; > > - case THERMAL_TRIP_HOT: > > - if (temp >= trip_temp) > > - if (tz->ops->notify) > > - tz->ops->notify(tz, count, trip_type); > > - break; > > - case THERMAL_TRIP_ACTIVE: > > - thermal_zone_trip_update(tz, count, temp); > > - break; > > - case THERMAL_TRIP_PASSIVE: > > - if (temp >= trip_temp || tz->passive) > > - thermal_zone_trip_update(tz, count, temp); > > - break; > > - } > > - } > > - > > - if (tz->forced_passive) > > - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, > temp); > > - thermal_zone_do_update(tz); > > - > > -leave: > > - if (tz->passive) > > - thermal_zone_device_set_polling(tz, tz->passive_delay); > > - else if (tz->polling_delay) > > - thermal_zone_device_set_polling(tz, tz->polling_delay); > > - else > > - thermal_zone_device_set_polling(tz, 0); > > - mutex_unlock(&tz->lock); > > -} > > -EXPORT_SYMBOL(thermal_zone_device_update); > > - > > /** > > * create_trip_attrs - create attributes for trip points > > * @tz: the thermal zone device >
On ?, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote: > Hi Rui, > > > -----Original Message----- > > From: Zhang, Rui > > Sent: Monday, September 10, 2012 2:14 PM > > To: R, Durgadoss > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; eduardo.valentin@ti.com > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of > > thermal_sys.c > [cut.] > > > > + > > > +static void handle_non_critical_trips(struct thermal_zone_device *tz, > > > + int trip, enum thermal_trip_type trip_type) > > > +{ > > > + tz->governor->throttle(tz, trip); > > > +} > > here is the problem, we must make sure every registered thermal zone > > have a governor when it is running, right? > > Yes, agree with you. Had some thoughts here, but wanted to get your opinion > before I implemented them. > > 1. We can make the default governor as 'user space', and make it load inside > thermal_sys.c (so that every zone will always have a default governor) > No, the default governor should be step wise so that it behaves the same as before. if we use userspace as default governor, most of the thermal driver will stop working with this patch set. IMO, we should make all of the governors configurable, but at least one of them must be selected as the default governor, that's why we need something below. choice prompt "Default thermal governor" default THERMAL_DEFAULT_GOV_STEP_WISE help This option sets which thermal governor shall be loaded at startup. thanks, rui > 2. All other governors, that are implemented in a separate .c file can be > optional i.e. left to the user to select/deselect. > > IMO, this will make our implementation easier and cleaner. > What do you think ? > > Thanks, > Durga > > > > > then the default governor must always be built in. > > We can have a Kconfig option for step_wise, but we should not make it > > configurable by users. > > or we can use prompt to get the default governor at build time. say > > > > choice > > prompt "Default thermal governor" > > default THERMAL_DEFAULT_GOV_STEP_WISE > > help > > This option sets which thermal governor shall be loaded at > > startup. > > > > config THERMAL_DEFAULT_GOV_STEP_WISE > > bool "step-wise" > > select THERMAL_GOV_STEP_WISE > > help > > Use the thermal governor 'step-wise' as default.blabla > > > > > > thanks, > > rui > > > > > + > > > +static void handle_critical_trips(struct thermal_zone_device *tz, > > > + int trip, enum thermal_trip_type trip_type) > > > +{ > > > + long trip_temp; > > > + > > > + tz->ops->get_trip_temp(tz, trip, &trip_temp); > > > + > > > + /* If we have not crossed the trip_temp, we do not care. */ > > > + if (tz->temperature < trip_temp) > > > + return; > > > + > > > + if (tz->ops->notify) > > > + tz->ops->notify(tz, trip, trip_type); > > > + > > > + if (trip_type == THERMAL_TRIP_CRITICAL) { > > > + pr_emerg("Critical temperature reached(%d C),shutting > > down\n", > > > + tz->temperature / 1000); > > > + orderly_poweroff(true); > > > + } > > > +} > > > + > > > +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) > > > +{ > > > + enum thermal_trip_type type; > > > + > > > + tz->ops->get_trip_type(tz, trip, &type); > > > + > > > + if (type == THERMAL_TRIP_CRITICAL || type == > > THERMAL_TRIP_HOT) > > > + handle_critical_trips(tz, trip, type); > > > + else > > > + handle_non_critical_trips(tz, trip, type); > > > + /* > > > + * Alright, we handled this trip successfully. > > > + * So, start monitoring again. > > > + */ > > > + monitor_thermal_zone(tz); > > > +} > > > + > > > +static void update_temperature(struct thermal_zone_device *tz) > > > +{ > > > + long temp; > > > + int ret; > > > + > > > + mutex_lock(&tz->lock); > > > + > > > + ret = tz->ops->get_temp(tz, &temp); > > > + if (ret) { > > > + pr_warn("failed to read out thermal zone %d\n", tz->id); > > > + return; > > > + } > > > + > > > + tz->last_temperature = tz->temperature; > > > + tz->temperature = temp; > > > + > > > + mutex_unlock(&tz->lock); > > > +} > > > + > > > +void thermal_zone_device_update(struct thermal_zone_device *tz) > > > +{ > > > + int count; > > > + > > > + update_temperature(tz); > > > + > > > + for (count = 0; count < tz->trips; count++) > > > + handle_thermal_trip(tz, count); > > > +} > > > +EXPORT_SYMBOL(thermal_zone_device_update); > > > + > > > +static void thermal_zone_device_check(struct work_struct *work) > > > +{ > > > + struct thermal_zone_device *tz = container_of(work, struct > > > + thermal_zone_device, > > > + poll_queue.work); > > > + thermal_zone_device_update(tz); > > > +} > > > + > > > /* sys I/F for thermal zone */ > > > > > > #define to_thermal_zone(_dev) \ > > > @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct > > thermal_zone_device *tz) > > > } > > > #endif > > > > > > -static void thermal_zone_device_set_polling(struct thermal_zone_device > > *tz, > > > - int delay) > > > -{ > > > - cancel_delayed_work(&(tz->poll_queue)); > > > - > > > - if (!delay) > > > - return; > > > - > > > - if (delay > 1000) > > > - queue_delayed_work(system_freezable_wq, &(tz- > > >poll_queue), > > > - round_jiffies(msecs_to_jiffies(delay))); > > > - else > > > - queue_delayed_work(system_freezable_wq, &(tz- > > >poll_queue), > > > - msecs_to_jiffies(delay)); > > > -} > > > - > > > -static void thermal_zone_device_check(struct work_struct *work) > > > -{ > > > - struct thermal_zone_device *tz = container_of(work, struct > > > - thermal_zone_device, > > > - poll_queue.work); > > > - thermal_zone_device_update(tz); > > > -} > > > - > > > /** > > > * thermal_zone_bind_cooling_device - bind a cooling device to a thermal > > zone > > > * @tz: thermal zone device > > > @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct > > thermal_cooling_device *cdev) > > > } > > > EXPORT_SYMBOL(thermal_cdev_update); > > > > > > -static void thermal_zone_do_update(struct thermal_zone_device *tz) > > > -{ > > > - struct thermal_instance *instance; > > > - > > > - list_for_each_entry(instance, &tz->thermal_instances, tz_node) > > > - thermal_cdev_update(instance->cdev); > > > -} > > > - > > > -/* > > > - * Cooling algorithm for both active and passive cooling > > > - * > > > - * 1. if the temperature is higher than a trip point, > > > - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling > > > - * state for this trip point > > > - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling > > > - * state for this trip point > > > - * > > > - * 2. if the temperature is lower than a trip point, use lower > > > - * cooling state for this trip point > > > - * > > > - * Note that this behaves the same as the previous passive cooling > > > - * algorithm. > > > - */ > > > - > > > -static void thermal_zone_trip_update(struct thermal_zone_device *tz, > > > - int trip, long temp) > > > -{ > > > - struct thermal_instance *instance; > > > - struct thermal_cooling_device *cdev = NULL; > > > - unsigned long cur_state, max_state; > > > - long trip_temp; > > > - enum thermal_trip_type trip_type; > > > - enum thermal_trend trend; > > > - > > > - if (trip == THERMAL_TRIPS_NONE) { > > > - trip_temp = tz->forced_passive; > > > - trip_type = THERMAL_TRIPS_NONE; > > > - } else { > > > - tz->ops->get_trip_temp(tz, trip, &trip_temp); > > > - tz->ops->get_trip_type(tz, trip, &trip_type); > > > - } > > > - > > > - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { > > > - /* > > > - * compare the current temperature and previous > > temperature > > > - * to get the thermal trend, if no special requirement > > > - */ > > > - if (tz->temperature > tz->last_temperature) > > > - trend = THERMAL_TREND_RAISING; > > > - else if (tz->temperature < tz->last_temperature) > > > - trend = THERMAL_TREND_DROPPING; > > > - else > > > - trend = THERMAL_TREND_STABLE; > > > - } > > > - > > > - if (temp >= trip_temp) { > > > - list_for_each_entry(instance, &tz->thermal_instances, > > tz_node) { > > > - if (instance->trip != trip) > > > - continue; > > > - > > > - cdev = instance->cdev; > > > - > > > - cdev->ops->get_cur_state(cdev, &cur_state); > > > - cdev->ops->get_max_state(cdev, &max_state); > > > - > > > - if (trend == THERMAL_TREND_RAISING) { > > > - cur_state = cur_state < instance->upper ? > > > - (cur_state + 1) : instance->upper; > > > - } else if (trend == THERMAL_TREND_DROPPING) { > > > - cur_state = cur_state > instance->lower ? > > > - (cur_state - 1) : instance->lower; > > > - } > > > - > > > - /* activate a passive thermal instance */ > > > - if ((trip_type == THERMAL_TRIP_PASSIVE || > > > - trip_type == THERMAL_TRIPS_NONE) && > > > - instance->target == THERMAL_NO_TARGET) > > > - tz->passive++; > > > - > > > - instance->target = cur_state; > > > - cdev->updated = false; /* cooling device needs > > update */ > > > - } > > > - } else { /* below trip */ > > > - list_for_each_entry(instance, &tz->thermal_instances, > > tz_node) { > > > - if (instance->trip != trip) > > > - continue; > > > - > > > - /* Do not use the inactive thermal instance */ > > > - if (instance->target == THERMAL_NO_TARGET) > > > - continue; > > > - cdev = instance->cdev; > > > - cdev->ops->get_cur_state(cdev, &cur_state); > > > - > > > - cur_state = cur_state > instance->lower ? > > > - (cur_state - 1) : THERMAL_NO_TARGET; > > > - > > > - /* deactivate a passive thermal instance */ > > > - if ((trip_type == THERMAL_TRIP_PASSIVE || > > > - trip_type == THERMAL_TRIPS_NONE) && > > > - cur_state == THERMAL_NO_TARGET) > > > - tz->passive--; > > > - instance->target = cur_state; > > > - cdev->updated = false; /* cooling device needs > > update */ > > > - } > > > - } > > > - > > > - return; > > > -} > > > -/** > > > - * thermal_zone_device_update - force an update of a thermal zone's > > state > > > - * @ttz: the thermal zone to update > > > - */ > > > - > > > -void thermal_zone_device_update(struct thermal_zone_device *tz) > > > -{ > > > - int count, ret = 0; > > > - long temp, trip_temp; > > > - enum thermal_trip_type trip_type; > > > - > > > - mutex_lock(&tz->lock); > > > - > > > - if (tz->ops->get_temp(tz, &temp)) { > > > - /* get_temp failed - retry it later */ > > > - pr_warn("failed to read out thermal zone %d\n", tz->id); > > > - goto leave; > > > - } > > > - > > > - tz->last_temperature = tz->temperature; > > > - tz->temperature = temp; > > > - > > > - for (count = 0; count < tz->trips; count++) { > > > - tz->ops->get_trip_type(tz, count, &trip_type); > > > - tz->ops->get_trip_temp(tz, count, &trip_temp); > > > - > > > - switch (trip_type) { > > > - case THERMAL_TRIP_CRITICAL: > > > - if (temp >= trip_temp) { > > > - if (tz->ops->notify) > > > - ret = tz->ops->notify(tz, count, > > > - trip_type); > > > - if (!ret) { > > > - pr_emerg("Critical temperature > > reached (%ld C), shutting down\n", > > > - temp/1000); > > > - orderly_poweroff(true); > > > - } > > > - } > > > - break; > > > - case THERMAL_TRIP_HOT: > > > - if (temp >= trip_temp) > > > - if (tz->ops->notify) > > > - tz->ops->notify(tz, count, trip_type); > > > - break; > > > - case THERMAL_TRIP_ACTIVE: > > > - thermal_zone_trip_update(tz, count, temp); > > > - break; > > > - case THERMAL_TRIP_PASSIVE: > > > - if (temp >= trip_temp || tz->passive) > > > - thermal_zone_trip_update(tz, count, temp); > > > - break; > > > - } > > > - } > > > - > > > - if (tz->forced_passive) > > > - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, > > temp); > > > - thermal_zone_do_update(tz); > > > - > > > -leave: > > > - if (tz->passive) > > > - thermal_zone_device_set_polling(tz, tz->passive_delay); > > > - else if (tz->polling_delay) > > > - thermal_zone_device_set_polling(tz, tz->polling_delay); > > > - else > > > - thermal_zone_device_set_polling(tz, 0); > > > - mutex_unlock(&tz->lock); > > > -} > > > -EXPORT_SYMBOL(thermal_zone_device_update); > > > - > > > /** > > > * create_trip_attrs - create attributes for trip points > > > * @tz: the thermal zone device > > > -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Rui, > On ?, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote: > > Hi Rui, > > > > > -----Original Message----- > > > From: Zhang, Rui > > > Sent: Monday, September 10, 2012 2:14 PM > > > To: R, Durgadoss > > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; > eduardo.valentin@ti.com > > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of > > > thermal_sys.c > > [cut.] > > > > > > + > > > > +static void handle_non_critical_trips(struct thermal_zone_device *tz, > > > > + int trip, enum thermal_trip_type trip_type) > > > > +{ > > > > + tz->governor->throttle(tz, trip); > > > > +} > > > here is the problem, we must make sure every registered thermal zone > > > have a governor when it is running, right? > > > > Yes, agree with you. Had some thoughts here, but wanted to get your > opinion > > before I implemented them. > > > > 1. We can make the default governor as 'user space', and make it load > inside > > thermal_sys.c (so that every zone will always have a default governor) > > > No, the default governor should be step wise so that it behaves the same > as before. if we use userspace as default governor, most of the thermal > driver will stop working with this patch set. yes, I understand. Shall make step_wise default, and always loaded. For user space, should we move it to a new .c file, and make it like other governors or can we keep it as it is ? Thanks, Durga > > IMO, we should make all of the governors configurable, but at least one > of them must be selected as the default governor, that's why we need > something below. > > choice > prompt "Default thermal governor" > default THERMAL_DEFAULT_GOV_STEP_WISE > help > This option sets which thermal governor shall be loaded at > startup. > > thanks, > rui > > > 2. All other governors, that are implemented in a separate .c file can be > > optional i.e. left to the user to select/deselect. > > > > IMO, this will make our implementation easier and cleaner. > > What do you think ? > > > > Thanks, > > Durga > > > > > > > > then the default governor must always be built in. > > > We can have a Kconfig option for step_wise, but we should not make it > > > configurable by users. > > > or we can use prompt to get the default governor at build time. say > > > > > > choice > > > prompt "Default thermal governor" > > > default THERMAL_DEFAULT_GOV_STEP_WISE > > > help > > > This option sets which thermal governor shall be loaded at > > > startup. > > > > > > config THERMAL_DEFAULT_GOV_STEP_WISE > > > bool "step-wise" > > > select THERMAL_GOV_STEP_WISE > > > help > > > Use the thermal governor 'step-wise' as default.blabla > > > > > > > > > thanks, > > > rui
On ?, 2012-09-10 at 21:05 -0600, R, Durgadoss wrote: > Hi Rui, > > > On ?, 2012-09-10 at 02:56 -0600, R, Durgadoss wrote: > > > Hi Rui, > > > > > > > -----Original Message----- > > > > From: Zhang, Rui > > > > Sent: Monday, September 10, 2012 2:14 PM > > > > To: R, Durgadoss > > > > Cc: lenb@kernel.org; linux-acpi@vger.kernel.org; > > eduardo.valentin@ti.com > > > > Subject: Re: [PATCHv3 13/15] Thermal: Remove throttling logic out of > > > > thermal_sys.c > > > [cut.] > > > > > > > > + > > > > > +static void handle_non_critical_trips(struct thermal_zone_device *tz, > > > > > + int trip, enum thermal_trip_type trip_type) > > > > > +{ > > > > > + tz->governor->throttle(tz, trip); > > > > > +} > > > > here is the problem, we must make sure every registered thermal zone > > > > have a governor when it is running, right? > > > > > > Yes, agree with you. Had some thoughts here, but wanted to get your > > opinion > > > before I implemented them. > > > > > > 1. We can make the default governor as 'user space', and make it load > > inside > > > thermal_sys.c (so that every zone will always have a default governor) > > > > > No, the default governor should be step wise so that it behaves the same > > as before. if we use userspace as default governor, most of the thermal > > driver will stop working with this patch set. > > yes, I understand. Shall make step_wise default, and always loaded. > we can always make step-wise default, or we can ask users to select one as default and load it. > For user space, should we move it to a new .c file, and make it like > other governors or can we keep it as it is ? > a new .c file for userspace governor. > Thanks, > Durga > > > > > IMO, we should make all of the governors configurable, but at least one > > of them must be selected as the default governor, that's why we need > > something below. > > > > choice > > prompt "Default thermal governor" > > default THERMAL_DEFAULT_GOV_STEP_WISE > > help > > This option sets which thermal governor shall be loaded at > > startup. > > > > thanks, > > rui > > > > > 2. All other governors, that are implemented in a separate .c file can be > > > optional i.e. left to the user to select/deselect. > > > > > > IMO, this will make our implementation easier and cleaner. > > > What do you think ? > > > > > > Thanks, > > > Durga > > > > > > > > > > > then the default governor must always be built in. > > > > We can have a Kconfig option for step_wise, but we should not make it > > > > configurable by users. > > > > or we can use prompt to get the default governor at build time. say > > > > > > > > choice > > > > prompt "Default thermal governor" > > > > default THERMAL_DEFAULT_GOV_STEP_WISE > > > > help > > > > This option sets which thermal governor shall be loaded at > > > > startup. > > > > > > > > config THERMAL_DEFAULT_GOV_STEP_WISE > > > > bool "step-wise" > > > > select THERMAL_GOV_STEP_WISE > > > > help > > > > Use the thermal governor 'step-wise' as default.blabla > > > > > > > > > > > > thanks, > > > > rui -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
SGkgUnVpLA0KDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogWmhhbmcs IFJ1aQ0KPiBTZW50OiBUdWVzZGF5LCBTZXB0ZW1iZXIgMTEsIDIwMTIgODo1MSBBTQ0KPiBUbzog UiwgRHVyZ2Fkb3NzDQo+IENjOiBsZW5iQGtlcm5lbC5vcmc7IGxpbnV4LWFjcGlAdmdlci5rZXJu ZWwub3JnOyBlZHVhcmRvLnZhbGVudGluQHRpLmNvbQ0KPiBTdWJqZWN0OiBSRTogW1BBVENIdjMg MTMvMTVdIFRoZXJtYWw6IFJlbW92ZSB0aHJvdHRsaW5nIGxvZ2ljIG91dCBvZg0KPiB0aGVybWFs X3N5cy5jDQo+IA0KPiBPbiDkuIAsIDIwMTItMDktMTAgYXQgMjE6MDUgLTA2MDAsIFIsIER1cmdh ZG9zcyB3cm90ZToNCj4gPiBIaSBSdWksDQo+ID4NCj4gPiA+IE9uIOS4gCwgMjAxMi0wOS0xMCBh dCAwMjo1NiAtMDYwMCwgUiwgRHVyZ2Fkb3NzIHdyb3RlOg0KPiA+ID4gPiBIaSBSdWksDQo+ID4g PiA+DQo+ID4gPiA+ID4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gPiA+ID4gPiBGcm9t OiBaaGFuZywgUnVpDQo+ID4gPiA+ID4gU2VudDogTW9uZGF5LCBTZXB0ZW1iZXIgMTAsIDIwMTIg MjoxNCBQTQ0KPiA+ID4gPiA+IFRvOiBSLCBEdXJnYWRvc3MNCj4gPiA+ID4gPiBDYzogbGVuYkBr ZXJuZWwub3JnOyBsaW51eC1hY3BpQHZnZXIua2VybmVsLm9yZzsNCj4gPiA+IGVkdWFyZG8udmFs ZW50aW5AdGkuY29tDQo+ID4gPiA+ID4gU3ViamVjdDogUmU6IFtQQVRDSHYzIDEzLzE1XSBUaGVy bWFsOiBSZW1vdmUgdGhyb3R0bGluZyBsb2dpYyBvdXQgb2YNCj4gPiA+ID4gPiB0aGVybWFsX3N5 cy5jDQo+ID4gPiA+IFtjdXQuXQ0KPiA+ID4gPg0KPiA+ID4gPiA+ID4gKw0KPiA+ID4gPiA+ID4g K3N0YXRpYyB2b2lkIGhhbmRsZV9ub25fY3JpdGljYWxfdHJpcHMoc3RydWN0IHRoZXJtYWxfem9u ZV9kZXZpY2UNCj4gKnR6LA0KPiA+ID4gPiA+ID4gKwkJCWludCB0cmlwLCBlbnVtIHRoZXJtYWxf dHJpcF90eXBlIHRyaXBfdHlwZSkNCj4gPiA+ID4gPiA+ICt7DQo+ID4gPiA+ID4gPiArCXR6LT5n b3Zlcm5vci0+dGhyb3R0bGUodHosIHRyaXApOw0KPiA+ID4gPiA+ID4gK30NCj4gPiA+ID4gPiBo ZXJlIGlzIHRoZSBwcm9ibGVtLCB3ZSBtdXN0IG1ha2Ugc3VyZSBldmVyeSByZWdpc3RlcmVkIHRo ZXJtYWwNCj4gem9uZQ0KPiA+ID4gPiA+IGhhdmUgYSBnb3Zlcm5vciB3aGVuIGl0IGlzIHJ1bm5p bmcsIHJpZ2h0Pw0KPiA+ID4gPg0KPiA+ID4gPiBZZXMsIGFncmVlIHdpdGggeW91LiBIYWQgc29t ZSB0aG91Z2h0cyBoZXJlLCBidXQgd2FudGVkIHRvIGdldCB5b3VyDQo+ID4gPiBvcGluaW9uDQo+ ID4gPiA+IGJlZm9yZSBJIGltcGxlbWVudGVkIHRoZW0uDQo+ID4gPiA+DQo+ID4gPiA+IDEuIFdl IGNhbiBtYWtlIHRoZSBkZWZhdWx0IGdvdmVybm9yIGFzICd1c2VyIHNwYWNlJywgYW5kIG1ha2Ug aXQgbG9hZA0KPiA+ID4gaW5zaWRlDQo+ID4gPiA+IHRoZXJtYWxfc3lzLmMgKHNvIHRoYXQgZXZl cnkgem9uZSB3aWxsIGFsd2F5cyBoYXZlIGEgZGVmYXVsdCBnb3Zlcm5vcikNCj4gPiA+ID4NCj4g PiA+IE5vLCB0aGUgZGVmYXVsdCBnb3Zlcm5vciBzaG91bGQgYmUgc3RlcCB3aXNlIHNvIHRoYXQg aXQgYmVoYXZlcyB0aGUgc2FtZQ0KPiA+ID4gYXMgYmVmb3JlLiBpZiB3ZSB1c2UgdXNlcnNwYWNl IGFzIGRlZmF1bHQgZ292ZXJub3IsIG1vc3Qgb2YgdGhlIHRoZXJtYWwNCj4gPiA+IGRyaXZlciB3 aWxsIHN0b3Agd29ya2luZyB3aXRoIHRoaXMgcGF0Y2ggc2V0Lg0KPiA+DQo+ID4geWVzLCBJIHVu ZGVyc3RhbmQuIFNoYWxsIG1ha2Ugc3RlcF93aXNlIGRlZmF1bHQsIGFuZCBhbHdheXMgbG9hZGVk Lg0KPiA+DQo+IHdlIGNhbiBhbHdheXMgbWFrZSBzdGVwLXdpc2UgZGVmYXVsdCwgb3Igd2UgY2Fu IGFzayB1c2VycyB0byBzZWxlY3Qgb25lDQo+IGFzIGRlZmF1bHQgYW5kIGxvYWQgaXQuDQoNCldp bGwgYWx3YXlzIHN0ZXBfd2lzZSBkZWZhdWx0LiBUaGF0IHdpbGwgZXhhY3RseSBtaW1pYyB0aGUg b2xkIGJlaGF2aW9yLg0Kd2lsbCBhbHNvIGNyZWF0ZSBhIG5ldyBmaWxlIGZvciB1c2VyIHNwYWNl IGdvdmVybm9yLg0KDQpUaGFua3MsDQpEdXJnYQ0K -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 93672aa..086c1c9 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -315,6 +315,118 @@ exit: mutex_unlock(&thermal_list_lock); } +static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, + int delay) +{ + cancel_delayed_work(&(tz->poll_queue)); + + if (!delay) + return; + + if (delay > 1000) + queue_delayed_work(system_freezable_wq, &(tz->poll_queue), + round_jiffies(msecs_to_jiffies(delay))); + else + queue_delayed_work(system_freezable_wq, &(tz->poll_queue), + msecs_to_jiffies(delay)); +} + +static void monitor_thermal_zone(struct thermal_zone_device *tz) +{ + mutex_lock(&tz->lock); + + if (tz->passive) + thermal_zone_device_set_polling(tz, tz->passive_delay); + else if (tz->polling_delay) + thermal_zone_device_set_polling(tz, tz->polling_delay); + else + thermal_zone_device_set_polling(tz, 0); + + mutex_unlock(&tz->lock); +} + +static void handle_non_critical_trips(struct thermal_zone_device *tz, + int trip, enum thermal_trip_type trip_type) +{ + tz->governor->throttle(tz, trip); +} + +static void handle_critical_trips(struct thermal_zone_device *tz, + int trip, enum thermal_trip_type trip_type) +{ + long trip_temp; + + tz->ops->get_trip_temp(tz, trip, &trip_temp); + + /* If we have not crossed the trip_temp, we do not care. */ + if (tz->temperature < trip_temp) + return; + + if (tz->ops->notify) + tz->ops->notify(tz, trip, trip_type); + + if (trip_type == THERMAL_TRIP_CRITICAL) { + pr_emerg("Critical temperature reached(%d C),shutting down\n", + tz->temperature / 1000); + orderly_poweroff(true); + } +} + +static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) +{ + enum thermal_trip_type type; + + tz->ops->get_trip_type(tz, trip, &type); + + if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) + handle_critical_trips(tz, trip, type); + else + handle_non_critical_trips(tz, trip, type); + /* + * Alright, we handled this trip successfully. + * So, start monitoring again. + */ + monitor_thermal_zone(tz); +} + +static void update_temperature(struct thermal_zone_device *tz) +{ + long temp; + int ret; + + mutex_lock(&tz->lock); + + ret = tz->ops->get_temp(tz, &temp); + if (ret) { + pr_warn("failed to read out thermal zone %d\n", tz->id); + return; + } + + tz->last_temperature = tz->temperature; + tz->temperature = temp; + + mutex_unlock(&tz->lock); +} + +void thermal_zone_device_update(struct thermal_zone_device *tz) +{ + int count; + + update_temperature(tz); + + for (count = 0; count < tz->trips; count++) + handle_thermal_trip(tz, count); +} +EXPORT_SYMBOL(thermal_zone_device_update); + +static void thermal_zone_device_check(struct work_struct *work) +{ + struct thermal_zone_device *tz = container_of(work, struct + thermal_zone_device, + poll_queue.work); + thermal_zone_device_update(tz); +} + /* sys I/F for thermal zone */ #define to_thermal_zone(_dev) \ @@ -936,30 +1048,6 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) } #endif -static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, - int delay) -{ - cancel_delayed_work(&(tz->poll_queue)); - - if (!delay) - return; - - if (delay > 1000) - queue_delayed_work(system_freezable_wq, &(tz->poll_queue), - round_jiffies(msecs_to_jiffies(delay))); - else - queue_delayed_work(system_freezable_wq, &(tz->poll_queue), - msecs_to_jiffies(delay)); -} - -static void thermal_zone_device_check(struct work_struct *work) -{ - struct thermal_zone_device *tz = container_of(work, struct - thermal_zone_device, - poll_queue.work); - thermal_zone_device_update(tz); -} - /** * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone * @tz: thermal zone device @@ -1283,183 +1371,6 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) } EXPORT_SYMBOL(thermal_cdev_update); -static void thermal_zone_do_update(struct thermal_zone_device *tz) -{ - struct thermal_instance *instance; - - list_for_each_entry(instance, &tz->thermal_instances, tz_node) - thermal_cdev_update(instance->cdev); -} - -/* - * Cooling algorithm for both active and passive cooling - * - * 1. if the temperature is higher than a trip point, - * a. if the trend is THERMAL_TREND_RAISING, use higher cooling - * state for this trip point - * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling - * state for this trip point - * - * 2. if the temperature is lower than a trip point, use lower - * cooling state for this trip point - * - * Note that this behaves the same as the previous passive cooling - * algorithm. - */ - -static void thermal_zone_trip_update(struct thermal_zone_device *tz, - int trip, long temp) -{ - struct thermal_instance *instance; - struct thermal_cooling_device *cdev = NULL; - unsigned long cur_state, max_state; - long trip_temp; - enum thermal_trip_type trip_type; - enum thermal_trend trend; - - if (trip == THERMAL_TRIPS_NONE) { - trip_temp = tz->forced_passive; - trip_type = THERMAL_TRIPS_NONE; - } else { - tz->ops->get_trip_temp(tz, trip, &trip_temp); - tz->ops->get_trip_type(tz, trip, &trip_type); - } - - if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { - /* - * compare the current temperature and previous temperature - * to get the thermal trend, if no special requirement - */ - if (tz->temperature > tz->last_temperature) - trend = THERMAL_TREND_RAISING; - else if (tz->temperature < tz->last_temperature) - trend = THERMAL_TREND_DROPPING; - else - trend = THERMAL_TREND_STABLE; - } - - if (temp >= trip_temp) { - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip) - continue; - - cdev = instance->cdev; - - cdev->ops->get_cur_state(cdev, &cur_state); - cdev->ops->get_max_state(cdev, &max_state); - - if (trend == THERMAL_TREND_RAISING) { - cur_state = cur_state < instance->upper ? - (cur_state + 1) : instance->upper; - } else if (trend == THERMAL_TREND_DROPPING) { - cur_state = cur_state > instance->lower ? - (cur_state - 1) : instance->lower; - } - - /* activate a passive thermal instance */ - if ((trip_type == THERMAL_TRIP_PASSIVE || - trip_type == THERMAL_TRIPS_NONE) && - instance->target == THERMAL_NO_TARGET) - tz->passive++; - - instance->target = cur_state; - cdev->updated = false; /* cooling device needs update */ - } - } else { /* below trip */ - list_for_each_entry(instance, &tz->thermal_instances, tz_node) { - if (instance->trip != trip) - continue; - - /* Do not use the inactive thermal instance */ - if (instance->target == THERMAL_NO_TARGET) - continue; - cdev = instance->cdev; - cdev->ops->get_cur_state(cdev, &cur_state); - - cur_state = cur_state > instance->lower ? - (cur_state - 1) : THERMAL_NO_TARGET; - - /* deactivate a passive thermal instance */ - if ((trip_type == THERMAL_TRIP_PASSIVE || - trip_type == THERMAL_TRIPS_NONE) && - cur_state == THERMAL_NO_TARGET) - tz->passive--; - instance->target = cur_state; - cdev->updated = false; /* cooling device needs update */ - } - } - - return; -} -/** - * thermal_zone_device_update - force an update of a thermal zone's state - * @ttz: the thermal zone to update - */ - -void thermal_zone_device_update(struct thermal_zone_device *tz) -{ - int count, ret = 0; - long temp, trip_temp; - enum thermal_trip_type trip_type; - - mutex_lock(&tz->lock); - - if (tz->ops->get_temp(tz, &temp)) { - /* get_temp failed - retry it later */ - pr_warn("failed to read out thermal zone %d\n", tz->id); - goto leave; - } - - tz->last_temperature = tz->temperature; - tz->temperature = temp; - - for (count = 0; count < tz->trips; count++) { - tz->ops->get_trip_type(tz, count, &trip_type); - tz->ops->get_trip_temp(tz, count, &trip_temp); - - switch (trip_type) { - case THERMAL_TRIP_CRITICAL: - if (temp >= trip_temp) { - if (tz->ops->notify) - ret = tz->ops->notify(tz, count, - trip_type); - if (!ret) { - pr_emerg("Critical temperature reached (%ld C), shutting down\n", - temp/1000); - orderly_poweroff(true); - } - } - break; - case THERMAL_TRIP_HOT: - if (temp >= trip_temp) - if (tz->ops->notify) - tz->ops->notify(tz, count, trip_type); - break; - case THERMAL_TRIP_ACTIVE: - thermal_zone_trip_update(tz, count, temp); - break; - case THERMAL_TRIP_PASSIVE: - if (temp >= trip_temp || tz->passive) - thermal_zone_trip_update(tz, count, temp); - break; - } - } - - if (tz->forced_passive) - thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp); - thermal_zone_do_update(tz); - -leave: - if (tz->passive) - thermal_zone_device_set_polling(tz, tz->passive_delay); - else if (tz->polling_delay) - thermal_zone_device_set_polling(tz, tz->polling_delay); - else - thermal_zone_device_set_polling(tz, 0); - mutex_unlock(&tz->lock); -} -EXPORT_SYMBOL(thermal_zone_device_update); - /** * create_trip_attrs - create attributes for trip points * @tz: the thermal zone device
This patch removes the throttling logic out of thermal_sys.c; also refactors the code into smaller functions so that are easy to read/maintain. * Seperates the handling of critical and non-critical trips * Re-arranges the set_polling and device_check methods, so that all related functions are arranged in one place. * Removes the 'do_update' and 'trip_update' method, as part of moving the throttling logic out of thermal_sys.c Signed-off-by: Durgadoss R <durgadoss.r@intel.com> --- drivers/thermal/thermal_sys.c | 313 +++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 201 deletions(-)