From 1595d887afe46b0ad721f27df895a61d4879ede2 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:16 +0200 Subject: thermal: Store thermal mode in a dedicated enum Prepare for storing mode in struct thermal_zone_device. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Guenter Roeck [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-3-andrzej.p@collabora.com --- .../thermal/intel/int340x_thermal/int3400_thermal.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 0b3a62655843..e84faaadff87 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -48,7 +48,7 @@ struct int3400_thermal_priv { struct acpi_device *adev; struct platform_device *pdev; struct thermal_zone_device *thermal; - int mode; + enum thermal_device_mode mode; int art_count; struct art *arts; int trt_count; @@ -395,24 +395,20 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { struct int3400_thermal_priv *priv = thermal->devdata; - bool enable; int result = 0; if (!priv) return -EINVAL; - if (mode == THERMAL_DEVICE_ENABLED) - enable = true; - else if (mode == THERMAL_DEVICE_DISABLED) - enable = false; - else + if (mode != THERMAL_DEVICE_ENABLED && + mode != THERMAL_DEVICE_DISABLED) return -EINVAL; - if (enable != priv->mode) { - priv->mode = enable; + if (mode != priv->mode) { + priv->mode = mode; result = int3400_thermal_run_osc(priv->adev->handle, - priv->current_uuid_index, - enable); + priv->current_uuid_index, + mode == THERMAL_DEVICE_ENABLED); } evaluate_odvp(priv); -- cgit v1.2.3-58-ga151 From 5a3506657f71d7ca124c040aff98639673c5dc97 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:18 +0200 Subject: thermal: Store device mode in struct thermal_zone_device Prepare for eliminating get_mode(). Signed-off-by: Andrzej Pietrasiewicz [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-5-andrzej.p@collabora.com --- drivers/acpi/thermal.c | 18 ++++++------------ drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 21 ++++++++------------- drivers/platform/x86/acerhdf.c | 15 ++++++++------- drivers/thermal/da9062-thermal.c | 6 ++---- drivers/thermal/imx_thermal.c | 17 +++++++---------- .../thermal/intel/int340x_thermal/int3400_thermal.c | 12 +++--------- drivers/thermal/intel/intel_quark_dts_thermal.c | 16 +++++++--------- drivers/thermal/thermal_of.c | 10 +++------- 8 files changed, 44 insertions(+), 71 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index fb46070c66d8..4ba273f49d87 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -172,7 +172,6 @@ struct acpi_thermal { struct acpi_thermal_trips trips; struct acpi_handle_list devices; struct thermal_zone_device *thermal_zone; - enum thermal_device_mode mode; int kelvin_offset; /* in millidegrees */ struct work_struct thermal_check_work; }; @@ -500,7 +499,7 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; - if (tz->mode != THERMAL_DEVICE_ENABLED) + if (tz->thermal_zone->mode != THERMAL_DEVICE_ENABLED) return; thermal_zone_device_update(tz->thermal_zone, @@ -529,12 +528,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) static int thermal_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { - struct acpi_thermal *tz = thermal->devdata; - - if (!tz) - return -EINVAL; - - *mode = tz->mode; + *mode = thermal->mode; return 0; } @@ -556,11 +550,11 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, if (mode == THERMAL_DEVICE_DISABLED) pr_warn("thermal zone will be disabled\n"); - if (mode != tz->mode) { - tz->mode = mode; + if (mode != tz->thermal_zone->mode) { + tz->thermal_zone->mode = mode; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s kernel ACPI thermal control\n", - tz->mode == THERMAL_DEVICE_ENABLED ? + tz->thermal_zone->mode == THERMAL_DEVICE_ENABLED ? "Enable" : "Disable")); acpi_thermal_check(tz); } @@ -912,7 +906,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) goto remove_dev_link; } - tz->mode = THERMAL_DEVICE_ENABLED; + tz->thermal_zone->mode = THERMAL_DEVICE_ENABLED; dev_info(&tz->device->dev, "registered as thermal_zone%d\n", tz->thermal_zone->id); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 05f8d5a92862..51667ed99c21 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -98,7 +98,6 @@ struct mlxsw_thermal_module { struct mlxsw_thermal *parent; struct thermal_zone_device *tzdev; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; - enum thermal_device_mode mode; int module; /* Module or gearbox number */ }; @@ -110,7 +109,6 @@ struct mlxsw_thermal { struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX]; u8 cooling_levels[MLXSW_THERMAL_MAX_STATE + 1]; struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS]; - enum thermal_device_mode mode; struct mlxsw_thermal_module *tz_module_arr; u8 tz_module_num; struct mlxsw_thermal_module *tz_gearbox_arr; @@ -280,9 +278,7 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev, enum thermal_device_mode *mode) { - struct mlxsw_thermal *thermal = tzdev->devdata; - - *mode = thermal->mode; + *mode = tzdev->mode; return 0; } @@ -299,9 +295,9 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, else tzdev->polling_delay = 0; + tzdev->mode = mode; mutex_unlock(&tzdev->lock); - thermal->mode = mode; thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); return 0; @@ -468,9 +464,7 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev, enum thermal_device_mode *mode) { - struct mlxsw_thermal_module *tz = tzdev->devdata; - - *mode = tz->mode; + *mode = tzdev->mode; return 0; } @@ -488,9 +482,10 @@ static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, else tzdev->polling_delay = 0; + tzdev->mode = mode; + mutex_unlock(&tzdev->lock); - tz->mode = mode; thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); return 0; @@ -780,7 +775,7 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) return err; } - module_tz->mode = THERMAL_DEVICE_ENABLED; + module_tz->tzdev->mode = THERMAL_DEVICE_ENABLED; return 0; } @@ -896,7 +891,7 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) if (IS_ERR(gearbox_tz->tzdev)) return PTR_ERR(gearbox_tz->tzdev); - gearbox_tz->mode = THERMAL_DEVICE_ENABLED; + gearbox_tz->tzdev->mode = THERMAL_DEVICE_ENABLED; return 0; } @@ -1065,7 +1060,7 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (err) goto err_unreg_modules_tzdev; - thermal->mode = THERMAL_DEVICE_ENABLED; + thermal->tzdev->mode = THERMAL_DEVICE_ENABLED; *p_thermal = thermal; return 0; diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 9d1030b1a4f4..6f21015e5fd9 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -68,7 +68,6 @@ static int kernelmode = 1; #else static int kernelmode; #endif -static enum thermal_device_mode thermal_mode; static unsigned int interval = 10; static unsigned int fanon = 60000; @@ -398,15 +397,16 @@ static inline void acerhdf_revert_to_bios_mode(void) { acerhdf_change_fanstate(ACERHDF_FAN_AUTO); kernelmode = 0; - thermal_mode = THERMAL_DEVICE_DISABLED; - if (thz_dev) + if (thz_dev) { + thz_dev->mode = THERMAL_DEVICE_DISABLED; thz_dev->polling_delay = 0; + } pr_notice("kernel mode fan control OFF\n"); } static inline void acerhdf_enable_kernelmode(void) { kernelmode = 1; - thermal_mode = THERMAL_DEVICE_ENABLED; + thz_dev->mode = THERMAL_DEVICE_ENABLED; thz_dev->polling_delay = interval*1000; thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED); @@ -419,7 +419,7 @@ static int acerhdf_get_mode(struct thermal_zone_device *thermal, if (verbose) pr_notice("kernel mode fan control %d\n", kernelmode); - *mode = thermal_mode; + *mode = thermal->mode; return 0; } @@ -741,8 +741,6 @@ static int __init acerhdf_register_thermal(void) if (IS_ERR(cl_dev)) return -EINVAL; - thermal_mode = kernelmode ? - THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED; thz_dev = thermal_zone_device_register("acerhdf", 2, 0, NULL, &acerhdf_dev_ops, &acerhdf_zone_params, 0, @@ -750,6 +748,9 @@ static int __init acerhdf_register_thermal(void) if (IS_ERR(thz_dev)) return -EINVAL; + thz_dev->mode = kernelmode ? + THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED; + if (strcmp(thz_dev->governor->name, acerhdf_zone_params.governor_name)) { pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n", diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index c32709badeda..a14c7981c7c7 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -49,7 +49,6 @@ struct da9062_thermal { struct da9062 *hw; struct delayed_work work; struct thermal_zone_device *zone; - enum thermal_device_mode mode; struct mutex lock; /* protection for da9062_thermal temperature */ int temperature; int irq; @@ -124,8 +123,7 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) static int da9062_thermal_get_mode(struct thermal_zone_device *z, enum thermal_device_mode *mode) { - struct da9062_thermal *thermal = z->devdata; - *mode = thermal->mode; + *mode = z->mode; return 0; } @@ -233,7 +231,6 @@ static int da9062_thermal_probe(struct platform_device *pdev) thermal->config = match->data; thermal->hw = chip; - thermal->mode = THERMAL_DEVICE_ENABLED; thermal->dev = &pdev->dev; INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on); @@ -248,6 +245,7 @@ static int da9062_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(thermal->zone); goto err; } + thermal->zone->mode = THERMAL_DEVICE_ENABLED; dev_dbg(&pdev->dev, "TJUNC temperature polling period set at %d ms\n", diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index e761c9b42217..9a1114d721b6 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -197,7 +197,6 @@ struct imx_thermal_data { struct cpufreq_policy *policy; struct thermal_zone_device *tz; struct thermal_cooling_device *cdev; - enum thermal_device_mode mode; struct regmap *tempmon; u32 c1, c2; /* See formula in imx_init_calib() */ int temp_passive; @@ -256,7 +255,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) bool wait; u32 val; - if (data->mode == THERMAL_DEVICE_ENABLED) { + if (tz->mode == THERMAL_DEVICE_ENABLED) { /* Check if a measurement is currently in progress */ regmap_read(map, soc_data->temp_data, &val); wait = !(val & soc_data->temp_valid_mask); @@ -283,7 +282,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) regmap_read(map, soc_data->temp_data, &val); - if (data->mode != THERMAL_DEVICE_ENABLED) { + if (tz->mode != THERMAL_DEVICE_ENABLED) { regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->measure_temp_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, @@ -334,9 +333,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) static int imx_get_mode(struct thermal_zone_device *tz, enum thermal_device_mode *mode) { - struct imx_thermal_data *data = tz->devdata; - - *mode = data->mode; + *mode = tz->mode; return 0; } @@ -376,7 +373,7 @@ static int imx_set_mode(struct thermal_zone_device *tz, } } - data->mode = mode; + tz->mode = mode; thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); return 0; @@ -831,7 +828,7 @@ static int imx_thermal_probe(struct platform_device *pdev) data->socdata->measure_temp_mask); data->irq_enabled = true; - data->mode = THERMAL_DEVICE_ENABLED; + data->tz->mode = THERMAL_DEVICE_ENABLED; ret = devm_request_threaded_irq(&pdev->dev, data->irq, imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, @@ -885,7 +882,7 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) data->socdata->measure_temp_mask); regmap_write(map, data->socdata->sensor_ctrl + REG_SET, data->socdata->power_down_mask); - data->mode = THERMAL_DEVICE_DISABLED; + data->tz->mode = THERMAL_DEVICE_DISABLED; clk_disable_unprepare(data->thermal_clk); return 0; @@ -905,7 +902,7 @@ static int __maybe_unused imx_thermal_resume(struct device *dev) data->socdata->power_down_mask); regmap_write(map, data->socdata->sensor_ctrl + REG_SET, data->socdata->measure_temp_mask); - data->mode = THERMAL_DEVICE_ENABLED; + data->tz->mode = THERMAL_DEVICE_ENABLED; return 0; } diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index e84faaadff87..f65b2fc09198 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -48,7 +48,6 @@ struct int3400_thermal_priv { struct acpi_device *adev; struct platform_device *pdev; struct thermal_zone_device *thermal; - enum thermal_device_mode mode; int art_count; struct art *arts; int trt_count; @@ -381,12 +380,7 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, static int int3400_thermal_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { - struct int3400_thermal_priv *priv = thermal->devdata; - - if (!priv) - return -EINVAL; - - *mode = priv->mode; + *mode = thermal->mode; return 0; } @@ -404,8 +398,8 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, mode != THERMAL_DEVICE_DISABLED) return -EINVAL; - if (mode != priv->mode) { - priv->mode = mode; + if (mode != thermal->mode) { + thermal->mode = mode; result = int3400_thermal_run_osc(priv->adev->handle, priv->current_uuid_index, mode == THERMAL_DEVICE_ENABLED); diff --git a/drivers/thermal/intel/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c index d704fc104cfd..d77cb3df5ade 100644 --- a/drivers/thermal/intel/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel/intel_quark_dts_thermal.c @@ -103,7 +103,6 @@ struct soc_sensor_entry { bool locked; u32 store_ptps; u32 store_dts_enable; - enum thermal_device_mode mode; struct thermal_zone_device *tzone; }; @@ -128,7 +127,7 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) return ret; if (out & QRK_DTS_ENABLE_BIT) { - aux_entry->mode = THERMAL_DEVICE_ENABLED; + tzd->mode = THERMAL_DEVICE_ENABLED; return 0; } @@ -139,9 +138,9 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) if (ret) return ret; - aux_entry->mode = THERMAL_DEVICE_ENABLED; + tzd->mode = THERMAL_DEVICE_ENABLED; } else { - aux_entry->mode = THERMAL_DEVICE_DISABLED; + tzd->mode = THERMAL_DEVICE_DISABLED; pr_info("DTS is locked. Cannot enable DTS\n"); ret = -EPERM; } @@ -161,7 +160,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) return ret; if (!(out & QRK_DTS_ENABLE_BIT)) { - aux_entry->mode = THERMAL_DEVICE_DISABLED; + tzd->mode = THERMAL_DEVICE_DISABLED; return 0; } @@ -173,9 +172,9 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) if (ret) return ret; - aux_entry->mode = THERMAL_DEVICE_DISABLED; + tzd->mode = THERMAL_DEVICE_DISABLED; } else { - aux_entry->mode = THERMAL_DEVICE_ENABLED; + tzd->mode = THERMAL_DEVICE_ENABLED; pr_info("DTS is locked. Cannot disable DTS\n"); ret = -EPERM; } @@ -312,8 +311,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, static int sys_get_mode(struct thermal_zone_device *tzd, enum thermal_device_mode *mode) { - struct soc_sensor_entry *aux_entry = tzd->devdata; - *mode = aux_entry->mode; + *mode = tzd->mode; return 0; } diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index ddf88dbe7ba2..c495b1e48ef2 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -51,7 +51,6 @@ struct __thermal_bind_params { /** * struct __thermal_zone - internal representation of a thermal zone - * @mode: current thermal zone device mode (enabled/disabled) * @passive_delay: polling interval while passive cooling is activated * @polling_delay: zone polling interval * @slope: slope of the temperature adjustment curve @@ -65,7 +64,6 @@ struct __thermal_bind_params { */ struct __thermal_zone { - enum thermal_device_mode mode; int passive_delay; int polling_delay; int slope; @@ -272,9 +270,7 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, static int of_thermal_get_mode(struct thermal_zone_device *tz, enum thermal_device_mode *mode) { - struct __thermal_zone *data = tz->devdata; - - *mode = data->mode; + *mode = tz->mode; return 0; } @@ -296,7 +292,7 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, mutex_unlock(&tz->lock); - data->mode = mode; + tz->mode = mode; thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); return 0; @@ -979,7 +975,6 @@ __init *thermal_of_build_thermal_zone(struct device_node *np) finish: of_node_put(child); - tz->mode = THERMAL_DEVICE_DISABLED; return tz; @@ -1134,6 +1129,7 @@ int __init of_parse_thermal_zones(void) of_thermal_free_zone(tz); /* attempting to build remaining zones still */ } + zone->mode = THERMAL_DEVICE_DISABLED; } of_node_put(np); -- cgit v1.2.3-58-ga151 From 1ee14820fd8ee79c4fc191155f48c985f28040e2 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:19 +0200 Subject: thermal: remove get_mode() operation of drivers get_mode() is now redundant, as the state is stored in struct thermal_zone_device. Consequently the "mode" attribute in sysfs can always be visible, because it is always possible to get the mode from struct tzd. Signed-off-by: Andrzej Pietrasiewicz [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-6-andrzej.p@collabora.com --- drivers/acpi/thermal.c | 9 ------- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 19 -------------- drivers/platform/x86/acerhdf.c | 12 --------- drivers/thermal/da9062-thermal.c | 8 ------ drivers/thermal/imx_thermal.c | 9 ------- .../intel/int340x_thermal/int3400_thermal.c | 9 ------- drivers/thermal/intel/intel_quark_dts_thermal.c | 8 ------ drivers/thermal/thermal_core.c | 7 +---- drivers/thermal/thermal_of.c | 9 ------- drivers/thermal/thermal_sysfs.c | 30 ++-------------------- include/linux/thermal.h | 2 -- 11 files changed, 3 insertions(+), 119 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 4ba273f49d87..592be97c4456 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -525,14 +525,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) return 0; } -static int thermal_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) -{ - *mode = thermal->mode; - - return 0; -} - static int thermal_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { @@ -847,7 +839,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .bind = acpi_thermal_bind_cooling_device, .unbind = acpi_thermal_unbind_cooling_device, .get_temp = thermal_get_temp, - .get_mode = thermal_get_mode, .set_mode = thermal_set_mode, .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 51667ed99c21..ad61b2db30b8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -275,14 +275,6 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, return 0; } -static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev, - enum thermal_device_mode *mode) -{ - *mode = tzdev->mode; - - return 0; -} - static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, enum thermal_device_mode mode) { @@ -402,7 +394,6 @@ static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_ops = { .bind = mlxsw_thermal_bind, .unbind = mlxsw_thermal_unbind, - .get_mode = mlxsw_thermal_get_mode, .set_mode = mlxsw_thermal_set_mode, .get_temp = mlxsw_thermal_get_temp, .get_trip_type = mlxsw_thermal_get_trip_type, @@ -461,14 +452,6 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, return err; } -static int mlxsw_thermal_module_mode_get(struct thermal_zone_device *tzdev, - enum thermal_device_mode *mode) -{ - *mode = tzdev->mode; - - return 0; -} - static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, enum thermal_device_mode mode) { @@ -606,7 +589,6 @@ static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .get_mode = mlxsw_thermal_module_mode_get, .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_module_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, @@ -645,7 +627,6 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .get_mode = mlxsw_thermal_module_mode_get, .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_gearbox_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 6f21015e5fd9..58c4e1caaa09 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -413,17 +413,6 @@ static inline void acerhdf_enable_kernelmode(void) pr_notice("kernel mode fan control ON\n"); } -static int acerhdf_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) -{ - if (verbose) - pr_notice("kernel mode fan control %d\n", kernelmode); - - *mode = thermal->mode; - - return 0; -} - /* * set operation mode; * enabled: the thermal layer of the kernel takes care about @@ -490,7 +479,6 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = { .bind = acerhdf_bind, .unbind = acerhdf_unbind, .get_temp = acerhdf_get_ec_temp, - .get_mode = acerhdf_get_mode, .set_mode = acerhdf_set_mode, .get_trip_type = acerhdf_get_trip_type, .get_trip_hyst = acerhdf_get_trip_hyst, diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index a14c7981c7c7..a7ac8afb063e 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -120,13 +120,6 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static int da9062_thermal_get_mode(struct thermal_zone_device *z, - enum thermal_device_mode *mode) -{ - *mode = z->mode; - return 0; -} - static int da9062_thermal_get_trip_type(struct thermal_zone_device *z, int trip, enum thermal_trip_type *type) @@ -179,7 +172,6 @@ static int da9062_thermal_get_temp(struct thermal_zone_device *z, static struct thermal_zone_device_ops da9062_thermal_ops = { .get_temp = da9062_thermal_get_temp, - .get_mode = da9062_thermal_get_mode, .get_trip_type = da9062_thermal_get_trip_type, .get_trip_temp = da9062_thermal_get_trip_temp, }; diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 9a1114d721b6..2c7ee5da608a 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -330,14 +330,6 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) return 0; } -static int imx_get_mode(struct thermal_zone_device *tz, - enum thermal_device_mode *mode) -{ - *mode = tz->mode; - - return 0; -} - static int imx_set_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode) { @@ -464,7 +456,6 @@ static struct thermal_zone_device_ops imx_tz_ops = { .bind = imx_bind, .unbind = imx_unbind, .get_temp = imx_get_temp, - .get_mode = imx_get_mode, .set_mode = imx_set_mode, .get_trip_type = imx_get_trip_type, .get_trip_temp = imx_get_trip_temp, diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index f65b2fc09198..9a622aaf29dd 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -377,14 +377,6 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, return 0; } -static int int3400_thermal_get_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode *mode) -{ - *mode = thermal->mode; - - return 0; -} - static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { @@ -412,7 +404,6 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, static struct thermal_zone_device_ops int3400_thermal_ops = { .get_temp = int3400_thermal_get_temp, - .get_mode = int3400_thermal_get_mode, .set_mode = int3400_thermal_set_mode, }; diff --git a/drivers/thermal/intel/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c index d77cb3df5ade..c4879b4bfbf1 100644 --- a/drivers/thermal/intel/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel/intel_quark_dts_thermal.c @@ -308,13 +308,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, return 0; } -static int sys_get_mode(struct thermal_zone_device *tzd, - enum thermal_device_mode *mode) -{ - *mode = tzd->mode; - return 0; -} - static int sys_set_mode(struct thermal_zone_device *tzd, enum thermal_device_mode mode) { @@ -336,7 +329,6 @@ static struct thermal_zone_device_ops tzone_ops = { .get_trip_type = sys_get_trip_type, .set_trip_temp = sys_set_trip_temp, .get_crit_temp = sys_get_crit_temp, - .get_mode = sys_get_mode, .set_mode = sys_set_mode, }; diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b71196eaf90e..14d3b1b94c4f 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1456,7 +1456,6 @@ static int thermal_pm_notify(struct notifier_block *nb, unsigned long mode, void *_unused) { struct thermal_zone_device *tz; - enum thermal_device_mode tz_mode; switch (mode) { case PM_HIBERNATION_PREPARE: @@ -1469,11 +1468,7 @@ static int thermal_pm_notify(struct notifier_block *nb, case PM_POST_SUSPEND: atomic_set(&in_suspend, 0); list_for_each_entry(tz, &thermal_tz_list, node) { - tz_mode = THERMAL_DEVICE_ENABLED; - if (tz->ops->get_mode) - tz->ops->get_mode(tz, &tz_mode); - - if (tz_mode == THERMAL_DEVICE_DISABLED) + if (tz->mode == THERMAL_DEVICE_DISABLED) continue; thermal_zone_device_init(tz); diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index c495b1e48ef2..ba65d48a48cb 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -267,14 +267,6 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, return 0; } -static int of_thermal_get_mode(struct thermal_zone_device *tz, - enum thermal_device_mode *mode) -{ - *mode = tz->mode; - - return 0; -} - static int of_thermal_set_mode(struct thermal_zone_device *tz, enum thermal_device_mode mode) { @@ -389,7 +381,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, } static struct thermal_zone_device_ops of_thermal_ops = { - .get_mode = of_thermal_get_mode, .set_mode = of_thermal_set_mode, .get_trip_type = of_thermal_get_trip_type, diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index aa99edb4dff7..096370977068 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -49,18 +49,9 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - enum thermal_device_mode mode; - int result; - - if (!tz->ops->get_mode) - return -EPERM; - result = tz->ops->get_mode(tz, &mode); - if (result) - return result; - - return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" - : "disabled"); + return sprintf(buf, "%s\n", tz->mode == THERMAL_DEVICE_ENABLED ? + "enabled" : "disabled"); } static ssize_t @@ -428,30 +419,13 @@ static struct attribute_group thermal_zone_attribute_group = { .attrs = thermal_zone_dev_attrs, }; -/* We expose mode only if .get_mode is present */ static struct attribute *thermal_zone_mode_attrs[] = { &dev_attr_mode.attr, NULL, }; -static umode_t thermal_zone_mode_is_visible(struct kobject *kobj, - struct attribute *attr, - int attrno) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct thermal_zone_device *tz; - - tz = container_of(dev, struct thermal_zone_device, device); - - if (tz->ops->get_mode) - return attr->mode; - - return 0; -} - static struct attribute_group thermal_zone_mode_attribute_group = { .attrs = thermal_zone_mode_attrs, - .is_visible = thermal_zone_mode_is_visible, }; /* We expose passive only if passive trips are present */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 5f91d7f04512..a808f6fa2777 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -76,8 +76,6 @@ struct thermal_zone_device_ops { struct thermal_cooling_device *); int (*get_temp) (struct thermal_zone_device *, int *); int (*set_trips) (struct thermal_zone_device *, int, int); - int (*get_mode) (struct thermal_zone_device *, - enum thermal_device_mode *); int (*set_mode) (struct thermal_zone_device *, enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, -- cgit v1.2.3-58-ga151 From ac5d9ecc74d8beee8c87f1441e4adaf4e9fe90c5 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:20 +0200 Subject: thermal: Add mode helpers Prepare for making the drivers not access tzd's private members. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Bartlomiej Zolnierkiewicz [staticize thermal_zone_device_set_mode()] Signed-off-by: kernel test robot Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-7-andrzej.p@collabora.com --- drivers/thermal/thermal_core.c | 53 ++++++++++++++++++++++++++++++++++++++++++ include/linux/thermal.h | 13 +++++++++++ 2 files changed, 66 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 14d3b1b94c4f..f02c57c986f0 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -459,6 +459,59 @@ static void thermal_zone_device_reset(struct thermal_zone_device *tz) thermal_zone_device_init(tz); } +static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) +{ + int ret = 0; + + mutex_lock(&tz->lock); + + /* do nothing if mode isn't changing */ + if (mode == tz->mode) { + mutex_unlock(&tz->lock); + + return ret; + } + + if (tz->ops->set_mode) + ret = tz->ops->set_mode(tz, mode); + + if (!ret) + tz->mode = mode; + + mutex_unlock(&tz->lock); + + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + + return ret; +} + +int thermal_zone_device_enable(struct thermal_zone_device *tz) +{ + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_ENABLED); +} +EXPORT_SYMBOL_GPL(thermal_zone_device_enable); + +int thermal_zone_device_disable(struct thermal_zone_device *tz) +{ + return thermal_zone_device_set_mode(tz, THERMAL_DEVICE_DISABLED); +} +EXPORT_SYMBOL_GPL(thermal_zone_device_disable); + +int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) +{ + enum thermal_device_mode mode; + + mutex_lock(&tz->lock); + + mode = tz->mode; + + mutex_unlock(&tz->lock); + + return mode == THERMAL_DEVICE_ENABLED; +} +EXPORT_SYMBOL_GPL(thermal_zone_device_is_enabled); + void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) { diff --git a/include/linux/thermal.h b/include/linux/thermal.h index a808f6fa2777..df013c39ba9b 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -416,6 +416,9 @@ int thermal_zone_get_offset(struct thermal_zone_device *tz); void thermal_cdev_update(struct thermal_cooling_device *); void thermal_notify_framework(struct thermal_zone_device *, int); +int thermal_zone_device_enable(struct thermal_zone_device *tz); +int thermal_zone_device_disable(struct thermal_zone_device *tz); +int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); #else static inline struct thermal_zone_device *thermal_zone_device_register( const char *type, int trips, int mask, void *devdata, @@ -463,6 +466,16 @@ static inline void thermal_cdev_update(struct thermal_cooling_device *cdev) static inline void thermal_notify_framework(struct thermal_zone_device *tz, int trip) { } + +static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) +{ return -ENODEV; } + +static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) +{ return -ENODEV; } + +static inline int +thermal_zone_device_is_enabled(struct thermal_zone_device *tz) +{ return -ENODEV; } #endif /* CONFIG_THERMAL */ #endif /* __THERMAL_H__ */ -- cgit v1.2.3-58-ga151 From 7f4957be0d5b83c8964491863202136c916107ae Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:21 +0200 Subject: thermal: Use mode helpers in drivers Use thermal_zone_device_{en|dis}able() and thermal_zone_device_is_enabled(). Consequently, all set_mode() implementations in drivers: - can stop modifying tzd's "mode" member, - shall stop taking tzd's lock, as it is taken in the helpers - shall stop calling thermal_zone_device_update() as it is called in the helpers - can assume they are called when the mode truly changes, so checks to verify that can be dropped Not providing set_mode() by a driver no longer prevents the core from being able to set tzd's mode, so the relevant check in mode_store() is removed. Other comments: - acpi/thermal.c: tz->thermal_zone->mode will be updated only after we return from set_mode(), so use function parameter in thermal_set_mode() instead, no need to call acpi_thermal_check() in set_mode() - thermal/imx_thermal.c: regmap writes and mode assignment are done in thermal_zone_device_{en|dis}able() and set_mode() callback - thermal/intel/intel_quark_dts_thermal.c: soc_dts_{en|dis}able() are a part of set_mode() callback, so they don't need to modify tzd->mode, and don't need to fall back to the opposite mode if unsuccessful, as the return value will be propagated to thermal_zone_device_{en|dis}able() and ultimately tzd's member will not be changed in thermal_zone_device_set_mode(). - thermal/of-thermal.c: no need to set zone->mode to DISABLED in of_parse_thermal_zones() as a tzd is kzalloc'ed so mode is DISABLED anyway Signed-off-by: Andrzej Pietrasiewicz [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Amit Kucheria Reviewed-by: Bartlomiej Zolnierkiewicz Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-8-andrzej.p@collabora.com --- drivers/acpi/thermal.c | 21 ++++++------ drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 37 ++++++++++------------ drivers/platform/x86/acerhdf.c | 17 ++++++---- drivers/thermal/da9062-thermal.c | 6 +++- drivers/thermal/hisi_thermal.c | 6 ++-- drivers/thermal/imx_thermal.c | 33 ++++++++----------- .../intel/int340x_thermal/int3400_thermal.c | 5 ++- drivers/thermal/intel/intel_quark_dts_thermal.c | 18 ++--------- drivers/thermal/rockchip_thermal.c | 6 ++-- drivers/thermal/sprd_thermal.c | 6 ++-- drivers/thermal/thermal_core.c | 2 +- drivers/thermal/thermal_of.c | 10 +----- drivers/thermal/thermal_sysfs.c | 11 +++---- 13 files changed, 80 insertions(+), 98 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 592be97c4456..52b6cda1bcc3 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -499,7 +499,7 @@ static void acpi_thermal_check(void *data) { struct acpi_thermal *tz = data; - if (tz->thermal_zone->mode != THERMAL_DEVICE_ENABLED) + if (!thermal_zone_device_is_enabled(tz->thermal_zone)) return; thermal_zone_device_update(tz->thermal_zone, @@ -542,14 +542,11 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, if (mode == THERMAL_DEVICE_DISABLED) pr_warn("thermal zone will be disabled\n"); - if (mode != tz->thermal_zone->mode) { - tz->thermal_zone->mode = mode; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "%s kernel ACPI thermal control\n", - tz->thermal_zone->mode == THERMAL_DEVICE_ENABLED ? - "Enable" : "Disable")); - acpi_thermal_check(tz); - } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "%s kernel ACPI thermal control\n", + mode == THERMAL_DEVICE_ENABLED ? + "Enable" : "Disable")); + return 0; } @@ -897,13 +894,17 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) goto remove_dev_link; } - tz->thermal_zone->mode = THERMAL_DEVICE_ENABLED; + result = thermal_zone_device_enable(tz->thermal_zone); + if (result) + goto acpi_bus_detach; dev_info(&tz->device->dev, "registered as thermal_zone%d\n", tz->thermal_zone->id); return 0; +acpi_bus_detach: + acpi_bus_detach_private_data(tz->device->handle); remove_dev_link: sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); remove_tz_link: diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index ad61b2db30b8..4fb73d0fd167 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -280,18 +280,11 @@ static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, { struct mlxsw_thermal *thermal = tzdev->devdata; - mutex_lock(&tzdev->lock); - if (mode == THERMAL_DEVICE_ENABLED) tzdev->polling_delay = thermal->polling_delay; else tzdev->polling_delay = 0; - tzdev->mode = mode; - mutex_unlock(&tzdev->lock); - - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); - return 0; } @@ -458,19 +451,11 @@ static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, struct mlxsw_thermal_module *tz = tzdev->devdata; struct mlxsw_thermal *thermal = tz->parent; - mutex_lock(&tzdev->lock); - if (mode == THERMAL_DEVICE_ENABLED) tzdev->polling_delay = thermal->polling_delay; else tzdev->polling_delay = 0; - tzdev->mode = mode; - - mutex_unlock(&tzdev->lock); - - thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED); - return 0; } @@ -756,8 +741,11 @@ mlxsw_thermal_module_tz_init(struct mlxsw_thermal_module *module_tz) return err; } - module_tz->tzdev->mode = THERMAL_DEVICE_ENABLED; - return 0; + err = thermal_zone_device_enable(module_tz->tzdev); + if (err) + thermal_zone_device_unregister(module_tz->tzdev); + + return err; } static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev) @@ -860,6 +848,7 @@ static int mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) { char tz_name[MLXSW_THERMAL_ZONE_MAX_NAME]; + int ret; snprintf(tz_name, sizeof(tz_name), "mlxsw-gearbox%d", gearbox_tz->module + 1); @@ -872,8 +861,11 @@ mlxsw_thermal_gearbox_tz_init(struct mlxsw_thermal_module *gearbox_tz) if (IS_ERR(gearbox_tz->tzdev)) return PTR_ERR(gearbox_tz->tzdev); - gearbox_tz->tzdev->mode = THERMAL_DEVICE_ENABLED; - return 0; + ret = thermal_zone_device_enable(gearbox_tz->tzdev); + if (ret) + thermal_zone_device_unregister(gearbox_tz->tzdev); + + return ret; } static void @@ -1041,10 +1033,15 @@ int mlxsw_thermal_init(struct mlxsw_core *core, if (err) goto err_unreg_modules_tzdev; - thermal->tzdev->mode = THERMAL_DEVICE_ENABLED; + err = thermal_zone_device_enable(thermal->tzdev); + if (err) + goto err_unreg_gearboxes; + *p_thermal = thermal; return 0; +err_unreg_gearboxes: + mlxsw_thermal_gearboxes_fini(thermal); err_unreg_modules_tzdev: mlxsw_thermal_modules_fini(thermal); err_unreg_tzdev: diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 58c4e1caaa09..8fe0ecb6a626 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -397,19 +397,16 @@ static inline void acerhdf_revert_to_bios_mode(void) { acerhdf_change_fanstate(ACERHDF_FAN_AUTO); kernelmode = 0; - if (thz_dev) { - thz_dev->mode = THERMAL_DEVICE_DISABLED; + if (thz_dev) thz_dev->polling_delay = 0; - } + pr_notice("kernel mode fan control OFF\n"); } static inline void acerhdf_enable_kernelmode(void) { kernelmode = 1; - thz_dev->mode = THERMAL_DEVICE_ENABLED; thz_dev->polling_delay = interval*1000; - thermal_zone_device_update(thz_dev, THERMAL_EVENT_UNSPECIFIED); pr_notice("kernel mode fan control ON\n"); } @@ -723,6 +720,8 @@ static void acerhdf_unregister_platform(void) static int __init acerhdf_register_thermal(void) { + int ret; + cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL, &acerhdf_cooling_ops); @@ -736,8 +735,12 @@ static int __init acerhdf_register_thermal(void) if (IS_ERR(thz_dev)) return -EINVAL; - thz_dev->mode = kernelmode ? - THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED; + if (kernelmode) + ret = thermal_zone_device_enable(thz_dev); + else + ret = thermal_zone_device_disable(thz_dev); + if (ret) + return ret; if (strcmp(thz_dev->governor->name, acerhdf_zone_params.governor_name)) { diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index a7ac8afb063e..4d74994f160a 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -237,7 +237,11 @@ static int da9062_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(thermal->zone); goto err; } - thermal->zone->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(thermal->zone); + if (ret) { + dev_err(&pdev->dev, "Cannot enable thermal zone device\n"); + goto err_zone; + } dev_dbg(&pdev->dev, "TJUNC temperature polling period set at %d ms\n", diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 2d26ae80e202..ee05950afd2f 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -549,8 +549,10 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, { struct thermal_zone_device *tzd = sensor->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static int hisi_thermal_probe(struct platform_device *pdev) diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 2c7ee5da608a..53abb1be1cba 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -255,7 +255,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) bool wait; u32 val; - if (tz->mode == THERMAL_DEVICE_ENABLED) { + if (thermal_zone_device_is_enabled(tz)) { /* Check if a measurement is currently in progress */ regmap_read(map, soc_data->temp_data, &val); wait = !(val & soc_data->temp_valid_mask); @@ -282,7 +282,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) regmap_read(map, soc_data->temp_data, &val); - if (tz->mode != THERMAL_DEVICE_ENABLED) { + if (!thermal_zone_device_is_enabled(tz)) { regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->measure_temp_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, @@ -365,9 +365,6 @@ static int imx_set_mode(struct thermal_zone_device *tz, } } - tz->mode = mode; - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - return 0; } @@ -819,7 +816,9 @@ static int imx_thermal_probe(struct platform_device *pdev) data->socdata->measure_temp_mask); data->irq_enabled = true; - data->tz->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(data->tz); + if (ret) + goto thermal_zone_unregister; ret = devm_request_threaded_irq(&pdev->dev, data->irq, imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, @@ -861,19 +860,18 @@ static int imx_thermal_remove(struct platform_device *pdev) static int __maybe_unused imx_thermal_suspend(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); - struct regmap *map = data->tempmon; + int ret; /* * Need to disable thermal sensor, otherwise, when thermal core * try to get temperature before thermal sensor resume, a wrong * temperature will be read as the thermal sensor is powered - * down. + * down. This is done in set_mode() operation called from + * thermal_zone_device_disable() */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->measure_temp_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->power_down_mask); - data->tz->mode = THERMAL_DEVICE_DISABLED; + ret = thermal_zone_device_disable(data->tz); + if (ret) + return ret; clk_disable_unprepare(data->thermal_clk); return 0; @@ -882,18 +880,15 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) static int __maybe_unused imx_thermal_resume(struct device *dev) { struct imx_thermal_data *data = dev_get_drvdata(dev); - struct regmap *map = data->tempmon; int ret; ret = clk_prepare_enable(data->thermal_clk); if (ret) return ret; /* Enabled thermal sensor after resume */ - regmap_write(map, data->socdata->sensor_ctrl + REG_CLR, - data->socdata->power_down_mask); - regmap_write(map, data->socdata->sensor_ctrl + REG_SET, - data->socdata->measure_temp_mask); - data->tz->mode = THERMAL_DEVICE_ENABLED; + ret = thermal_zone_device_enable(data->tz); + if (ret) + return ret; return 0; } diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 9a622aaf29dd..3c0397a29b8c 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -390,12 +390,11 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, mode != THERMAL_DEVICE_DISABLED) return -EINVAL; - if (mode != thermal->mode) { - thermal->mode = mode; + if (mode != thermal->mode) result = int3400_thermal_run_osc(priv->adev->handle, priv->current_uuid_index, mode == THERMAL_DEVICE_ENABLED); - } + evaluate_odvp(priv); diff --git a/drivers/thermal/intel/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c index c4879b4bfbf1..e29c3e330b17 100644 --- a/drivers/thermal/intel/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel/intel_quark_dts_thermal.c @@ -126,10 +126,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) if (ret) return ret; - if (out & QRK_DTS_ENABLE_BIT) { - tzd->mode = THERMAL_DEVICE_ENABLED; + if (out & QRK_DTS_ENABLE_BIT) return 0; - } if (!aux_entry->locked) { out |= QRK_DTS_ENABLE_BIT; @@ -137,10 +135,7 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) QRK_DTS_REG_OFFSET_ENABLE, out); if (ret) return ret; - - tzd->mode = THERMAL_DEVICE_ENABLED; } else { - tzd->mode = THERMAL_DEVICE_DISABLED; pr_info("DTS is locked. Cannot enable DTS\n"); ret = -EPERM; } @@ -159,10 +154,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) if (ret) return ret; - if (!(out & QRK_DTS_ENABLE_BIT)) { - tzd->mode = THERMAL_DEVICE_DISABLED; + if (!(out & QRK_DTS_ENABLE_BIT)) return 0; - } if (!aux_entry->locked) { out &= ~QRK_DTS_ENABLE_BIT; @@ -171,10 +164,7 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) if (ret) return ret; - - tzd->mode = THERMAL_DEVICE_DISABLED; } else { - tzd->mode = THERMAL_DEVICE_ENABLED; pr_info("DTS is locked. Cannot disable DTS\n"); ret = -EPERM; } @@ -404,9 +394,7 @@ static struct soc_sensor_entry *alloc_soc_dts(void) goto err_ret; } - mutex_lock(&dts_update_mutex); - err = soc_dts_enable(aux_entry->tzone); - mutex_unlock(&dts_update_mutex); + err = thermal_zone_device_enable(aux_entry->tzone); if (err) goto err_aux_status; diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 15a71ecc916c..aa9e0e31ef98 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -1068,8 +1068,10 @@ rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on) { struct thermal_zone_device *tzd = sensor->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev) diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index a340374e8c51..58f995b0f804 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -322,8 +322,10 @@ static void sprd_thm_toggle_sensor(struct sprd_thermal_sensor *sen, bool on) { struct thermal_zone_device *tzd = sen->tzd; - tzd->ops->set_mode(tzd, - on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); + if (on) + thermal_zone_device_enable(tzd); + else + thermal_zone_device_disable(tzd); } static int sprd_thm_probe(struct platform_device *pdev) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index f02c57c986f0..52d136780577 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1521,7 +1521,7 @@ static int thermal_pm_notify(struct notifier_block *nb, case PM_POST_SUSPEND: atomic_set(&in_suspend, 0); list_for_each_entry(tz, &thermal_tz_list, node) { - if (tz->mode == THERMAL_DEVICE_DISABLED) + if (!thermal_zone_device_is_enabled(tz)) continue; thermal_zone_device_init(tz); diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index ba65d48a48cb..43a516a35d64 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -272,8 +272,6 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, { struct __thermal_zone *data = tz->devdata; - mutex_lock(&tz->lock); - if (mode == THERMAL_DEVICE_ENABLED) { tz->polling_delay = data->polling_delay; tz->passive_delay = data->passive_delay; @@ -282,11 +280,6 @@ static int of_thermal_set_mode(struct thermal_zone_device *tz, tz->passive_delay = 0; } - mutex_unlock(&tz->lock); - - tz->mode = mode; - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - return 0; } @@ -541,7 +534,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, tzd = thermal_zone_of_add_sensor(child, sensor_np, data, ops); if (!IS_ERR(tzd)) - tzd->ops->set_mode(tzd, THERMAL_DEVICE_ENABLED); + thermal_zone_device_enable(tzd); of_node_put(child); goto exit; @@ -1120,7 +1113,6 @@ int __init of_parse_thermal_zones(void) of_thermal_free_zone(tz); /* attempting to build remaining zones still */ } - zone->mode = THERMAL_DEVICE_DISABLED; } of_node_put(np); diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index 096370977068..c23d67c4dc4e 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -49,9 +49,9 @@ static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); + int enabled = thermal_zone_device_is_enabled(tz); - return sprintf(buf, "%s\n", tz->mode == THERMAL_DEVICE_ENABLED ? - "enabled" : "disabled"); + return sprintf(buf, "%s\n", enabled ? "enabled" : "disabled"); } static ssize_t @@ -61,13 +61,10 @@ mode_store(struct device *dev, struct device_attribute *attr, struct thermal_zone_device *tz = to_thermal_zone(dev); int result; - if (!tz->ops->set_mode) - return -EPERM; - if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) - result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); + result = thermal_zone_device_enable(tz); else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) - result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); + result = thermal_zone_device_disable(tz); else result = -EINVAL; -- cgit v1.2.3-58-ga151 From bbcf90c0646ac797700269fa6645a6a46466c79f Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:22 +0200 Subject: thermal: Explicitly enable non-changing thermal zone devices Some thermal zone devices never change their state, so they should be always enabled. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Bartlomiej Zolnierkiewicz Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-9-andrzej.p@collabora.com --- drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c | 8 ++++++++ drivers/net/wireless/intel/iwlwifi/mvm/tt.c | 9 ++++++++- drivers/platform/x86/intel_mid_thermal.c | 6 ++++++ drivers/power/supply/power_supply_core.c | 9 +++++++-- drivers/thermal/armada_thermal.c | 6 ++++++ drivers/thermal/dove_thermal.c | 6 ++++++ drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c | 5 +++++ drivers/thermal/intel/intel_pch_thermal.c | 5 +++++ drivers/thermal/intel/intel_soc_dts_iosf.c | 3 +++ drivers/thermal/intel/x86_pkg_temp_thermal.c | 6 ++++++ drivers/thermal/kirkwood_thermal.c | 7 +++++++ drivers/thermal/rcar_thermal.c | 9 ++++++++- drivers/thermal/spear_thermal.c | 7 +++++++ drivers/thermal/st/st_thermal.c | 5 +++++ 14 files changed, 87 insertions(+), 4 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c index 3de8a5e83b6c..e3510e9b21f3 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c @@ -92,6 +92,14 @@ int cxgb4_thermal_init(struct adapter *adap) ch_thermal->tzdev = NULL; return ret; } + + ret = thermal_zone_device_enable(ch_thermal->tzdev); + if (ret) { + dev_err(adap->pdev_dev, "Failed to enable thermal zone\n"); + thermal_zone_device_unregister(adap->ch_thermal.tzdev); + return ret; + } + return 0; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 418e59b7c671..0c95663bf9ed 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -733,7 +733,7 @@ static struct thermal_zone_device_ops tzone_ops = { static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) { - int i; + int i, ret; char name[16]; static atomic_t counter = ATOMIC_INIT(0); @@ -759,6 +759,13 @@ static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm) return; } + ret = thermal_zone_device_enable(mvm->tz_device.tzone); + if (ret) { + IWL_DEBUG_TEMP(mvm, "Failed to enable thermal zone\n"); + thermal_zone_device_unregister(mvm->tz_device.tzone); + return; + } + /* 0 is a valid temperature, * so initialize the array with S16_MIN which invalid temperature */ diff --git a/drivers/platform/x86/intel_mid_thermal.c b/drivers/platform/x86/intel_mid_thermal.c index f402e2e74a38..f12f4e7bd971 100644 --- a/drivers/platform/x86/intel_mid_thermal.c +++ b/drivers/platform/x86/intel_mid_thermal.c @@ -493,6 +493,12 @@ static int mid_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(pinfo->tzd[i]); goto err; } + ret = thermal_zone_device_enable(pinfo->tzd[i]); + if (ret) { + kfree(td_info); + thermal_zone_device_unregister(pinfo->tzd[i]); + goto err; + } } pinfo->pdev = pdev; diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 02b37fe6061c..90e56736d479 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -939,7 +939,7 @@ static struct thermal_zone_device_ops psy_tzd_ops = { static int psy_register_thermal(struct power_supply *psy) { - int i; + int i, ret; if (psy->desc->no_thermal) return 0; @@ -949,7 +949,12 @@ static int psy_register_thermal(struct power_supply *psy) if (psy->desc->properties[i] == POWER_SUPPLY_PROP_TEMP) { psy->tzd = thermal_zone_device_register(psy->desc->name, 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); - return PTR_ERR_OR_ZERO(psy->tzd); + if (IS_ERR(psy->tzd)) + return PTR_ERR(psy->tzd); + ret = thermal_zone_device_enable(psy->tzd); + if (ret) + thermal_zone_device_unregister(psy->tzd); + return ret; } } return 0; diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 7c447cd149e7..c2ebfb5be4b3 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -874,6 +874,12 @@ static int armada_thermal_probe(struct platform_device *pdev) return PTR_ERR(tz); } + ret = thermal_zone_device_enable(tz); + if (ret) { + thermal_zone_device_unregister(tz); + return ret; + } + drvdata->type = LEGACY; drvdata->data.tz = tz; platform_set_drvdata(pdev, drvdata); diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 75901ced4a62..73182eb94bc0 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c @@ -153,6 +153,12 @@ static int dove_thermal_probe(struct platform_device *pdev) return PTR_ERR(thermal); } + ret = thermal_zone_device_enable(thermal); + if (ret) { + thermal_zone_device_unregister(thermal); + return ret; + } + platform_set_drvdata(pdev, thermal); return 0; diff --git a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c index 432213272f1e..6e479deff76b 100644 --- a/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c +++ b/drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c @@ -259,9 +259,14 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev, ret = PTR_ERR(int34x_thermal_zone->zone); goto err_thermal_zone; } + ret = thermal_zone_device_enable(int34x_thermal_zone->zone); + if (ret) + goto err_enable; return int34x_thermal_zone; +err_enable: + thermal_zone_device_unregister(int34x_thermal_zone->zone); err_thermal_zone: acpi_lpat_free_conversion_table(int34x_thermal_zone->lpat_table); kfree(int34x_thermal_zone->aux_trips); diff --git a/drivers/thermal/intel/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c index 56401fd4708d..65702094f3d3 100644 --- a/drivers/thermal/intel/intel_pch_thermal.c +++ b/drivers/thermal/intel/intel_pch_thermal.c @@ -352,9 +352,14 @@ static int intel_pch_thermal_probe(struct pci_dev *pdev, err = PTR_ERR(ptd->tzd); goto error_cleanup; } + err = thermal_zone_device_enable(ptd->tzd); + if (err) + goto err_unregister; return 0; +err_unregister: + thermal_zone_device_unregister(ptd->tzd); error_cleanup: iounmap(ptd->hw_base); error_release: diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c index f75271b669c6..4f1a2f7c016c 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel/intel_soc_dts_iosf.c @@ -329,6 +329,9 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, ret = PTR_ERR(dts->tzone); goto err_ret; } + ret = thermal_zone_device_enable(dts->tzone); + if (ret) + goto err_enable; ret = soc_dts_enable(id); if (ret) diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c index a006b9fd1d72..b81c33202f41 100644 --- a/drivers/thermal/intel/x86_pkg_temp_thermal.c +++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c @@ -363,6 +363,12 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) kfree(zonedev); return err; } + err = thermal_zone_device_enable(zonedev->tzone); + if (err) { + thermal_zone_device_unregister(zonedev->tzone); + kfree(zonedev); + return err; + } /* Store MSR value for package thermal interrupt, to restore at exit */ rdmsr(MSR_IA32_PACKAGE_THERM_INTERRUPT, zonedev->msr_pkg_therm_low, zonedev->msr_pkg_therm_high); diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index 189b675cf14d..7fb6e476c82a 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c @@ -65,6 +65,7 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) struct thermal_zone_device *thermal = NULL; struct kirkwood_thermal_priv *priv; struct resource *res; + int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -82,6 +83,12 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) "Failed to register thermal zone device\n"); return PTR_ERR(thermal); } + ret = thermal_zone_device_enable(thermal); + if (ret) { + thermal_zone_device_unregister(thermal); + dev_err(&pdev->dev, "Failed to enable thermal zone device\n"); + return ret; + } platform_set_drvdata(pdev, thermal); diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 46aeb28b4e90..787710bb88fe 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -550,12 +550,19 @@ static int rcar_thermal_probe(struct platform_device *pdev) priv->zone = devm_thermal_zone_of_sensor_register( dev, i, priv, &rcar_thermal_zone_of_ops); - else + else { priv->zone = thermal_zone_device_register( "rcar_thermal", 1, 0, priv, &rcar_thermal_zone_ops, NULL, 0, idle); + + ret = thermal_zone_device_enable(priv->zone); + if (ret) { + thermal_zone_device_unregister(priv->zone); + priv->zone = ERR_PTR(ret); + } + } if (IS_ERR(priv->zone)) { dev_err(dev, "can't register thermal zone\n"); ret = PTR_ERR(priv->zone); diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c index f68f581fd669..ee33ed692e4f 100644 --- a/drivers/thermal/spear_thermal.c +++ b/drivers/thermal/spear_thermal.c @@ -131,6 +131,11 @@ static int spear_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(spear_thermal); goto disable_clk; } + ret = thermal_zone_device_enable(spear_thermal); + if (ret) { + dev_err(&pdev->dev, "Cannot enable thermal zone\n"); + goto unregister_tzd; + } platform_set_drvdata(pdev, spear_thermal); @@ -139,6 +144,8 @@ static int spear_thermal_probe(struct platform_device *pdev) return 0; +unregister_tzd: + thermal_zone_device_unregister(spear_thermal); disable_clk: clk_disable(stdev->clk); diff --git a/drivers/thermal/st/st_thermal.c b/drivers/thermal/st/st_thermal.c index b928ca6a289b..1276b95604fe 100644 --- a/drivers/thermal/st/st_thermal.c +++ b/drivers/thermal/st/st_thermal.c @@ -246,11 +246,16 @@ int st_thermal_register(struct platform_device *pdev, ret = PTR_ERR(sensor->thermal_dev); goto sensor_off; } + ret = thermal_zone_device_enable(sensor->thermal_dev); + if (ret) + goto tzd_unregister; platform_set_drvdata(pdev, sensor); return 0; +tzd_unregister: + thermal_zone_device_unregister(sensor->thermal_dev); sensor_off: st_thermal_sensor_off(sensor); -- cgit v1.2.3-58-ga151 From b56bdff78e0b65fd2b2ed8eba4c645a7f71ba652 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:23 +0200 Subject: thermal: core: Stop polling DISABLED thermal devices Polling DISABLED devices is not desired, as all such "disabled" devices are meant to be handled by userspace. This patch introduces and uses should_stop_polling() to decide whether the device should be polled or not. Signed-off-by: Andrzej Pietrasiewicz Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-10-andrzej.p@collabora.com --- drivers/thermal/thermal_core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 52d136780577..e613f5c07bad 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -301,13 +301,22 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, cancel_delayed_work(&tz->poll_queue); } +static inline bool should_stop_polling(struct thermal_zone_device *tz) +{ + return !thermal_zone_device_is_enabled(tz); +} + static void monitor_thermal_zone(struct thermal_zone_device *tz) { + bool stop; + + stop = should_stop_polling(tz); + mutex_lock(&tz->lock); - if (tz->passive) + if (!stop && tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); - else if (tz->polling_delay) + else if (!stop && tz->polling_delay) thermal_zone_device_set_polling(tz, tz->polling_delay); else thermal_zone_device_set_polling(tz, 0); @@ -517,6 +526,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, { int count; + if (should_stop_polling(tz)) + return; + if (atomic_read(&in_suspend)) return; -- cgit v1.2.3-58-ga151 From 5d7bd8aa7c35873f448d60ffbd996cfa151d2a11 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:24 +0200 Subject: thermal: Simplify or eliminate unnecessary set_mode() methods Setting polling_delay is now done at thermal_core level (by not polling DISABLED devices), so no need to repeat this code. int340x: Checking for an impossible enum value is unnecessary. acpi/thermal: It only prints debug messages. Signed-off-by: Andrzej Pietrasiewicz [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-11-andrzej.p@collabora.com --- drivers/acpi/thermal.c | 26 ------------------- drivers/net/ethernet/mellanox/mlxsw/core_thermal.c | 30 ---------------------- drivers/platform/x86/acerhdf.c | 3 --- drivers/thermal/imx_thermal.c | 6 ----- .../intel/int340x_thermal/int3400_thermal.c | 4 --- drivers/thermal/thermal_of.c | 18 ------------- 6 files changed, 87 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 52b6cda1bcc3..29a2b73fe035 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -525,31 +525,6 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) return 0; } -static int thermal_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) -{ - struct acpi_thermal *tz = thermal->devdata; - - if (!tz) - return -EINVAL; - - if (mode != THERMAL_DEVICE_DISABLED && - mode != THERMAL_DEVICE_ENABLED) - return -EINVAL; - /* - * enable/disable thermal management from ACPI thermal driver - */ - if (mode == THERMAL_DEVICE_DISABLED) - pr_warn("thermal zone will be disabled\n"); - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "%s kernel ACPI thermal control\n", - mode == THERMAL_DEVICE_ENABLED ? - "Enable" : "Disable")); - - return 0; -} - static int thermal_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { @@ -836,7 +811,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .bind = acpi_thermal_bind_cooling_device, .unbind = acpi_thermal_unbind_cooling_device, .get_temp = thermal_get_temp, - .set_mode = thermal_set_mode, .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, .get_crit_temp = thermal_get_crit_temp, diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c index 4fb73d0fd167..8fa286ccdd6b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c @@ -275,19 +275,6 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev, return 0; } -static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev, - enum thermal_device_mode mode) -{ - struct mlxsw_thermal *thermal = tzdev->devdata; - - if (mode == THERMAL_DEVICE_ENABLED) - tzdev->polling_delay = thermal->polling_delay; - else - tzdev->polling_delay = 0; - - return 0; -} - static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev, int *p_temp) { @@ -387,7 +374,6 @@ static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_ops = { .bind = mlxsw_thermal_bind, .unbind = mlxsw_thermal_unbind, - .set_mode = mlxsw_thermal_set_mode, .get_temp = mlxsw_thermal_get_temp, .get_trip_type = mlxsw_thermal_get_trip_type, .get_trip_temp = mlxsw_thermal_get_trip_temp, @@ -445,20 +431,6 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev, return err; } -static int mlxsw_thermal_module_mode_set(struct thermal_zone_device *tzdev, - enum thermal_device_mode mode) -{ - struct mlxsw_thermal_module *tz = tzdev->devdata; - struct mlxsw_thermal *thermal = tz->parent; - - if (mode == THERMAL_DEVICE_ENABLED) - tzdev->polling_delay = thermal->polling_delay; - else - tzdev->polling_delay = 0; - - return 0; -} - static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev, int *p_temp) { @@ -574,7 +546,6 @@ static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_module_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_module_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, .get_trip_temp = mlxsw_thermal_module_trip_temp_get, @@ -612,7 +583,6 @@ static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev, static struct thermal_zone_device_ops mlxsw_thermal_gearbox_ops = { .bind = mlxsw_thermal_module_bind, .unbind = mlxsw_thermal_module_unbind, - .set_mode = mlxsw_thermal_module_mode_set, .get_temp = mlxsw_thermal_gearbox_temp_get, .get_trip_type = mlxsw_thermal_module_trip_type_get, .get_trip_temp = mlxsw_thermal_module_trip_temp_get, diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 8fe0ecb6a626..76323855c80c 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -397,8 +397,6 @@ static inline void acerhdf_revert_to_bios_mode(void) { acerhdf_change_fanstate(ACERHDF_FAN_AUTO); kernelmode = 0; - if (thz_dev) - thz_dev->polling_delay = 0; pr_notice("kernel mode fan control OFF\n"); } @@ -406,7 +404,6 @@ static inline void acerhdf_enable_kernelmode(void) { kernelmode = 1; - thz_dev->polling_delay = interval*1000; pr_notice("kernel mode fan control ON\n"); } diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 53abb1be1cba..a02398118d88 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -338,9 +338,6 @@ static int imx_set_mode(struct thermal_zone_device *tz, const struct thermal_soc_data *soc_data = data->socdata; if (mode == THERMAL_DEVICE_ENABLED) { - tz->polling_delay = IMX_POLLING_DELAY; - tz->passive_delay = IMX_PASSIVE_DELAY; - regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->power_down_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, @@ -356,9 +353,6 @@ static int imx_set_mode(struct thermal_zone_device *tz, regmap_write(map, soc_data->sensor_ctrl + REG_SET, soc_data->power_down_mask); - tz->polling_delay = 0; - tz->passive_delay = 0; - if (data->irq_enabled) { disable_irq(data->irq); data->irq_enabled = false; diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 3c0397a29b8c..ce49d3b100d5 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -386,10 +386,6 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, if (!priv) return -EINVAL; - if (mode != THERMAL_DEVICE_ENABLED && - mode != THERMAL_DEVICE_DISABLED) - return -EINVAL; - if (mode != thermal->mode) result = int3400_thermal_run_osc(priv->adev->handle, priv->current_uuid_index, diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 43a516a35d64..69ef12f852b7 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -267,22 +267,6 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, return 0; } -static int of_thermal_set_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) -{ - struct __thermal_zone *data = tz->devdata; - - if (mode == THERMAL_DEVICE_ENABLED) { - tz->polling_delay = data->polling_delay; - tz->passive_delay = data->passive_delay; - } else { - tz->polling_delay = 0; - tz->passive_delay = 0; - } - - return 0; -} - static int of_thermal_get_trip_type(struct thermal_zone_device *tz, int trip, enum thermal_trip_type *type) { @@ -374,8 +358,6 @@ static int of_thermal_get_crit_temp(struct thermal_zone_device *tz, } static struct thermal_zone_device_ops of_thermal_ops = { - .set_mode = of_thermal_set_mode, - .get_trip_type = of_thermal_get_trip_type, .get_trip_temp = of_thermal_get_trip_temp, .set_trip_temp = of_thermal_set_trip_temp, -- cgit v1.2.3-58-ga151 From f5e50bf4d3ef0aba4d5414c9ed51fa4a02e2ed12 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Mon, 29 Jun 2020 14:29:25 +0200 Subject: thermal: Rename set_mode() to change_mode() set_mode() is only called when tzd's mode is about to change. Actual setting is performed in thermal_core, in thermal_zone_device_set_mode(). The meaning of set_mode() callback is actually to notify the driver about the mode being changed and giving the driver a chance to oppose such change. To better reflect the purpose of the method rename it to change_mode() Signed-off-by: Andrzej Pietrasiewicz [for acerhdf] Acked-by: Peter Kaestle Reviewed-by: Bartlomiej Zolnierkiewicz Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629122925.21729-12-andrzej.p@collabora.com --- drivers/platform/x86/acerhdf.c | 6 +++--- drivers/thermal/imx_thermal.c | 8 ++++---- drivers/thermal/intel/int340x_thermal/int3400_thermal.c | 6 +++--- drivers/thermal/intel/intel_quark_dts_thermal.c | 6 +++--- drivers/thermal/thermal_core.c | 4 ++-- include/linux/thermal.h | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 76323855c80c..f816a8a13039 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -413,8 +413,8 @@ static inline void acerhdf_enable_kernelmode(void) * the temperature and the fan. * disabled: the BIOS takes control of the fan. */ -static int acerhdf_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) +static int acerhdf_change_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode mode) { if (mode == THERMAL_DEVICE_DISABLED && kernelmode) acerhdf_revert_to_bios_mode(); @@ -473,7 +473,7 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = { .bind = acerhdf_bind, .unbind = acerhdf_unbind, .get_temp = acerhdf_get_ec_temp, - .set_mode = acerhdf_set_mode, + .change_mode = acerhdf_change_mode, .get_trip_type = acerhdf_get_trip_type, .get_trip_hyst = acerhdf_get_trip_hyst, .get_trip_temp = acerhdf_get_trip_temp, diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index a02398118d88..9700ae39feb7 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -330,8 +330,8 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) return 0; } -static int imx_set_mode(struct thermal_zone_device *tz, - enum thermal_device_mode mode) +static int imx_change_mode(struct thermal_zone_device *tz, + enum thermal_device_mode mode) { struct imx_thermal_data *data = tz->devdata; struct regmap *map = data->tempmon; @@ -447,7 +447,7 @@ static struct thermal_zone_device_ops imx_tz_ops = { .bind = imx_bind, .unbind = imx_unbind, .get_temp = imx_get_temp, - .set_mode = imx_set_mode, + .change_mode = imx_change_mode, .get_trip_type = imx_get_trip_type, .get_trip_temp = imx_get_trip_temp, .get_crit_temp = imx_get_crit_temp, @@ -860,7 +860,7 @@ static int __maybe_unused imx_thermal_suspend(struct device *dev) * Need to disable thermal sensor, otherwise, when thermal core * try to get temperature before thermal sensor resume, a wrong * temperature will be read as the thermal sensor is powered - * down. This is done in set_mode() operation called from + * down. This is done in change_mode() operation called from * thermal_zone_device_disable() */ ret = thermal_zone_device_disable(data->tz); diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index ce49d3b100d5..d3732f624913 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -377,8 +377,8 @@ static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, return 0; } -static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, - enum thermal_device_mode mode) +static int int3400_thermal_change_mode(struct thermal_zone_device *thermal, + enum thermal_device_mode mode) { struct int3400_thermal_priv *priv = thermal->devdata; int result = 0; @@ -399,7 +399,7 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal, static struct thermal_zone_device_ops int3400_thermal_ops = { .get_temp = int3400_thermal_get_temp, - .set_mode = int3400_thermal_set_mode, + .change_mode = int3400_thermal_change_mode, }; static struct thermal_zone_params int3400_thermal_params = { diff --git a/drivers/thermal/intel/intel_quark_dts_thermal.c b/drivers/thermal/intel/intel_quark_dts_thermal.c index e29c3e330b17..3eafc6b0e6c3 100644 --- a/drivers/thermal/intel/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel/intel_quark_dts_thermal.c @@ -298,8 +298,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, return 0; } -static int sys_set_mode(struct thermal_zone_device *tzd, - enum thermal_device_mode mode) +static int sys_change_mode(struct thermal_zone_device *tzd, + enum thermal_device_mode mode) { int ret; @@ -319,7 +319,7 @@ static struct thermal_zone_device_ops tzone_ops = { .get_trip_type = sys_get_trip_type, .set_trip_temp = sys_set_trip_temp, .get_crit_temp = sys_get_crit_temp, - .set_mode = sys_set_mode, + .change_mode = sys_change_mode, }; static void free_soc_dts(struct soc_sensor_entry *aux_entry) diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index e613f5c07bad..a61e91513584 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -482,8 +482,8 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, return ret; } - if (tz->ops->set_mode) - ret = tz->ops->set_mode(tz, mode); + if (tz->ops->change_mode) + ret = tz->ops->change_mode(tz, mode); if (!ret) tz->mode = mode; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index df013c39ba9b..b9efaa780d88 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -76,7 +76,7 @@ struct thermal_zone_device_ops { struct thermal_cooling_device *); int (*get_temp) (struct thermal_zone_device *, int *); int (*set_trips) (struct thermal_zone_device *, int, int); - int (*set_mode) (struct thermal_zone_device *, + int (*change_mode) (struct thermal_zone_device *, enum thermal_device_mode); int (*get_trip_type) (struct thermal_zone_device *, int, enum thermal_trip_type *); -- cgit v1.2.3-58-ga151 From d92ed2c9d3ff65b4d8740135a0f348cc073f013e Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Fri, 3 Jul 2020 12:43:53 +0200 Subject: thermal: imx: Use driver's local data to decide whether to run a measurement Use driver's local data to evaluate the need to run or not to run a measurement. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200703104354.19657-3-andrzej.p@collabora.com --- drivers/thermal/imx_thermal.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 9700ae39feb7..c0efa7bc48e2 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -252,10 +252,11 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) const struct thermal_soc_data *soc_data = data->socdata; struct regmap *map = data->tempmon; unsigned int n_meas; - bool wait; + bool wait, run_measurement; u32 val; - if (thermal_zone_device_is_enabled(tz)) { + run_measurement = !data->irq_enabled; + if (!run_measurement) { /* Check if a measurement is currently in progress */ regmap_read(map, soc_data->temp_data, &val); wait = !(val & soc_data->temp_valid_mask); @@ -282,7 +283,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp) regmap_read(map, soc_data->temp_data, &val); - if (!thermal_zone_device_is_enabled(tz)) { + if (run_measurement) { regmap_write(map, soc_data->sensor_ctrl + REG_CLR, soc_data->measure_temp_mask); regmap_write(map, soc_data->sensor_ctrl + REG_SET, -- cgit v1.2.3-58-ga151 From 514acd00f957afa9b2a1fd521b2f180a950ee5e3 Mon Sep 17 00:00:00 2001 From: Andrzej Pietrasiewicz Date: Fri, 3 Jul 2020 12:43:54 +0200 Subject: thermal: Make thermal_zone_device_is_enabled() available to core only This function is not needed by drivers. Signed-off-by: Andrzej Pietrasiewicz Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200703104354.19657-4-andrzej.p@collabora.com --- drivers/thermal/thermal_core.c | 1 - drivers/thermal/thermal_core.h | 2 ++ include/linux/thermal.h | 5 ----- 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index a61e91513584..052343c59b0a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -519,7 +519,6 @@ int thermal_zone_device_is_enabled(struct thermal_zone_device *tz) return mode == THERMAL_DEVICE_ENABLED; } -EXPORT_SYMBOL_GPL(thermal_zone_device_is_enabled); void thermal_zone_device_update(struct thermal_zone_device *tz, enum thermal_notify_event event) diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index c95689586e19..b1464b3a21e2 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -166,4 +166,6 @@ of_thermal_get_trip_points(struct thermal_zone_device *tz) } #endif +int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); + #endif /* __THERMAL_CORE_H__ */ diff --git a/include/linux/thermal.h b/include/linux/thermal.h index b9efaa780d88..108251f23e5c 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -418,7 +418,6 @@ void thermal_cdev_update(struct thermal_cooling_device *); void thermal_notify_framework(struct thermal_zone_device *, int); int thermal_zone_device_enable(struct thermal_zone_device *tz); int thermal_zone_device_disable(struct thermal_zone_device *tz); -int thermal_zone_device_is_enabled(struct thermal_zone_device *tz); #else static inline struct thermal_zone_device *thermal_zone_device_register( const char *type, int trips, int mask, void *devdata, @@ -472,10 +471,6 @@ static inline int thermal_zone_device_enable(struct thermal_zone_device *tz) static inline int thermal_zone_device_disable(struct thermal_zone_device *tz) { return -ENODEV; } - -static inline int -thermal_zone_device_is_enabled(struct thermal_zone_device *tz) -{ return -ENODEV; } #endif /* CONFIG_THERMAL */ #endif /* __THERMAL_H__ */ -- cgit v1.2.3-58-ga151 From 3d44a509c1dafb75adfe218f022ad216885c135e Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 6 Jul 2020 12:55:35 +0200 Subject: thermal: core: Add helpers to browse the cdev, tz and governor list The cdev, tz and governor list, as well as their respective locks are statically defined in the thermal_core.c file. In order to give a sane access to these list, like browsing all the thermal zones or all the cooling devices, let's define a set of helpers where we pass a callback as a parameter to be called for each thermal entity. We keep the self-encapsulation and ensure the locks are correctly taken when looking at the list. Acked-by: Zhang Rui Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200706105538.2159-1-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 51 ++++++++++++++++++++++++++++++++++++++++++ drivers/thermal/thermal_core.h | 9 ++++++++ 2 files changed, 60 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 052343c59b0a..438edd173eed 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -681,6 +681,57 @@ void thermal_zone_device_rebind_exception(struct thermal_zone_device *tz, mutex_unlock(&thermal_list_lock); } +int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), + void *data) +{ + struct thermal_governor *gov; + int ret = 0; + + mutex_lock(&thermal_governor_lock); + list_for_each_entry(gov, &thermal_governor_list, governor_list) { + ret = cb(gov, data); + if (ret) + break; + } + mutex_unlock(&thermal_governor_lock); + + return ret; +} + +int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, + void *), void *data) +{ + struct thermal_cooling_device *cdev; + int ret = 0; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + ret = cb(cdev, data); + if (ret) + break; + } + mutex_unlock(&thermal_list_lock); + + return ret; +} + +int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), + void *data) +{ + struct thermal_zone_device *tz; + int ret = 0; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(tz, &thermal_tz_list, node) { + ret = cb(tz, data); + if (ret) + break; + } + mutex_unlock(&thermal_list_lock); + + return ret; +} + void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, const char *cdev_type, size_t size) { diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index b1464b3a21e2..fc8990c22704 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -41,6 +41,15 @@ extern struct thermal_governor *__governor_thermal_table_end[]; __governor < __governor_thermal_table_end; \ __governor++) +int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), + void *); + +int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, + void *), void *); + +int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), + void *thermal_governor); + struct thermal_attr { struct device_attribute attr; char name[THERMAL_NAME_LENGTH]; -- cgit v1.2.3-58-ga151 From 329b064fbd13d6526fdc35d4a220adedeadf0816 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 6 Jul 2020 12:55:36 +0200 Subject: thermal: core: Get thermal zone by id The next patch will introduce the generic netlink protocol to handle events, sampling and command from the thermal framework. In order to deal with the thermal zone, it uses its unique identifier to characterize it in the message. Passing an integer is more efficient than passing an entire string. This change provides a function returning back a thermal zone pointer corresponding to the identifier passed as parameter. Signed-off-by: Daniel Lezcano Reviewed-by: Amit Kucheria Acked-by: Zhang Rui Link: https://lore.kernel.org/r/20200706105538.2159-2-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 14 ++++++++++++++ drivers/thermal/thermal_core.h | 2 ++ 2 files changed, 16 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 438edd173eed..fc1270c8ce11 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -732,6 +732,20 @@ int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), return ret; } +struct thermal_zone_device *thermal_zone_get_by_id(int id) +{ + struct thermal_zone_device *tz = NULL; + + mutex_lock(&thermal_list_lock); + list_for_each_entry(tz, &thermal_tz_list, node) { + if (tz->id == id) + break; + } + mutex_unlock(&thermal_list_lock); + + return tz; +} + void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, const char *cdev_type, size_t size) { diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index fc8990c22704..967b0ba6593e 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -50,6 +50,8 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), void *thermal_governor); +struct thermal_zone_device *thermal_zone_get_by_id(int id); + struct thermal_attr { struct device_attribute attr; char name[THERMAL_NAME_LENGTH]; -- cgit v1.2.3-58-ga151 From 1ce50e7d408ef2bdc8ca021363fd46d1b8bfad00 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 6 Jul 2020 12:55:37 +0200 Subject: thermal: core: genetlink support for events/cmd/sampling Initially the thermal framework had a very simple notification mechanism to send generic netlink messages to the userspace. The notification function was never called from anywhere and the corresponding dead code was removed. It was probably a first attempt to introduce the netlink notification. At LPC2018, the presentation "Linux thermal: User kernel interface", proposed to create the notifications to the userspace via a kfifo. The advantage of the kfifo is the performance. It is usually used from a 1:1 communication channel where a driver captures data and sends it as fast as possible to a userspace process. The drawback is that only one process uses the notification channel exclusively, thus no other process is allowed to use the channel to get temperature or notifications. This patch defines a generic netlink API to discover the current thermal setup and adds event notifications as well as temperature sampling. As any genetlink protocol, it can evolve and the versioning allows to keep the backward compatibility. In order to prevent the user from getting flooded with data on a single channel, there are two multicast channels, one for the temperature sampling when the thermal zone is updated and another one for the events, so the user can get the events only without the thermal zone temperature sampling. Also, a list of commands to discover the thermal setup is added and can be extended when needed. Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Acked-by: Zhang Rui Link: https://lore.kernel.org/r/20200706105538.2159-3-daniel.lezcano@linaro.org --- drivers/thermal/Makefile | 2 +- drivers/thermal/thermal_core.h | 18 ++ drivers/thermal/thermal_netlink.c | 648 ++++++++++++++++++++++++++++++++++++++ include/linux/thermal.h | 17 - include/uapi/linux/thermal.h | 89 +++++- 5 files changed, 739 insertions(+), 35 deletions(-) create mode 100644 drivers/thermal/thermal_netlink.c (limited to 'drivers/thermal') diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 0c8b84a09b9a..1bbf0805fb04 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o thermal_sys-y += thermal_core.o thermal_sysfs.o \ - thermal_helpers.o + thermal_helpers.o thermal_netlink.o # interface to/from other layers providing sensors thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 967b0ba6593e..4d9455ef0c32 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -52,6 +52,24 @@ int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), struct thermal_zone_device *thermal_zone_get_by_id(int id); +/* Netlink notification function */ +int thermal_notify_tz_create(int tz_id, const char *name); +int thermal_notify_tz_delete(int tz_id); +int thermal_notify_tz_enable(int tz_id); +int thermal_notify_tz_disable(int tz_id); +int thermal_notify_tz_trip_down(int tz_id, int id); +int thermal_notify_tz_trip_up(int tz_id, int id); +int thermal_notify_tz_trip_delete(int tz_id, int id); +int thermal_notify_tz_trip_add(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_tz_trip_change(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_cdev_state_update(int cdev_id, int state); +int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state); +int thermal_notify_cdev_delete(int cdev_id); +int thermal_notify_tz_gov_change(int tz_id, const char *name); +int thermal_genl_sampling_temp(int id, int temp); + struct thermal_attr { struct device_attribute attr; char name[THERMAL_NAME_LENGTH]; diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c new file mode 100644 index 000000000000..dd0a3b889674 --- /dev/null +++ b/drivers/thermal/thermal_netlink.c @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2020 Linaro Limited + * + * Author: Daniel Lezcano + * + * Generic netlink for thermal management framework + */ +#include +#include +#include +#include + +#include "thermal_core.h" + +static const struct genl_multicast_group thermal_genl_mcgrps[] = { + { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, }, + { .name = THERMAL_GENL_EVENT_GROUP_NAME, }, +}; + +static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] = { + /* Thermal zone */ + [THERMAL_GENL_ATTR_TZ] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_TRIP_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_TEMP] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_TYPE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_TRIP_HYST] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_MODE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_TZ_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, + /* Governor(s) */ + [THERMAL_GENL_ATTR_TZ_GOV] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_TZ_GOV_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, + /* Cooling devices */ + [THERMAL_GENL_ATTR_CDEV] = { .type = NLA_NESTED }, + [THERMAL_GENL_ATTR_CDEV_ID] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_CUR_STATE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_MAX_STATE] = { .type = NLA_U32 }, + [THERMAL_GENL_ATTR_CDEV_NAME] = { .type = NLA_STRING, + .len = THERMAL_NAME_LENGTH }, +}; + +struct param { + struct nlattr **attrs; + struct sk_buff *msg; + const char *name; + int tz_id; + int cdev_id; + int trip_id; + int trip_temp; + int trip_type; + int trip_hyst; + int temp; + int cdev_state; + int cdev_max_state; +}; + +typedef int (*cb_t)(struct param *); + +static struct genl_family thermal_gnl_family; + +/************************** Sampling encoding *******************************/ + +int thermal_genl_sampling_temp(int id, int temp) +{ + struct sk_buff *skb; + void *hdr; + + skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, + THERMAL_GENL_SAMPLING_TEMP); + if (!hdr) + return -EMSGSIZE; + + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_ID, id)) + goto out_cancel; + + if (nla_put_u32(skb, THERMAL_GENL_ATTR_TZ_TEMP, temp)) + goto out_cancel; + + genlmsg_end(skb, hdr); + + genlmsg_multicast(&thermal_gnl_family, skb, 0, 0, GFP_KERNEL); + + return 0; +out_cancel: + genlmsg_cancel(skb, hdr); + nlmsg_free(skb); + + return -EMSGSIZE; +} + +/**************************** Event encoding *********************************/ + +static int thermal_genl_event_tz_create(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_string(p->msg, THERMAL_GENL_ATTR_TZ_NAME, p->name)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_up(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_add(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, p->trip_type) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, p->trip_temp) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, p->trip_hyst)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_tz_trip_delete(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, p->trip_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_add(struct param *p) +{ + if (nla_put_string(p->msg, THERMAL_GENL_ATTR_CDEV_NAME, + p->name) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, + p->cdev_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_MAX_STATE, + p->cdev_max_state)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_delete(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, p->cdev_id)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_cdev_state_update(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_ID, + p->cdev_id) || + nla_put_u32(p->msg, THERMAL_GENL_ATTR_CDEV_CUR_STATE, + p->cdev_state)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_event_gov_change(struct param *p) +{ + if (nla_put_u32(p->msg, THERMAL_GENL_ATTR_TZ_ID, p->tz_id) || + nla_put_string(p->msg, THERMAL_GENL_ATTR_GOV_NAME, p->name)) + return -EMSGSIZE; + + return 0; +} + +int thermal_genl_event_tz_delete(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_enable(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_disable(struct param *p) + __attribute__((alias("thermal_genl_event_tz"))); + +int thermal_genl_event_tz_trip_down(struct param *p) + __attribute__((alias("thermal_genl_event_tz_trip_up"))); + +int thermal_genl_event_tz_trip_change(struct param *p) + __attribute__((alias("thermal_genl_event_tz_trip_add"))); + +static cb_t event_cb[] = { + [THERMAL_GENL_EVENT_TZ_CREATE] = thermal_genl_event_tz_create, + [THERMAL_GENL_EVENT_TZ_DELETE] = thermal_genl_event_tz_delete, + [THERMAL_GENL_EVENT_TZ_ENABLE] = thermal_genl_event_tz_enable, + [THERMAL_GENL_EVENT_TZ_DISABLE] = thermal_genl_event_tz_disable, + [THERMAL_GENL_EVENT_TZ_TRIP_UP] = thermal_genl_event_tz_trip_up, + [THERMAL_GENL_EVENT_TZ_TRIP_DOWN] = thermal_genl_event_tz_trip_down, + [THERMAL_GENL_EVENT_TZ_TRIP_CHANGE] = thermal_genl_event_tz_trip_change, + [THERMAL_GENL_EVENT_TZ_TRIP_ADD] = thermal_genl_event_tz_trip_add, + [THERMAL_GENL_EVENT_TZ_TRIP_DELETE] = thermal_genl_event_tz_trip_delete, + [THERMAL_GENL_EVENT_CDEV_ADD] = thermal_genl_event_cdev_add, + [THERMAL_GENL_EVENT_CDEV_DELETE] = thermal_genl_event_cdev_delete, + [THERMAL_GENL_EVENT_CDEV_STATE_UPDATE] = thermal_genl_event_cdev_state_update, + [THERMAL_GENL_EVENT_TZ_GOV_CHANGE] = thermal_genl_event_gov_change, +}; + +/* + * Generic netlink event encoding + */ +static int thermal_genl_send_event(enum thermal_genl_event event, + struct param *p) +{ + struct sk_buff *msg; + int ret = -EMSGSIZE; + void *hdr; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p->msg = msg; + + hdr = genlmsg_put(msg, 0, 0, &thermal_gnl_family, 0, event); + if (!hdr) + goto out_free_msg; + + ret = event_cb[event](p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(&thermal_gnl_family, msg, 0, 1, GFP_KERNEL); + + return 0; + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +int thermal_notify_tz_create(int tz_id, const char *name) +{ + struct param p = { .tz_id = tz_id, .name = name }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_CREATE, &p); +} + +int thermal_notify_tz_delete(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DELETE, &p); +} + +int thermal_notify_tz_enable(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_ENABLE, &p); +} + +int thermal_notify_tz_disable(int tz_id) +{ + struct param p = { .tz_id = tz_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_DISABLE, &p); +} + +int thermal_notify_tz_trip_down(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DOWN, &p); +} + +int thermal_notify_tz_trip_up(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_UP, &p); +} + +int thermal_notify_tz_trip_add(int tz_id, int trip_id, int trip_type, + int trip_temp, int trip_hyst) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id, + .trip_type = trip_type, .trip_temp = trip_temp, + .trip_hyst = trip_hyst }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_ADD, &p); +} + +int thermal_notify_tz_trip_delete(int tz_id, int trip_id) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_DELETE, &p); +} + +int thermal_notify_tz_trip_change(int tz_id, int trip_id, int trip_type, + int trip_temp, int trip_hyst) +{ + struct param p = { .tz_id = tz_id, .trip_id = trip_id, + .trip_type = trip_type, .trip_temp = trip_temp, + .trip_hyst = trip_hyst }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, &p); +} + +int thermal_notify_cdev_state_update(int cdev_id, int cdev_state) +{ + struct param p = { .cdev_id = cdev_id, .cdev_state = cdev_state }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, &p); +} + +int thermal_notify_cdev_add(int cdev_id, const char *name, int cdev_max_state) +{ + struct param p = { .cdev_id = cdev_id, .name = name, + .cdev_max_state = cdev_max_state }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_ADD, &p); +} + +int thermal_notify_cdev_delete(int cdev_id) +{ + struct param p = { .cdev_id = cdev_id }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_CDEV_DELETE, &p); +} + +int thermal_notify_tz_gov_change(int tz_id, const char *name) +{ + struct param p = { .tz_id = tz_id, .name = name }; + + return thermal_genl_send_event(THERMAL_GENL_EVENT_TZ_GOV_CHANGE, &p); +} + +/*************************** Command encoding ********************************/ + +static int __thermal_genl_cmd_tz_get_id(struct thermal_zone_device *tz, + void *data) +{ + struct sk_buff *msg = data; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, tz->id) || + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_NAME, tz->type)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_tz_get_id(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct nlattr *start_tz; + int ret; + + start_tz = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ); + if (!start_tz) + return -EMSGSIZE; + + ret = for_each_thermal_zone(__thermal_genl_cmd_tz_get_id, msg); + if (ret) + goto out_cancel_nest; + + nla_nest_end(msg, start_tz); + + return 0; + +out_cancel_nest: + nla_nest_cancel(msg, start_tz); + + return ret; +} + +static int thermal_genl_cmd_tz_get_trip(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + struct nlattr *start_trip; + int i, id; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + start_trip = nla_nest_start(msg, THERMAL_GENL_ATTR_TZ_TRIP); + if (!start_trip) + return -EMSGSIZE; + + mutex_lock(&tz->lock); + + for (i = 0; i < tz->trips; i++) { + + enum thermal_trip_type type; + int temp, hyst; + + tz->ops->get_trip_type(tz, i, &type); + tz->ops->get_trip_temp(tz, i, &temp); + tz->ops->get_trip_hyst(tz, i, &hyst); + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_ID, i) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TYPE, type) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_TEMP, temp) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TRIP_HYST, hyst)) + goto out_cancel_nest; + } + + mutex_unlock(&tz->lock); + + nla_nest_end(msg, start_trip); + + return 0; + +out_cancel_nest: + mutex_unlock(&tz->lock); + + return -EMSGSIZE; +} + +static int thermal_genl_cmd_tz_get_temp(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + int temp, ret, id; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + ret = thermal_zone_get_temp(tz, &temp); + if (ret) + return ret; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || + nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_TEMP, temp)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_tz_get_gov(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct thermal_zone_device *tz; + int id, ret = 0; + + if (!p->attrs[THERMAL_GENL_ATTR_TZ_ID]) + return -EINVAL; + + id = nla_get_u32(p->attrs[THERMAL_GENL_ATTR_TZ_ID]); + + tz = thermal_zone_get_by_id(id); + if (!tz) + return -EINVAL; + + mutex_lock(&tz->lock); + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_TZ_ID, id) || + nla_put_string(msg, THERMAL_GENL_ATTR_TZ_GOV_NAME, + tz->governor->name)) + ret = -EMSGSIZE; + + mutex_unlock(&tz->lock); + + return ret; +} + +static int __thermal_genl_cmd_cdev_get(struct thermal_cooling_device *cdev, + void *data) +{ + struct sk_buff *msg = data; + + if (nla_put_u32(msg, THERMAL_GENL_ATTR_CDEV_ID, cdev->id)) + return -EMSGSIZE; + + if (nla_put_string(msg, THERMAL_GENL_ATTR_CDEV_NAME, cdev->type)) + return -EMSGSIZE; + + return 0; +} + +static int thermal_genl_cmd_cdev_get(struct param *p) +{ + struct sk_buff *msg = p->msg; + struct nlattr *start_cdev; + int ret; + + start_cdev = nla_nest_start(msg, THERMAL_GENL_ATTR_CDEV); + if (!start_cdev) + return -EMSGSIZE; + + ret = for_each_thermal_cooling_device(__thermal_genl_cmd_cdev_get, msg); + if (ret) + goto out_cancel_nest; + + nla_nest_end(msg, start_cdev); + + return 0; +out_cancel_nest: + nla_nest_cancel(msg, start_cdev); + + return ret; +} + +static cb_t cmd_cb[] = { + [THERMAL_GENL_CMD_TZ_GET_ID] = thermal_genl_cmd_tz_get_id, + [THERMAL_GENL_CMD_TZ_GET_TRIP] = thermal_genl_cmd_tz_get_trip, + [THERMAL_GENL_CMD_TZ_GET_TEMP] = thermal_genl_cmd_tz_get_temp, + [THERMAL_GENL_CMD_TZ_GET_GOV] = thermal_genl_cmd_tz_get_gov, + [THERMAL_GENL_CMD_CDEV_GET] = thermal_genl_cmd_cdev_get, +}; + +static int thermal_genl_cmd_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct param p = { .msg = skb }; + const struct genl_dumpit_info *info = genl_dumpit_info(cb); + int cmd = info->ops->cmd; + int ret = -EMSGSIZE; + void *hdr; + + hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd); + if (!hdr) + return -EMSGSIZE; + + ret = cmd_cb[cmd](&p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(skb, hdr); + + return 0; + +out_cancel_msg: + genlmsg_cancel(skb, hdr); + + return ret; +} + +static int thermal_genl_cmd_doit(struct sk_buff *skb, + struct genl_info *info) +{ + struct param p = { .attrs = info->attrs }; + struct sk_buff *msg; + void *hdr; + int cmd = info->genlhdr->cmd; + int ret = -EMSGSIZE; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p.msg = msg; + + hdr = genlmsg_put_reply(msg, info, &thermal_gnl_family, 0, cmd); + if (!hdr) + goto out_free_msg; + + ret = cmd_cb[cmd](&p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + return genlmsg_reply(msg, info); + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +static const struct genl_ops thermal_genl_ops[] = { + { + .cmd = THERMAL_GENL_CMD_TZ_GET_ID, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .dumpit = thermal_genl_cmd_dumpit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_TRIP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_TEMP, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_TZ_GET_GOV, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = thermal_genl_cmd_doit, + }, + { + .cmd = THERMAL_GENL_CMD_CDEV_GET, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .dumpit = thermal_genl_cmd_dumpit, + }, +}; + +static struct genl_family thermal_gnl_family __ro_after_init = { + .hdrsize = 0, + .name = THERMAL_GENL_FAMILY_NAME, + .version = THERMAL_GENL_VERSION, + .maxattr = THERMAL_GENL_ATTR_MAX, + .policy = thermal_genl_policy, + .ops = thermal_genl_ops, + .n_ops = ARRAY_SIZE(thermal_genl_ops), + .mcgrps = thermal_genl_mcgrps, + .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps), +}; + +static int __init thermal_netlink_init(void) +{ + return genl_register_family(&thermal_gnl_family); +} +core_initcall(thermal_netlink_init); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 108251f23e5c..42ef807e5d84 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -37,18 +37,6 @@ struct thermal_cooling_device; struct thermal_instance; struct thermal_attr; -enum thermal_device_mode { - THERMAL_DEVICE_DISABLED = 0, - THERMAL_DEVICE_ENABLED, -}; - -enum thermal_trip_type { - THERMAL_TRIP_ACTIVE = 0, - THERMAL_TRIP_PASSIVE, - THERMAL_TRIP_HOT, - THERMAL_TRIP_CRITICAL, -}; - enum thermal_trend { THERMAL_TREND_STABLE, /* temperature is stable */ THERMAL_TREND_RAISING, /* temperature is raising */ @@ -303,11 +291,6 @@ struct thermal_zone_params { int offset; }; -struct thermal_genl_event { - u32 orig; - enum events event; -}; - /** * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones * diff --git a/include/uapi/linux/thermal.h b/include/uapi/linux/thermal.h index 96218378dda8..c105054cbb57 100644 --- a/include/uapi/linux/thermal.h +++ b/include/uapi/linux/thermal.h @@ -4,31 +4,86 @@ #define THERMAL_NAME_LENGTH 20 -/* Adding event notification support elements */ -#define THERMAL_GENL_FAMILY_NAME "thermal_event" -#define THERMAL_GENL_VERSION 0x01 -#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp" - -/* Events supported by Thermal Netlink */ -enum events { - THERMAL_AUX0, - THERMAL_AUX1, - THERMAL_CRITICAL, - THERMAL_DEV_FAULT, +enum thermal_device_mode { + THERMAL_DEVICE_DISABLED = 0, + THERMAL_DEVICE_ENABLED, +}; + +enum thermal_trip_type { + THERMAL_TRIP_ACTIVE = 0, + THERMAL_TRIP_PASSIVE, + THERMAL_TRIP_HOT, + THERMAL_TRIP_CRITICAL, }; -/* attributes of thermal_genl_family */ -enum { +/* Adding event notification support elements */ +#define THERMAL_GENL_FAMILY_NAME "thermal" +#define THERMAL_GENL_VERSION 0x01 +#define THERMAL_GENL_SAMPLING_GROUP_NAME "sampling" +#define THERMAL_GENL_EVENT_GROUP_NAME "event" + +/* Attributes of thermal_genl_family */ +enum thermal_genl_attr { THERMAL_GENL_ATTR_UNSPEC, - THERMAL_GENL_ATTR_EVENT, + THERMAL_GENL_ATTR_TZ, + THERMAL_GENL_ATTR_TZ_ID, + THERMAL_GENL_ATTR_TZ_TEMP, + THERMAL_GENL_ATTR_TZ_TRIP, + THERMAL_GENL_ATTR_TZ_TRIP_ID, + THERMAL_GENL_ATTR_TZ_TRIP_TYPE, + THERMAL_GENL_ATTR_TZ_TRIP_TEMP, + THERMAL_GENL_ATTR_TZ_TRIP_HYST, + THERMAL_GENL_ATTR_TZ_MODE, + THERMAL_GENL_ATTR_TZ_NAME, + THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT, + THERMAL_GENL_ATTR_TZ_GOV, + THERMAL_GENL_ATTR_TZ_GOV_NAME, + THERMAL_GENL_ATTR_CDEV, + THERMAL_GENL_ATTR_CDEV_ID, + THERMAL_GENL_ATTR_CDEV_CUR_STATE, + THERMAL_GENL_ATTR_CDEV_MAX_STATE, + THERMAL_GENL_ATTR_CDEV_NAME, + THERMAL_GENL_ATTR_GOV_NAME, + __THERMAL_GENL_ATTR_MAX, }; #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1) -/* commands supported by the thermal_genl_family */ -enum { +enum thermal_genl_sampling { + THERMAL_GENL_SAMPLING_TEMP, + __THERMAL_GENL_SAMPLING_MAX, +}; +#define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1) + +/* Events of thermal_genl_family */ +enum thermal_genl_event { + THERMAL_GENL_EVENT_UNSPEC, + THERMAL_GENL_EVENT_TZ_CREATE, /* Thermal zone creation */ + THERMAL_GENL_EVENT_TZ_DELETE, /* Thermal zone deletion */ + THERMAL_GENL_EVENT_TZ_DISABLE, /* Thermal zone disabed */ + THERMAL_GENL_EVENT_TZ_ENABLE, /* Thermal zone enabled */ + THERMAL_GENL_EVENT_TZ_TRIP_UP, /* Trip point crossed the way up */ + THERMAL_GENL_EVENT_TZ_TRIP_DOWN, /* Trip point crossed the way down */ + THERMAL_GENL_EVENT_TZ_TRIP_CHANGE, /* Trip point changed */ + THERMAL_GENL_EVENT_TZ_TRIP_ADD, /* Trip point added */ + THERMAL_GENL_EVENT_TZ_TRIP_DELETE, /* Trip point deleted */ + THERMAL_GENL_EVENT_CDEV_ADD, /* Cdev bound to the thermal zone */ + THERMAL_GENL_EVENT_CDEV_DELETE, /* Cdev unbound */ + THERMAL_GENL_EVENT_CDEV_STATE_UPDATE, /* Cdev state updated */ + THERMAL_GENL_EVENT_TZ_GOV_CHANGE, /* Governor policy changed */ + __THERMAL_GENL_EVENT_MAX, +}; +#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1) + +/* Commands supported by the thermal_genl_family */ +enum thermal_genl_cmd { THERMAL_GENL_CMD_UNSPEC, - THERMAL_GENL_CMD_EVENT, + THERMAL_GENL_CMD_TZ_GET_ID, /* List of thermal zones id */ + THERMAL_GENL_CMD_TZ_GET_TRIP, /* List of thermal trips */ + THERMAL_GENL_CMD_TZ_GET_TEMP, /* Get the thermal zone temperature */ + THERMAL_GENL_CMD_TZ_GET_GOV, /* Get the thermal zone governor */ + THERMAL_GENL_CMD_TZ_GET_MODE, /* Get the thermal zone mode */ + THERMAL_GENL_CMD_CDEV_GET, /* List of cdev id */ __THERMAL_GENL_CMD_MAX, }; #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1) -- cgit v1.2.3-58-ga151 From 55cdf0a283b876050f0c502685adc346180d7a2f Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Mon, 6 Jul 2020 12:55:38 +0200 Subject: thermal: core: Add notifications call in the framework The generic netlink protocol is implemented but the different notification functions are not yet connected to the core code. These changes add the notification calls in the different corresponding places. Reviewed-by: Amit Kucheria Signed-off-by: Daniel Lezcano Acked-by: Zhang Rui Link: https://lore.kernel.org/r/20200706105538.2159-4-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 21 +++++++++++++++++++++ drivers/thermal/thermal_helpers.c | 13 +++++++++++-- drivers/thermal/thermal_sysfs.c | 15 ++++++++++++++- 3 files changed, 46 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index fc1270c8ce11..750a89f0c20a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -215,6 +215,8 @@ exit: mutex_unlock(&tz->lock); mutex_unlock(&thermal_governor_lock); + thermal_notify_tz_gov_change(tz->id, policy); + return ret; } @@ -415,12 +417,25 @@ static void handle_critical_trips(struct thermal_zone_device *tz, static void handle_thermal_trip(struct thermal_zone_device *tz, int trip) { enum thermal_trip_type type; + int trip_temp, hyst = 0; /* Ignore disabled trip points */ if (test_bit(trip, &tz->trips_disabled)) return; + tz->ops->get_trip_temp(tz, trip, &trip_temp); tz->ops->get_trip_type(tz, trip, &type); + if (tz->ops->get_trip_hyst) + tz->ops->get_trip_hyst(tz, trip, &hyst); + + if (tz->last_temperature != THERMAL_TEMP_INVALID) { + if (tz->last_temperature < trip_temp && + tz->temperature >= trip_temp) + thermal_notify_tz_trip_up(tz->id, trip); + if (tz->last_temperature >= trip_temp && + tz->temperature < (trip_temp - hyst)) + thermal_notify_tz_trip_down(tz->id, trip); + } if (type == THERMAL_TRIP_CRITICAL || type == THERMAL_TRIP_HOT) handle_critical_trips(tz, trip, type); @@ -452,6 +467,8 @@ static void update_temperature(struct thermal_zone_device *tz) mutex_unlock(&tz->lock); trace_thermal_temperature(tz); + + thermal_genl_sampling_temp(tz->id, temp); } static void thermal_zone_device_init(struct thermal_zone_device *tz) @@ -1469,6 +1486,8 @@ thermal_zone_device_register(const char *type, int trips, int mask, if (atomic_cmpxchg(&tz->need_update, 1, 0)) thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + thermal_notify_tz_create(tz->id, tz->type); + return tz; unregister: @@ -1540,6 +1559,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) ida_destroy(&tz->ida); mutex_destroy(&tz->lock); device_unregister(&tz->device); + + thermal_notify_tz_delete(tz->id); } EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c index 87b1256fa2f2..c94bc824e5d3 100644 --- a/drivers/thermal/thermal_helpers.c +++ b/drivers/thermal/thermal_helpers.c @@ -175,6 +175,16 @@ exit: mutex_unlock(&tz->lock); } +static void thermal_cdev_set_cur_state(struct thermal_cooling_device *cdev, + int target) +{ + if (cdev->ops->set_cur_state(cdev, target)) + return; + + thermal_notify_cdev_state_update(cdev->id, target); + thermal_cooling_device_stats_update(cdev, target); +} + void thermal_cdev_update(struct thermal_cooling_device *cdev) { struct thermal_instance *instance; @@ -197,8 +207,7 @@ void thermal_cdev_update(struct thermal_cooling_device *cdev) target = instance->target; } - if (!cdev->ops->set_cur_state(cdev, target)) - thermal_cooling_device_stats_update(cdev, target); + thermal_cdev_set_cur_state(cdev, target); cdev->updated = true; mutex_unlock(&cdev->lock); diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index c23d67c4dc4e..8c231219e15d 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -112,7 +112,8 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, { struct thermal_zone_device *tz = to_thermal_zone(dev); int trip, ret; - int temperature; + int temperature, hyst = 0; + enum thermal_trip_type type; if (!tz->ops->set_trip_temp) return -EPERM; @@ -127,6 +128,18 @@ trip_point_temp_store(struct device *dev, struct device_attribute *attr, if (ret) return ret; + if (tz->ops->get_trip_hyst) { + ret = tz->ops->get_trip_hyst(tz, trip, &hyst); + if (ret) + return ret; + } + + ret = tz->ops->get_trip_type(tz, trip, &type); + if (ret) + return ret; + + thermal_notify_tz_trip_change(tz->id, trip, type, temperature, hyst); + thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); return count; -- cgit v1.2.3-58-ga151 From 5b8583d3bd7fc10cea07e4a5bfa59465758a39dc Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 7 Jul 2020 11:01:57 +0200 Subject: thermal: netlink: Fix compilation error when CONFIG_NET=n When the network is not configured, the netlink is disabled on all the system. The thermal framework assumed the netlink is always opt-in. Fix this by adding a Kconfig option for the netlink notification, defaulting to yes and depending on CONFIG_NET. As the change implies multiple stubs and in order to not pollute the internal thermal header, the thermal_nelink.h has been added and included in the thermal_core.h, so this one regain some kind of clarity. Reported-by: Randy Dunlap Signed-off-by: Daniel Lezcano Reviewed-by: Amit Kucheria Link: https://lore.kernel.org/r/20200707090159.1018-1-daniel.lezcano@linaro.org --- drivers/thermal/Kconfig | 10 ++++ drivers/thermal/Makefile | 5 +- drivers/thermal/thermal_core.h | 20 +------- drivers/thermal/thermal_netlink.h | 98 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 drivers/thermal/thermal_netlink.h (limited to 'drivers/thermal') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 3eb2348e5242..07983bef8d6a 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -17,6 +17,16 @@ menuconfig THERMAL if THERMAL +config THERMAL_NETLINK + bool "Thermal netlink management" + depends on NET + default y + help + The thermal framework has a netlink interface to do thermal + zones discovery, temperature readings and events such as + trip point crossed, cooling device update or governor + change. It is recommended to enable the feature. + config THERMAL_STATISTICS bool "Thermal state transition statistics" help diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 1bbf0805fb04..589f6fb0d381 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -5,7 +5,10 @@ obj-$(CONFIG_THERMAL) += thermal_sys.o thermal_sys-y += thermal_core.o thermal_sysfs.o \ - thermal_helpers.o thermal_netlink.o + thermal_helpers.o + +# netlink interface to manage the thermal framework +thermal_sys-$(CONFIG_THERMAL_NETLINK) += thermal_netlink.o # interface to/from other layers providing sensors thermal_sys-$(CONFIG_THERMAL_HWMON) += thermal_hwmon.o diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 4d9455ef0c32..e00fc5585ea8 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -12,6 +12,8 @@ #include #include +#include "thermal_netlink.h" + /* Default Thermal Governor */ #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) #define DEFAULT_THERMAL_GOVERNOR "step_wise" @@ -52,24 +54,6 @@ int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), struct thermal_zone_device *thermal_zone_get_by_id(int id); -/* Netlink notification function */ -int thermal_notify_tz_create(int tz_id, const char *name); -int thermal_notify_tz_delete(int tz_id); -int thermal_notify_tz_enable(int tz_id); -int thermal_notify_tz_disable(int tz_id); -int thermal_notify_tz_trip_down(int tz_id, int id); -int thermal_notify_tz_trip_up(int tz_id, int id); -int thermal_notify_tz_trip_delete(int tz_id, int id); -int thermal_notify_tz_trip_add(int tz_id, int id, int type, - int temp, int hyst); -int thermal_notify_tz_trip_change(int tz_id, int id, int type, - int temp, int hyst); -int thermal_notify_cdev_state_update(int cdev_id, int state); -int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state); -int thermal_notify_cdev_delete(int cdev_id); -int thermal_notify_tz_gov_change(int tz_id, const char *name); -int thermal_genl_sampling_temp(int id, int temp); - struct thermal_attr { struct device_attribute attr; char name[THERMAL_NAME_LENGTH]; diff --git a/drivers/thermal/thermal_netlink.h b/drivers/thermal/thermal_netlink.h new file mode 100644 index 000000000000..0ec28d105da5 --- /dev/null +++ b/drivers/thermal/thermal_netlink.h @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Linaro Ltd 2020 + * Author: Daniel Lezcano + */ + +/* Netlink notification function */ +#ifdef CONFIG_THERMAL_NETLINK +int thermal_notify_tz_create(int tz_id, const char *name); +int thermal_notify_tz_delete(int tz_id); +int thermal_notify_tz_enable(int tz_id); +int thermal_notify_tz_disable(int tz_id); +int thermal_notify_tz_trip_down(int tz_id, int id); +int thermal_notify_tz_trip_up(int tz_id, int id); +int thermal_notify_tz_trip_delete(int tz_id, int id); +int thermal_notify_tz_trip_add(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_tz_trip_change(int tz_id, int id, int type, + int temp, int hyst); +int thermal_notify_cdev_state_update(int cdev_id, int state); +int thermal_notify_cdev_add(int cdev_id, const char *name, int max_state); +int thermal_notify_cdev_delete(int cdev_id); +int thermal_notify_tz_gov_change(int tz_id, const char *name); +int thermal_genl_sampling_temp(int id, int temp); +#else +static inline int thermal_notify_tz_create(int tz_id, const char *name) +{ + return 0; +} + +static inline int thermal_notify_tz_delete(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_enable(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_disable(int tz_id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_down(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_up(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_delete(int tz_id, int id) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_add(int tz_id, int id, int type, + int temp, int hyst) +{ + return 0; +} + +static inline int thermal_notify_tz_trip_change(int tz_id, int id, int type, + int temp, int hyst) +{ + return 0; +} + +static inline int thermal_notify_cdev_state_update(int cdev_id, int state) +{ + return 0; +} + +static inline int thermal_notify_cdev_add(int cdev_id, const char *name, + int max_state) +{ + return 0; +} + +static inline int thermal_notify_cdev_delete(int cdev_id) +{ + return 0; +} + +static inline int thermal_notify_tz_gov_change(int tz_id, const char *name) +{ + return 0; +} + +static inline int thermal_genl_sampling_temp(int id, int temp) +{ + return 0; +} +#endif /* CONFIG_THERMAL_NETLINK */ -- cgit v1.2.3-58-ga151 From 52674f565718f18893da9a05e8e2528446d26792 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 6 Jul 2020 15:07:47 +0100 Subject: thermal: core: remove redundant initialization of variable ret The variable ret is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Signed-off-by: Zhang Rui Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200706140747.489075-1-colin.king@canonical.com --- drivers/thermal/thermal_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index dd0a3b889674..9299e7975f31 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -546,7 +546,7 @@ static int thermal_genl_cmd_dumpit(struct sk_buff *skb, struct param p = { .msg = skb }; const struct genl_dumpit_info *info = genl_dumpit_info(cb); int cmd = info->ops->cmd; - int ret = -EMSGSIZE; + int ret; void *hdr; hdr = genlmsg_put(skb, 0, 0, &thermal_gnl_family, 0, cmd); -- cgit v1.2.3-58-ga151 From af0e5f1f47d8b7139ee446bc2367f74e4f034202 Mon Sep 17 00:00:00 2001 From: Amit Kucheria Date: Wed, 1 Jul 2020 21:44:14 +0530 Subject: thermal/drivers/clock_cooling: Remove clock_cooling code clock_cooling has no in-kernel users. It has never found any use in drivers as far as I can tell. Remove the code. Signed-off-by: Amit Kucheria Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/aa5d5ac2589cf7b14ece882130731b4a916849a6.1593619943.git.amit.kucheria@linaro.org --- drivers/thermal/Kconfig | 10 - drivers/thermal/Makefile | 3 - drivers/thermal/clock_cooling.c | 445 ---------------------------------------- include/linux/clock_cooling.h | 57 ----- 4 files changed, 515 deletions(-) delete mode 100644 drivers/thermal/clock_cooling.c delete mode 100644 include/linux/clock_cooling.h (limited to 'drivers/thermal') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 07983bef8d6a..13991d68c844 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -190,16 +190,6 @@ config CPU_IDLE_THERMAL idle cycle. endif -config CLOCK_THERMAL - bool "Generic clock cooling support" - depends on COMMON_CLK - depends on PM_OPP - help - This entry implements the generic clock cooling mechanism through - frequency clipping. Typically used to cool off co-processors. The - device that is configured to use this cooling mechanism will be - controlled to reduce clock frequency whenever temperature is high. - config DEVFREQ_THERMAL bool "Generic device cooling support" depends on PM_DEVFREQ diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 589f6fb0d381..b8d96d26f9ec 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -25,9 +25,6 @@ thermal_sys-$(CONFIG_THERMAL_GOV_POWER_ALLOCATOR) += gov_power_allocator.o thermal_sys-$(CONFIG_CPU_FREQ_THERMAL) += cpufreq_cooling.o thermal_sys-$(CONFIG_CPU_IDLE_THERMAL) += cpuidle_cooling.o -# clock cooling -thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o - # devfreq cooling thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c deleted file mode 100644 index 56cb1f46a428..000000000000 --- a/drivers/thermal/clock_cooling.c +++ /dev/null @@ -1,445 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * drivers/thermal/clock_cooling.c - * - * Copyright (C) 2014 Eduardo Valentin - * - * Copyright (C) 2013 Texas Instruments Inc. - * Contact: Eduardo Valentin - * - * Highly based on cpufreq_cooling.c. - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) - * Copyright (C) 2012 Amit Daniel - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct clock_cooling_device - data for cooling device with clock - * @id: unique integer value corresponding to each clock_cooling_device - * registered. - * @dev: struct device pointer to the device being used to cool off using - * clock frequencies. - * @cdev: thermal_cooling_device pointer to keep track of the - * registered cooling device. - * @clk_rate_change_nb: reference to notifier block used to receive clock - * rate changes. - * @freq_table: frequency table used to keep track of available frequencies. - * @clock_state: integer value representing the current state of clock - * cooling devices. - * @clock_val: integer value representing the absolute value of the clipped - * frequency. - * @clk: struct clk reference used to enforce clock limits. - * @lock: mutex lock to protect this struct. - * - * This structure is required for keeping information of each - * clock_cooling_device registered. In order to prevent corruption of this a - * mutex @lock is used. - */ -struct clock_cooling_device { - int id; - struct device *dev; - struct thermal_cooling_device *cdev; - struct notifier_block clk_rate_change_nb; - struct cpufreq_frequency_table *freq_table; - unsigned long clock_state; - unsigned long clock_val; - struct clk *clk; - struct mutex lock; /* lock to protect the content of this struct */ -}; -#define to_clock_cooling_device(x) \ - container_of(x, struct clock_cooling_device, clk_rate_change_nb) -static DEFINE_IDA(clock_ida); - -/* Below code defines functions to be used for clock as cooling device */ - -enum clock_cooling_property { - GET_LEVEL, - GET_FREQ, - GET_MAXL, -}; - -/** - * clock_cooling_get_property - fetch a property of interest for a give cpu. - * @ccdev: clock cooling device reference - * @input: query parameter - * @output: query return - * @property: type of query (frequency, level, max level) - * - * This is the common function to - * 1. get maximum clock cooling states - * 2. translate frequency to cooling state - * 3. translate cooling state to frequency - * Note that the code may be not in good shape - * but it is written in this way in order to: - * a) reduce duplicate code as most of the code can be shared. - * b) make sure the logic is consistent when translating between - * cooling states and frequencies. - * - * Return: 0 on success, -EINVAL when invalid parameters are passed. - */ -static int clock_cooling_get_property(struct clock_cooling_device *ccdev, - unsigned long input, - unsigned long *output, - enum clock_cooling_property property) -{ - int i; - unsigned long max_level = 0, level = 0; - unsigned int freq = CPUFREQ_ENTRY_INVALID; - int descend = -1; - struct cpufreq_frequency_table *pos, *table = ccdev->freq_table; - - if (!output) - return -EINVAL; - - if (!table) - return -EINVAL; - - cpufreq_for_each_valid_entry(pos, table) { - /* ignore duplicate entry */ - if (freq == pos->frequency) - continue; - - /* get the frequency order */ - if (freq != CPUFREQ_ENTRY_INVALID && descend == -1) - descend = freq > pos->frequency; - - freq = pos->frequency; - max_level++; - } - - /* No valid cpu frequency entry */ - if (max_level == 0) - return -EINVAL; - - /* max_level is an index, not a counter */ - max_level--; - - /* get max level */ - if (property == GET_MAXL) { - *output = max_level; - return 0; - } - - if (property == GET_FREQ) - level = descend ? input : (max_level - input); - - i = 0; - cpufreq_for_each_valid_entry(pos, table) { - /* ignore duplicate entry */ - if (freq == pos->frequency) - continue; - - /* now we have a valid frequency entry */ - freq = pos->frequency; - - if (property == GET_LEVEL && (unsigned int)input == freq) { - /* get level by frequency */ - *output = descend ? i : (max_level - i); - return 0; - } - if (property == GET_FREQ && level == i) { - /* get frequency by level */ - *output = freq; - return 0; - } - i++; - } - - return -EINVAL; -} - -/** - * clock_cooling_get_level - return the cooling level of given clock cooling. - * @cdev: reference of a thermal cooling device of used as clock cooling device - * @freq: the frequency of interest - * - * This function will match the cooling level corresponding to the - * requested @freq and return it. - * - * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID - * otherwise. - */ -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - unsigned long val; - - if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val, - GET_LEVEL)) - return THERMAL_CSTATE_INVALID; - - return val; -} -EXPORT_SYMBOL_GPL(clock_cooling_get_level); - -/** - * clock_cooling_get_frequency - get the absolute value of frequency from level. - * @ccdev: clock cooling device reference - * @level: cooling level - * - * This function matches cooling level with frequency. Based on a cooling level - * of frequency, equals cooling state of cpu cooling device, it will return - * the corresponding frequency. - * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc - * - * Return: 0 on error, the corresponding frequency otherwise. - */ -static unsigned long -clock_cooling_get_frequency(struct clock_cooling_device *ccdev, - unsigned long level) -{ - int ret = 0; - unsigned long freq; - - ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ); - if (ret) - return 0; - - return freq; -} - -/** - * clock_cooling_apply - function to apply frequency clipping. - * @ccdev: clock_cooling_device pointer containing frequency clipping data. - * @cooling_state: value of the cooling state. - * - * Function used to make sure the clock layer is aware of current thermal - * limits. The limits are applied by updating the clock rate in case it is - * higher than the corresponding frequency based on the requested cooling_state. - * - * Return: 0 on success, an error code otherwise (-EINVAL in case wrong - * cooling state). - */ -static int clock_cooling_apply(struct clock_cooling_device *ccdev, - unsigned long cooling_state) -{ - unsigned long clip_freq, cur_freq; - int ret = 0; - - /* Here we write the clipping */ - /* Check if the old cooling action is same as new cooling action */ - if (ccdev->clock_state == cooling_state) - return 0; - - clip_freq = clock_cooling_get_frequency(ccdev, cooling_state); - if (!clip_freq) - return -EINVAL; - - cur_freq = clk_get_rate(ccdev->clk); - - mutex_lock(&ccdev->lock); - ccdev->clock_state = cooling_state; - ccdev->clock_val = clip_freq; - /* enforce clock level */ - if (cur_freq > clip_freq) - ret = clk_set_rate(ccdev->clk, clip_freq); - mutex_unlock(&ccdev->lock); - - return ret; -} - -/** - * clock_cooling_clock_notifier - notifier callback on clock rate changes. - * @nb: struct notifier_block * with callback info. - * @event: value showing clock event for which this function invoked. - * @data: callback-specific data - * - * Callback to hijack the notification on clock transition. - * Every time there is a clock change, we intercept all pre change events - * and block the transition in case the new rate infringes thermal limits. - * - * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit). - */ -static int clock_cooling_clock_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct clk_notifier_data *ndata = data; - struct clock_cooling_device *ccdev = to_clock_cooling_device(nb); - - switch (event) { - case PRE_RATE_CHANGE: - /* - * checks on current state - * TODO: current method is not best we can find as it - * allows possibly voltage transitions, in case DVFS - * layer is also hijacking clock pre notifications. - */ - if (ndata->new_rate > ccdev->clock_val) - return NOTIFY_BAD; - /* fall through */ - case POST_RATE_CHANGE: - case ABORT_RATE_CHANGE: - default: - return NOTIFY_DONE; - } -} - -/* clock cooling device thermal callback functions are defined below */ - -/** - * clock_cooling_get_max_state - callback function to get the max cooling state. - * @cdev: thermal cooling device pointer. - * @state: fill this variable with the max cooling state. - * - * Callback for the thermal cooling device to return the clock - * max cooling state. - * - * Return: 0 on success, an error code otherwise. - */ -static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev, - unsigned long *state) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - unsigned long count = 0; - int ret; - - ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL); - if (!ret) - *state = count; - - return ret; -} - -/** - * clock_cooling_get_cur_state - function to get the current cooling state. - * @cdev: thermal cooling device pointer. - * @state: fill this variable with the current cooling state. - * - * Callback for the thermal cooling device to return the clock - * current cooling state. - * - * Return: 0 (success) - */ -static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev, - unsigned long *state) -{ - struct clock_cooling_device *ccdev = cdev->devdata; - - *state = ccdev->clock_state; - - return 0; -} - -/** - * clock_cooling_set_cur_state - function to set the current cooling state. - * @cdev: thermal cooling device pointer. - * @state: set this variable to the current cooling state. - * - * Callback for the thermal cooling device to change the clock cooling - * current cooling state. - * - * Return: 0 on success, an error code otherwise. - */ -static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev, - unsigned long state) -{ - struct clock_cooling_device *clock_device = cdev->devdata; - - return clock_cooling_apply(clock_device, state); -} - -/* Bind clock callbacks to thermal cooling device ops */ -static struct thermal_cooling_device_ops const clock_cooling_ops = { - .get_max_state = clock_cooling_get_max_state, - .get_cur_state = clock_cooling_get_cur_state, - .set_cur_state = clock_cooling_set_cur_state, -}; - -/** - * clock_cooling_register - function to create clock cooling device. - * @dev: struct device pointer to the device used as clock cooling device. - * @clock_name: string containing the clock used as cooling mechanism. - * - * This interface function registers the clock cooling device with the name - * "thermal-clock-%x". The cooling device is based on clock frequencies. - * The struct device is assumed to be capable of DVFS transitions. - * The OPP layer is used to fetch and fill the available frequencies for - * the referred device. The ordered frequency table is used to control - * the clock cooling device cooling states and to limit clock transitions - * based on the cooling state requested by the thermal framework. - * - * Return: a valid struct thermal_cooling_device pointer on success, - * on failure, it returns a corresponding ERR_PTR(). - */ -struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name) -{ - struct thermal_cooling_device *cdev; - struct clock_cooling_device *ccdev = NULL; - char dev_name[THERMAL_NAME_LENGTH]; - int ret = 0; - - ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL); - if (!ccdev) - return ERR_PTR(-ENOMEM); - - mutex_init(&ccdev->lock); - ccdev->dev = dev; - ccdev->clk = devm_clk_get(dev, clock_name); - if (IS_ERR(ccdev->clk)) - return ERR_CAST(ccdev->clk); - - ret = ida_simple_get(&clock_ida, 0, 0, GFP_KERNEL); - if (ret < 0) - return ERR_PTR(ret); - ccdev->id = ret; - - snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id); - - cdev = thermal_cooling_device_register(dev_name, ccdev, - &clock_cooling_ops); - if (IS_ERR(cdev)) { - ida_simple_remove(&clock_ida, ccdev->id); - return ERR_PTR(-EINVAL); - } - ccdev->cdev = cdev; - ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier; - - /* Assuming someone has already filled the opp table for this device */ - ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table); - if (ret) { - ida_simple_remove(&clock_ida, ccdev->id); - return ERR_PTR(ret); - } - ccdev->clock_state = 0; - ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0); - - clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb); - - return cdev; -} -EXPORT_SYMBOL_GPL(clock_cooling_register); - -/** - * clock_cooling_unregister - function to remove clock cooling device. - * @cdev: thermal cooling device pointer. - * - * This interface function unregisters the "thermal-clock-%x" cooling device. - */ -void clock_cooling_unregister(struct thermal_cooling_device *cdev) -{ - struct clock_cooling_device *ccdev; - - if (!cdev) - return; - - ccdev = cdev->devdata; - - clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb); - dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table); - - thermal_cooling_device_unregister(ccdev->cdev); - ida_simple_remove(&clock_ida, ccdev->id); -} -EXPORT_SYMBOL_GPL(clock_cooling_unregister); diff --git a/include/linux/clock_cooling.h b/include/linux/clock_cooling.h deleted file mode 100644 index 4b0a69863656..000000000000 --- a/include/linux/clock_cooling.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/include/linux/clock_cooling.h - * - * Copyright (C) 2014 Eduardo Valentin - * - * Copyright (C) 2013 Texas Instruments Inc. - * Contact: Eduardo Valentin - * - * Highly based on cpufreq_cooling.c. - * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com) - * Copyright (C) 2012 Amit Daniel - */ - -#ifndef __CPU_COOLING_H__ -#define __CPU_COOLING_H__ - -#include -#include -#include - -#ifdef CONFIG_CLOCK_THERMAL -/** - * clock_cooling_register - function to create clock cooling device. - * @dev: struct device pointer to the device used as clock cooling device. - * @clock_name: string containing the clock used as cooling mechanism. - */ -struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name); - -/** - * clock_cooling_unregister - function to remove clock cooling device. - * @cdev: thermal cooling device pointer. - */ -void clock_cooling_unregister(struct thermal_cooling_device *cdev); - -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq); -#else /* !CONFIG_CLOCK_THERMAL */ -static inline struct thermal_cooling_device * -clock_cooling_register(struct device *dev, const char *clock_name) -{ - return NULL; -} -static inline -void clock_cooling_unregister(struct thermal_cooling_device *cdev) -{ -} -static inline -unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev, - unsigned long freq) -{ - return THERMAL_CSTATE_INVALID; -} -#endif /* CONFIG_CLOCK_THERMAL */ - -#endif /* __CPU_COOLING_H__ */ -- cgit v1.2.3-58-ga151 From 947d85f00c030aa88eef0c065b6f4636547257d7 Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Wed, 15 Jul 2020 12:08:53 +0100 Subject: thermal: rcar_gen3_thermal: Add r8a774e1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add r8a774e1 specific compatible string. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1594811350-14066-4-git-send-email-prabhakar.mahadev-lad.rj@bp.renesas.com --- drivers/thermal/rcar_gen3_thermal.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 58fe7c1ef00b..d4d73e88d5d1 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -314,6 +314,10 @@ static const struct of_device_id rcar_gen3_thermal_dt_ids[] = { .compatible = "renesas,r8a774b1-thermal", .data = &rcar_gen3_ths_tj_1, }, + { + .compatible = "renesas,r8a774e1-thermal", + .data = &rcar_gen3_ths_tj_1, + }, { .compatible = "renesas,r8a7795-thermal", .data = &rcar_gen3_ths_tj_1, -- cgit v1.2.3-58-ga151 From d2a89b52839597c70746d9f46a21b1aab0a26c02 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 17 Jul 2020 18:42:16 +0200 Subject: thermal: netlink: Improve the initcall ordering The initcalls like to play joke. In our case, the thermal-netlink initcall is called after the thermal-core initcall but this one sends a notification before the former is initialized. No issue was spotted, but it could lead to a memory corruption, so instead of relying on the core_initcall for the thermal-netlink, let's initialize directly from the thermal-core init routine, so we have full control of the init ordering. Reported-by: Marek Szyprowski Signed-off-by: Daniel Lezcano Tested-by: Marek Szyprowski Reviewed-by: Amit Kucheria Link: https://lore.kernel.org/r/20200717164217.18819-1-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 4 ++++ drivers/thermal/thermal_netlink.c | 3 +-- drivers/thermal/thermal_netlink.h | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 750a89f0c20a..d2e5a223377a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1640,6 +1640,10 @@ static int __init thermal_init(void) { int result; + result = thermal_netlink_init(); + if (result) + goto error; + mutex_init(&poweroff_lock); result = thermal_register_governors(); if (result) diff --git a/drivers/thermal/thermal_netlink.c b/drivers/thermal/thermal_netlink.c index 9299e7975f31..af7b2383e8f6 100644 --- a/drivers/thermal/thermal_netlink.c +++ b/drivers/thermal/thermal_netlink.c @@ -641,8 +641,7 @@ static struct genl_family thermal_gnl_family __ro_after_init = { .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps), }; -static int __init thermal_netlink_init(void) +int __init thermal_netlink_init(void) { return genl_register_family(&thermal_gnl_family); } -core_initcall(thermal_netlink_init); diff --git a/drivers/thermal/thermal_netlink.h b/drivers/thermal/thermal_netlink.h index 0ec28d105da5..828d1dddfa98 100644 --- a/drivers/thermal/thermal_netlink.h +++ b/drivers/thermal/thermal_netlink.h @@ -6,6 +6,7 @@ /* Netlink notification function */ #ifdef CONFIG_THERMAL_NETLINK +int __init thermal_netlink_init(void); int thermal_notify_tz_create(int tz_id, const char *name); int thermal_notify_tz_delete(int tz_id); int thermal_notify_tz_enable(int tz_id); @@ -23,6 +24,11 @@ int thermal_notify_cdev_delete(int cdev_id); int thermal_notify_tz_gov_change(int tz_id, const char *name); int thermal_genl_sampling_temp(int id, int temp); #else +static inline int thermal_netlink_init(void) +{ + return 0; +} + static inline int thermal_notify_tz_create(int tz_id, const char *name) { return 0; -- cgit v1.2.3-58-ga151 From 3f5a2cbe0f5c54adcada54a6a0567690241e7b3a Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Fri, 17 Jul 2020 18:42:17 +0200 Subject: thermal: core: Move initialization after core initcall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generic netlink is initialized at subsys_initcall, so far after the thermal init routine and the thermal generic netlink family initialization. On ŝome platforms, that leads to a memory corruption. The fix was sent to netdev@ to move the genetlink framework initialization at core_initcall. Move the thermal core initialization to postcore level which is very close to core level. Reported-by: Marek Szyprowski Signed-off-by: Daniel Lezcano Tested-by: Marek Szyprowski Reviewed-by: Amit Kucheria Link: https://lore.kernel.org/r/20200717164217.18819-2-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index d2e5a223377a..007f9618e20a 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1676,4 +1676,4 @@ error: mutex_destroy(&poweroff_lock); return result; } -core_initcall(thermal_init); +postcore_initcall(thermal_init); -- cgit v1.2.3-58-ga151 From 679d10df716b78ece007414817ff6219f217afc9 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 10 Jun 2020 02:33:00 +0200 Subject: thermal: rcar_gen3_thermal: Do not shadow thcode variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function rcar_gen3_thermal_calc_coefs() takes an argument called 'thcode' which shadows the static global 'thcode' variable. This is not harmful but bad for readability and is harmful for planned changes to the driver. The THCODE values should be read from hardware fuses if they are available and only fallback to the global 'thcode' variable if they are not fused. Rename the global 'thcode' variable to 'thcodes' to avoid shadowing the symbol in functions that take it as an argument. Signed-off-by: Niklas Söderlund Reviewed-by: Geert Uytterhoeven Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200610003300.884258-1-niklas.soderlund+renesas@ragnatech.se --- drivers/thermal/rcar_gen3_thermal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index d4d73e88d5d1..8333f92aff74 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -63,7 +63,7 @@ #define TSC_MAX_NUM 3 /* default THCODE values if FUSEs are missing */ -static const int thcode[TSC_MAX_NUM][3] = { +static const int thcodes[TSC_MAX_NUM][3] = { { 3397, 2800, 2221 }, { 3393, 2795, 2216 }, { 3389, 2805, 2237 }, @@ -172,7 +172,7 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp) /* Read register and convert to mili Celsius */ reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK; - if (reg <= thcode[tsc->id][1]) + if (reg <= thcodes[tsc->id][1]) val = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1); else @@ -434,7 +434,7 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev) priv->tscs[i] = tsc; priv->thermal_init(tsc); - rcar_gen3_thermal_calc_coefs(tsc, ptat, thcode[i], + rcar_gen3_thermal_calc_coefs(tsc, ptat, thcodes[i], *rcar_gen3_ths_tj_1); zone = devm_thermal_zone_of_sensor_register(dev, i, tsc, -- cgit v1.2.3-58-ga151 From 0f348db01fdf128813fdd659fcc339038fb421a4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 16 Jun 2020 12:19:49 +0300 Subject: thermal: ti-soc-thermal: Fix reversed condition in ti_thermal_expose_sensor() This condition is reversed and will cause breakage. Fixes: 7440f518dad9 ("thermal/drivers/ti-soc-thermal: Avoid dereferencing ERR_PTR") Signed-off-by: Dan Carpenter Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200616091949.GA11940@mwanda --- drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index 85776db4bf34..2ce4b19f312a 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -169,7 +169,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, data = ti_bandgap_get_sensor_data(bgp, id); - if (!IS_ERR_OR_NULL(data)) + if (IS_ERR_OR_NULL(data)) data = ti_thermal_build_data(bgp, id); if (!data) -- cgit v1.2.3-58-ga151 From 4b9e373e04ca22780a4355252d415268de559493 Mon Sep 17 00:00:00 2001 From: Anson Huang Date: Wed, 17 Jun 2020 15:47:54 +0800 Subject: thermal: imx8mm: Support module autoloading Add a missing MODULE_DEVICE_TABLE entry to support module autoloading. Signed-off-by: Anson Huang Reviewed-by: Dong Aisheng Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1592380074-19222-1-git-send-email-Anson.Huang@nxp.com --- drivers/thermal/imx8mm_thermal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index e6061e26d4ac..f5124f14cf81 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -220,6 +220,7 @@ static const struct of_device_id imx8mm_tmu_table[] = { { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, }, { }, }; +MODULE_DEVICE_TABLE(of, imx8mm_tmu_table); static struct platform_driver imx8mm_tmu = { .driver = { -- cgit v1.2.3-58-ga151 From 287d959558357e155c889bc35579eb35691a8fcb Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Fri, 24 Jul 2020 13:22:26 +0530 Subject: thermal: int340x: processor_thermal: fix: update Jasper Lake PCI id Update PCI device id for Jasper Lake processor thermal device. With this proc_thermal driver is getting loaded and processor thermal functionality works on Jasper Lake system. Fixes: f64a6583d3f5 ("thermal: int340x: processor_thermal: Add Jasper Lake support") Signed-off-by: Sumeet Pawnikar Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1595577146-1221-1-git-send-email-sumeet.r.pawnikar@intel.com --- drivers/thermal/intel/int340x_thermal/processor_thermal_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 297db1d2d960..81e8b15ef405 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -43,7 +43,7 @@ #define PCI_DEVICE_ID_PROC_ICL_THERMAL 0x8a03 /* JasperLake thermal reporting device */ -#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4503 +#define PCI_DEVICE_ID_PROC_JSL_THERMAL 0x4E03 /* TigerLake thermal reporting device */ #define PCI_DEVICE_ID_PROC_TGL_THERMAL 0x9A03 -- cgit v1.2.3-58-ga151 From 82aa68afa16819d9f05b899a5fcf174c2f1fb889 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 24 Jul 2020 19:01:05 +0200 Subject: thermal: core: Fix thermal zone lookup by ID When a thermal zone is looked up by an ID and no zone is found matching that ID, the thermal_zone_get_by_id() function will return a pointer to the thermal zone list head which isn't actually a valid thermal zone. This can lead to a subsequent crash because a valid pointer is returned to the called, but dereferencing that pointer as struct thermal_zone is not safe. Fixes: 329b064fbd13 ("thermal: core: Get thermal zone by id") Signed-off-by: Thierry Reding Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200724170105.2705467-1-thierry.reding@gmail.com --- drivers/thermal/thermal_core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 007f9618e20a..9748fbb9a3a1 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -751,16 +751,18 @@ int for_each_thermal_zone(int (*cb)(struct thermal_zone_device *, void *), struct thermal_zone_device *thermal_zone_get_by_id(int id) { - struct thermal_zone_device *tz = NULL; + struct thermal_zone_device *tz, *match = NULL; mutex_lock(&thermal_list_lock); list_for_each_entry(tz, &thermal_tz_list, node) { - if (tz->id == id) + if (tz->id == id) { + match = tz; break; + } } mutex_unlock(&thermal_list_lock); - return tz; + return match; } void thermal_zone_device_unbind_exception(struct thermal_zone_device *tz, -- cgit v1.2.3-58-ga151 From 332bc8ebab2c0d00e80dd23377ec23ad3de83214 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 29 Jun 2020 22:49:26 +0800 Subject: thermal: qcom: tsens-v0_1: Add support for MSM8939 The TSENS integrated on MSM8939 is a v0_1 device with 10 sensors. Different from its predecessor MSM8916, where 'calib_sel' bits sit in separate qfprom word, MSM8939 has 'cailb' and 'calib_sel' bits mixed and spread on discrete offsets. That's why all qfprom bits are read as one go and later mapped to calibration data for MSM8939. Signed-off-by: Shawn Guo Acked-by: Amit Kucheria Tested-by: Konrad Dybcio /* on Asus Z00T smartphone */ Acked-by: Konrad Dybcio Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200629144926.665-3-shawn.guo@linaro.org --- drivers/thermal/qcom/tsens-v0_1.c | 144 +++++++++++++++++++++++++++++++++++++- drivers/thermal/qcom/tsens.c | 3 + drivers/thermal/qcom/tsens.h | 2 +- 3 files changed, 147 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index 959a9371d205..e64db5f80d90 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -48,6 +48,63 @@ #define MSM8916_CAL_SEL_MASK 0xe0000000 #define MSM8916_CAL_SEL_SHIFT 29 +/* eeprom layout data for 8939 */ +#define MSM8939_BASE0_MASK 0x000000ff +#define MSM8939_BASE1_MASK 0xff000000 +#define MSM8939_BASE0_SHIFT 0 +#define MSM8939_BASE1_SHIFT 24 + +#define MSM8939_S0_P1_MASK 0x000001f8 +#define MSM8939_S1_P1_MASK 0x001f8000 +#define MSM8939_S2_P1_MASK_0_4 0xf8000000 +#define MSM8939_S2_P1_MASK_5 0x00000001 +#define MSM8939_S3_P1_MASK 0x00001f80 +#define MSM8939_S4_P1_MASK 0x01f80000 +#define MSM8939_S5_P1_MASK 0x00003f00 +#define MSM8939_S6_P1_MASK 0x03f00000 +#define MSM8939_S7_P1_MASK 0x0000003f +#define MSM8939_S8_P1_MASK 0x0003f000 +#define MSM8939_S9_P1_MASK 0x07e00000 + +#define MSM8939_S0_P2_MASK 0x00007e00 +#define MSM8939_S1_P2_MASK 0x07e00000 +#define MSM8939_S2_P2_MASK 0x0000007e +#define MSM8939_S3_P2_MASK 0x0007e000 +#define MSM8939_S4_P2_MASK 0x7e000000 +#define MSM8939_S5_P2_MASK 0x000fc000 +#define MSM8939_S6_P2_MASK 0xfc000000 +#define MSM8939_S7_P2_MASK 0x00000fc0 +#define MSM8939_S8_P2_MASK 0x00fc0000 +#define MSM8939_S9_P2_MASK_0_4 0xf8000000 +#define MSM8939_S9_P2_MASK_5 0x00002000 + +#define MSM8939_S0_P1_SHIFT 3 +#define MSM8939_S1_P1_SHIFT 15 +#define MSM8939_S2_P1_SHIFT_0_4 27 +#define MSM8939_S2_P1_SHIFT_5 0 +#define MSM8939_S3_P1_SHIFT 7 +#define MSM8939_S4_P1_SHIFT 19 +#define MSM8939_S5_P1_SHIFT 8 +#define MSM8939_S6_P1_SHIFT 20 +#define MSM8939_S7_P1_SHIFT 0 +#define MSM8939_S8_P1_SHIFT 12 +#define MSM8939_S9_P1_SHIFT 21 + +#define MSM8939_S0_P2_SHIFT 9 +#define MSM8939_S1_P2_SHIFT 21 +#define MSM8939_S2_P2_SHIFT 1 +#define MSM8939_S3_P2_SHIFT 13 +#define MSM8939_S4_P2_SHIFT 25 +#define MSM8939_S5_P2_SHIFT 14 +#define MSM8939_S6_P2_SHIFT 26 +#define MSM8939_S7_P2_SHIFT 6 +#define MSM8939_S8_P2_SHIFT 18 +#define MSM8939_S9_P2_SHIFT_0_4 27 +#define MSM8939_S9_P2_SHIFT_5 13 + +#define MSM8939_CAL_SEL_MASK 0x7 +#define MSM8939_CAL_SEL_SHIFT 0 + /* eeprom layout data for 8974 */ #define BASE1_MASK 0xff #define S0_P1_MASK 0x3f00 @@ -189,6 +246,76 @@ static int calibrate_8916(struct tsens_priv *priv) return 0; } +static int calibrate_8939(struct tsens_priv *priv) +{ + int base0 = 0, base1 = 0, i; + u32 p1[10], p2[10]; + int mode = 0; + u32 *qfprom_cdata; + u32 cdata[6]; + + qfprom_cdata = (u32 *)qfprom_read(priv->dev, "calib"); + if (IS_ERR(qfprom_cdata)) + return PTR_ERR(qfprom_cdata); + + /* Mapping between qfprom nvmem and calibration data */ + cdata[0] = qfprom_cdata[12]; + cdata[1] = qfprom_cdata[13]; + cdata[2] = qfprom_cdata[0]; + cdata[3] = qfprom_cdata[1]; + cdata[4] = qfprom_cdata[22]; + cdata[5] = qfprom_cdata[21]; + + mode = (cdata[0] & MSM8939_CAL_SEL_MASK) >> MSM8939_CAL_SEL_SHIFT; + dev_dbg(priv->dev, "calibration mode is %d\n", mode); + + switch (mode) { + case TWO_PT_CALIB: + base1 = (cdata[3] & MSM8939_BASE1_MASK) >> MSM8939_BASE1_SHIFT; + p2[0] = (cdata[0] & MSM8939_S0_P2_MASK) >> MSM8939_S0_P2_SHIFT; + p2[1] = (cdata[0] & MSM8939_S1_P2_MASK) >> MSM8939_S1_P2_SHIFT; + p2[2] = (cdata[1] & MSM8939_S2_P2_MASK) >> MSM8939_S2_P2_SHIFT; + p2[3] = (cdata[1] & MSM8939_S3_P2_MASK) >> MSM8939_S3_P2_SHIFT; + p2[4] = (cdata[1] & MSM8939_S4_P2_MASK) >> MSM8939_S4_P2_SHIFT; + p2[5] = (cdata[2] & MSM8939_S5_P2_MASK) >> MSM8939_S5_P2_SHIFT; + p2[6] = (cdata[2] & MSM8939_S6_P2_MASK) >> MSM8939_S6_P2_SHIFT; + p2[7] = (cdata[3] & MSM8939_S7_P2_MASK) >> MSM8939_S7_P2_SHIFT; + p2[8] = (cdata[3] & MSM8939_S8_P2_MASK) >> MSM8939_S8_P2_SHIFT; + p2[9] = (cdata[4] & MSM8939_S9_P2_MASK_0_4) >> MSM8939_S9_P2_SHIFT_0_4; + p2[9] |= ((cdata[5] & MSM8939_S9_P2_MASK_5) >> MSM8939_S9_P2_SHIFT_5) << 5; + for (i = 0; i < priv->num_sensors; i++) + p2[i] = (base1 + p2[i]) << 2; + fallthrough; + case ONE_PT_CALIB2: + base0 = (cdata[2] & MSM8939_BASE0_MASK) >> MSM8939_BASE0_SHIFT; + p1[0] = (cdata[0] & MSM8939_S0_P1_MASK) >> MSM8939_S0_P1_SHIFT; + p1[1] = (cdata[0] & MSM8939_S1_P1_MASK) >> MSM8939_S1_P1_SHIFT; + p1[2] = (cdata[0] & MSM8939_S2_P1_MASK_0_4) >> MSM8939_S2_P1_SHIFT_0_4; + p1[2] |= ((cdata[1] & MSM8939_S2_P1_MASK_5) >> MSM8939_S2_P1_SHIFT_5) << 5; + p1[3] = (cdata[1] & MSM8939_S3_P1_MASK) >> MSM8939_S3_P1_SHIFT; + p1[4] = (cdata[1] & MSM8939_S4_P1_MASK) >> MSM8939_S4_P1_SHIFT; + p1[5] = (cdata[2] & MSM8939_S5_P1_MASK) >> MSM8939_S5_P1_SHIFT; + p1[6] = (cdata[2] & MSM8939_S6_P1_MASK) >> MSM8939_S6_P1_SHIFT; + p1[7] = (cdata[3] & MSM8939_S7_P1_MASK) >> MSM8939_S7_P1_SHIFT; + p1[8] = (cdata[3] & MSM8939_S8_P1_MASK) >> MSM8939_S8_P1_SHIFT; + p1[9] = (cdata[4] & MSM8939_S9_P1_MASK) >> MSM8939_S9_P1_SHIFT; + for (i = 0; i < priv->num_sensors; i++) + p1[i] = ((base0) + p1[i]) << 2; + break; + default: + for (i = 0; i < priv->num_sensors; i++) { + p1[i] = 500; + p2[i] = 780; + } + break; + } + + compute_intercept_slope(priv, p1, p2, mode); + kfree(qfprom_cdata); + + return 0; +} + static int calibrate_8974(struct tsens_priv *priv) { int base1 = 0, base2 = 0, i; @@ -325,7 +452,7 @@ static int calibrate_8974(struct tsens_priv *priv) return 0; } -/* v0.1: 8916, 8974 */ +/* v0.1: 8916, 8939, 8974 */ static struct tsens_features tsens_v0_1_feat = { .ver_major = VER_0_1, @@ -386,6 +513,21 @@ struct tsens_plat_data data_8916 = { .fields = tsens_v0_1_regfields, }; +static const struct tsens_ops ops_8939 = { + .init = init_common, + .calibrate = calibrate_8939, + .get_temp = get_temp_common, +}; + +struct tsens_plat_data data_8939 = { + .num_sensors = 10, + .ops = &ops_8939, + .hw_ids = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 }, + + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +}; + static const struct tsens_ops ops_8974 = { .init = init_common, .calibrate = calibrate_8974, diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 8d3e94d2a9ed..52656a24f813 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -897,6 +897,9 @@ static const struct of_device_id tsens_table[] = { { .compatible = "qcom,msm8916-tsens", .data = &data_8916, + }, { + .compatible = "qcom,msm8939-tsens", + .data = &data_8939, }, { .compatible = "qcom,msm8974-tsens", .data = &data_8974, diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h index 59d01162c66a..f40b625f897e 100644 --- a/drivers/thermal/qcom/tsens.h +++ b/drivers/thermal/qcom/tsens.h @@ -585,7 +585,7 @@ int get_temp_common(const struct tsens_sensor *s, int *temp); extern struct tsens_plat_data data_8960; /* TSENS v0.1 targets */ -extern struct tsens_plat_data data_8916, data_8974; +extern struct tsens_plat_data data_8916, data_8939, data_8974; /* TSENS v1 targets */ extern struct tsens_plat_data data_tsens_v1, data_8976; -- cgit v1.2.3-58-ga151 From 25be77e588a63b064e8d9c1b59975e6882abc2f9 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 28 Jul 2020 01:10:33 +0200 Subject: thermal: core: Add thermal zone enable/disable notification Now the calls to enable/disable a thermal zone are centralized in a call to a function, we can add in these the corresponding netlink notifications. Signed-off-by: Daniel Lezcano Acked-by: Zhang Rui Reviewed-by: Amit Kucheria Link: https://lore.kernel.org/r/20200727231033.26512-1-daniel.lezcano@linaro.org --- drivers/thermal/thermal_core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index 9748fbb9a3a1..72bf159bcecc 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -509,6 +509,11 @@ static int thermal_zone_device_set_mode(struct thermal_zone_device *tz, thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); + if (mode == THERMAL_DEVICE_ENABLED) + thermal_notify_tz_enable(tz->id); + else + thermal_notify_tz_disable(tz->id); + return ret; } -- cgit v1.2.3-58-ga151 From 0de967f24e6c26fca3845e5a5970866ae59ac766 Mon Sep 17 00:00:00 2001 From: Lukasz Luba Date: Thu, 30 Jul 2020 17:51:17 +0100 Subject: thermal: Update power allocator and devfreq cooling to SPDX licensing Update the license to the SPDX licensing format. Signed-off-by: Lukasz Luba Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/20200730165117.13998-1-lukasz.luba@arm.com --- drivers/thermal/devfreq_cooling.c | 10 +--------- drivers/thermal/gov_power_allocator.c | 9 +-------- include/linux/devfreq_cooling.h | 9 +-------- 3 files changed, 3 insertions(+), 25 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index f7f32e98331b..a12d29096229 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -1,18 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 /* * devfreq_cooling: Thermal cooling device implementation for devices using * devfreq * * Copyright (C) 2014-2015 ARM Limited * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * * TODO: * - If OPPs are added or removed after devfreq cooling has * registered, the devfreq cooling won't react to it. diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c index 44636475b2a3..5cb518d8f156 100644 --- a/drivers/thermal/gov_power_allocator.c +++ b/drivers/thermal/gov_power_allocator.c @@ -1,16 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * A power allocator to manage temperature * * Copyright (C) 2014 ARM Ltd. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #define pr_fmt(fmt) "Power allocator: " fmt diff --git a/include/linux/devfreq_cooling.h b/include/linux/devfreq_cooling.h index 79a6e37a1d6f..9df2dfca68dd 100644 --- a/include/linux/devfreq_cooling.h +++ b/include/linux/devfreq_cooling.h @@ -1,17 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * devfreq_cooling: Thermal cooling device implementation for devices using * devfreq * * Copyright (C) 2014-2015 ARM Limited * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef __DEVFREQ_COOLING_H__ -- cgit v1.2.3-58-ga151 From 54bf1e5a629dfbd0ee1b1e286d4e8119be23b902 Mon Sep 17 00:00:00 2001 From: Henry Yen Date: Thu, 30 Apr 2020 17:14:33 +0800 Subject: thermal: mediatek: Prepare to add support for other platforms It is known that Mediatek owns two thermal systems, which only differ in the way of reading calibration data and converting temperature. MT8173, MT8183, MT2701 and MT2712 belongs to version 1 thermal system, and MT7622 belongs to version 2. In order to handle both systems, the suffix _V1 is appended to the current code, and then the second patch will add _V2 functions with the same purpose but different implementation. Signed-off-by: Henry Yen Reviewed-by: Matthias Brugger Tested-By: Frank Wunderlich Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1588238074-19338-2-git-send-email-henry.yen@mediatek.com --- drivers/thermal/mtk_thermal.c | 114 +++++++++++++++++++++++------------------- 1 file changed, 62 insertions(+), 52 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 76e30603d4d5..10107d9d56a8 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -120,18 +120,18 @@ * MT2701 has 3 sensors and needs 3 VTS calibration data. * MT2712 has 4 sensors and needs 4 VTS calibration data. */ -#define CALIB_BUF0_VALID BIT(0) -#define CALIB_BUF1_ADC_GE(x) (((x) >> 22) & 0x3ff) -#define CALIB_BUF0_VTS_TS1(x) (((x) >> 17) & 0x1ff) -#define CALIB_BUF0_VTS_TS2(x) (((x) >> 8) & 0x1ff) -#define CALIB_BUF1_VTS_TS3(x) (((x) >> 0) & 0x1ff) -#define CALIB_BUF2_VTS_TS4(x) (((x) >> 23) & 0x1ff) -#define CALIB_BUF2_VTS_TS5(x) (((x) >> 5) & 0x1ff) -#define CALIB_BUF2_VTS_TSABB(x) (((x) >> 14) & 0x1ff) -#define CALIB_BUF0_DEGC_CALI(x) (((x) >> 1) & 0x3f) -#define CALIB_BUF0_O_SLOPE(x) (((x) >> 26) & 0x3f) -#define CALIB_BUF0_O_SLOPE_SIGN(x) (((x) >> 7) & 0x1) -#define CALIB_BUF1_ID(x) (((x) >> 9) & 0x1) +#define CALIB_BUF0_VALID_V1 BIT(0) +#define CALIB_BUF1_ADC_GE_V1(x) (((x) >> 22) & 0x3ff) +#define CALIB_BUF0_VTS_TS1_V1(x) (((x) >> 17) & 0x1ff) +#define CALIB_BUF0_VTS_TS2_V1(x) (((x) >> 8) & 0x1ff) +#define CALIB_BUF1_VTS_TS3_V1(x) (((x) >> 0) & 0x1ff) +#define CALIB_BUF2_VTS_TS4_V1(x) (((x) >> 23) & 0x1ff) +#define CALIB_BUF2_VTS_TS5_V1(x) (((x) >> 5) & 0x1ff) +#define CALIB_BUF2_VTS_TSABB_V1(x) (((x) >> 14) & 0x1ff) +#define CALIB_BUF0_DEGC_CALI_V1(x) (((x) >> 1) & 0x3f) +#define CALIB_BUF0_O_SLOPE_V1(x) (((x) >> 26) & 0x3f) +#define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) +#define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) enum { VTS1, @@ -525,7 +525,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { * This converts the raw ADC value to mcelsius using the SoC specific * calibration constants */ -static int raw_to_mcelsius(struct mtk_thermal *mt, int sensno, s32 raw) +static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) { s32 tmp; @@ -594,9 +594,9 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) raw = readl(mt->thermal_base + conf->msr[conf->bank_data[bank->id].sensors[i]]); - temp = raw_to_mcelsius(mt, - conf->bank_data[bank->id].sensors[i], - raw); + temp = raw_to_mcelsius_v1(mt, + conf->bank_data[bank->id].sensors[i], + raw); /* * The first read of a sensor often contains very high bogus @@ -758,6 +758,51 @@ static u64 of_get_phys_base(struct device_node *np) return of_translate_address(np, regaddr_p); } +static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) +{ + int i; + + if (!(buf[0] & CALIB_BUF0_VALID_V1)) + return -EINVAL; + + mt->adc_ge = CALIB_BUF1_ADC_GE_V1(buf[1]); + + for (i = 0; i < mt->conf->num_sensors; i++) { + switch (mt->conf->vts_index[i]) { + case VTS1: + mt->vts[VTS1] = CALIB_BUF0_VTS_TS1_V1(buf[0]); + break; + case VTS2: + mt->vts[VTS2] = CALIB_BUF0_VTS_TS2_V1(buf[0]); + break; + case VTS3: + mt->vts[VTS3] = CALIB_BUF1_VTS_TS3_V1(buf[1]); + break; + case VTS4: + mt->vts[VTS4] = CALIB_BUF2_VTS_TS4_V1(buf[2]); + break; + case VTS5: + mt->vts[VTS5] = CALIB_BUF2_VTS_TS5_V1(buf[2]); + break; + case VTSABB: + mt->vts[VTSABB] = + CALIB_BUF2_VTS_TSABB_V1(buf[2]); + break; + default: + break; + } + } + + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V1(buf[0]); + if (CALIB_BUF1_ID_V1(buf[1]) & + CALIB_BUF0_O_SLOPE_SIGN_V1(buf[0])) + mt->o_slope = -CALIB_BUF0_O_SLOPE_V1(buf[0]); + else + mt->o_slope = CALIB_BUF0_O_SLOPE_V1(buf[0]); + + return 0; +} + static int mtk_thermal_get_calibration_data(struct device *dev, struct mtk_thermal *mt) { @@ -793,43 +838,8 @@ static int mtk_thermal_get_calibration_data(struct device *dev, goto out; } - if (buf[0] & CALIB_BUF0_VALID) { - mt->adc_ge = CALIB_BUF1_ADC_GE(buf[1]); - - for (i = 0; i < mt->conf->num_sensors; i++) { - switch (mt->conf->vts_index[i]) { - case VTS1: - mt->vts[VTS1] = CALIB_BUF0_VTS_TS1(buf[0]); - break; - case VTS2: - mt->vts[VTS2] = CALIB_BUF0_VTS_TS2(buf[0]); - break; - case VTS3: - mt->vts[VTS3] = CALIB_BUF1_VTS_TS3(buf[1]); - break; - case VTS4: - mt->vts[VTS4] = CALIB_BUF2_VTS_TS4(buf[2]); - break; - case VTS5: - mt->vts[VTS5] = CALIB_BUF2_VTS_TS5(buf[2]); - break; - case VTSABB: - mt->vts[VTSABB] = CALIB_BUF2_VTS_TSABB(buf[2]); - break; - default: - break; - } - } - - mt->degc_cali = CALIB_BUF0_DEGC_CALI(buf[0]); - if (CALIB_BUF1_ID(buf[1]) & - CALIB_BUF0_O_SLOPE_SIGN(buf[0])) - mt->o_slope = -CALIB_BUF0_O_SLOPE(buf[0]); - else - mt->o_slope = CALIB_BUF0_O_SLOPE(buf[0]); - } else { + if (mtk_thermal_extract_efuse_v1(mt, buf)) dev_info(dev, "Device not calibrated, using default calibration values\n"); - } out: kfree(buf); -- cgit v1.2.3-58-ga151 From 89945047b1666c021c4222ef285239c1275f8e24 Mon Sep 17 00:00:00 2001 From: Henry Yen Date: Thu, 30 Apr 2020 17:14:34 +0800 Subject: thermal: mediatek: Add tsensor support for V2 thermal system This patch adds full support for ver 2 thermal system (e.g., MT7622 SoC). The new changes include reading calibration data, converting temperature and hardware initialization which are specific for version 2 system. Each platform decides which function to call according to its version. Fixes: 3966be3c08c3 ("thermal: mediatek: add support for MT7622 SoC") Signed-off-by: Henry Yen Reviewed-by: Matthias Brugger Tested-By: Frank Wunderlich Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1588238074-19338-3-git-send-email-henry.yen@mediatek.com --- drivers/thermal/mtk_thermal.c | 132 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 7 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 10107d9d56a8..88620f7e9890 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -38,6 +38,7 @@ #define TEMP_MONIDET0 0x014 #define TEMP_MONIDET1 0x018 #define TEMP_MSRCTL0 0x038 +#define TEMP_MSRCTL1 0x03c #define TEMP_AHBPOLL 0x040 #define TEMP_AHBTO 0x044 #define TEMP_ADCPNP0 0x048 @@ -133,6 +134,20 @@ #define CALIB_BUF0_O_SLOPE_SIGN_V1(x) (((x) >> 7) & 0x1) #define CALIB_BUF1_ID_V1(x) (((x) >> 9) & 0x1) +/* + * Layout of the fuses providing the calibration data + * These macros could be used for MT7622. + */ +#define CALIB_BUF0_ADC_OE_V2(x) (((x) >> 22) & 0x3ff) +#define CALIB_BUF0_ADC_GE_V2(x) (((x) >> 12) & 0x3ff) +#define CALIB_BUF0_DEGC_CALI_V2(x) (((x) >> 6) & 0x3f) +#define CALIB_BUF0_O_SLOPE_V2(x) (((x) >> 0) & 0x3f) +#define CALIB_BUF1_VTS_TS1_V2(x) (((x) >> 23) & 0x1ff) +#define CALIB_BUF1_VTS_TS2_V2(x) (((x) >> 14) & 0x1ff) +#define CALIB_BUF1_VTS_TSABB_V2(x) (((x) >> 5) & 0x1ff) +#define CALIB_BUF1_VALID_V2(x) (((x) >> 4) & 0x1) +#define CALIB_BUF1_O_SLOPE_SIGN_V2(x) (((x) >> 3) & 0x1) + enum { VTS1, VTS2, @@ -143,6 +158,11 @@ enum { MAX_NUM_VTS, }; +enum mtk_thermal_version { + MTK_THERMAL_V1 = 1, + MTK_THERMAL_V2, +}; + /* MT2701 thermal sensors */ #define MT2701_TS1 0 #define MT2701_TS2 1 @@ -245,6 +265,7 @@ struct mtk_thermal_data { const int *controller_offset; bool need_switch_bank; struct thermal_bank_cfg bank_data[MAX_NUM_ZONES]; + enum mtk_thermal_version version; }; struct mtk_thermal { @@ -258,8 +279,10 @@ struct mtk_thermal { /* Calibration values */ s32 adc_ge; + s32 adc_oe; s32 degc_cali; s32 o_slope; + s32 o_slope_sign; s32 vts[MAX_NUM_VTS]; const struct mtk_thermal_data *conf; @@ -398,6 +421,7 @@ static const struct mtk_thermal_data mt8173_thermal_data = { .msr = mt8173_msr, .adcpnp = mt8173_adcpnp, .sensor_mux_values = mt8173_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -428,6 +452,7 @@ static const struct mtk_thermal_data mt2701_thermal_data = { .msr = mt2701_msr, .adcpnp = mt2701_adcpnp, .sensor_mux_values = mt2701_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -458,6 +483,7 @@ static const struct mtk_thermal_data mt2712_thermal_data = { .msr = mt2712_msr, .adcpnp = mt2712_adcpnp, .sensor_mux_values = mt2712_mux_values, + .version = MTK_THERMAL_V1, }; /* @@ -482,6 +508,7 @@ static const struct mtk_thermal_data mt7622_thermal_data = { .msr = mt7622_msr, .adcpnp = mt7622_adcpnp, .sensor_mux_values = mt7622_mux_values, + .version = MTK_THERMAL_V2, }; /* @@ -514,6 +541,7 @@ static const struct mtk_thermal_data mt8183_thermal_data = { .msr = mt8183_msr, .adcpnp = mt8183_adcpnp, .sensor_mux_values = mt8183_mux_values, + .version = MTK_THERMAL_V1, }; /** @@ -540,6 +568,36 @@ static int raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw) return mt->degc_cali * 500 - tmp; } +static int raw_to_mcelsius_v2(struct mtk_thermal *mt, int sensno, s32 raw) +{ + s32 format_1 = 0; + s32 format_2 = 0; + s32 g_oe = 1; + s32 g_gain = 1; + s32 g_x_roomt = 0; + s32 tmp = 0; + + if (raw == 0) + return 0; + + raw &= 0xfff; + g_gain = 10000 + (((mt->adc_ge - 512) * 10000) >> 12); + g_oe = mt->adc_oe - 512; + format_1 = mt->vts[VTS2] + 3105 - g_oe; + format_2 = (mt->degc_cali * 10) >> 1; + g_x_roomt = (((format_1 * 10000) >> 12) * 10000) / g_gain; + + tmp = (((((raw - g_oe) * 10000) >> 12) * 10000) / g_gain) - g_x_roomt; + tmp = tmp * 10 * 100 / 11; + + if (mt->o_slope_sign == 0) + tmp = tmp / (165 - mt->o_slope); + else + tmp = tmp / (165 + mt->o_slope); + + return (format_2 - tmp) * 100; +} + /** * mtk_thermal_get_bank - get bank * @bank: The bank @@ -594,9 +652,13 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank) raw = readl(mt->thermal_base + conf->msr[conf->bank_data[bank->id].sensors[i]]); - temp = raw_to_mcelsius_v1(mt, - conf->bank_data[bank->id].sensors[i], - raw); + if (mt->conf->version == MTK_THERMAL_V1) { + temp = raw_to_mcelsius_v1( + mt, conf->bank_data[bank->id].sensors[i], raw); + } else { + temp = raw_to_mcelsius_v2( + mt, conf->bank_data[bank->id].sensors[i], raw); + } /* * The first read of a sensor often contains very high bogus @@ -698,9 +760,11 @@ static void mtk_thermal_init_bank(struct mtk_thermal *mt, int num, writel(auxadc_phys_base + AUXADC_CON1_CLR_V, controller_base + TEMP_ADCMUXADDR); - /* AHB address for pnp sensor mux selection */ - writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, - controller_base + TEMP_PNPMUXADDR); + if (mt->conf->version == MTK_THERMAL_V1) { + /* AHB address for pnp sensor mux selection */ + writel(apmixed_phys_base + APMIXED_SYS_TS_CON1, + controller_base + TEMP_PNPMUXADDR); + } /* AHB value for auxadc enable */ writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCEN); @@ -803,6 +867,23 @@ static int mtk_thermal_extract_efuse_v1(struct mtk_thermal *mt, u32 *buf) return 0; } +static int mtk_thermal_extract_efuse_v2(struct mtk_thermal *mt, u32 *buf) +{ + if (!CALIB_BUF1_VALID_V2(buf[1])) + return -EINVAL; + + mt->adc_oe = CALIB_BUF0_ADC_OE_V2(buf[0]); + mt->adc_ge = CALIB_BUF0_ADC_GE_V2(buf[0]); + mt->degc_cali = CALIB_BUF0_DEGC_CALI_V2(buf[0]); + mt->o_slope = CALIB_BUF0_O_SLOPE_V2(buf[0]); + mt->vts[VTS1] = CALIB_BUF1_VTS_TS1_V2(buf[1]); + mt->vts[VTS2] = CALIB_BUF1_VTS_TS2_V2(buf[1]); + mt->vts[VTSABB] = CALIB_BUF1_VTS_TSABB_V2(buf[1]); + mt->o_slope_sign = CALIB_BUF1_O_SLOPE_SIGN_V2(buf[1]); + + return 0; +} + static int mtk_thermal_get_calibration_data(struct device *dev, struct mtk_thermal *mt) { @@ -838,8 +919,15 @@ static int mtk_thermal_get_calibration_data(struct device *dev, goto out; } - if (mtk_thermal_extract_efuse_v1(mt, buf)) + if (mt->conf->version == MTK_THERMAL_V1) + ret = mtk_thermal_extract_efuse_v1(mt, buf); + else + ret = mtk_thermal_extract_efuse_v2(mt, buf); + + if (ret) { dev_info(dev, "Device not calibrated, using default calibration values\n"); + ret = 0; + } out: kfree(buf); @@ -872,6 +960,28 @@ static const struct of_device_id mtk_thermal_of_match[] = { }; MODULE_DEVICE_TABLE(of, mtk_thermal_of_match); +static void mtk_thermal_turn_on_buffer(void __iomem *apmixed_base) +{ + int tmp; + + tmp = readl(apmixed_base + APMIXED_SYS_TS_CON1); + tmp &= ~(0x37); + tmp |= 0x1; + writel(tmp, apmixed_base + APMIXED_SYS_TS_CON1); + udelay(200); +} + +static void mtk_thermal_release_periodic_ts(struct mtk_thermal *mt, + void __iomem *auxadc_base) +{ + int tmp; + + writel(0x800, auxadc_base + AUXADC_CON1_SET_V); + writel(0x1, mt->thermal_base + TEMP_MONCTL0); + tmp = readl(mt->thermal_base + TEMP_MSRCTL1); + writel((tmp & (~0x10e)), mt->thermal_base + TEMP_MSRCTL1); +} + static int mtk_thermal_probe(struct platform_device *pdev) { int ret, i, ctrl_id; @@ -880,6 +990,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) struct resource *res; u64 auxadc_phys_base, apmixed_phys_base; struct thermal_zone_device *tzdev; + void __iomem *apmixed_base, *auxadc_base; mt = devm_kzalloc(&pdev->dev, sizeof(*mt), GFP_KERNEL); if (!mt) @@ -914,6 +1025,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } + auxadc_base = of_iomap(auxadc, 0); auxadc_phys_base = of_get_phys_base(auxadc); of_node_put(auxadc); @@ -929,6 +1041,7 @@ static int mtk_thermal_probe(struct platform_device *pdev) return -ENODEV; } + apmixed_base = of_iomap(apmixedsys, 0); apmixed_phys_base = of_get_phys_base(apmixedsys); of_node_put(apmixedsys); @@ -954,6 +1067,11 @@ static int mtk_thermal_probe(struct platform_device *pdev) goto err_disable_clk_auxadc; } + if (mt->conf->version == MTK_THERMAL_V2) { + mtk_thermal_turn_on_buffer(apmixed_base); + mtk_thermal_release_periodic_ts(mt, auxadc_base); + } + for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) for (i = 0; i < mt->conf->num_banks; i++) mtk_thermal_init_bank(mt, i, apmixed_phys_base, -- cgit v1.2.3-58-ga151 From c569e805c7bcebdd069e5c97ce5f8543f6d02433 Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Thu, 30 Jul 2020 13:55:03 +0530 Subject: thermal: intel: intel_pch_thermal: Add Cannon Lake Low Power PCH support Add LP (Low Power) PCH id for Cannon Lake (CNL) based platforms. Signed-off-by: Sumeet Pawnikar Signed-off-by: Daniel Lezcano Link: https://lore.kernel.org/r/1596097503-27924-1-git-send-email-sumeet.r.pawnikar@intel.com --- drivers/thermal/intel/intel_pch_thermal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/intel/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c index 65702094f3d3..3b813ebb6ca1 100644 --- a/drivers/thermal/intel/intel_pch_thermal.c +++ b/drivers/thermal/intel/intel_pch_thermal.c @@ -24,6 +24,7 @@ #define PCH_THERMAL_DID_SKL_H 0xA131 /* Skylake PCH 100 series */ #define PCH_THERMAL_DID_CNL 0x9Df9 /* CNL PCH */ #define PCH_THERMAL_DID_CNL_H 0xA379 /* CNL-H PCH */ +#define PCH_THERMAL_DID_CNL_LP 0x02F9 /* CNL-LP PCH */ #define PCH_THERMAL_DID_CML_H 0X06F9 /* CML-H PCH */ /* Wildcat Point-LP PCH Thermal registers */ @@ -410,6 +411,8 @@ static const struct pci_device_id intel_pch_thermal_id[] = { .driver_data = board_cnl, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_H), .driver_data = board_cnl, }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CNL_LP), + .driver_data = board_cnl, }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_CML_H), .driver_data = board_cml, }, { 0, }, -- cgit v1.2.3-58-ga151