Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'thermal-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control updates from Rafael Wysocki:
"These further rework the ACPI thermal driver, after the changes made
to it in the previous cycle, to make it easier to grasp, get rid of
redundant pieces of internal data structures and eliminate its
reliance on a specific ordering of trip point objects in the thermal
core, make thermal core adjustments needed for the ACPI thermal driver
rework, modify the thermal governor interface so as to use trip
pointers for representing trip points in it, switch over multiple
thermal drivers to using void platform driver remove callbacks, add
support for 2 hardware features to the Intel int340x thermal driver,
add support for new hardware on ARM platforms, update documentation,
fix problems, clean up code and update the MAINTAINERS record for
thermal control.

Specifics:

- Untangle the initialization and updates of passive and active trip
points in the ACPI thermal driver (Rafael Wysocki)

- Reduce code duplication related to the initialization and updates
of trip points in the ACPI thermal driver (Rafael Wysocki)

- Use trip pointers for cooling device binding in the ACPI thermal
driver (Rafael Wysocki)

- Simplify critical and hot trips representation in the ACPI thermal
driver (Rafael Wysocki)

- Use trip pointers in thermal governors and in the related part of
the thermal core (Rafael Wysocki)

- Drop the trips_disabled bitmask that has become redundant from the
thermal core (Rafael Wysocki)

- Avoid updating trip points when the thermal zone temperature falls
into a trip point's hysteresis range (ícolas F. R. A. Prado)

- Add power floor notifications support to the int340x thermal
control driver (Srinivas Pandruvada)

- Rework updating trip points in the int340x thermal driver so that
it does not access thermal zone internals directly (Rafael
Wysocki)

- Use param_get_byte() instead of param_get_int() as the max_idle
module parameter .get() callback in the Intel powerclamp thermal
driver to avoid possible out-of-bounds access (David Arcari)

- Add workload hints support to the int340x thermal driver (Srinivas
Pandruvada)

- Add support for Mediatek LVTS MT8192 along with suspend/resume
routines (Balsam Chihi)

- Fix probe for THERMAL_V2 in the Mediatek LVTS driver (Markus
Schneider-Pargmann)

- Remove duplicate error message from the max76620 driver when
thermal_of_zone_register() fails (Thierry Reding)

- Add i.MX7D compatible bindings to fix a warning from dtbs_check for
the imx6ul platform (Alexander Stein)

- Add sa8775p compatible to the QCom tsens driver (Priyansh Jain)

- Fix error check in lvts_debugfs_init() to be against PTR_ERR() in
the LVTS Mediatek driver (Minjie Du)

- Remove unused variable in thermal/tools (Kuan-Wei Chiu)

- Document the imx8dl thermal sensor (Fabio Estevam)

- Add variable names in callback prototypes to prevent warning from
checkpatch.pl in the imx8mm driver (Bragatheswaran Manickavel)

- Add missing unevaluatedProperties on child node schemas for
tegra124 (Rob Herring)

- Add mt7988 support to the Mediatek LVTS driver (Frank Wunderlich)"

* tag 'thermal-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (111 commits)
thermal: ACPI: Include the right header file
thermal: core: Don't update trip points inside the hysteresis range
thermal: core: Pass trip pointer to governor throttle callback
thermal: gov_step_wise: Fold update_passive_instance() into its caller
thermal: gov_power_allocator: Use trip pointers instead of trip indices
thermal: gov_fair_share: Rearrange get_trip_level()
thermal: trip: Define for_each_trip() macro
thermal: trip: Simplify computing trip indices
thermal/qcom/tsens: Drop ops_v0_1
thermal/drivers/mediatek/lvts_thermal: Update calibration data documentation
thermal/drivers/mediatek/lvts_thermal: Add mt8192 support
thermal/drivers/mediatek/lvts_thermal: Add suspend and resume
dt-bindings: thermal: mediatek: Add LVTS thermal controller definition for mt8192
thermal/drivers/mediatek: Fix probe for THERMAL_V2
thermal/drivers/max77620: Remove duplicate error message
dt-bindings: timer: add imx7d compatible
dt-bindings: net: microchip: Allow nvmem-cell usage
dt-bindings: imx-thermal: Add #thermal-sensor-cells property
dt-bindings: thermal: tsens: Add sa8775p compatible
thermal/drivers/mediatek/lvts_thermal: Fix error check in lvts_debugfs_init()
...

+2192 -1070
+2
Documentation/devicetree/bindings/net/microchip,lan95xx.yaml
··· 44 44 45 45 local-mac-address: true 46 46 mac-address: true 47 + nvmem-cells: true 48 + nvmem-cell-names: true 47 49 48 50 required: 49 51 - compatible
+3 -1
Documentation/devicetree/bindings/thermal/fsl,scu-thermal.yaml
··· 18 18 properties: 19 19 compatible: 20 20 items: 21 - - const: fsl,imx8qxp-sc-thermal 21 + - enum: 22 + - fsl,imx8dxl-sc-thermal 23 + - fsl,imx8qxp-sc-thermal 22 24 - const: fsl,imx-sc-thermal 23 25 24 26 '#thermal-sensor-cells':
+7
Documentation/devicetree/bindings/thermal/imx-thermal.yaml
··· 60 60 clocks: 61 61 maxItems: 1 62 62 63 + "#thermal-sensor-cells": 64 + const: 0 65 + 63 66 required: 64 67 - compatible 65 68 - interrupts 66 69 - fsl,tempmon 67 70 - nvmem-cells 68 71 - nvmem-cell-names 72 + 73 + allOf: 74 + - $ref: thermal-sensor.yaml# 69 75 70 76 additionalProperties: false 71 77 ··· 110 104 nvmem-cells = <&tempmon_calib>, <&tempmon_temp_grade>; 111 105 nvmem-cell-names = "calib", "temp_grade"; 112 106 clocks = <&clks IMX6SX_CLK_PLL3_USB_OTG>; 107 + #thermal-sensor-cells = <0>; 113 108 }; 114 109 };
+1
Documentation/devicetree/bindings/thermal/mediatek,lvts-thermal.yaml
··· 18 18 properties: 19 19 compatible: 20 20 enum: 21 + - mediatek,mt7988-lvts-ap 21 22 - mediatek,mt8192-lvts-ap 22 23 - mediatek,mt8192-lvts-mcu 23 24 - mediatek,mt8195-lvts-ap
+5
Documentation/devicetree/bindings/thermal/nvidia,tegra124-soctherm.yaml
··· 68 68 patternProperties: 69 69 "^(light|heavy|oc1)$": 70 70 type: object 71 + additionalProperties: false 72 + 71 73 properties: 74 + "#cooling-cells": 75 + const: 2 76 + 72 77 nvidia,priority: 73 78 $ref: /schemas/types.yaml#/definitions/uint32 74 79 minimum: 1
+1
Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
··· 51 51 - qcom,msm8996-tsens 52 52 - qcom,msm8998-tsens 53 53 - qcom,qcm2290-tsens 54 + - qcom,sa8775p-tsens 54 55 - qcom,sc7180-tsens 55 56 - qcom,sc7280-tsens 56 57 - qcom,sc8180x-tsens
+1 -1
Documentation/devicetree/bindings/thermal/thermal-zones.yaml
··· 8 8 title: Thermal zone 9 9 10 10 maintainers: 11 - - Amit Kucheria <amitk@kernel.org> 11 + - Daniel Lezcano <daniel.lezcano@linaro.org> 12 12 13 13 description: | 14 14 Thermal management is achieved in devicetree by describing the sensor hardware
+3 -1
Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
··· 36 36 - fsl,imxrt1170-gpt 37 37 - const: fsl,imx6dl-gpt 38 38 - items: 39 - - const: fsl,imx6ul-gpt 39 + - enum: 40 + - fsl,imx6ul-gpt 41 + - fsl,imx7d-gpt 40 42 - const: fsl,imx6sx-gpt 41 43 42 44 reg:
+64
Documentation/driver-api/thermal/intel_dptf.rst
··· 164 164 ``power_limit_1_tmax_us`` (RO) 165 165 Maximum powercap sysfs constraint_1_time_window_us for Intel RAPL 166 166 167 + ``power_floor_status`` (RO) 168 + When set to 1, the power floor of the system in the current 169 + configuration has been reached. It needs to be reconfigured to allow 170 + power to be reduced any further. 171 + 172 + ``power_floor_enable`` (RW) 173 + When set to 1, enable reading and notification of the power floor 174 + status. Notifications are triggered for the power_floor_status 175 + attribute value changes. 176 + 167 177 :file:`/sys/bus/pci/devices/0000\:00\:04.0/` 168 178 169 179 ``tcc_offset_degree_celsius`` (RW) ··· 325 315 ---------------------------------------- 326 316 327 317 Refer to Documentation/admin-guide/acpi/fan_performance_states.rst 318 + 319 + Workload Type Hints 320 + ---------------------------------------- 321 + 322 + The firmware in Meteor Lake processor generation is capable of identifying 323 + workload type and passing hints regarding it to the OS. A special sysfs 324 + interface is provided to allow user space to obtain workload type hints from 325 + the firmware and control the rate at which they are provided. 326 + 327 + User space can poll attribute "workload_type_index" for the current hint or 328 + can receive a notification whenever the value of this attribute is updated. 329 + 330 + file:`/sys/bus/pci/devices/0000:00:04.0/workload_hint/` 331 + Segment 0, bus 0, device 4, function 0 is reserved for the processor thermal 332 + device on all Intel client processors. So, the above path doesn't change 333 + based on the processor generation. 334 + 335 + ``workload_hint_enable`` (RW) 336 + Enable firmware to send workload type hints to user space. 337 + 338 + ``notification_delay_ms`` (RW) 339 + Minimum delay in milliseconds before firmware will notify OS. This is 340 + for the rate control of notifications. This delay is between changing 341 + the workload type prediction in the firmware and notifying the OS about 342 + the change. The default delay is 1024 ms. The delay of 0 is invalid. 343 + The delay is rounded up to the nearest power of 2 to simplify firmware 344 + programming of the delay value. The read of notification_delay_ms 345 + attribute shows the effective value used. 346 + 347 + ``workload_type_index`` (RO) 348 + Predicted workload type index. User space can get notification of 349 + change via existing sysfs attribute change notification mechanism. 350 + 351 + The supported index values and their meaning for the Meteor Lake 352 + processor generation are as follows: 353 + 354 + 0 - Idle: System performs no tasks, power and idle residency are 355 + consistently low for long periods of time. 356 + 357 + 1 – Battery Life: Power is relatively low, but the processor may 358 + still be actively performing a task, such as video playback for 359 + a long period of time. 360 + 361 + 2 – Sustained: Power level that is relatively high for a long period 362 + of time, with very few to no periods of idleness, which will 363 + eventually exhaust RAPL Power Limit 1 and 2. 364 + 365 + 3 – Bursty: Consumes a relatively constant average amount of power, but 366 + periods of relative idleness are interrupted by bursts of 367 + activity. The bursts are relatively short and the periods of 368 + relative idleness between them typically prevent RAPL Power 369 + Limit 1 from being exhausted. 370 + 371 + 4 – Unknown: Can't classify.
+1 -1
MAINTAINERS
··· 21402 21402 THERMAL 21403 21403 M: Rafael J. Wysocki <rafael@kernel.org> 21404 21404 M: Daniel Lezcano <daniel.lezcano@linaro.org> 21405 - R: Amit Kucheria <amitk@kernel.org> 21406 21405 R: Zhang Rui <rui.zhang@intel.com> 21406 + R: Lukasz Luba <lukasz.luba@arm.com> 21407 21407 L: linux-pm@vger.kernel.org 21408 21408 S: Supported 21409 21409 Q: https://patchwork.kernel.org/project/linux-pm/list/
+423 -446
drivers/acpi/thermal.c
··· 43 43 #define ACPI_THERMAL_MAX_ACTIVE 10 44 44 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 45 45 46 - #define ACPI_TRIPS_CRITICAL BIT(0) 47 - #define ACPI_TRIPS_HOT BIT(1) 48 - #define ACPI_TRIPS_PASSIVE BIT(2) 49 - #define ACPI_TRIPS_ACTIVE BIT(3) 50 - #define ACPI_TRIPS_DEVICES BIT(4) 51 - 52 - #define ACPI_TRIPS_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) 53 - 54 - #define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ 55 - ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ 56 - ACPI_TRIPS_DEVICES) 46 + #define ACPI_THERMAL_TRIP_PASSIVE (-1) 57 47 58 48 /* 59 49 * This exception is thrown out in two cases: ··· 52 62 * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. 53 63 * We need to re-bind the cooling devices of a thermal zone when this occurs. 54 64 */ 55 - #define ACPI_THERMAL_TRIPS_EXCEPTION(flags, tz, str) \ 65 + #define ACPI_THERMAL_TRIPS_EXCEPTION(tz, str) \ 56 66 do { \ 57 - if (flags != ACPI_TRIPS_INIT) \ 58 - acpi_handle_info(tz->device->handle, \ 59 - "ACPI thermal trip point %s changed\n" \ 60 - "Please report to linux-acpi@vger.kernel.org\n", str); \ 67 + acpi_handle_info(tz->device->handle, \ 68 + "ACPI thermal trip point %s changed\n" \ 69 + "Please report to linux-acpi@vger.kernel.org\n", str); \ 61 70 } while (0) 62 71 63 72 static int act; ··· 82 93 static struct workqueue_struct *acpi_thermal_pm_queue; 83 94 84 95 struct acpi_thermal_trip { 85 - unsigned long temperature; 86 - bool valid; 96 + unsigned long temp_dk; 97 + struct acpi_handle_list devices; 87 98 }; 88 99 89 100 struct acpi_thermal_passive { 90 101 struct acpi_thermal_trip trip; 91 - struct acpi_handle_list devices; 92 102 unsigned long tc1; 93 103 unsigned long tc2; 94 104 unsigned long tsp; ··· 95 107 96 108 struct acpi_thermal_active { 97 109 struct acpi_thermal_trip trip; 98 - struct acpi_handle_list devices; 99 110 }; 100 111 101 112 struct acpi_thermal_trips { 102 - struct acpi_thermal_trip critical; 103 - struct acpi_thermal_trip hot; 104 113 struct acpi_thermal_passive passive; 105 114 struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; 106 115 }; ··· 105 120 struct acpi_thermal { 106 121 struct acpi_device *device; 107 122 acpi_bus_id name; 108 - unsigned long temperature; 109 - unsigned long last_temperature; 123 + unsigned long temp_dk; 124 + unsigned long last_temp_dk; 110 125 unsigned long polling_frequency; 111 126 volatile u8 zombie; 112 127 struct acpi_thermal_trips trips; 113 128 struct thermal_trip *trip_table; 114 - struct acpi_handle_list devices; 115 129 struct thermal_zone_device *thermal_zone; 116 130 int kelvin_offset; /* in millidegrees */ 117 131 struct work_struct thermal_check_work; ··· 130 146 if (!tz) 131 147 return -EINVAL; 132 148 133 - tz->last_temperature = tz->temperature; 149 + tz->last_temp_dk = tz->temp_dk; 134 150 135 151 status = acpi_evaluate_integer(tz->device->handle, "_TMP", NULL, &tmp); 136 152 if (ACPI_FAILURE(status)) 137 153 return -ENODEV; 138 154 139 - tz->temperature = tmp; 155 + tz->temp_dk = tmp; 140 156 141 157 acpi_handle_debug(tz->device->handle, "Temperature is %lu dK\n", 142 - tz->temperature); 158 + tz->temp_dk); 143 159 144 160 return 0; 145 161 } ··· 172 188 tz->kelvin_offset); 173 189 } 174 190 175 - static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) 191 + static bool acpi_thermal_trip_valid(struct acpi_thermal_trip *acpi_trip) 176 192 { 177 - acpi_status status; 178 - unsigned long long tmp; 179 - struct acpi_handle_list devices; 180 - bool valid = false; 181 - int i; 182 - 183 - /* Critical Shutdown */ 184 - if (flag & ACPI_TRIPS_CRITICAL) { 185 - status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); 186 - tz->trips.critical.temperature = tmp; 187 - /* 188 - * Treat freezing temperatures as invalid as well; some 189 - * BIOSes return really low values and cause reboots at startup. 190 - * Below zero (Celsius) values clearly aren't right for sure.. 191 - * ... so lets discard those as invalid. 192 - */ 193 - if (ACPI_FAILURE(status)) { 194 - tz->trips.critical.valid = false; 195 - acpi_handle_debug(tz->device->handle, 196 - "No critical threshold\n"); 197 - } else if (tmp <= 2732) { 198 - pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); 199 - tz->trips.critical.valid = false; 200 - } else { 201 - tz->trips.critical.valid = true; 202 - acpi_handle_debug(tz->device->handle, 203 - "Found critical threshold [%lu]\n", 204 - tz->trips.critical.temperature); 205 - } 206 - if (tz->trips.critical.valid) { 207 - if (crt == -1) { 208 - tz->trips.critical.valid = false; 209 - } else if (crt > 0) { 210 - unsigned long crt_k = celsius_to_deci_kelvin(crt); 211 - 212 - /* 213 - * Allow override critical threshold 214 - */ 215 - if (crt_k > tz->trips.critical.temperature) 216 - pr_info("Critical threshold %d C\n", crt); 217 - 218 - tz->trips.critical.temperature = crt_k; 219 - } 220 - } 221 - } 222 - 223 - /* Critical Sleep (optional) */ 224 - if (flag & ACPI_TRIPS_HOT) { 225 - status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); 226 - if (ACPI_FAILURE(status)) { 227 - tz->trips.hot.valid = false; 228 - acpi_handle_debug(tz->device->handle, 229 - "No hot threshold\n"); 230 - } else { 231 - tz->trips.hot.temperature = tmp; 232 - tz->trips.hot.valid = true; 233 - acpi_handle_debug(tz->device->handle, 234 - "Found hot threshold [%lu]\n", 235 - tz->trips.hot.temperature); 236 - } 237 - } 238 - 239 - /* Passive (optional) */ 240 - if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) || 241 - flag == ACPI_TRIPS_INIT) { 242 - valid = tz->trips.passive.trip.valid; 243 - if (psv == -1) { 244 - status = AE_SUPPORT; 245 - } else if (psv > 0) { 246 - tmp = celsius_to_deci_kelvin(psv); 247 - status = AE_OK; 248 - } else { 249 - status = acpi_evaluate_integer(tz->device->handle, 250 - "_PSV", NULL, &tmp); 251 - } 252 - 253 - if (ACPI_FAILURE(status)) { 254 - tz->trips.passive.trip.valid = false; 255 - } else { 256 - tz->trips.passive.trip.temperature = tmp; 257 - tz->trips.passive.trip.valid = true; 258 - if (flag == ACPI_TRIPS_INIT) { 259 - status = acpi_evaluate_integer(tz->device->handle, 260 - "_TC1", NULL, &tmp); 261 - if (ACPI_FAILURE(status)) 262 - tz->trips.passive.trip.valid = false; 263 - else 264 - tz->trips.passive.tc1 = tmp; 265 - 266 - status = acpi_evaluate_integer(tz->device->handle, 267 - "_TC2", NULL, &tmp); 268 - if (ACPI_FAILURE(status)) 269 - tz->trips.passive.trip.valid = false; 270 - else 271 - tz->trips.passive.tc2 = tmp; 272 - 273 - status = acpi_evaluate_integer(tz->device->handle, 274 - "_TSP", NULL, &tmp); 275 - if (ACPI_FAILURE(status)) 276 - tz->trips.passive.trip.valid = false; 277 - else 278 - tz->trips.passive.tsp = tmp; 279 - } 280 - } 281 - } 282 - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) { 283 - memset(&devices, 0, sizeof(struct acpi_handle_list)); 284 - status = acpi_evaluate_reference(tz->device->handle, "_PSL", 285 - NULL, &devices); 286 - if (ACPI_FAILURE(status)) { 287 - acpi_handle_info(tz->device->handle, 288 - "Invalid passive threshold\n"); 289 - tz->trips.passive.trip.valid = false; 290 - } else { 291 - tz->trips.passive.trip.valid = true; 292 - } 293 - 294 - if (memcmp(&tz->trips.passive.devices, &devices, 295 - sizeof(struct acpi_handle_list))) { 296 - memcpy(&tz->trips.passive.devices, &devices, 297 - sizeof(struct acpi_handle_list)); 298 - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); 299 - } 300 - } 301 - if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { 302 - if (valid != tz->trips.passive.trip.valid) 303 - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); 304 - } 305 - 306 - /* Active (optional) */ 307 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 308 - char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 309 - valid = tz->trips.active[i].trip.valid; 310 - 311 - if (act == -1) 312 - break; /* disable all active trip points */ 313 - 314 - if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) && 315 - tz->trips.active[i].trip.valid)) { 316 - status = acpi_evaluate_integer(tz->device->handle, 317 - name, NULL, &tmp); 318 - if (ACPI_FAILURE(status)) { 319 - tz->trips.active[i].trip.valid = false; 320 - if (i == 0) 321 - break; 322 - 323 - if (act <= 0) 324 - break; 325 - 326 - if (i == 1) 327 - tz->trips.active[0].trip.temperature = 328 - celsius_to_deci_kelvin(act); 329 - else 330 - /* 331 - * Don't allow override higher than 332 - * the next higher trip point 333 - */ 334 - tz->trips.active[i-1].trip.temperature = 335 - min_t(unsigned long, 336 - tz->trips.active[i-2].trip.temperature, 337 - celsius_to_deci_kelvin(act)); 338 - 339 - break; 340 - } else { 341 - tz->trips.active[i].trip.temperature = tmp; 342 - tz->trips.active[i].trip.valid = true; 343 - } 344 - } 345 - 346 - name[2] = 'L'; 347 - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) { 348 - memset(&devices, 0, sizeof(struct acpi_handle_list)); 349 - status = acpi_evaluate_reference(tz->device->handle, 350 - name, NULL, &devices); 351 - if (ACPI_FAILURE(status)) { 352 - acpi_handle_info(tz->device->handle, 353 - "Invalid active%d threshold\n", i); 354 - tz->trips.active[i].trip.valid = false; 355 - } else { 356 - tz->trips.active[i].trip.valid = true; 357 - } 358 - 359 - if (memcmp(&tz->trips.active[i].devices, &devices, 360 - sizeof(struct acpi_handle_list))) { 361 - memcpy(&tz->trips.active[i].devices, &devices, 362 - sizeof(struct acpi_handle_list)); 363 - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); 364 - } 365 - } 366 - if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) 367 - if (valid != tz->trips.active[i].trip.valid) 368 - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); 369 - 370 - if (!tz->trips.active[i].trip.valid) 371 - break; 372 - } 373 - 374 - if (flag & ACPI_TRIPS_DEVICES) { 375 - memset(&devices, 0, sizeof(devices)); 376 - status = acpi_evaluate_reference(tz->device->handle, "_TZD", 377 - NULL, &devices); 378 - if (ACPI_SUCCESS(status) && 379 - memcmp(&tz->devices, &devices, sizeof(devices))) { 380 - tz->devices = devices; 381 - ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); 382 - } 383 - } 193 + return acpi_trip->temp_dk != THERMAL_TEMP_INVALID; 384 194 } 195 + 196 + static int active_trip_index(struct acpi_thermal *tz, 197 + struct acpi_thermal_trip *acpi_trip) 198 + { 199 + struct acpi_thermal_active *active; 200 + 201 + active = container_of(acpi_trip, struct acpi_thermal_active, trip); 202 + return active - tz->trips.active; 203 + } 204 + 205 + static long get_passive_temp(struct acpi_thermal *tz) 206 + { 207 + unsigned long long tmp; 208 + acpi_status status; 209 + 210 + status = acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, &tmp); 211 + if (ACPI_FAILURE(status)) 212 + return THERMAL_TEMP_INVALID; 213 + 214 + return tmp; 215 + } 216 + 217 + static long get_active_temp(struct acpi_thermal *tz, int index) 218 + { 219 + char method[] = { '_', 'A', 'C', '0' + index, '\0' }; 220 + unsigned long long tmp; 221 + acpi_status status; 222 + 223 + status = acpi_evaluate_integer(tz->device->handle, method, NULL, &tmp); 224 + if (ACPI_FAILURE(status)) 225 + return THERMAL_TEMP_INVALID; 226 + 227 + /* 228 + * If an override has been provided, apply it so there are no active 229 + * trips with thresholds greater than the override. 230 + */ 231 + if (act > 0) { 232 + unsigned long long override = celsius_to_deci_kelvin(act); 233 + 234 + if (tmp > override) 235 + tmp = override; 236 + } 237 + return tmp; 238 + } 239 + 240 + static void acpi_thermal_update_trip(struct acpi_thermal *tz, 241 + const struct thermal_trip *trip) 242 + { 243 + struct acpi_thermal_trip *acpi_trip = trip->priv; 244 + 245 + if (trip->type == THERMAL_TRIP_PASSIVE) { 246 + if (psv > 0) 247 + return; 248 + 249 + acpi_trip->temp_dk = get_passive_temp(tz); 250 + } else { 251 + int index = active_trip_index(tz, acpi_trip); 252 + 253 + acpi_trip->temp_dk = get_active_temp(tz, index); 254 + } 255 + 256 + if (!acpi_thermal_trip_valid(acpi_trip)) 257 + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); 258 + } 259 + 260 + static bool update_trip_devices(struct acpi_thermal *tz, 261 + struct acpi_thermal_trip *acpi_trip, 262 + int index, bool compare) 263 + { 264 + struct acpi_handle_list devices; 265 + char method[] = "_PSL"; 266 + acpi_status status; 267 + 268 + if (index != ACPI_THERMAL_TRIP_PASSIVE) { 269 + method[1] = 'A'; 270 + method[2] = 'L'; 271 + method[3] = '0' + index; 272 + } 273 + 274 + memset(&devices, 0, sizeof(devices)); 275 + 276 + status = acpi_evaluate_reference(tz->device->handle, method, NULL, &devices); 277 + if (ACPI_FAILURE(status)) { 278 + acpi_handle_info(tz->device->handle, "%s evaluation failure\n", method); 279 + return false; 280 + } 281 + 282 + if (compare && memcmp(&acpi_trip->devices, &devices, sizeof(devices))) 283 + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "device"); 284 + 285 + memcpy(&acpi_trip->devices, &devices, sizeof(devices)); 286 + return true; 287 + } 288 + 289 + static void acpi_thermal_update_trip_devices(struct acpi_thermal *tz, 290 + const struct thermal_trip *trip) 291 + { 292 + struct acpi_thermal_trip *acpi_trip = trip->priv; 293 + int index = trip->type == THERMAL_TRIP_PASSIVE ? 294 + ACPI_THERMAL_TRIP_PASSIVE : active_trip_index(tz, acpi_trip); 295 + 296 + if (update_trip_devices(tz, acpi_trip, index, true)) 297 + return; 298 + 299 + acpi_trip->temp_dk = THERMAL_TEMP_INVALID; 300 + ACPI_THERMAL_TRIPS_EXCEPTION(tz, "state"); 301 + } 302 + 303 + struct adjust_trip_data { 304 + struct acpi_thermal *tz; 305 + u32 event; 306 + }; 385 307 386 308 static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) 387 309 { 388 310 struct acpi_thermal_trip *acpi_trip = trip->priv; 389 - struct acpi_thermal *tz = data; 311 + struct adjust_trip_data *atd = data; 312 + struct acpi_thermal *tz = atd->tz; 390 313 391 - if (!acpi_trip) 314 + if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip)) 392 315 return 0; 393 316 394 - if (acpi_trip->valid) 395 - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); 317 + if (atd->event == ACPI_THERMAL_NOTIFY_THRESHOLDS) 318 + acpi_thermal_update_trip(tz, trip); 319 + else 320 + acpi_thermal_update_trip_devices(tz, trip); 321 + 322 + if (acpi_thermal_trip_valid(acpi_trip)) 323 + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); 396 324 else 397 325 trip->temperature = THERMAL_TEMP_INVALID; 398 326 399 327 return 0; 400 - } 401 - 402 - static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal, 403 - unsigned long data) 404 - { 405 - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); 406 - int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ? 407 - ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES; 408 - 409 - __acpi_thermal_trips_update(tz, flag); 410 - 411 - for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); 412 328 } 413 329 414 330 static void acpi_queue_thermal_check(struct acpi_thermal *tz) ··· 319 435 320 436 static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) 321 437 { 438 + struct adjust_trip_data atd = { .tz = tz, .event = event }; 322 439 struct acpi_device *adev = tz->device; 323 440 324 441 /* 325 - * Use thermal_zone_device_exec() to carry out the trip points 442 + * Use thermal_zone_for_each_trip() to carry out the trip points 326 443 * update, so as to protect thermal_get_trend() from getting stale 327 444 * trip point temperatures and to prevent thermal_zone_device_update() 328 445 * invoked from acpi_thermal_check_fn() from producing inconsistent 329 446 * results. 330 447 */ 331 - thermal_zone_device_exec(tz->thermal_zone, 332 - acpi_thermal_adjust_thermal_zone, event); 448 + thermal_zone_for_each_trip(tz->thermal_zone, 449 + acpi_thermal_adjust_trip, &atd); 333 450 acpi_queue_thermal_check(tz); 334 451 acpi_bus_generate_netlink_event(adev->pnp.device_class, 335 452 dev_name(&adev->dev), event, 0); 336 453 } 337 454 455 + static long acpi_thermal_get_critical_trip(struct acpi_thermal *tz) 456 + { 457 + unsigned long long tmp; 458 + acpi_status status; 459 + 460 + if (crt > 0) { 461 + tmp = celsius_to_deci_kelvin(crt); 462 + goto set; 463 + } 464 + if (crt == -1) { 465 + acpi_handle_debug(tz->device->handle, "Critical threshold disabled\n"); 466 + return THERMAL_TEMP_INVALID; 467 + } 468 + 469 + status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, &tmp); 470 + if (ACPI_FAILURE(status)) { 471 + acpi_handle_debug(tz->device->handle, "No critical threshold\n"); 472 + return THERMAL_TEMP_INVALID; 473 + } 474 + if (tmp <= 2732) { 475 + /* 476 + * Below zero (Celsius) values clearly aren't right for sure, 477 + * so discard them as invalid. 478 + */ 479 + pr_info(FW_BUG "Invalid critical threshold (%llu)\n", tmp); 480 + return THERMAL_TEMP_INVALID; 481 + } 482 + 483 + set: 484 + acpi_handle_debug(tz->device->handle, "Critical threshold [%llu]\n", tmp); 485 + return tmp; 486 + } 487 + 488 + static long acpi_thermal_get_hot_trip(struct acpi_thermal *tz) 489 + { 490 + unsigned long long tmp; 491 + acpi_status status; 492 + 493 + status = acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, &tmp); 494 + if (ACPI_FAILURE(status)) { 495 + acpi_handle_debug(tz->device->handle, "No hot threshold\n"); 496 + return THERMAL_TEMP_INVALID; 497 + } 498 + 499 + acpi_handle_debug(tz->device->handle, "Hot threshold [%llu]\n", tmp); 500 + return tmp; 501 + } 502 + 503 + static bool passive_trip_params_init(struct acpi_thermal *tz) 504 + { 505 + unsigned long long tmp; 506 + acpi_status status; 507 + 508 + status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); 509 + if (ACPI_FAILURE(status)) 510 + return false; 511 + 512 + tz->trips.passive.tc1 = tmp; 513 + 514 + status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); 515 + if (ACPI_FAILURE(status)) 516 + return false; 517 + 518 + tz->trips.passive.tc2 = tmp; 519 + 520 + status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); 521 + if (ACPI_FAILURE(status)) 522 + return false; 523 + 524 + tz->trips.passive.tsp = tmp; 525 + 526 + return true; 527 + } 528 + 529 + static bool acpi_thermal_init_trip(struct acpi_thermal *tz, int index) 530 + { 531 + struct acpi_thermal_trip *acpi_trip; 532 + long temp; 533 + 534 + if (index == ACPI_THERMAL_TRIP_PASSIVE) { 535 + acpi_trip = &tz->trips.passive.trip; 536 + 537 + if (psv == -1) 538 + goto fail; 539 + 540 + if (!passive_trip_params_init(tz)) 541 + goto fail; 542 + 543 + temp = psv > 0 ? celsius_to_deci_kelvin(psv) : 544 + get_passive_temp(tz); 545 + } else { 546 + acpi_trip = &tz->trips.active[index].trip; 547 + 548 + if (act == -1) 549 + goto fail; 550 + 551 + temp = get_active_temp(tz, index); 552 + } 553 + 554 + if (temp == THERMAL_TEMP_INVALID) 555 + goto fail; 556 + 557 + if (!update_trip_devices(tz, acpi_trip, index, false)) 558 + goto fail; 559 + 560 + acpi_trip->temp_dk = temp; 561 + return true; 562 + 563 + fail: 564 + acpi_trip->temp_dk = THERMAL_TEMP_INVALID; 565 + return false; 566 + } 567 + 338 568 static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) 339 569 { 340 - bool valid; 570 + unsigned int count = 0; 341 571 int i; 342 572 343 - __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); 573 + if (acpi_thermal_init_trip(tz, ACPI_THERMAL_TRIP_PASSIVE)) 574 + count++; 344 575 345 - valid = tz->trips.critical.valid | 346 - tz->trips.hot.valid | 347 - tz->trips.passive.trip.valid; 576 + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 577 + if (acpi_thermal_init_trip(tz, i)) 578 + count++; 579 + else 580 + break; 348 581 349 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) 350 - valid = valid || tz->trips.active[i].trip.valid; 351 - 352 - if (!valid) { 353 - pr_warn(FW_BUG "No valid trip found\n"); 354 - return -ENODEV; 355 582 } 356 - return 0; 583 + 584 + while (++i < ACPI_THERMAL_MAX_ACTIVE) 585 + tz->trips.active[i].trip.temp_dk = THERMAL_TEMP_INVALID; 586 + 587 + return count; 357 588 } 358 589 359 590 /* sys I/F for generic thermal sysfs support */ ··· 485 486 if (result) 486 487 return result; 487 488 488 - *temp = deci_kelvin_to_millicelsius_with_offset(tz->temperature, 489 + *temp = deci_kelvin_to_millicelsius_with_offset(tz->temp_dk, 489 490 tz->kelvin_offset); 490 491 return 0; 491 492 } ··· 502 503 return -EINVAL; 503 504 504 505 acpi_trip = trip->priv; 505 - if (!acpi_trip || !acpi_trip->valid) 506 + if (!acpi_trip || !acpi_thermal_trip_valid(acpi_trip)) 506 507 return -EINVAL; 507 508 508 509 switch (trip->type) { 509 510 case THERMAL_TRIP_PASSIVE: 510 - t = tz->trips.passive.tc1 * (tz->temperature - 511 - tz->last_temperature) + 512 - tz->trips.passive.tc2 * (tz->temperature - 513 - acpi_trip->temperature); 511 + t = tz->trips.passive.tc1 * (tz->temp_dk - 512 + tz->last_temp_dk) + 513 + tz->trips.passive.tc2 * (tz->temp_dk - 514 + acpi_trip->temp_dk); 514 515 if (t > 0) 515 516 *trend = THERMAL_TREND_RAISING; 516 517 else if (t < 0) ··· 521 522 return 0; 522 523 523 524 case THERMAL_TRIP_ACTIVE: 524 - t = acpi_thermal_temp(tz, tz->temperature); 525 + t = acpi_thermal_temp(tz, tz->temp_dk); 525 526 if (t <= trip->temperature) 526 527 break; 527 528 ··· 556 557 thermal_zone_device_critical(thermal); 557 558 } 558 559 559 - static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, 560 - struct thermal_cooling_device *cdev, 561 - bool bind) 560 + struct acpi_thermal_bind_data { 561 + struct thermal_zone_device *thermal; 562 + struct thermal_cooling_device *cdev; 563 + bool bind; 564 + }; 565 + 566 + static int bind_unbind_cdev_cb(struct thermal_trip *trip, void *arg) 562 567 { 563 - struct acpi_device *device = cdev->devdata; 564 - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); 565 - struct acpi_device *dev; 566 - acpi_handle handle; 568 + struct acpi_thermal_trip *acpi_trip = trip->priv; 569 + struct acpi_thermal_bind_data *bd = arg; 570 + struct thermal_zone_device *thermal = bd->thermal; 571 + struct thermal_cooling_device *cdev = bd->cdev; 572 + struct acpi_device *cdev_adev = cdev->devdata; 567 573 int i; 568 - int j; 569 - int trip = -1; 570 - int result = 0; 571 574 572 - if (tz->trips.critical.valid) 573 - trip++; 575 + /* Skip critical and hot trips. */ 576 + if (!acpi_trip) 577 + return 0; 574 578 575 - if (tz->trips.hot.valid) 576 - trip++; 579 + for (i = 0; i < acpi_trip->devices.count; i++) { 580 + acpi_handle handle = acpi_trip->devices.handles[i]; 581 + struct acpi_device *adev = acpi_fetch_acpi_dev(handle); 577 582 578 - if (tz->trips.passive.trip.valid) { 579 - trip++; 580 - for (i = 0; i < tz->trips.passive.devices.count; i++) { 581 - handle = tz->trips.passive.devices.handles[i]; 582 - dev = acpi_fetch_acpi_dev(handle); 583 - if (dev != device) 584 - continue; 583 + if (adev != cdev_adev) 584 + continue; 585 585 586 - if (bind) 587 - result = thermal_zone_bind_cooling_device( 588 - thermal, trip, cdev, 589 - THERMAL_NO_LIMIT, 590 - THERMAL_NO_LIMIT, 591 - THERMAL_WEIGHT_DEFAULT); 592 - else 593 - result = 594 - thermal_zone_unbind_cooling_device( 595 - thermal, trip, cdev); 586 + if (bd->bind) { 587 + int ret; 596 588 597 - if (result) 598 - goto failed; 589 + ret = thermal_bind_cdev_to_trip(thermal, trip, cdev, 590 + THERMAL_NO_LIMIT, 591 + THERMAL_NO_LIMIT, 592 + THERMAL_WEIGHT_DEFAULT); 593 + if (ret) 594 + return ret; 595 + } else { 596 + thermal_unbind_cdev_from_trip(thermal, trip, cdev); 599 597 } 600 598 } 601 599 602 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 603 - if (!tz->trips.active[i].trip.valid) 604 - break; 600 + return 0; 601 + } 605 602 606 - trip++; 607 - for (j = 0; j < tz->trips.active[i].devices.count; j++) { 608 - handle = tz->trips.active[i].devices.handles[j]; 609 - dev = acpi_fetch_acpi_dev(handle); 610 - if (dev != device) 611 - continue; 603 + static int acpi_thermal_bind_unbind_cdev(struct thermal_zone_device *thermal, 604 + struct thermal_cooling_device *cdev, 605 + bool bind) 606 + { 607 + struct acpi_thermal_bind_data bd = { 608 + .thermal = thermal, .cdev = cdev, .bind = bind 609 + }; 612 610 613 - if (bind) 614 - result = thermal_zone_bind_cooling_device( 615 - thermal, trip, cdev, 616 - THERMAL_NO_LIMIT, 617 - THERMAL_NO_LIMIT, 618 - THERMAL_WEIGHT_DEFAULT); 619 - else 620 - result = thermal_zone_unbind_cooling_device( 621 - thermal, trip, cdev); 622 - 623 - if (result) 624 - goto failed; 625 - } 626 - } 627 - 628 - failed: 629 - return result; 611 + return for_each_thermal_trip(thermal, bind_unbind_cdev_cb, &bd); 630 612 } 631 613 632 614 static int 633 615 acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, 634 616 struct thermal_cooling_device *cdev) 635 617 { 636 - return acpi_thermal_cooling_device_cb(thermal, cdev, true); 618 + return acpi_thermal_bind_unbind_cdev(thermal, cdev, true); 637 619 } 638 620 639 621 static int 640 622 acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, 641 623 struct thermal_cooling_device *cdev) 642 624 { 643 - return acpi_thermal_cooling_device_cb(thermal, cdev, false); 625 + return acpi_thermal_bind_unbind_cdev(thermal, cdev, false); 644 626 } 645 627 646 628 static struct thermal_zone_device_ops acpi_thermal_zone_ops = { ··· 659 679 sysfs_remove_link(&tzdev->kobj, "device"); 660 680 } 661 681 662 - static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) 682 + static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, 683 + unsigned int trip_count, 684 + int passive_delay) 663 685 { 664 - struct acpi_thermal_trip *acpi_trip; 665 - struct thermal_trip *trip; 666 - int passive_delay = 0; 667 - int trip_count = 0; 668 686 int result; 669 - int i; 670 - 671 - if (tz->trips.critical.valid) 672 - trip_count++; 673 - 674 - if (tz->trips.hot.valid) 675 - trip_count++; 676 - 677 - if (tz->trips.passive.trip.valid) { 678 - trip_count++; 679 - passive_delay = tz->trips.passive.tsp * 100; 680 - } 681 - 682 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++) 683 - trip_count++; 684 - 685 - trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); 686 - if (!trip) 687 - return -ENOMEM; 688 - 689 - tz->trip_table = trip; 690 - 691 - if (tz->trips.critical.valid) { 692 - trip->type = THERMAL_TRIP_CRITICAL; 693 - trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); 694 - trip++; 695 - } 696 - 697 - if (tz->trips.hot.valid) { 698 - trip->type = THERMAL_TRIP_HOT; 699 - trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); 700 - trip++; 701 - } 702 - 703 - acpi_trip = &tz->trips.passive.trip; 704 - if (acpi_trip->valid) { 705 - trip->type = THERMAL_TRIP_PASSIVE; 706 - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); 707 - trip->priv = acpi_trip; 708 - trip++; 709 - } 710 - 711 - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 712 - acpi_trip = &tz->trips.active[i].trip; 713 - 714 - if (!acpi_trip->valid) 715 - break; 716 - 717 - trip->type = THERMAL_TRIP_ACTIVE; 718 - trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); 719 - trip->priv = acpi_trip; 720 - trip++; 721 - } 722 687 723 688 tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz", 724 689 tz->trip_table, ··· 673 748 NULL, 674 749 passive_delay, 675 750 tz->polling_frequency * 100); 676 - if (IS_ERR(tz->thermal_zone)) { 677 - result = PTR_ERR(tz->thermal_zone); 678 - goto free_trip_table; 679 - } 751 + if (IS_ERR(tz->thermal_zone)) 752 + return PTR_ERR(tz->thermal_zone); 680 753 681 754 result = acpi_thermal_zone_sysfs_add(tz); 682 755 if (result) ··· 693 770 acpi_thermal_zone_sysfs_remove(tz); 694 771 unregister_tzd: 695 772 thermal_zone_device_unregister(tz->thermal_zone); 696 - free_trip_table: 697 - kfree(tz->trip_table); 698 773 699 774 return result; 700 775 } ··· 765 844 acpi_evaluate_integer(handle, "_TMP", NULL, &value); 766 845 } 767 846 768 - static int acpi_thermal_get_info(struct acpi_thermal *tz) 769 - { 770 - int result; 771 - 772 - if (!tz) 773 - return -EINVAL; 774 - 775 - acpi_thermal_aml_dependency_fix(tz); 776 - 777 - /* Get trip points [_CRT, _PSV, etc.] (required) */ 778 - result = acpi_thermal_get_trip_points(tz); 779 - if (result) 780 - return result; 781 - 782 - /* Get temperature [_TMP] (required) */ 783 - result = acpi_thermal_get_temperature(tz); 784 - if (result) 785 - return result; 786 - 787 - /* Set the cooling mode [_SCP] to active cooling (default) */ 788 - acpi_execute_simple_method(tz->device->handle, "_SCP", 789 - ACPI_THERMAL_MODE_ACTIVE); 790 - 791 - /* Get default polling frequency [_TZP] (optional) */ 792 - if (tzp) 793 - tz->polling_frequency = tzp; 794 - else 795 - acpi_thermal_get_polling_frequency(tz); 796 - 797 - return 0; 798 - } 799 - 800 847 /* 801 848 * The exact offset between Kelvin and degree Celsius is 273.15. However ACPI 802 849 * handles temperature values with a single decimal place. As a consequence, ··· 775 886 * The heuristic below should work for all ACPI thermal zones which have a 776 887 * critical trip point with a value being a multiple of 0.5 degree Celsius. 777 888 */ 778 - static void acpi_thermal_guess_offset(struct acpi_thermal *tz) 889 + static void acpi_thermal_guess_offset(struct acpi_thermal *tz, long crit_temp) 779 890 { 780 - if (tz->trips.critical.valid && 781 - (tz->trips.critical.temperature % 5) == 1) 891 + if (crit_temp != THERMAL_TEMP_INVALID && crit_temp % 5 == 1) 782 892 tz->kelvin_offset = 273100; 783 893 else 784 894 tz->kelvin_offset = 273200; ··· 810 922 811 923 static int acpi_thermal_add(struct acpi_device *device) 812 924 { 925 + struct acpi_thermal_trip *acpi_trip; 926 + struct thermal_trip *trip; 813 927 struct acpi_thermal *tz; 928 + unsigned int trip_count; 929 + int crit_temp, hot_temp; 930 + int passive_delay = 0; 814 931 int result; 932 + int i; 815 933 816 934 if (!device) 817 935 return -EINVAL; ··· 832 938 strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); 833 939 device->driver_data = tz; 834 940 835 - result = acpi_thermal_get_info(tz); 941 + acpi_thermal_aml_dependency_fix(tz); 942 + 943 + /* Get trip points [_CRT, _PSV, etc.] (required). */ 944 + trip_count = acpi_thermal_get_trip_points(tz); 945 + 946 + crit_temp = acpi_thermal_get_critical_trip(tz); 947 + if (crit_temp != THERMAL_TEMP_INVALID) 948 + trip_count++; 949 + 950 + hot_temp = acpi_thermal_get_hot_trip(tz); 951 + if (hot_temp != THERMAL_TEMP_INVALID) 952 + trip_count++; 953 + 954 + if (!trip_count) { 955 + pr_warn(FW_BUG "No valid trip points!\n"); 956 + result = -ENODEV; 957 + goto free_memory; 958 + } 959 + 960 + /* Get temperature [_TMP] (required). */ 961 + result = acpi_thermal_get_temperature(tz); 836 962 if (result) 837 963 goto free_memory; 838 964 839 - acpi_thermal_guess_offset(tz); 965 + /* Set the cooling mode [_SCP] to active cooling. */ 966 + acpi_execute_simple_method(tz->device->handle, "_SCP", 967 + ACPI_THERMAL_MODE_ACTIVE); 840 968 841 - result = acpi_thermal_register_thermal_zone(tz); 842 - if (result) 969 + /* Determine the default polling frequency [_TZP]. */ 970 + if (tzp) 971 + tz->polling_frequency = tzp; 972 + else 973 + acpi_thermal_get_polling_frequency(tz); 974 + 975 + acpi_thermal_guess_offset(tz, crit_temp); 976 + 977 + trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); 978 + if (!trip) { 979 + result = -ENOMEM; 843 980 goto free_memory; 981 + } 982 + 983 + tz->trip_table = trip; 984 + 985 + if (crit_temp != THERMAL_TEMP_INVALID) { 986 + trip->type = THERMAL_TRIP_CRITICAL; 987 + trip->temperature = acpi_thermal_temp(tz, crit_temp); 988 + trip++; 989 + } 990 + 991 + if (hot_temp != THERMAL_TEMP_INVALID) { 992 + trip->type = THERMAL_TRIP_HOT; 993 + trip->temperature = acpi_thermal_temp(tz, hot_temp); 994 + trip++; 995 + } 996 + 997 + acpi_trip = &tz->trips.passive.trip; 998 + if (acpi_thermal_trip_valid(acpi_trip)) { 999 + passive_delay = tz->trips.passive.tsp * 100; 1000 + 1001 + trip->type = THERMAL_TRIP_PASSIVE; 1002 + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); 1003 + trip->priv = acpi_trip; 1004 + trip++; 1005 + } 1006 + 1007 + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 1008 + acpi_trip = &tz->trips.active[i].trip; 1009 + 1010 + if (!acpi_thermal_trip_valid(acpi_trip)) 1011 + break; 1012 + 1013 + trip->type = THERMAL_TRIP_ACTIVE; 1014 + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temp_dk); 1015 + trip->priv = acpi_trip; 1016 + trip++; 1017 + } 1018 + 1019 + result = acpi_thermal_register_thermal_zone(tz, trip_count, passive_delay); 1020 + if (result) 1021 + goto free_trips; 844 1022 845 1023 refcount_set(&tz->thermal_check_count, 3); 846 1024 mutex_init(&tz->thermal_check_lock); 847 1025 INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); 848 1026 849 1027 pr_info("%s [%s] (%ld C)\n", acpi_device_name(device), 850 - acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature)); 1028 + acpi_device_bid(device), deci_kelvin_to_celsius(tz->temp_dk)); 851 1029 852 1030 result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, 853 1031 acpi_thermal_notify); ··· 931 965 flush_wq: 932 966 flush_workqueue(acpi_thermal_pm_queue); 933 967 acpi_thermal_unregister_thermal_zone(tz); 968 + free_trips: 969 + kfree(tz->trip_table); 934 970 free_memory: 935 971 kfree(tz); 936 972 ··· 978 1010 return -EINVAL; 979 1011 980 1012 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 981 - if (!tz->trips.active[i].trip.valid) 1013 + struct acpi_thermal_trip *acpi_trip = &tz->trips.active[i].trip; 1014 + 1015 + if (!acpi_thermal_trip_valid(acpi_trip)) 982 1016 break; 983 1017 984 - for (j = 0; j < tz->trips.active[i].devices.count; j++) { 985 - acpi_bus_update_power(tz->trips.active[i].devices.handles[j], 1018 + for (j = 0; j < acpi_trip->devices.count; j++) { 1019 + acpi_bus_update_power(acpi_trip->devices.handles[j], 986 1020 &power_state); 987 1021 } 988 1022 } ··· 1016 1046 .drv.pm = &acpi_thermal_pm, 1017 1047 }; 1018 1048 1019 - static int thermal_act(const struct dmi_system_id *d) { 1049 + static int thermal_act(const struct dmi_system_id *d) 1050 + { 1020 1051 if (act == 0) { 1021 1052 pr_notice("%s detected: disabling all active thermal trip points\n", 1022 1053 d->ident); ··· 1025 1054 } 1026 1055 return 0; 1027 1056 } 1028 - static int thermal_nocrt(const struct dmi_system_id *d) { 1057 + 1058 + static int thermal_nocrt(const struct dmi_system_id *d) 1059 + { 1029 1060 pr_notice("%s detected: disabling all critical thermal trip point actions.\n", 1030 1061 d->ident); 1031 1062 crt = -1; 1032 1063 return 0; 1033 1064 } 1034 - static int thermal_tzp(const struct dmi_system_id *d) { 1065 + 1066 + static int thermal_tzp(const struct dmi_system_id *d) 1067 + { 1035 1068 if (tzp == 0) { 1036 1069 pr_notice("%s detected: enabling thermal zone polling\n", 1037 1070 d->ident); ··· 1043 1068 } 1044 1069 return 0; 1045 1070 } 1046 - static int thermal_psv(const struct dmi_system_id *d) { 1071 + 1072 + static int thermal_psv(const struct dmi_system_id *d) 1073 + { 1047 1074 if (psv == 0) { 1048 1075 pr_notice("%s detected: disabling all passive thermal trip points\n", 1049 1076 d->ident);
+4 -4
drivers/thermal/amlogic_thermal.c
··· 291 291 return ret; 292 292 } 293 293 294 - static int amlogic_thermal_remove(struct platform_device *pdev) 294 + static void amlogic_thermal_remove(struct platform_device *pdev) 295 295 { 296 296 struct amlogic_thermal *data = platform_get_drvdata(pdev); 297 297 298 - return amlogic_thermal_disable(data); 298 + amlogic_thermal_disable(data); 299 299 } 300 300 301 301 static int __maybe_unused amlogic_thermal_suspend(struct device *dev) ··· 321 321 .pm = &amlogic_thermal_pm_ops, 322 322 .of_match_table = of_amlogic_thermal_match, 323 323 }, 324 - .probe = amlogic_thermal_probe, 325 - .remove = amlogic_thermal_remove, 324 + .probe = amlogic_thermal_probe, 325 + .remove_new = amlogic_thermal_remove, 326 326 }; 327 327 328 328 module_platform_driver(amlogic_thermal_driver);
+2 -4
drivers/thermal/armada_thermal.c
··· 965 965 return 0; 966 966 } 967 967 968 - static int armada_thermal_exit(struct platform_device *pdev) 968 + static void armada_thermal_exit(struct platform_device *pdev) 969 969 { 970 970 struct armada_drvdata *drvdata = platform_get_drvdata(pdev); 971 971 972 972 if (drvdata->type == LEGACY) 973 973 thermal_zone_device_unregister(drvdata->data.tz); 974 - 975 - return 0; 976 974 } 977 975 978 976 static struct platform_driver armada_thermal_driver = { 979 977 .probe = armada_thermal_probe, 980 - .remove = armada_thermal_exit, 978 + .remove_new = armada_thermal_exit, 981 979 .driver = { 982 980 .name = "armada_thermal", 983 981 .of_match_table = armada_thermal_id_table,
+2 -4
drivers/thermal/broadcom/bcm2835_thermal.c
··· 282 282 return err; 283 283 } 284 284 285 - static int bcm2835_thermal_remove(struct platform_device *pdev) 285 + static void bcm2835_thermal_remove(struct platform_device *pdev) 286 286 { 287 287 struct bcm2835_thermal_data *data = platform_get_drvdata(pdev); 288 288 289 289 debugfs_remove_recursive(data->debugfsdir); 290 290 clk_disable_unprepare(data->clk); 291 - 292 - return 0; 293 291 } 294 292 295 293 static struct platform_driver bcm2835_thermal_driver = { 296 294 .probe = bcm2835_thermal_probe, 297 - .remove = bcm2835_thermal_remove, 295 + .remove_new = bcm2835_thermal_remove, 298 296 .driver = { 299 297 .name = "bcm2835_thermal", 300 298 .of_match_table = bcm2835_thermal_of_match_table,
+2 -4
drivers/thermal/broadcom/ns-thermal.c
··· 65 65 return 0; 66 66 } 67 67 68 - static int ns_thermal_remove(struct platform_device *pdev) 68 + static void ns_thermal_remove(struct platform_device *pdev) 69 69 { 70 70 void __iomem *pvtmon = platform_get_drvdata(pdev); 71 71 72 72 iounmap(pvtmon); 73 - 74 - return 0; 75 73 } 76 74 77 75 static const struct of_device_id ns_thermal_of_match[] = { ··· 80 82 81 83 static struct platform_driver ns_thermal_driver = { 82 84 .probe = ns_thermal_probe, 83 - .remove = ns_thermal_remove, 85 + .remove_new = ns_thermal_remove, 84 86 .driver = { 85 87 .name = "ns-thermal", 86 88 .of_match_table = ns_thermal_of_match,
+2 -3
drivers/thermal/da9062-thermal.c
··· 239 239 return ret; 240 240 } 241 241 242 - static int da9062_thermal_remove(struct platform_device *pdev) 242 + static void da9062_thermal_remove(struct platform_device *pdev) 243 243 { 244 244 struct da9062_thermal *thermal = platform_get_drvdata(pdev); 245 245 246 246 free_irq(thermal->irq, thermal); 247 247 cancel_delayed_work_sync(&thermal->work); 248 248 thermal_zone_device_unregister(thermal->zone); 249 - return 0; 250 249 } 251 250 252 251 static struct platform_driver da9062_thermal_driver = { 253 252 .probe = da9062_thermal_probe, 254 - .remove = da9062_thermal_remove, 253 + .remove_new = da9062_thermal_remove, 255 254 .driver = { 256 255 .name = "da9062-thermal", 257 256 .of_match_table = da9062_compatible_reg_id_table,
+2 -4
drivers/thermal/dove_thermal.c
··· 158 158 return 0; 159 159 } 160 160 161 - static int dove_thermal_exit(struct platform_device *pdev) 161 + static void dove_thermal_exit(struct platform_device *pdev) 162 162 { 163 163 struct thermal_zone_device *dove_thermal = 164 164 platform_get_drvdata(pdev); 165 165 166 166 thermal_zone_device_unregister(dove_thermal); 167 - 168 - return 0; 169 167 } 170 168 171 169 MODULE_DEVICE_TABLE(of, dove_thermal_id_table); 172 170 173 171 static struct platform_driver dove_thermal_driver = { 174 172 .probe = dove_thermal_probe, 175 - .remove = dove_thermal_exit, 173 + .remove_new = dove_thermal_exit, 176 174 .driver = { 177 175 .name = "dove_thermal", 178 176 .of_match_table = dove_thermal_id_table,
+11 -16
drivers/thermal/gov_bang_bang.c
··· 13 13 14 14 #include "thermal_core.h" 15 15 16 - static int thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) 16 + static int thermal_zone_trip_update(struct thermal_zone_device *tz, 17 + const struct thermal_trip *trip) 17 18 { 18 - struct thermal_trip trip; 19 + int trip_index = thermal_zone_trip_id(tz, trip); 19 20 struct thermal_instance *instance; 20 - int ret; 21 21 22 - ret = __thermal_zone_get_trip(tz, trip_id, &trip); 23 - if (ret) { 24 - pr_warn_once("Failed to retrieve trip point %d\n", trip_id); 25 - return ret; 26 - } 27 - 28 - if (!trip.hysteresis) 22 + if (!trip->hysteresis) 29 23 dev_info_once(&tz->device, 30 24 "Zero hysteresis value for thermal zone %s\n", tz->type); 31 25 32 26 dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", 33 - trip_id, trip.temperature, tz->temperature, 34 - trip.hysteresis); 27 + trip_index, trip->temperature, tz->temperature, 28 + trip->hysteresis); 35 29 36 30 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 37 - if (instance->trip != trip_id) 31 + if (instance->trip != trip) 38 32 continue; 39 33 40 34 /* in case fan is in initial state, switch the fan off */ ··· 46 52 * enable fan when temperature exceeds trip_temp and disable 47 53 * the fan in case it falls below trip_temp minus hysteresis 48 54 */ 49 - if (instance->target == 0 && tz->temperature >= trip.temperature) 55 + if (instance->target == 0 && tz->temperature >= trip->temperature) 50 56 instance->target = 1; 51 57 else if (instance->target == 1 && 52 - tz->temperature <= trip.temperature - trip.hysteresis) 58 + tz->temperature <= trip->temperature - trip->hysteresis) 53 59 instance->target = 0; 54 60 55 61 dev_dbg(&instance->cdev->device, "target=%d\n", ··· 90 96 * (trip_temp - hyst) so that the fan gets turned off again. 91 97 * 92 98 */ 93 - static int bang_bang_control(struct thermal_zone_device *tz, int trip) 99 + static int bang_bang_control(struct thermal_zone_device *tz, 100 + const struct thermal_trip *trip) 94 101 { 95 102 struct thermal_instance *instance; 96 103 int ret;
+17 -18
drivers/thermal/gov_fair_share.c
··· 15 15 16 16 #include "thermal_core.h" 17 17 18 - /** 19 - * get_trip_level: - obtains the current trip level for a zone 20 - * @tz: thermal zone device 21 - */ 22 18 static int get_trip_level(struct thermal_zone_device *tz) 23 19 { 24 - struct thermal_trip trip; 25 - int count; 20 + const struct thermal_trip *trip, *level_trip = NULL; 21 + int trip_level; 26 22 27 - for (count = 0; count < tz->num_trips; count++) { 28 - __thermal_zone_get_trip(tz, count, &trip); 29 - if (tz->temperature < trip.temperature) 23 + for_each_trip(tz, trip) { 24 + if (trip->temperature >= tz->temperature) 30 25 break; 26 + 27 + level_trip = trip; 31 28 } 32 29 33 - /* 34 - * count > 0 only if temperature is greater than first trip 35 - * point, in which case, trip_point = count - 1 36 - */ 37 - if (count > 0) 38 - trace_thermal_zone_trip(tz, count - 1, trip.type); 30 + /* Bail out if the temperature is not greater than any trips. */ 31 + if (!level_trip) 32 + return 0; 39 33 40 - return count; 34 + trip_level = thermal_zone_trip_id(tz, level_trip); 35 + 36 + trace_thermal_zone_trip(tz, trip_level, level_trip->type); 37 + 38 + return trip_level; 41 39 } 42 40 43 41 static long get_target_state(struct thermal_zone_device *tz, ··· 47 49 /** 48 50 * fair_share_throttle - throttles devices associated with the given zone 49 51 * @tz: thermal_zone_device 50 - * @trip: trip point index 52 + * @trip: trip point 51 53 * 52 54 * Throttling Logic: This uses three parameters to calculate the new 53 55 * throttle state of the cooling devices associated with the given zone. ··· 63 65 * (Heavily assumes the trip points are in ascending order) 64 66 * new_state of cooling device = P3 * P2 * P1 65 67 */ 66 - static int fair_share_throttle(struct thermal_zone_device *tz, int trip) 68 + static int fair_share_throttle(struct thermal_zone_device *tz, 69 + const struct thermal_trip *trip) 67 70 { 68 71 struct thermal_instance *instance; 69 72 int total_weight = 0;
+48 -72
drivers/thermal/gov_power_allocator.c
··· 16 16 17 17 #include "thermal_core.h" 18 18 19 - #define INVALID_TRIP -1 20 - 21 19 #define FRAC_BITS 10 22 20 #define int_to_frac(x) ((x) << FRAC_BITS) 23 21 #define frac_to_int(x) ((x) >> FRAC_BITS) ··· 53 55 * @err_integral: accumulated error in the PID controller. 54 56 * @prev_err: error in the previous iteration of the PID controller. 55 57 * Used to calculate the derivative term. 58 + * @sustainable_power: Sustainable power (heat) that this thermal zone can 59 + * dissipate 56 60 * @trip_switch_on: first passive trip point of the thermal zone. The 57 61 * governor switches on when this trip point is crossed. 58 62 * If the thermal zone only has one passive trip point, 59 - * @trip_switch_on should be INVALID_TRIP. 63 + * @trip_switch_on should be NULL. 60 64 * @trip_max_desired_temperature: last passive trip point of the thermal 61 65 * zone. The temperature we are 62 66 * controlling for. 63 - * @sustainable_power: Sustainable power (heat) that this thermal zone can 64 - * dissipate 65 67 */ 66 68 struct power_allocator_params { 67 69 bool allocated_tzp; 68 70 s64 err_integral; 69 71 s32 prev_err; 70 - int trip_switch_on; 71 - int trip_max_desired_temperature; 72 72 u32 sustainable_power; 73 + const struct thermal_trip *trip_switch_on; 74 + const struct thermal_trip *trip_max_desired_temperature; 73 75 }; 74 76 75 77 /** ··· 112 114 * estimate_pid_constants() - Estimate the constants for the PID controller 113 115 * @tz: thermal zone for which to estimate the constants 114 116 * @sustainable_power: sustainable power for the thermal zone 115 - * @trip_switch_on: trip point number for the switch on temperature 117 + * @trip_switch_on: trip point for the switch on temperature 116 118 * @control_temp: target temperature for the power allocator governor 117 119 * 118 120 * This function is used to update the estimation of the PID 119 121 * controller constants in struct thermal_zone_parameters. 120 122 */ 121 123 static void estimate_pid_constants(struct thermal_zone_device *tz, 122 - u32 sustainable_power, int trip_switch_on, 124 + u32 sustainable_power, 125 + const struct thermal_trip *trip_switch_on, 123 126 int control_temp) 124 127 { 125 - struct thermal_trip trip; 126 128 u32 temperature_threshold = control_temp; 127 - int ret; 128 129 s32 k_i; 129 130 130 - ret = __thermal_zone_get_trip(tz, trip_switch_on, &trip); 131 - if (!ret) 132 - temperature_threshold -= trip.temperature; 131 + if (trip_switch_on) 132 + temperature_threshold -= trip_switch_on->temperature; 133 133 134 134 /* 135 135 * estimate_pid_constants() tries to find appropriate default ··· 379 383 { 380 384 struct thermal_instance *instance; 381 385 struct power_allocator_params *params = tz->governor_data; 386 + const struct thermal_trip *trip_max_desired_temperature = 387 + params->trip_max_desired_temperature; 382 388 u32 *req_power, *max_power, *granted_power, *extra_actor_power; 383 389 u32 *weighted_req_power; 384 390 u32 total_req_power, max_allocatable_power, total_weighted_req_power; 385 391 u32 total_granted_power, power_range; 386 392 int i, num_actors, total_weight, ret = 0; 387 - int trip_max_desired_temperature = params->trip_max_desired_temperature; 388 393 389 394 num_actors = 0; 390 395 total_weight = 0; ··· 490 493 } 491 494 492 495 /** 493 - * get_governor_trips() - get the number of the two trip points that are key for this governor 496 + * get_governor_trips() - get the two trip points that are key for this governor 494 497 * @tz: thermal zone to operate on 495 498 * @params: pointer to private data for this governor 496 499 * ··· 507 510 static void get_governor_trips(struct thermal_zone_device *tz, 508 511 struct power_allocator_params *params) 509 512 { 510 - int i, last_active, last_passive; 511 - bool found_first_passive; 513 + const struct thermal_trip *first_passive = NULL; 514 + const struct thermal_trip *last_passive = NULL; 515 + const struct thermal_trip *last_active = NULL; 516 + const struct thermal_trip *trip; 512 517 513 - found_first_passive = false; 514 - last_active = INVALID_TRIP; 515 - last_passive = INVALID_TRIP; 516 - 517 - for (i = 0; i < tz->num_trips; i++) { 518 - struct thermal_trip trip; 519 - int ret; 520 - 521 - ret = __thermal_zone_get_trip(tz, i, &trip); 522 - if (ret) { 523 - dev_warn(&tz->device, 524 - "Failed to get trip point %d type: %d\n", i, 525 - ret); 526 - continue; 527 - } 528 - 529 - if (trip.type == THERMAL_TRIP_PASSIVE) { 530 - if (!found_first_passive) { 531 - params->trip_switch_on = i; 532 - found_first_passive = true; 533 - } else { 534 - last_passive = i; 518 + for_each_trip(tz, trip) { 519 + switch (trip->type) { 520 + case THERMAL_TRIP_PASSIVE: 521 + if (!first_passive) { 522 + first_passive = trip; 523 + break; 535 524 } 536 - } else if (trip.type == THERMAL_TRIP_ACTIVE) { 537 - last_active = i; 538 - } else { 525 + last_passive = trip; 526 + break; 527 + case THERMAL_TRIP_ACTIVE: 528 + last_active = trip; 529 + break; 530 + default: 539 531 break; 540 532 } 541 533 } 542 534 543 - if (last_passive != INVALID_TRIP) { 535 + if (last_passive) { 536 + params->trip_switch_on = first_passive; 544 537 params->trip_max_desired_temperature = last_passive; 545 - } else if (found_first_passive) { 546 - params->trip_max_desired_temperature = params->trip_switch_on; 547 - params->trip_switch_on = INVALID_TRIP; 538 + } else if (first_passive) { 539 + params->trip_switch_on = NULL; 540 + params->trip_max_desired_temperature = first_passive; 548 541 } else { 549 - params->trip_switch_on = INVALID_TRIP; 542 + params->trip_switch_on = NULL; 550 543 params->trip_max_desired_temperature = last_active; 551 544 } 552 545 } ··· 556 569 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 557 570 struct thermal_cooling_device *cdev = instance->cdev; 558 571 559 - if ((instance->trip != params->trip_max_desired_temperature) || 572 + if (instance->trip != params->trip_max_desired_temperature || 560 573 (!cdev_is_power_actor(instance->cdev))) 561 574 continue; 562 575 ··· 618 631 { 619 632 int ret; 620 633 struct power_allocator_params *params; 621 - struct thermal_trip trip; 622 634 623 635 ret = check_power_actors(tz); 624 636 if (ret) ··· 642 656 643 657 get_governor_trips(tz, params); 644 658 645 - if (tz->num_trips > 0) { 646 - ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, 647 - &trip); 648 - if (!ret) 649 - estimate_pid_constants(tz, tz->tzp->sustainable_power, 650 - params->trip_switch_on, 651 - trip.temperature); 659 + if (params->trip_max_desired_temperature) { 660 + int temp = params->trip_max_desired_temperature->temperature; 661 + 662 + estimate_pid_constants(tz, tz->tzp->sustainable_power, 663 + params->trip_switch_on, temp); 652 664 } 653 665 654 666 reset_pid_controller(params); ··· 676 692 tz->governor_data = NULL; 677 693 } 678 694 679 - static int power_allocator_throttle(struct thermal_zone_device *tz, int trip_id) 695 + static int power_allocator_throttle(struct thermal_zone_device *tz, 696 + const struct thermal_trip *trip) 680 697 { 681 698 struct power_allocator_params *params = tz->governor_data; 682 - struct thermal_trip trip; 683 - int ret; 684 699 bool update; 685 700 686 701 lockdep_assert_held(&tz->lock); ··· 688 705 * We get called for every trip point but we only need to do 689 706 * our calculations once 690 707 */ 691 - if (trip_id != params->trip_max_desired_temperature) 708 + if (trip != params->trip_max_desired_temperature) 692 709 return 0; 693 710 694 - ret = __thermal_zone_get_trip(tz, params->trip_switch_on, &trip); 695 - if (!ret && (tz->temperature < trip.temperature)) { 696 - update = (tz->last_temperature >= trip.temperature); 711 + trip = params->trip_switch_on; 712 + if (trip && tz->temperature < trip->temperature) { 713 + update = tz->last_temperature >= trip->temperature; 697 714 tz->passive = 0; 698 715 reset_pid_controller(params); 699 716 allow_maximum_power(tz, update); ··· 702 719 703 720 tz->passive = 1; 704 721 705 - ret = __thermal_zone_get_trip(tz, params->trip_max_desired_temperature, &trip); 706 - if (ret) { 707 - dev_warn(&tz->device, "Failed to get the maximum desired temperature: %d\n", 708 - ret); 709 - return ret; 710 - } 711 - 712 - return allocate_power(tz, trip.temperature); 722 + return allocate_power(tz, params->trip_max_desired_temperature->temperature); 713 723 } 714 724 715 725 static struct thermal_governor thermal_gov_power_allocator = {
+21 -29
drivers/thermal/gov_step_wise.c
··· 68 68 return next_target; 69 69 } 70 70 71 - static void update_passive_instance(struct thermal_zone_device *tz, 72 - enum thermal_trip_type type, int value) 71 + static void thermal_zone_trip_update(struct thermal_zone_device *tz, 72 + const struct thermal_trip *trip) 73 73 { 74 - /* 75 - * If value is +1, activate a passive instance. 76 - * If value is -1, deactivate a passive instance. 77 - */ 78 - if (type == THERMAL_TRIP_PASSIVE) 79 - tz->passive += value; 80 - } 81 - 82 - static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip_id) 83 - { 74 + int trip_id = thermal_zone_trip_id(tz, trip); 84 75 enum thermal_trend trend; 85 76 struct thermal_instance *instance; 86 - struct thermal_trip trip; 87 77 bool throttle = false; 88 78 int old_target; 89 79 90 - __thermal_zone_get_trip(tz, trip_id, &trip); 80 + trend = get_tz_trend(tz, trip); 91 81 92 - trend = get_tz_trend(tz, trip_id); 93 - 94 - if (tz->temperature >= trip.temperature) { 82 + if (tz->temperature >= trip->temperature) { 95 83 throttle = true; 96 - trace_thermal_zone_trip(tz, trip_id, trip.type); 84 + trace_thermal_zone_trip(tz, trip_id, trip->type); 97 85 } 98 86 99 87 dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", 100 - trip_id, trip.type, trip.temperature, trend, throttle); 88 + trip_id, trip->type, trip->temperature, trend, throttle); 101 89 102 90 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 103 - if (instance->trip != trip_id) 91 + if (instance->trip != trip) 104 92 continue; 105 93 106 94 old_target = instance->target; ··· 99 111 if (instance->initialized && old_target == instance->target) 100 112 continue; 101 113 102 - /* Activate a passive thermal instance */ 103 114 if (old_target == THERMAL_NO_TARGET && 104 - instance->target != THERMAL_NO_TARGET) 105 - update_passive_instance(tz, trip.type, 1); 106 - /* Deactivate a passive thermal instance */ 107 - else if (old_target != THERMAL_NO_TARGET && 108 - instance->target == THERMAL_NO_TARGET) 109 - update_passive_instance(tz, trip.type, -1); 115 + instance->target != THERMAL_NO_TARGET) { 116 + /* Activate a passive thermal instance */ 117 + if (trip->type == THERMAL_TRIP_PASSIVE) 118 + tz->passive++; 119 + } else if (old_target != THERMAL_NO_TARGET && 120 + instance->target == THERMAL_NO_TARGET) { 121 + /* Deactivate a passive thermal instance */ 122 + if (trip->type == THERMAL_TRIP_PASSIVE) 123 + tz->passive--; 124 + } 110 125 111 126 instance->initialized = true; 112 127 mutex_lock(&instance->cdev->lock); ··· 121 130 /** 122 131 * step_wise_throttle - throttles devices associated with the given zone 123 132 * @tz: thermal_zone_device 124 - * @trip: trip point index 133 + * @trip: trip point 125 134 * 126 135 * Throttling Logic: This uses the trend of the thermal zone to throttle. 127 136 * If the thermal zone is 'heating up' this throttles all the cooling ··· 129 138 * step. If the zone is 'cooling down' it brings back the performance of 130 139 * the devices by one step. 131 140 */ 132 - static int step_wise_throttle(struct thermal_zone_device *tz, int trip) 141 + static int step_wise_throttle(struct thermal_zone_device *tz, 142 + const struct thermal_trip *trip) 133 143 { 134 144 struct thermal_instance *instance; 135 145
+5 -3
drivers/thermal/gov_user_space.c
··· 25 25 /** 26 26 * notify_user_space - Notifies user space about thermal events 27 27 * @tz: thermal_zone_device 28 - * @trip: trip point index 28 + * @trip: trip point 29 29 * 30 30 * This function notifies the user space through UEvents. 31 31 */ 32 - static int notify_user_space(struct thermal_zone_device *tz, int trip) 32 + static int notify_user_space(struct thermal_zone_device *tz, 33 + const struct thermal_trip *trip) 33 34 { 34 35 char *thermal_prop[5]; 35 36 int i; ··· 39 38 40 39 thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", tz->type); 41 40 thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", tz->temperature); 42 - thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", trip); 41 + thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP=%d", 42 + thermal_zone_trip_id(tz, trip)); 43 43 thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", tz->notify_event); 44 44 thermal_prop[4] = NULL; 45 45 kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, thermal_prop);
+2 -4
drivers/thermal/hisi_thermal.c
··· 597 597 return 0; 598 598 } 599 599 600 - static int hisi_thermal_remove(struct platform_device *pdev) 600 + static void hisi_thermal_remove(struct platform_device *pdev) 601 601 { 602 602 struct hisi_thermal_data *data = platform_get_drvdata(pdev); 603 603 int i; ··· 608 608 hisi_thermal_toggle_sensor(sensor, false); 609 609 data->ops->disable_sensor(sensor); 610 610 } 611 - 612 - return 0; 613 611 } 614 612 615 613 static int hisi_thermal_suspend(struct device *dev) ··· 642 644 .of_match_table = of_hisi_thermal_match, 643 645 }, 644 646 .probe = hisi_thermal_probe, 645 - .remove = hisi_thermal_remove, 647 + .remove_new = hisi_thermal_remove, 646 648 }; 647 649 648 650 module_platform_driver(hisi_thermal_driver);
+3 -5
drivers/thermal/imx8mm_thermal.c
··· 78 78 struct thermal_soc_data { 79 79 u32 num_sensors; 80 80 u32 version; 81 - int (*get_temp)(void *, int *); 81 + int (*get_temp)(void *data, int *temp); 82 82 }; 83 83 84 84 struct tmu_sensor { ··· 363 363 return ret; 364 364 } 365 365 366 - static int imx8mm_tmu_remove(struct platform_device *pdev) 366 + static void imx8mm_tmu_remove(struct platform_device *pdev) 367 367 { 368 368 struct imx8mm_tmu *tmu = platform_get_drvdata(pdev); 369 369 ··· 372 372 373 373 clk_disable_unprepare(tmu->clk); 374 374 platform_set_drvdata(pdev, NULL); 375 - 376 - return 0; 377 375 } 378 376 379 377 static struct thermal_soc_data imx8mm_tmu_data = { ··· 399 401 .of_match_table = imx8mm_tmu_table, 400 402 }, 401 403 .probe = imx8mm_tmu_probe, 402 - .remove = imx8mm_tmu_remove, 404 + .remove_new = imx8mm_tmu_remove, 403 405 }; 404 406 module_platform_driver(imx8mm_tmu); 405 407
+2 -4
drivers/thermal/imx_thermal.c
··· 771 771 return ret; 772 772 } 773 773 774 - static int imx_thermal_remove(struct platform_device *pdev) 774 + static void imx_thermal_remove(struct platform_device *pdev) 775 775 { 776 776 struct imx_thermal_data *data = platform_get_drvdata(pdev); 777 777 ··· 780 780 781 781 thermal_zone_device_unregister(data->tz); 782 782 imx_thermal_unregister_legacy_cooling(data); 783 - 784 - return 0; 785 783 } 786 784 787 785 static int __maybe_unused imx_thermal_suspend(struct device *dev) ··· 878 880 .of_match_table = of_imx_thermal_match, 879 881 }, 880 882 .probe = imx_thermal_probe, 881 - .remove = imx_thermal_remove, 883 + .remove_new = imx_thermal_remove, 882 884 }; 883 885 module_platform_driver(imx_thermal); 884 886
+3
drivers/thermal/intel/int340x_thermal/Makefile
··· 10 10 obj-$(CONFIG_PROC_THERMAL_MMIO_RAPL) += processor_thermal_rapl.o 11 11 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_rfim.o 12 12 obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_mbox.o 13 + obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_req.o 14 + obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_wt_hint.o 15 + obj-$(CONFIG_INT340X_THERMAL) += processor_thermal_power_floor.o 13 16 obj-$(CONFIG_INT3406_THERMAL) += int3406_thermal.o 14 17 obj-$(CONFIG_ACPI_THERMAL_REL) += acpi_thermal_rel.o
+2 -3
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
··· 674 674 return result; 675 675 } 676 676 677 - static int int3400_thermal_remove(struct platform_device *pdev) 677 + static void int3400_thermal_remove(struct platform_device *pdev) 678 678 { 679 679 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); 680 680 ··· 698 698 kfree(priv->trts); 699 699 kfree(priv->arts); 700 700 kfree(priv); 701 - return 0; 702 701 } 703 702 704 703 static const struct acpi_device_id int3400_thermal_match[] = { ··· 713 714 714 715 static struct platform_driver int3400_thermal_driver = { 715 716 .probe = int3400_thermal_probe, 716 - .remove = int3400_thermal_remove, 717 + .remove_new = int3400_thermal_remove, 717 718 .driver = { 718 719 .name = "int3400 thermal", 719 720 .acpi_match_table = ACPI_PTR(int3400_thermal_match),
+2 -4
drivers/thermal/intel/int340x_thermal/int3401_thermal.c
··· 36 36 return ret; 37 37 } 38 38 39 - static int int3401_remove(struct platform_device *pdev) 39 + static void int3401_remove(struct platform_device *pdev) 40 40 { 41 41 proc_thermal_remove(platform_get_drvdata(pdev)); 42 - 43 - return 0; 44 42 } 45 43 46 44 #ifdef CONFIG_PM_SLEEP ··· 60 62 61 63 static struct platform_driver int3401_driver = { 62 64 .probe = int3401_add, 63 - .remove = int3401_remove, 65 + .remove_new = int3401_remove, 64 66 .driver = { 65 67 .name = "int3401 thermal", 66 68 .acpi_match_table = int3401_device_ids,
+2 -4
drivers/thermal/intel/int340x_thermal/int3402_thermal.c
··· 71 71 return 0; 72 72 } 73 73 74 - static int int3402_thermal_remove(struct platform_device *pdev) 74 + static void int3402_thermal_remove(struct platform_device *pdev) 75 75 { 76 76 struct int3402_thermal_data *d = platform_get_drvdata(pdev); 77 77 78 78 acpi_remove_notify_handler(d->handle, 79 79 ACPI_DEVICE_NOTIFY, int3402_notify); 80 80 int340x_thermal_zone_remove(d->int340x_zone); 81 - 82 - return 0; 83 81 } 84 82 85 83 static const struct acpi_device_id int3402_thermal_match[] = { ··· 89 91 90 92 static struct platform_driver int3402_thermal_driver = { 91 93 .probe = int3402_thermal_probe, 92 - .remove = int3402_thermal_remove, 94 + .remove_new = int3402_thermal_remove, 93 95 .driver = { 94 96 .name = "int3402 thermal", 95 97 .acpi_match_table = int3402_thermal_match,
+2 -4
drivers/thermal/intel/int340x_thermal/int3403_thermal.c
··· 262 262 return result; 263 263 } 264 264 265 - static int int3403_remove(struct platform_device *pdev) 265 + static void int3403_remove(struct platform_device *pdev) 266 266 { 267 267 struct int3403_priv *priv = platform_get_drvdata(pdev); 268 268 ··· 277 277 default: 278 278 break; 279 279 } 280 - 281 - return 0; 282 280 } 283 281 284 282 static const struct acpi_device_id int3403_device_ids[] = { ··· 291 293 292 294 static struct platform_driver int3403_driver = { 293 295 .probe = int3403_add, 294 - .remove = int3403_remove, 296 + .remove_new = int3403_remove, 295 297 .driver = { 296 298 .name = "int3403 thermal", 297 299 .acpi_match_table = int3403_device_ids,
+2 -3
drivers/thermal/intel/int340x_thermal/int3406_thermal.c
··· 178 178 return -ENODEV; 179 179 } 180 180 181 - static int int3406_thermal_remove(struct platform_device *pdev) 181 + static void int3406_thermal_remove(struct platform_device *pdev) 182 182 { 183 183 struct int3406_thermal_data *d = platform_get_drvdata(pdev); 184 184 185 185 thermal_cooling_device_unregister(d->cooling_dev); 186 186 kfree(d->br); 187 - return 0; 188 187 } 189 188 190 189 static const struct acpi_device_id int3406_thermal_match[] = { ··· 195 196 196 197 static struct platform_driver int3406_thermal_driver = { 197 198 .probe = int3406_thermal_probe, 198 - .remove = int3406_thermal_remove, 199 + .remove_new = int3406_thermal_remove, 199 200 .driver = { 200 201 .name = "int3406 thermal", 201 202 .acpi_match_table = int3406_thermal_match,
+43 -37
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
··· 67 67 .critical = int340x_thermal_critical, 68 68 }; 69 69 70 + static inline void *int_to_trip_priv(int i) 71 + { 72 + return (void *)(long)i; 73 + } 74 + 75 + static inline int trip_priv_to_int(const struct thermal_trip *trip) 76 + { 77 + return (long)trip->priv; 78 + } 79 + 70 80 static int int340x_thermal_read_trips(struct acpi_device *zone_adev, 71 81 struct thermal_trip *zone_trips, 72 82 int trip_cnt) ··· 111 101 break; 112 102 113 103 zone_trips[trip_cnt].type = THERMAL_TRIP_ACTIVE; 104 + zone_trips[trip_cnt].priv = int_to_trip_priv(i); 114 105 trip_cnt++; 115 106 } 116 107 ··· 223 212 } 224 213 EXPORT_SYMBOL_GPL(int340x_thermal_zone_remove); 225 214 215 + static int int340x_update_one_trip(struct thermal_trip *trip, void *arg) 216 + { 217 + struct acpi_device *zone_adev = arg; 218 + int temp, err; 219 + 220 + switch (trip->type) { 221 + case THERMAL_TRIP_CRITICAL: 222 + err = thermal_acpi_critical_trip_temp(zone_adev, &temp); 223 + break; 224 + case THERMAL_TRIP_HOT: 225 + err = thermal_acpi_hot_trip_temp(zone_adev, &temp); 226 + break; 227 + case THERMAL_TRIP_PASSIVE: 228 + err = thermal_acpi_passive_trip_temp(zone_adev, &temp); 229 + break; 230 + case THERMAL_TRIP_ACTIVE: 231 + err = thermal_acpi_active_trip_temp(zone_adev, 232 + trip_priv_to_int(trip), 233 + &temp); 234 + break; 235 + default: 236 + err = -ENODEV; 237 + } 238 + if (err) 239 + temp = THERMAL_TEMP_INVALID; 240 + 241 + trip->temperature = temp; 242 + return 0; 243 + } 244 + 226 245 void int340x_thermal_update_trips(struct int34x_thermal_zone *int34x_zone) 227 246 { 228 - struct acpi_device *zone_adev = int34x_zone->adev; 229 - struct thermal_trip *zone_trips = int34x_zone->trips; 230 - int trip_cnt = int34x_zone->zone->num_trips; 231 - int act_trip_nr = 0; 232 - int i; 233 - 234 - mutex_lock(&int34x_zone->zone->lock); 235 - 236 - for (i = int34x_zone->aux_trip_nr; i < trip_cnt; i++) { 237 - int temp, err; 238 - 239 - switch (zone_trips[i].type) { 240 - case THERMAL_TRIP_CRITICAL: 241 - err = thermal_acpi_critical_trip_temp(zone_adev, &temp); 242 - break; 243 - case THERMAL_TRIP_HOT: 244 - err = thermal_acpi_hot_trip_temp(zone_adev, &temp); 245 - break; 246 - case THERMAL_TRIP_PASSIVE: 247 - err = thermal_acpi_passive_trip_temp(zone_adev, &temp); 248 - break; 249 - case THERMAL_TRIP_ACTIVE: 250 - err = thermal_acpi_active_trip_temp(zone_adev, act_trip_nr++, 251 - &temp); 252 - break; 253 - default: 254 - err = -ENODEV; 255 - } 256 - if (err) { 257 - zone_trips[i].temperature = THERMAL_TEMP_INVALID; 258 - continue; 259 - } 260 - 261 - zone_trips[i].temperature = temp; 262 - } 263 - 264 - mutex_unlock(&int34x_zone->zone->lock); 247 + thermal_zone_for_each_trip(int34x_zone->zone, int340x_update_one_trip, 248 + int34x_zone->adev); 265 249 } 266 250 EXPORT_SYMBOL_GPL(int340x_thermal_update_trips); 267 251
+80 -5
drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
··· 26 26 (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ 27 27 } 28 28 29 + static ssize_t power_floor_status_show(struct device *dev, 30 + struct device_attribute *attr, 31 + char *buf) 32 + { 33 + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 34 + int ret; 35 + 36 + ret = proc_thermal_read_power_floor_status(proc_dev); 37 + 38 + return sysfs_emit(buf, "%d\n", ret); 39 + } 40 + 41 + static ssize_t power_floor_enable_show(struct device *dev, 42 + struct device_attribute *attr, 43 + char *buf) 44 + { 45 + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 46 + bool ret; 47 + 48 + ret = proc_thermal_power_floor_get_state(proc_dev); 49 + 50 + return sysfs_emit(buf, "%d\n", ret); 51 + } 52 + 53 + static ssize_t power_floor_enable_store(struct device *dev, 54 + struct device_attribute *attr, 55 + const char *buf, size_t count) 56 + { 57 + struct proc_thermal_device *proc_dev = dev_get_drvdata(dev); 58 + u8 state; 59 + int ret; 60 + 61 + if (kstrtou8(buf, 0, &state)) 62 + return -EINVAL; 63 + 64 + ret = proc_thermal_power_floor_set_state(proc_dev, !!state); 65 + if (ret) 66 + return ret; 67 + 68 + return count; 69 + } 70 + 29 71 POWER_LIMIT_SHOW(0, min_uw) 30 72 POWER_LIMIT_SHOW(0, max_uw) 31 73 POWER_LIMIT_SHOW(0, step_uw) ··· 92 50 static DEVICE_ATTR_RO(power_limit_1_tmin_us); 93 51 static DEVICE_ATTR_RO(power_limit_1_tmax_us); 94 52 53 + static DEVICE_ATTR_RO(power_floor_status); 54 + static DEVICE_ATTR_RW(power_floor_enable); 55 + 95 56 static struct attribute *power_limit_attrs[] = { 96 57 &dev_attr_power_limit_0_min_uw.attr, 97 58 &dev_attr_power_limit_1_min_uw.attr, ··· 106 61 &dev_attr_power_limit_1_tmin_us.attr, 107 62 &dev_attr_power_limit_0_tmax_us.attr, 108 63 &dev_attr_power_limit_1_tmax_us.attr, 64 + &dev_attr_power_floor_status.attr, 65 + &dev_attr_power_floor_enable.attr, 109 66 NULL 110 67 }; 111 68 69 + static umode_t power_limit_attr_visible(struct kobject *kobj, struct attribute *attr, int unused) 70 + { 71 + struct device *dev = kobj_to_dev(kobj); 72 + struct proc_thermal_device *proc_dev; 73 + 74 + if (attr != &dev_attr_power_floor_status.attr && attr != &dev_attr_power_floor_enable.attr) 75 + return attr->mode; 76 + 77 + proc_dev = dev_get_drvdata(dev); 78 + if (!proc_dev || !(proc_dev->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR)) 79 + return 0; 80 + 81 + return attr->mode; 82 + } 83 + 112 84 static const struct attribute_group power_limit_attribute_group = { 113 85 .attrs = power_limit_attrs, 114 - .name = "power_limits" 86 + .name = "power_limits", 87 + .is_visible = power_limit_attr_visible, 115 88 }; 116 89 117 90 static ssize_t tcc_offset_degree_celsius_show(struct device *dev, ··· 409 346 } 410 347 } 411 348 412 - if (feature_mask & PROC_THERMAL_FEATURE_MBOX) { 413 - ret = proc_thermal_mbox_add(pdev, proc_priv); 349 + if (feature_mask & PROC_THERMAL_FEATURE_WT_REQ) { 350 + ret = proc_thermal_wt_req_add(pdev, proc_priv); 414 351 if (ret) { 415 352 dev_err(&pdev->dev, "failed to add MBOX interface\n"); 353 + goto err_rem_rfim; 354 + } 355 + } else if (feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { 356 + ret = proc_thermal_wt_hint_add(pdev, proc_priv); 357 + if (ret) { 358 + dev_err(&pdev->dev, "failed to add WT Hint\n"); 416 359 goto err_rem_rfim; 417 360 } 418 361 } ··· 443 374 proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_DVFS) 444 375 proc_thermal_rfim_remove(pdev); 445 376 446 - if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_MBOX) 447 - proc_thermal_mbox_remove(pdev); 377 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) 378 + proc_thermal_power_floor_set_state(proc_priv, false); 379 + 380 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_REQ) 381 + proc_thermal_wt_req_remove(pdev); 382 + else if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) 383 + proc_thermal_wt_hint_remove(pdev); 448 384 } 449 385 EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove); 450 386 451 387 MODULE_IMPORT_NS(INTEL_TCC); 388 + MODULE_IMPORT_NS(INT340X_THERMAL); 452 389 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 453 390 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 454 391 MODULE_LICENSE("GPL v2");
+30 -3
drivers/thermal/intel/int340x_thermal/processor_thermal_device.h
··· 10 10 #include <linux/intel_rapl.h> 11 11 12 12 #define PCI_DEVICE_ID_INTEL_ADL_THERMAL 0x461d 13 + #define PCI_DEVICE_ID_INTEL_ARL_S_THERMAL 0xAD03 13 14 #define PCI_DEVICE_ID_INTEL_BDW_THERMAL 0x1603 14 15 #define PCI_DEVICE_ID_INTEL_BSW_THERMAL 0x22DC 15 16 ··· 60 59 #define PROC_THERMAL_FEATURE_RAPL 0x01 61 60 #define PROC_THERMAL_FEATURE_FIVR 0x02 62 61 #define PROC_THERMAL_FEATURE_DVFS 0x04 63 - #define PROC_THERMAL_FEATURE_MBOX 0x08 62 + #define PROC_THERMAL_FEATURE_WT_REQ 0x08 64 63 #define PROC_THERMAL_FEATURE_DLVR 0x10 64 + #define PROC_THERMAL_FEATURE_WT_HINT 0x20 65 + #define PROC_THERMAL_FEATURE_POWER_FLOOR 0x40 65 66 66 67 #if IS_ENABLED(CONFIG_PROC_THERMAL_MMIO_RAPL) 67 68 int proc_thermal_rapl_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); ··· 83 80 int proc_thermal_rfim_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 84 81 void proc_thermal_rfim_remove(struct pci_dev *pdev); 85 82 86 - int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 87 - void proc_thermal_mbox_remove(struct pci_dev *pdev); 83 + int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 84 + void proc_thermal_wt_req_remove(struct pci_dev *pdev); 85 + 86 + #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E 87 + #define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F 88 + 89 + #define MBOX_DATA_BIT_AC_DC 30 90 + #define MBOX_DATA_BIT_VALID 31 91 + 92 + #define SOC_WT_RES_INT_STATUS_OFFSET 0x5B18 93 + #define SOC_WT_RES_INT_STATUS_MASK GENMASK_ULL(3, 2) 94 + 95 + int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv); 96 + int proc_thermal_power_floor_set_state(struct proc_thermal_device *proc_priv, bool enable); 97 + bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv); 98 + void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev, 99 + struct proc_thermal_device *proc_priv); 100 + bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv); 88 101 89 102 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp); 90 103 int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data); 104 + int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, int enable_bit, 105 + int time_window); 91 106 int proc_thermal_add(struct device *dev, struct proc_thermal_device *priv); 92 107 void proc_thermal_remove(struct proc_thermal_device *proc_priv); 108 + 109 + int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 110 + void proc_thermal_wt_hint_remove(struct pci_dev *pdev); 111 + void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv); 112 + bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv); 113 + 93 114 int proc_thermal_suspend(struct device *dev); 94 115 int proc_thermal_resume(struct device *dev); 95 116 int proc_thermal_mmio_add(struct pci_dev *pdev,
+93 -30
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
··· 15 15 16 16 #define DRV_NAME "proc_thermal_pci" 17 17 18 + static bool use_msi; 19 + module_param(use_msi, bool, 0644); 20 + MODULE_PARM_DESC(use_msi, 21 + "Use PCI MSI based interrupts for processor thermal device."); 22 + 18 23 struct proc_thermal_pci { 19 24 struct pci_dev *pdev; 20 25 struct proc_thermal_device *proc_priv; ··· 122 117 schedule_delayed_work(work, ms); 123 118 } 124 119 120 + static void proc_thermal_clear_soc_int_status(struct proc_thermal_device *proc_priv) 121 + { 122 + u64 status; 123 + 124 + if (!(proc_priv->mmio_feature_mask & 125 + (PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR))) 126 + return; 127 + 128 + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 129 + writeq(status & ~SOC_WT_RES_INT_STATUS_MASK, 130 + proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 131 + } 132 + 133 + static irqreturn_t proc_thermal_irq_thread_handler(int irq, void *devid) 134 + { 135 + struct proc_thermal_pci *pci_info = devid; 136 + 137 + proc_thermal_wt_intr_callback(pci_info->pdev, pci_info->proc_priv); 138 + proc_thermal_power_floor_intr_callback(pci_info->pdev, pci_info->proc_priv); 139 + proc_thermal_clear_soc_int_status(pci_info->proc_priv); 140 + 141 + return IRQ_HANDLED; 142 + } 143 + 125 144 static irqreturn_t proc_thermal_irq_handler(int irq, void *devid) 126 145 { 127 146 struct proc_thermal_pci *pci_info = devid; 147 + struct proc_thermal_device *proc_priv; 148 + int ret = IRQ_HANDLED; 128 149 u32 status; 129 150 130 - proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 151 + proc_priv = pci_info->proc_priv; 131 152 132 - /* Disable enable interrupt flag */ 133 - proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 153 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_WT_HINT) { 154 + if (proc_thermal_check_wt_intr(pci_info->proc_priv)) 155 + ret = IRQ_WAKE_THREAD; 156 + } 157 + 158 + if (proc_priv->mmio_feature_mask & PROC_THERMAL_FEATURE_POWER_FLOOR) { 159 + if (proc_thermal_check_power_floor_intr(pci_info->proc_priv)) 160 + ret = IRQ_WAKE_THREAD; 161 + } 162 + 163 + /* 164 + * Since now there are two sources of interrupts: one from thermal threshold 165 + * and another from workload hint, add a check if there was really a threshold 166 + * interrupt before scheduling work function for thermal threshold. 167 + */ 168 + proc_thermal_mmio_read(pci_info, PROC_THERMAL_MMIO_INT_STATUS_0, &status); 169 + if (status) { 170 + /* Disable enable interrupt flag */ 171 + proc_thermal_mmio_write(pci_info, PROC_THERMAL_MMIO_INT_ENABLE_0, 0); 172 + pkg_thermal_schedule_work(&pci_info->work); 173 + } 174 + 134 175 pci_write_config_byte(pci_info->pdev, 0xdc, 0x01); 135 176 136 - pkg_thermal_schedule_work(&pci_info->work); 137 - 138 - return IRQ_HANDLED; 177 + return ret; 139 178 } 140 179 141 180 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) ··· 252 203 struct proc_thermal_device *proc_priv; 253 204 struct proc_thermal_pci *pci_info; 254 205 int irq_flag = 0, irq, ret; 206 + bool msi_irq = false; 255 207 256 208 proc_priv = devm_kzalloc(&pdev->dev, sizeof(*proc_priv), GFP_KERNEL); 257 209 if (!proc_priv) ··· 273 223 274 224 INIT_DELAYED_WORK(&pci_info->work, proc_thermal_threshold_work_fn); 275 225 276 - ret = proc_thermal_add(&pdev->dev, proc_priv); 277 - if (ret) { 278 - dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); 279 - pci_info->no_legacy = 1; 280 - } 281 - 282 226 proc_priv->priv_data = pci_info; 283 227 pci_info->proc_priv = proc_priv; 284 228 pci_set_drvdata(pdev, proc_priv); 285 229 286 230 ret = proc_thermal_mmio_add(pdev, proc_priv, id->driver_data); 287 231 if (ret) 288 - goto err_ret_thermal; 232 + return ret; 233 + 234 + ret = proc_thermal_add(&pdev->dev, proc_priv); 235 + if (ret) { 236 + dev_err(&pdev->dev, "error: proc_thermal_add, will continue\n"); 237 + pci_info->no_legacy = 1; 238 + } 289 239 290 240 psv_trip.temperature = get_trip_temp(pci_info); 291 241 ··· 295 245 &tzone_params, 0, 0); 296 246 if (IS_ERR(pci_info->tzone)) { 297 247 ret = PTR_ERR(pci_info->tzone); 298 - goto err_ret_mmio; 248 + goto err_del_legacy; 299 249 } 300 250 301 - /* request and enable interrupt */ 302 - ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 303 - if (ret < 0) { 304 - dev_err(&pdev->dev, "Failed to allocate vectors!\n"); 305 - goto err_ret_tzone; 306 - } 307 - if (!pdev->msi_enabled && !pdev->msix_enabled) 251 + if (use_msi && (pdev->msi_enabled || pdev->msix_enabled)) { 252 + /* request and enable interrupt */ 253 + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES); 254 + if (ret < 0) { 255 + dev_err(&pdev->dev, "Failed to allocate vectors!\n"); 256 + goto err_ret_tzone; 257 + } 258 + 259 + irq = pci_irq_vector(pdev, 0); 260 + msi_irq = true; 261 + } else { 308 262 irq_flag = IRQF_SHARED; 263 + irq = pdev->irq; 264 + } 309 265 310 - irq = pci_irq_vector(pdev, 0); 311 266 ret = devm_request_threaded_irq(&pdev->dev, irq, 312 - proc_thermal_irq_handler, NULL, 267 + proc_thermal_irq_handler, proc_thermal_irq_thread_handler, 313 268 irq_flag, KBUILD_MODNAME, pci_info); 314 269 if (ret) { 315 270 dev_err(&pdev->dev, "Request IRQ %d failed\n", pdev->irq); ··· 328 273 return 0; 329 274 330 275 err_free_vectors: 331 - pci_free_irq_vectors(pdev); 276 + if (msi_irq) 277 + pci_free_irq_vectors(pdev); 332 278 err_ret_tzone: 333 279 thermal_zone_device_unregister(pci_info->tzone); 334 - err_ret_mmio: 335 - proc_thermal_mmio_remove(pdev, proc_priv); 336 - err_ret_thermal: 280 + err_del_legacy: 337 281 if (!pci_info->no_legacy) 338 282 proc_thermal_remove(proc_priv); 283 + proc_thermal_mmio_remove(pdev, proc_priv); 339 284 pci_disable_device(pdev); 340 285 341 286 return ret; ··· 405 350 proc_thermal_pci_resume); 406 351 407 352 static const struct pci_device_id proc_thermal_pci_ids[] = { 408 - { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 409 - { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX | PROC_THERMAL_FEATURE_DLVR) }, 410 - { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_MBOX) }, 353 + { PCI_DEVICE_DATA(INTEL, ADL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 354 + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 355 + { PCI_DEVICE_DATA(INTEL, MTLP_THERMAL, PROC_THERMAL_FEATURE_RAPL | 356 + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | 357 + PROC_THERMAL_FEATURE_WT_HINT | PROC_THERMAL_FEATURE_POWER_FLOOR) }, 358 + { PCI_DEVICE_DATA(INTEL, ARL_S_THERMAL, PROC_THERMAL_FEATURE_RAPL | 359 + PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_DLVR | PROC_THERMAL_FEATURE_WT_HINT) }, 360 + { PCI_DEVICE_DATA(INTEL, RPL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 361 + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_DVFS | PROC_THERMAL_FEATURE_WT_REQ) }, 411 362 { }, 412 363 }; 413 364 ··· 428 367 }; 429 368 430 369 module_pci_driver(proc_thermal_pci_driver); 370 + 371 + MODULE_IMPORT_NS(INT340X_THERMAL); 431 372 432 373 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 433 374 MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
+2 -1
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c
··· 137 137 { PCI_DEVICE_DATA(INTEL, ICL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 138 138 { PCI_DEVICE_DATA(INTEL, JSL_THERMAL, 0) }, 139 139 { PCI_DEVICE_DATA(INTEL, SKL_THERMAL, PROC_THERMAL_FEATURE_RAPL) }, 140 - { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_MBOX) }, 140 + { PCI_DEVICE_DATA(INTEL, TGL_THERMAL, PROC_THERMAL_FEATURE_RAPL | 141 + PROC_THERMAL_FEATURE_FIVR | PROC_THERMAL_FEATURE_WT_REQ) }, 141 142 { }, 142 143 }; 143 144
+55 -138
drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
··· 10 10 #include <linux/io-64-nonatomic-lo-hi.h> 11 11 #include "processor_thermal_device.h" 12 12 13 - #define MBOX_CMD_WORKLOAD_TYPE_READ 0x0E 14 - #define MBOX_CMD_WORKLOAD_TYPE_WRITE 0x0F 15 - 16 13 #define MBOX_OFFSET_DATA 0x5810 17 14 #define MBOX_OFFSET_INTERFACE 0x5818 18 15 19 16 #define MBOX_BUSY_BIT 31 20 17 #define MBOX_RETRY_COUNT 100 21 - 22 - #define MBOX_DATA_BIT_VALID 31 23 - #define MBOX_DATA_BIT_AC_DC 30 24 18 25 19 static DEFINE_MUTEX(mbox_lock); 26 20 ··· 45 51 int ret; 46 52 47 53 proc_priv = pci_get_drvdata(pdev); 48 - 49 - mutex_lock(&mbox_lock); 50 - 51 54 ret = wait_for_mbox_ready(proc_priv); 52 55 if (ret) 53 - goto unlock_mbox; 56 + return ret; 54 57 55 58 writel(data, (proc_priv->mmio_base + MBOX_OFFSET_DATA)); 56 59 /* Write command register */ 57 60 reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; 58 61 writel(reg_data, (proc_priv->mmio_base + MBOX_OFFSET_INTERFACE)); 59 62 60 - ret = wait_for_mbox_ready(proc_priv); 61 - 62 - unlock_mbox: 63 - mutex_unlock(&mbox_lock); 64 - return ret; 63 + return wait_for_mbox_ready(proc_priv); 65 64 } 66 65 67 66 static int send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) ··· 64 77 int ret; 65 78 66 79 proc_priv = pci_get_drvdata(pdev); 67 - 68 - mutex_lock(&mbox_lock); 69 - 70 80 ret = wait_for_mbox_ready(proc_priv); 71 81 if (ret) 72 - goto unlock_mbox; 82 + return ret; 73 83 74 84 /* Write command register */ 75 85 reg_data = BIT_ULL(MBOX_BUSY_BIT) | id; ··· 74 90 75 91 ret = wait_for_mbox_ready(proc_priv); 76 92 if (ret) 77 - goto unlock_mbox; 93 + return ret; 78 94 79 95 if (id == MBOX_CMD_WORKLOAD_TYPE_READ) 80 96 *resp = readl(proc_priv->mmio_base + MBOX_OFFSET_DATA); 81 97 else 82 98 *resp = readq(proc_priv->mmio_base + MBOX_OFFSET_DATA); 83 99 84 - unlock_mbox: 85 - mutex_unlock(&mbox_lock); 86 - return ret; 100 + return 0; 87 101 } 88 102 89 103 int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp) 90 104 { 91 - return send_mbox_read_cmd(pdev, id, resp); 105 + int ret; 106 + 107 + mutex_lock(&mbox_lock); 108 + ret = send_mbox_read_cmd(pdev, id, resp); 109 + mutex_unlock(&mbox_lock); 110 + 111 + return ret; 92 112 } 93 113 EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL); 94 114 95 115 int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data) 96 116 { 97 - return send_mbox_write_cmd(pdev, id, data); 98 - } 99 - EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); 117 + int ret; 100 118 101 - /* List of workload types */ 102 - static const char * const workload_types[] = { 103 - "none", 104 - "idle", 105 - "semi_active", 106 - "bursty", 107 - "sustained", 108 - "battery_life", 109 - NULL 110 - }; 111 - 112 - static ssize_t workload_available_types_show(struct device *dev, 113 - struct device_attribute *attr, 114 - char *buf) 115 - { 116 - int i = 0; 117 - int ret = 0; 118 - 119 - while (workload_types[i] != NULL) 120 - ret += sprintf(&buf[ret], "%s ", workload_types[i++]); 121 - 122 - ret += sprintf(&buf[ret], "\n"); 119 + mutex_lock(&mbox_lock); 120 + ret = send_mbox_write_cmd(pdev, id, data); 121 + mutex_unlock(&mbox_lock); 123 122 124 123 return ret; 125 124 } 125 + EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL); 126 126 127 - static DEVICE_ATTR_RO(workload_available_types); 127 + #define MBOX_CAMARILLO_RD_INTR_CONFIG 0x1E 128 + #define MBOX_CAMARILLO_WR_INTR_CONFIG 0x1F 129 + #define WLT_TW_MASK GENMASK_ULL(30, 24) 130 + #define SOC_PREDICTION_TW_SHIFT 24 128 131 129 - static ssize_t workload_type_store(struct device *dev, 130 - struct device_attribute *attr, 131 - const char *buf, size_t count) 132 + int processor_thermal_mbox_interrupt_config(struct pci_dev *pdev, bool enable, 133 + int enable_bit, int time_window) 132 134 { 133 - struct pci_dev *pdev = to_pci_dev(dev); 134 - char str_preference[15]; 135 - u32 data = 0; 136 - ssize_t ret; 137 - 138 - ret = sscanf(buf, "%14s", str_preference); 139 - if (ret != 1) 140 - return -EINVAL; 141 - 142 - ret = match_string(workload_types, -1, str_preference); 143 - if (ret < 0) 144 - return ret; 145 - 146 - ret &= 0xff; 147 - 148 - if (ret) 149 - data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); 150 - 151 - data |= ret; 152 - 153 - ret = send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); 154 - if (ret) 155 - return false; 156 - 157 - return count; 158 - } 159 - 160 - static ssize_t workload_type_show(struct device *dev, 161 - struct device_attribute *attr, 162 - char *buf) 163 - { 164 - struct pci_dev *pdev = to_pci_dev(dev); 165 - u64 cmd_resp; 135 + u64 data; 166 136 int ret; 167 137 168 - ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 138 + if (!pdev) 139 + return -ENODEV; 140 + 141 + mutex_lock(&mbox_lock); 142 + 143 + /* Do read modify write for MBOX_CAMARILLO_RD_INTR_CONFIG */ 144 + 145 + ret = send_mbox_read_cmd(pdev, MBOX_CAMARILLO_RD_INTR_CONFIG, &data); 146 + if (ret) { 147 + dev_err(&pdev->dev, "MBOX_CAMARILLO_RD_INTR_CONFIG failed\n"); 148 + goto unlock; 149 + } 150 + 151 + if (time_window >= 0) { 152 + data &= ~WLT_TW_MASK; 153 + 154 + /* Program notification delay */ 155 + data |= ((u64)time_window << SOC_PREDICTION_TW_SHIFT) & WLT_TW_MASK; 156 + } 157 + 158 + if (enable) 159 + data |= BIT(enable_bit); 160 + else 161 + data &= ~BIT(enable_bit); 162 + 163 + ret = send_mbox_write_cmd(pdev, MBOX_CAMARILLO_WR_INTR_CONFIG, data); 169 164 if (ret) 170 - return false; 165 + dev_err(&pdev->dev, "MBOX_CAMARILLO_WR_INTR_CONFIG failed\n"); 171 166 172 - cmd_resp &= 0xff; 167 + unlock: 168 + mutex_unlock(&mbox_lock); 173 169 174 - if (cmd_resp > ARRAY_SIZE(workload_types) - 1) 175 - return -EINVAL; 176 - 177 - return sprintf(buf, "%s\n", workload_types[cmd_resp]); 170 + return ret; 178 171 } 179 - 180 - static DEVICE_ATTR_RW(workload_type); 181 - 182 - static struct attribute *workload_req_attrs[] = { 183 - &dev_attr_workload_available_types.attr, 184 - &dev_attr_workload_type.attr, 185 - NULL 186 - }; 187 - 188 - static const struct attribute_group workload_req_attribute_group = { 189 - .attrs = workload_req_attrs, 190 - .name = "workload_request" 191 - }; 192 - 193 - static bool workload_req_created; 194 - 195 - int proc_thermal_mbox_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 196 - { 197 - u64 cmd_resp; 198 - int ret; 199 - 200 - /* Check if there is a mailbox support, if fails return success */ 201 - ret = send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 202 - if (ret) 203 - return 0; 204 - 205 - ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); 206 - if (ret) 207 - return ret; 208 - 209 - workload_req_created = true; 210 - 211 - return 0; 212 - } 213 - EXPORT_SYMBOL_GPL(proc_thermal_mbox_add); 214 - 215 - void proc_thermal_mbox_remove(struct pci_dev *pdev) 216 - { 217 - if (workload_req_created) 218 - sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); 219 - 220 - workload_req_created = false; 221 - 222 - } 223 - EXPORT_SYMBOL_GPL(proc_thermal_mbox_remove); 172 + EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, INT340X_THERMAL); 224 173 225 174 MODULE_LICENSE("GPL v2");
+126
drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Processor thermal device module for registering and processing 4 + * power floor. When the hardware reduces the power to the minimum 5 + * possible, the power floor is notified via an interrupt. 6 + * 7 + * Operation: 8 + * When user space enables power floor reporting: 9 + * - Use mailbox to: 10 + * Enable processor thermal device interrupt 11 + * 12 + * - Current status of power floor is read from offset 0x5B18 13 + * bit 39. 14 + * 15 + * Two interface functions are provided to call when there is a 16 + * thermal device interrupt: 17 + * - proc_thermal_power_floor_intr(): 18 + * Check if the interrupt is for change in power floor. 19 + * Called from interrupt context. 20 + * 21 + * - proc_thermal_power_floor_intr_callback(): 22 + * Callback for interrupt processing in thread context. This involves 23 + * sending notification to user space that there is a change in the 24 + * power floor status. 25 + * 26 + * Copyright (c) 2023, Intel Corporation. 27 + */ 28 + 29 + #include <linux/pci.h> 30 + #include "processor_thermal_device.h" 31 + 32 + #define SOC_POWER_FLOOR_STATUS BIT(39) 33 + #define SOC_POWER_FLOOR_SHIFT 39 34 + 35 + #define SOC_POWER_FLOOR_INT_ENABLE_BIT 31 36 + #define SOC_POWER_FLOOR_INT_ACTIVE BIT(3) 37 + 38 + int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv) 39 + { 40 + u64 status = 0; 41 + 42 + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 43 + return (status & SOC_POWER_FLOOR_STATUS) >> SOC_POWER_FLOOR_SHIFT; 44 + } 45 + EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, INT340X_THERMAL); 46 + 47 + static bool enable_state; 48 + static DEFINE_MUTEX(pf_lock); 49 + 50 + int proc_thermal_power_floor_set_state(struct proc_thermal_device *proc_priv, bool enable) 51 + { 52 + int ret = 0; 53 + 54 + mutex_lock(&pf_lock); 55 + if (enable_state == enable) 56 + goto pf_unlock; 57 + 58 + /* 59 + * Time window parameter is not applicable to power floor interrupt configuration. 60 + * Hence use -1 for time window. 61 + */ 62 + ret = processor_thermal_mbox_interrupt_config(to_pci_dev(proc_priv->dev), enable, 63 + SOC_POWER_FLOOR_INT_ENABLE_BIT, -1); 64 + if (!ret) 65 + enable_state = enable; 66 + 67 + pf_unlock: 68 + mutex_unlock(&pf_lock); 69 + 70 + return ret; 71 + } 72 + EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, INT340X_THERMAL); 73 + 74 + bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv) 75 + { 76 + return enable_state; 77 + } 78 + EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, INT340X_THERMAL); 79 + 80 + /** 81 + * proc_thermal_check_power_floor_intr() - Check power floor interrupt. 82 + * @proc_priv: Processor thermal device instance. 83 + * 84 + * Callback to check if the interrupt for power floor is active. 85 + * 86 + * Context: Called from interrupt context. 87 + * 88 + * Return: true if power floor is active, false when not active. 89 + */ 90 + bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv) 91 + { 92 + u64 int_status; 93 + 94 + int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 95 + return !!(int_status & SOC_POWER_FLOOR_INT_ACTIVE); 96 + } 97 + EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, INT340X_THERMAL); 98 + 99 + /** 100 + * proc_thermal_power_floor_intr_callback() - Process power floor notification 101 + * @pdev: PCI device instance 102 + * @proc_priv: Processor thermal device instance. 103 + * 104 + * Check if the power floor interrupt is active, if active send notification to 105 + * user space for the attribute "power_limits", so that user can read the attribute 106 + * and take action. 107 + * 108 + * Context: Called from interrupt thread context. 109 + * 110 + * Return: None. 111 + */ 112 + void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev, 113 + struct proc_thermal_device *proc_priv) 114 + { 115 + u64 status; 116 + 117 + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 118 + if (!(status & SOC_POWER_FLOOR_INT_ACTIVE)) 119 + return; 120 + 121 + sysfs_notify(&pdev->dev.kobj, "power_limits", "power_floor_status"); 122 + } 123 + EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, INT340X_THERMAL); 124 + 125 + MODULE_IMPORT_NS(INT340X_THERMAL); 126 + MODULE_LICENSE("GPL");
+255
drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device interface for reading workload type hints 4 + * from the user space. The hints are provided by the firmware. 5 + * 6 + * Operation: 7 + * When user space enables workload type prediction: 8 + * - Use mailbox to: 9 + * Configure notification delay 10 + * Enable processor thermal device interrupt 11 + * 12 + * - The predicted workload type can be read from MMIO: 13 + * Offset 0x5B18 shows if there was an interrupt 14 + * active for change in workload type and also 15 + * predicted workload type. 16 + * 17 + * Two interface functions are provided to call when there is a 18 + * thermal device interrupt: 19 + * - proc_thermal_check_wt_intr(): 20 + * Check if the interrupt is for change in workload type. Called from 21 + * interrupt context. 22 + * 23 + * - proc_thermal_wt_intr_callback(): 24 + * Callback for interrupt processing in thread context. This involves 25 + * sending notification to user space that there is a change in the 26 + * workload type. 27 + * 28 + * Copyright (c) 2023, Intel Corporation. 29 + */ 30 + 31 + #include <linux/bitfield.h> 32 + #include <linux/pci.h> 33 + #include "processor_thermal_device.h" 34 + 35 + #define SOC_WT GENMASK_ULL(47, 40) 36 + 37 + #define SOC_WT_PREDICTION_INT_ENABLE_BIT 23 38 + 39 + #define SOC_WT_PREDICTION_INT_ACTIVE BIT(2) 40 + 41 + /* 42 + * Closest possible to 1 Second is 1024 ms with programmed time delay 43 + * of 0x0A. 44 + */ 45 + static u8 notify_delay = 0x0A; 46 + static u16 notify_delay_ms = 1024; 47 + 48 + static DEFINE_MUTEX(wt_lock); 49 + static u8 wt_enable; 50 + 51 + /* Show current predicted workload type index */ 52 + static ssize_t workload_type_index_show(struct device *dev, 53 + struct device_attribute *attr, 54 + char *buf) 55 + { 56 + struct proc_thermal_device *proc_priv; 57 + struct pci_dev *pdev = to_pci_dev(dev); 58 + u64 status = 0; 59 + int wt; 60 + 61 + mutex_lock(&wt_lock); 62 + if (!wt_enable) { 63 + mutex_unlock(&wt_lock); 64 + return -ENODATA; 65 + } 66 + 67 + proc_priv = pci_get_drvdata(pdev); 68 + 69 + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 70 + 71 + mutex_unlock(&wt_lock); 72 + 73 + wt = FIELD_GET(SOC_WT, status); 74 + 75 + return sysfs_emit(buf, "%d\n", wt); 76 + } 77 + 78 + static DEVICE_ATTR_RO(workload_type_index); 79 + 80 + static ssize_t workload_hint_enable_show(struct device *dev, 81 + struct device_attribute *attr, 82 + char *buf) 83 + { 84 + return sysfs_emit(buf, "%d\n", wt_enable); 85 + } 86 + 87 + static ssize_t workload_hint_enable_store(struct device *dev, 88 + struct device_attribute *attr, 89 + const char *buf, size_t size) 90 + { 91 + struct pci_dev *pdev = to_pci_dev(dev); 92 + u8 mode; 93 + int ret; 94 + 95 + if (kstrtou8(buf, 10, &mode) || mode > 1) 96 + return -EINVAL; 97 + 98 + mutex_lock(&wt_lock); 99 + 100 + if (mode) 101 + ret = processor_thermal_mbox_interrupt_config(pdev, true, 102 + SOC_WT_PREDICTION_INT_ENABLE_BIT, 103 + notify_delay); 104 + else 105 + ret = processor_thermal_mbox_interrupt_config(pdev, false, 106 + SOC_WT_PREDICTION_INT_ENABLE_BIT, 0); 107 + 108 + if (ret) 109 + goto ret_enable_store; 110 + 111 + ret = size; 112 + wt_enable = mode; 113 + 114 + ret_enable_store: 115 + mutex_unlock(&wt_lock); 116 + 117 + return ret; 118 + } 119 + 120 + static DEVICE_ATTR_RW(workload_hint_enable); 121 + 122 + static ssize_t notification_delay_ms_show(struct device *dev, 123 + struct device_attribute *attr, 124 + char *buf) 125 + { 126 + return sysfs_emit(buf, "%u\n", notify_delay_ms); 127 + } 128 + 129 + static ssize_t notification_delay_ms_store(struct device *dev, 130 + struct device_attribute *attr, 131 + const char *buf, size_t size) 132 + { 133 + struct pci_dev *pdev = to_pci_dev(dev); 134 + u16 new_tw; 135 + int ret; 136 + u8 tm; 137 + 138 + /* 139 + * Time window register value: 140 + * Formula: (1 + x/4) * power(2,y) 141 + * x = 2 msbs, that is [30:29] y = 5 [28:24] 142 + * in INTR_CONFIG register. 143 + * The result will be in milli seconds. 144 + * Here, just keep x = 0, and just change y. 145 + * First round up the user value to power of 2 and 146 + * then take log2, to get "y" value to program. 147 + */ 148 + ret = kstrtou16(buf, 10, &new_tw); 149 + if (ret) 150 + return ret; 151 + 152 + if (!new_tw) 153 + return -EINVAL; 154 + 155 + new_tw = roundup_pow_of_two(new_tw); 156 + tm = ilog2(new_tw); 157 + if (tm > 31) 158 + return -EINVAL; 159 + 160 + mutex_lock(&wt_lock); 161 + 162 + /* If the workload hint was already enabled, then update with the new delay */ 163 + if (wt_enable) 164 + ret = processor_thermal_mbox_interrupt_config(pdev, true, 165 + SOC_WT_PREDICTION_INT_ENABLE_BIT, 166 + tm); 167 + 168 + if (!ret) { 169 + ret = size; 170 + notify_delay = tm; 171 + notify_delay_ms = new_tw; 172 + } 173 + 174 + mutex_unlock(&wt_lock); 175 + 176 + return ret; 177 + } 178 + 179 + static DEVICE_ATTR_RW(notification_delay_ms); 180 + 181 + static struct attribute *workload_hint_attrs[] = { 182 + &dev_attr_workload_type_index.attr, 183 + &dev_attr_workload_hint_enable.attr, 184 + &dev_attr_notification_delay_ms.attr, 185 + NULL 186 + }; 187 + 188 + static const struct attribute_group workload_hint_attribute_group = { 189 + .attrs = workload_hint_attrs, 190 + .name = "workload_hint" 191 + }; 192 + 193 + /* 194 + * Callback to check if the interrupt for prediction is active. 195 + * Caution: Called from the interrupt context. 196 + */ 197 + bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv) 198 + { 199 + u64 int_status; 200 + 201 + int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 202 + if (int_status & SOC_WT_PREDICTION_INT_ACTIVE) 203 + return true; 204 + 205 + return false; 206 + } 207 + EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, INT340X_THERMAL); 208 + 209 + /* Callback to notify user space */ 210 + void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 211 + { 212 + u64 status; 213 + 214 + status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET); 215 + if (!(status & SOC_WT_PREDICTION_INT_ACTIVE)) 216 + return; 217 + 218 + sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index"); 219 + } 220 + EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL); 221 + 222 + static bool workload_hint_created; 223 + 224 + int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 225 + { 226 + int ret; 227 + 228 + ret = sysfs_create_group(&pdev->dev.kobj, &workload_hint_attribute_group); 229 + if (ret) 230 + return ret; 231 + 232 + workload_hint_created = true; 233 + 234 + return 0; 235 + } 236 + EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, INT340X_THERMAL); 237 + 238 + void proc_thermal_wt_hint_remove(struct pci_dev *pdev) 239 + { 240 + mutex_lock(&wt_lock); 241 + if (wt_enable) 242 + processor_thermal_mbox_interrupt_config(pdev, false, 243 + SOC_WT_PREDICTION_INT_ENABLE_BIT, 244 + 0); 245 + mutex_unlock(&wt_lock); 246 + 247 + if (workload_hint_created) 248 + sysfs_remove_group(&pdev->dev.kobj, &workload_hint_attribute_group); 249 + 250 + workload_hint_created = false; 251 + } 252 + EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, INT340X_THERMAL); 253 + 254 + MODULE_IMPORT_NS(INT340X_THERMAL); 255 + MODULE_LICENSE("GPL");
+136
drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * processor thermal device for Workload type hints 4 + * update from user space 5 + * 6 + * Copyright (c) 2020-2023, Intel Corporation. 7 + */ 8 + 9 + #include <linux/pci.h> 10 + #include "processor_thermal_device.h" 11 + 12 + /* List of workload types */ 13 + static const char * const workload_types[] = { 14 + "none", 15 + "idle", 16 + "semi_active", 17 + "bursty", 18 + "sustained", 19 + "battery_life", 20 + NULL 21 + }; 22 + 23 + static ssize_t workload_available_types_show(struct device *dev, 24 + struct device_attribute *attr, 25 + char *buf) 26 + { 27 + int i = 0; 28 + int ret = 0; 29 + 30 + while (workload_types[i] != NULL) 31 + ret += sprintf(&buf[ret], "%s ", workload_types[i++]); 32 + 33 + ret += sprintf(&buf[ret], "\n"); 34 + 35 + return ret; 36 + } 37 + 38 + static DEVICE_ATTR_RO(workload_available_types); 39 + 40 + static ssize_t workload_type_store(struct device *dev, 41 + struct device_attribute *attr, 42 + const char *buf, size_t count) 43 + { 44 + struct pci_dev *pdev = to_pci_dev(dev); 45 + char str_preference[15]; 46 + u32 data = 0; 47 + ssize_t ret; 48 + 49 + ret = sscanf(buf, "%14s", str_preference); 50 + if (ret != 1) 51 + return -EINVAL; 52 + 53 + ret = match_string(workload_types, -1, str_preference); 54 + if (ret < 0) 55 + return ret; 56 + 57 + ret &= 0xff; 58 + 59 + if (ret) 60 + data = BIT(MBOX_DATA_BIT_VALID) | BIT(MBOX_DATA_BIT_AC_DC); 61 + 62 + data |= ret; 63 + 64 + ret = processor_thermal_send_mbox_write_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_WRITE, data); 65 + if (ret) 66 + return false; 67 + 68 + return count; 69 + } 70 + 71 + static ssize_t workload_type_show(struct device *dev, 72 + struct device_attribute *attr, 73 + char *buf) 74 + { 75 + struct pci_dev *pdev = to_pci_dev(dev); 76 + u64 cmd_resp; 77 + int ret; 78 + 79 + ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 80 + if (ret) 81 + return false; 82 + 83 + cmd_resp &= 0xff; 84 + 85 + if (cmd_resp > ARRAY_SIZE(workload_types) - 1) 86 + return -EINVAL; 87 + 88 + return sprintf(buf, "%s\n", workload_types[cmd_resp]); 89 + } 90 + 91 + static DEVICE_ATTR_RW(workload_type); 92 + 93 + static struct attribute *workload_req_attrs[] = { 94 + &dev_attr_workload_available_types.attr, 95 + &dev_attr_workload_type.attr, 96 + NULL 97 + }; 98 + 99 + static const struct attribute_group workload_req_attribute_group = { 100 + .attrs = workload_req_attrs, 101 + .name = "workload_request" 102 + }; 103 + 104 + static bool workload_req_created; 105 + 106 + int proc_thermal_wt_req_add(struct pci_dev *pdev, struct proc_thermal_device *proc_priv) 107 + { 108 + u64 cmd_resp; 109 + int ret; 110 + 111 + /* Check if there is a mailbox support, if fails return success */ 112 + ret = processor_thermal_send_mbox_read_cmd(pdev, MBOX_CMD_WORKLOAD_TYPE_READ, &cmd_resp); 113 + if (ret) 114 + return 0; 115 + 116 + ret = sysfs_create_group(&pdev->dev.kobj, &workload_req_attribute_group); 117 + if (ret) 118 + return ret; 119 + 120 + workload_req_created = true; 121 + 122 + return 0; 123 + } 124 + EXPORT_SYMBOL_GPL(proc_thermal_wt_req_add); 125 + 126 + void proc_thermal_wt_req_remove(struct pci_dev *pdev) 127 + { 128 + if (workload_req_created) 129 + sysfs_remove_group(&pdev->dev.kobj, &workload_req_attribute_group); 130 + 131 + workload_req_created = false; 132 + } 133 + EXPORT_SYMBOL_GPL(proc_thermal_wt_req_remove); 134 + 135 + MODULE_IMPORT_NS(INT340X_THERMAL); 136 + MODULE_LICENSE("GPL");
+1 -1
drivers/thermal/intel/intel_powerclamp.c
··· 256 256 257 257 static const struct kernel_param_ops max_idle_ops = { 258 258 .set = max_idle_set, 259 - .get = param_get_int, 259 + .get = param_get_byte, 260 260 }; 261 261 262 262 module_param_cb(max_idle, &max_idle_ops, &max_idle, 0644);
+2 -4
drivers/thermal/k3_bandgap.c
··· 235 235 return ret; 236 236 } 237 237 238 - static int k3_bandgap_remove(struct platform_device *pdev) 238 + static void k3_bandgap_remove(struct platform_device *pdev) 239 239 { 240 240 pm_runtime_put_sync(&pdev->dev); 241 241 pm_runtime_disable(&pdev->dev); 242 - 243 - return 0; 244 242 } 245 243 246 244 static const struct of_device_id of_k3_bandgap_match[] = { ··· 251 253 252 254 static struct platform_driver k3_bandgap_sensor_driver = { 253 255 .probe = k3_bandgap_probe, 254 - .remove = k3_bandgap_remove, 256 + .remove_new = k3_bandgap_remove, 255 257 .driver = { 256 258 .name = "k3-soc-thermal", 257 259 .of_match_table = of_k3_bandgap_match,
+2 -4
drivers/thermal/k3_j72xx_bandgap.c
··· 521 521 return ret; 522 522 } 523 523 524 - static int k3_j72xx_bandgap_remove(struct platform_device *pdev) 524 + static void k3_j72xx_bandgap_remove(struct platform_device *pdev) 525 525 { 526 526 pm_runtime_put_sync(&pdev->dev); 527 527 pm_runtime_disable(&pdev->dev); 528 - 529 - return 0; 530 528 } 531 529 532 530 static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = { ··· 550 552 551 553 static struct platform_driver k3_j72xx_bandgap_sensor_driver = { 552 554 .probe = k3_j72xx_bandgap_probe, 553 - .remove = k3_j72xx_bandgap_remove, 555 + .remove_new = k3_j72xx_bandgap_remove, 554 556 .driver = { 555 557 .name = "k3-j72xx-soc-thermal", 556 558 .of_match_table = of_k3_j72xx_bandgap_match,
+2 -4
drivers/thermal/kirkwood_thermal.c
··· 90 90 return 0; 91 91 } 92 92 93 - static int kirkwood_thermal_exit(struct platform_device *pdev) 93 + static void kirkwood_thermal_exit(struct platform_device *pdev) 94 94 { 95 95 struct thermal_zone_device *kirkwood_thermal = 96 96 platform_get_drvdata(pdev); 97 97 98 98 thermal_zone_device_unregister(kirkwood_thermal); 99 - 100 - return 0; 101 99 } 102 100 103 101 MODULE_DEVICE_TABLE(of, kirkwood_thermal_id_table); 104 102 105 103 static struct platform_driver kirkwood_thermal_driver = { 106 104 .probe = kirkwood_thermal_probe, 107 - .remove = kirkwood_thermal_exit, 105 + .remove_new = kirkwood_thermal_exit, 108 106 .driver = { 109 107 .name = "kirkwood_thermal", 110 108 .of_match_table = kirkwood_thermal_id_table,
+2 -6
drivers/thermal/max77620_thermal.c
··· 114 114 115 115 mtherm->tz_device = devm_thermal_of_zone_register(&pdev->dev, 0, 116 116 mtherm, &max77620_thermal_ops); 117 - if (IS_ERR(mtherm->tz_device)) { 118 - ret = PTR_ERR(mtherm->tz_device); 119 - dev_err(&pdev->dev, "Failed to register thermal zone: %d\n", 120 - ret); 121 - return ret; 122 - } 117 + if (IS_ERR(mtherm->tz_device)) 118 + return PTR_ERR(mtherm->tz_device); 123 119 124 120 ret = devm_request_threaded_irq(&pdev->dev, mtherm->irq_tjalarm1, NULL, 125 121 max77620_thermal_irq,
+1 -1
drivers/thermal/mediatek/auxadc_thermal.c
··· 1267 1267 1268 1268 mtk_thermal_turn_on_buffer(mt, apmixed_base); 1269 1269 1270 - if (mt->conf->version != MTK_THERMAL_V2) 1270 + if (mt->conf->version != MTK_THERMAL_V1) 1271 1271 mtk_thermal_release_periodic_ts(mt, auxadc_base); 1272 1272 1273 1273 if (mt->conf->version == MTK_THERMAL_V1)
+234 -22
drivers/thermal/mediatek/lvts_thermal.c
··· 80 80 #define LVTS_SENSOR_MAX 4 81 81 #define LVTS_GOLDEN_TEMP_MAX 62 82 82 #define LVTS_GOLDEN_TEMP_DEFAULT 50 83 - #define LVTS_COEFF_A -250460 84 - #define LVTS_COEFF_B 250460 83 + #define LVTS_COEFF_A_MT8195 -250460 84 + #define LVTS_COEFF_B_MT8195 250460 85 + #define LVTS_COEFF_A_MT7988 -204650 86 + #define LVTS_COEFF_B_MT7988 204650 85 87 86 88 #define LVTS_MSR_IMMEDIATE_MODE 0 87 89 #define LVTS_MSR_FILTERED_MODE 1 ··· 91 89 #define LVTS_MSR_READ_TIMEOUT_US 400 92 90 #define LVTS_MSR_READ_WAIT_US (LVTS_MSR_READ_TIMEOUT_US / 2) 93 91 92 + #define LVTS_HW_SHUTDOWN_MT7988 105000 93 + #define LVTS_HW_SHUTDOWN_MT8192 105000 94 94 #define LVTS_HW_SHUTDOWN_MT8195 105000 95 95 96 96 #define LVTS_MINIMUM_THRESHOLD 20000 97 97 98 98 static int golden_temp = LVTS_GOLDEN_TEMP_DEFAULT; 99 - static int coeff_b = LVTS_COEFF_B; 99 + static int golden_temp_offset; 100 100 101 101 struct lvts_sensor_data { 102 102 int dt_id; ··· 116 112 struct lvts_data { 117 113 const struct lvts_ctrl_data *lvts_ctrl; 118 114 int num_lvts_ctrl; 115 + int temp_factor; 116 + int temp_offset; 119 117 }; 120 118 121 119 struct lvts_sensor { ··· 132 126 133 127 struct lvts_ctrl { 134 128 struct lvts_sensor sensors[LVTS_SENSOR_MAX]; 129 + const struct lvts_data *lvts_data; 135 130 u32 calibration[LVTS_SENSOR_MAX]; 136 131 u32 hw_tshut_raw_temp; 137 132 int num_lvts_sensor; ··· 220 213 221 214 sprintf(name, "controller%d", i); 222 215 dentry = debugfs_create_dir(name, lvts_td->dom_dentry); 223 - if (!dentry) 216 + if (IS_ERR(dentry)) 224 217 continue; 225 218 226 219 regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL); ··· 254 247 255 248 #endif 256 249 257 - static int lvts_raw_to_temp(u32 raw_temp) 250 + static int lvts_raw_to_temp(u32 raw_temp, int temp_factor) 258 251 { 259 252 int temperature; 260 253 261 - temperature = ((s64)(raw_temp & 0xFFFF) * LVTS_COEFF_A) >> 14; 262 - temperature += coeff_b; 254 + temperature = ((s64)(raw_temp & 0xFFFF) * temp_factor) >> 14; 255 + temperature += golden_temp_offset; 263 256 264 257 return temperature; 265 258 } 266 259 267 - static u32 lvts_temp_to_raw(int temperature) 260 + static u32 lvts_temp_to_raw(int temperature, int temp_factor) 268 261 { 269 - u32 raw_temp = ((s64)(coeff_b - temperature)) << 14; 262 + u32 raw_temp = ((s64)(golden_temp_offset - temperature)) << 14; 270 263 271 - raw_temp = div_s64(raw_temp, -LVTS_COEFF_A); 264 + raw_temp = div_s64(raw_temp, -temp_factor); 272 265 273 266 return raw_temp; 274 267 } ··· 276 269 static int lvts_get_temp(struct thermal_zone_device *tz, int *temp) 277 270 { 278 271 struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); 272 + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, 273 + sensors[lvts_sensor->id]); 274 + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; 279 275 void __iomem *msr = lvts_sensor->msr; 280 276 u32 value; 281 277 int rc; ··· 311 301 if (rc) 312 302 return -EAGAIN; 313 303 314 - *temp = lvts_raw_to_temp(value & 0xFFFF); 304 + *temp = lvts_raw_to_temp(value & 0xFFFF, lvts_data->temp_factor); 315 305 316 306 return 0; 317 307 } ··· 358 348 static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high) 359 349 { 360 350 struct lvts_sensor *lvts_sensor = thermal_zone_device_priv(tz); 361 - struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, sensors[lvts_sensor->id]); 351 + struct lvts_ctrl *lvts_ctrl = container_of(lvts_sensor, struct lvts_ctrl, 352 + sensors[lvts_sensor->id]); 353 + const struct lvts_data *lvts_data = lvts_ctrl->lvts_data; 362 354 void __iomem *base = lvts_sensor->base; 363 - u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD); 364 - u32 raw_high = lvts_temp_to_raw(high); 355 + u32 raw_low = lvts_temp_to_raw(low != -INT_MAX ? low : LVTS_MINIMUM_THRESHOLD, 356 + lvts_data->temp_factor); 357 + u32 raw_high = lvts_temp_to_raw(high, lvts_data->temp_factor); 365 358 bool should_update_thresh; 366 359 367 360 lvts_sensor->low_thresh = low; ··· 616 603 * The efuse blob values follows the sensor enumeration per thermal 617 604 * controller. The decoding of the stream is as follow: 618 605 * 619 - * stream index map for MCU Domain : 606 + * MT8192 : 607 + * Stream index map for MCU Domain mt8192 : 608 + * 609 + * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> 610 + * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 | 0x0A | 0x0B 611 + * 612 + * <-----sensor#2-----> <-----sensor#3-----> 613 + * 0x0C | 0x0D | 0x0E | 0x0F | 0x10 | 0x11 | 0x12 | 0x13 614 + * 615 + * <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> 616 + * 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 | 0x22 | 0x23 617 + * 618 + * Stream index map for AP Domain mt8192 : 619 + * 620 + * <-----sensor#0-----> <-----sensor#1-----> 621 + * 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B 622 + * 623 + * <-----sensor#2-----> <-----sensor#3-----> 624 + * 0x2C | 0x2D | 0x2E | 0x2F | 0x30 | 0x31 | 0x32 | 0x33 625 + * 626 + * <-----sensor#4-----> <-----sensor#5-----> 627 + * 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B 628 + * 629 + * <-----sensor#6-----> <-----sensor#7-----> <-----sensor#8-----> 630 + * 0x3C | 0x3D | 0x3E | 0x3F | 0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 631 + * 632 + * MT8195 : 633 + * Stream index map for MCU Domain mt8195 : 620 634 * 621 635 * <-----mcu-tc#0-----> <-----sensor#0-----> <-----sensor#1-----> 622 636 * 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 | 0x08 | 0x09 ··· 654 614 * <-----mcu-tc#2-----> <-----sensor#4-----> <-----sensor#5-----> <-----sensor#6-----> <-----sensor#7-----> 655 615 * 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C | 0x1D | 0x1E | 0x1F | 0x20 | 0x21 656 616 * 657 - * stream index map for AP Domain : 617 + * Stream index map for AP Domain mt8195 : 658 618 * 659 619 * <-----ap--tc#0-----> <-----sensor#0-----> <-----sensor#1-----> 660 620 * 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A ··· 732 692 return 0; 733 693 } 734 694 735 - static int lvts_golden_temp_init(struct device *dev, u32 *value) 695 + static int lvts_golden_temp_init(struct device *dev, u32 *value, int temp_offset) 736 696 { 737 697 u32 gt; 738 698 ··· 741 701 if (gt && gt < LVTS_GOLDEN_TEMP_MAX) 742 702 golden_temp = gt; 743 703 744 - coeff_b = golden_temp * 500 + LVTS_COEFF_B; 704 + golden_temp_offset = golden_temp * 500 + temp_offset; 745 705 746 706 return 0; 747 707 } ··· 764 724 * The golden temp information is contained in the first chunk 765 725 * of efuse data. 766 726 */ 767 - ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib); 727 + ret = lvts_golden_temp_init(dev, (u32 *)lvts_td->calib, lvts_data->temp_offset); 768 728 if (ret) 769 729 return ret; 770 730 ··· 775 735 for (i = 0; i < lvts_data->num_lvts_ctrl; i++) { 776 736 777 737 lvts_ctrl[i].base = lvts_td->base + lvts_data->lvts_ctrl[i].offset; 738 + lvts_ctrl[i].lvts_data = lvts_data; 778 739 779 740 ret = lvts_sensor_init(dev, &lvts_ctrl[i], 780 741 &lvts_data->lvts_ctrl[i]); ··· 799 758 * after initializing the calibration. 800 759 */ 801 760 lvts_ctrl[i].hw_tshut_raw_temp = 802 - lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp); 761 + lvts_temp_to_raw(lvts_data->lvts_ctrl[i].hw_tshut_temp, 762 + lvts_data->temp_factor); 803 763 804 764 lvts_ctrl[i].low_thresh = INT_MIN; 805 765 lvts_ctrl[i].high_thresh = INT_MIN; ··· 1265 1223 if (irq < 0) 1266 1224 return irq; 1267 1225 1226 + golden_temp_offset = lvts_data->temp_offset; 1227 + 1268 1228 ret = lvts_domain_init(dev, lvts_td, lvts_data); 1269 1229 if (ret) 1270 1230 return dev_err_probe(dev, ret, "Failed to initialize the lvts domain\n"); ··· 1285 1241 return 0; 1286 1242 } 1287 1243 1288 - static int lvts_remove(struct platform_device *pdev) 1244 + static void lvts_remove(struct platform_device *pdev) 1289 1245 { 1290 1246 struct lvts_domain *lvts_td; 1291 1247 int i; ··· 1296 1252 lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); 1297 1253 1298 1254 lvts_debugfs_exit(lvts_td); 1255 + } 1256 + 1257 + static const struct lvts_ctrl_data mt7988_lvts_ap_data_ctrl[] = { 1258 + { 1259 + .cal_offset = { 0x00, 0x04, 0x08, 0x0c }, 1260 + .lvts_sensor = { 1261 + { .dt_id = MT7988_CPU_0 }, 1262 + { .dt_id = MT7988_CPU_1 }, 1263 + { .dt_id = MT7988_ETH2P5G_0 }, 1264 + { .dt_id = MT7988_ETH2P5G_1 } 1265 + }, 1266 + .num_lvts_sensor = 4, 1267 + .offset = 0x0, 1268 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, 1269 + }, 1270 + { 1271 + .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, 1272 + .lvts_sensor = { 1273 + { .dt_id = MT7988_TOPS_0}, 1274 + { .dt_id = MT7988_TOPS_1}, 1275 + { .dt_id = MT7988_ETHWARP_0}, 1276 + { .dt_id = MT7988_ETHWARP_1} 1277 + }, 1278 + .num_lvts_sensor = 4, 1279 + .offset = 0x100, 1280 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT7988, 1281 + } 1282 + }; 1283 + 1284 + static int lvts_suspend(struct device *dev) 1285 + { 1286 + struct lvts_domain *lvts_td; 1287 + int i; 1288 + 1289 + lvts_td = dev_get_drvdata(dev); 1290 + 1291 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) 1292 + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], false); 1293 + 1294 + clk_disable_unprepare(lvts_td->clk); 1299 1295 1300 1296 return 0; 1301 1297 } 1298 + 1299 + static int lvts_resume(struct device *dev) 1300 + { 1301 + struct lvts_domain *lvts_td; 1302 + int i, ret; 1303 + 1304 + lvts_td = dev_get_drvdata(dev); 1305 + 1306 + ret = clk_prepare_enable(lvts_td->clk); 1307 + if (ret) 1308 + return ret; 1309 + 1310 + for (i = 0; i < lvts_td->num_lvts_ctrl; i++) 1311 + lvts_ctrl_set_enable(&lvts_td->lvts_ctrl[i], true); 1312 + 1313 + return 0; 1314 + } 1315 + 1316 + static const struct lvts_ctrl_data mt8192_lvts_mcu_data_ctrl[] = { 1317 + { 1318 + .cal_offset = { 0x04, 0x08 }, 1319 + .lvts_sensor = { 1320 + { .dt_id = MT8192_MCU_BIG_CPU0 }, 1321 + { .dt_id = MT8192_MCU_BIG_CPU1 } 1322 + }, 1323 + .num_lvts_sensor = 2, 1324 + .offset = 0x0, 1325 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1326 + .mode = LVTS_MSR_FILTERED_MODE, 1327 + }, 1328 + { 1329 + .cal_offset = { 0x0c, 0x10 }, 1330 + .lvts_sensor = { 1331 + { .dt_id = MT8192_MCU_BIG_CPU2 }, 1332 + { .dt_id = MT8192_MCU_BIG_CPU3 } 1333 + }, 1334 + .num_lvts_sensor = 2, 1335 + .offset = 0x100, 1336 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1337 + .mode = LVTS_MSR_FILTERED_MODE, 1338 + }, 1339 + { 1340 + .cal_offset = { 0x14, 0x18, 0x1c, 0x20 }, 1341 + .lvts_sensor = { 1342 + { .dt_id = MT8192_MCU_LITTLE_CPU0 }, 1343 + { .dt_id = MT8192_MCU_LITTLE_CPU1 }, 1344 + { .dt_id = MT8192_MCU_LITTLE_CPU2 }, 1345 + { .dt_id = MT8192_MCU_LITTLE_CPU3 } 1346 + }, 1347 + .num_lvts_sensor = 4, 1348 + .offset = 0x200, 1349 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1350 + .mode = LVTS_MSR_FILTERED_MODE, 1351 + } 1352 + }; 1353 + 1354 + static const struct lvts_ctrl_data mt8192_lvts_ap_data_ctrl[] = { 1355 + { 1356 + .cal_offset = { 0x24, 0x28 }, 1357 + .lvts_sensor = { 1358 + { .dt_id = MT8192_AP_VPU0 }, 1359 + { .dt_id = MT8192_AP_VPU1 } 1360 + }, 1361 + .num_lvts_sensor = 2, 1362 + .offset = 0x0, 1363 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1364 + }, 1365 + { 1366 + .cal_offset = { 0x2c, 0x30 }, 1367 + .lvts_sensor = { 1368 + { .dt_id = MT8192_AP_GPU0 }, 1369 + { .dt_id = MT8192_AP_GPU1 } 1370 + }, 1371 + .num_lvts_sensor = 2, 1372 + .offset = 0x100, 1373 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1374 + }, 1375 + { 1376 + .cal_offset = { 0x34, 0x38 }, 1377 + .lvts_sensor = { 1378 + { .dt_id = MT8192_AP_INFRA }, 1379 + { .dt_id = MT8192_AP_CAM }, 1380 + }, 1381 + .num_lvts_sensor = 2, 1382 + .offset = 0x200, 1383 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1384 + }, 1385 + { 1386 + .cal_offset = { 0x3c, 0x40, 0x44 }, 1387 + .lvts_sensor = { 1388 + { .dt_id = MT8192_AP_MD0 }, 1389 + { .dt_id = MT8192_AP_MD1 }, 1390 + { .dt_id = MT8192_AP_MD2 } 1391 + }, 1392 + .num_lvts_sensor = 3, 1393 + .offset = 0x300, 1394 + .hw_tshut_temp = LVTS_HW_SHUTDOWN_MT8192, 1395 + } 1396 + }; 1302 1397 1303 1398 static const struct lvts_ctrl_data mt8195_lvts_mcu_data_ctrl[] = { 1304 1399 { ··· 1518 1335 } 1519 1336 }; 1520 1337 1338 + static const struct lvts_data mt7988_lvts_ap_data = { 1339 + .lvts_ctrl = mt7988_lvts_ap_data_ctrl, 1340 + .num_lvts_ctrl = ARRAY_SIZE(mt7988_lvts_ap_data_ctrl), 1341 + .temp_factor = LVTS_COEFF_A_MT7988, 1342 + .temp_offset = LVTS_COEFF_B_MT7988, 1343 + }; 1344 + 1345 + static const struct lvts_data mt8192_lvts_mcu_data = { 1346 + .lvts_ctrl = mt8192_lvts_mcu_data_ctrl, 1347 + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl), 1348 + }; 1349 + 1350 + static const struct lvts_data mt8192_lvts_ap_data = { 1351 + .lvts_ctrl = mt8192_lvts_ap_data_ctrl, 1352 + .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl), 1353 + }; 1354 + 1521 1355 static const struct lvts_data mt8195_lvts_mcu_data = { 1522 1356 .lvts_ctrl = mt8195_lvts_mcu_data_ctrl, 1523 1357 .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_mcu_data_ctrl), 1358 + .temp_factor = LVTS_COEFF_A_MT8195, 1359 + .temp_offset = LVTS_COEFF_B_MT8195, 1524 1360 }; 1525 1361 1526 1362 static const struct lvts_data mt8195_lvts_ap_data = { 1527 1363 .lvts_ctrl = mt8195_lvts_ap_data_ctrl, 1528 1364 .num_lvts_ctrl = ARRAY_SIZE(mt8195_lvts_ap_data_ctrl), 1365 + .temp_factor = LVTS_COEFF_A_MT8195, 1366 + .temp_offset = LVTS_COEFF_B_MT8195, 1529 1367 }; 1530 1368 1531 1369 static const struct of_device_id lvts_of_match[] = { 1370 + { .compatible = "mediatek,mt7988-lvts-ap", .data = &mt7988_lvts_ap_data }, 1371 + { .compatible = "mediatek,mt8192-lvts-mcu", .data = &mt8192_lvts_mcu_data }, 1372 + { .compatible = "mediatek,mt8192-lvts-ap", .data = &mt8192_lvts_ap_data }, 1532 1373 { .compatible = "mediatek,mt8195-lvts-mcu", .data = &mt8195_lvts_mcu_data }, 1533 1374 { .compatible = "mediatek,mt8195-lvts-ap", .data = &mt8195_lvts_ap_data }, 1534 1375 {}, 1535 1376 }; 1536 1377 MODULE_DEVICE_TABLE(of, lvts_of_match); 1537 1378 1379 + static const struct dev_pm_ops lvts_pm_ops = { 1380 + NOIRQ_SYSTEM_SLEEP_PM_OPS(lvts_suspend, lvts_resume) 1381 + }; 1382 + 1538 1383 static struct platform_driver lvts_driver = { 1539 1384 .probe = lvts_probe, 1540 - .remove = lvts_remove, 1385 + .remove_new = lvts_remove, 1541 1386 .driver = { 1542 1387 .name = "mtk-lvts-thermal", 1543 1388 .of_match_table = lvts_of_match, 1389 + .pm = &lvts_pm_ops, 1544 1390 }, 1545 1391 }; 1546 1392 module_platform_driver(lvts_driver);
-6
drivers/thermal/qcom/tsens-v0_1.c
··· 325 325 [TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0), 326 326 }; 327 327 328 - static const struct tsens_ops ops_v0_1 = { 329 - .init = init_common, 330 - .calibrate = tsens_calibrate_common, 331 - .get_temp = get_temp_common, 332 - }; 333 - 334 328 static const struct tsens_ops ops_8226 = { 335 329 .init = init_8226, 336 330 .calibrate = tsens_calibrate_common,
+2 -4
drivers/thermal/qcom/tsens.c
··· 1319 1319 return ret; 1320 1320 } 1321 1321 1322 - static int tsens_remove(struct platform_device *pdev) 1322 + static void tsens_remove(struct platform_device *pdev) 1323 1323 { 1324 1324 struct tsens_priv *priv = platform_get_drvdata(pdev); 1325 1325 ··· 1327 1327 tsens_disable_irq(priv); 1328 1328 if (priv->ops->disable) 1329 1329 priv->ops->disable(priv); 1330 - 1331 - return 0; 1332 1330 } 1333 1331 1334 1332 static struct platform_driver tsens_driver = { 1335 1333 .probe = tsens_probe, 1336 - .remove = tsens_remove, 1334 + .remove_new = tsens_remove, 1337 1335 .driver = { 1338 1336 .name = "qcom-tsens", 1339 1337 .pm = &tsens_pm_ops,
+2 -4
drivers/thermal/rcar_gen3_thermal.c
··· 432 432 }; 433 433 MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids); 434 434 435 - static int rcar_gen3_thermal_remove(struct platform_device *pdev) 435 + static void rcar_gen3_thermal_remove(struct platform_device *pdev) 436 436 { 437 437 struct device *dev = &pdev->dev; 438 438 439 439 pm_runtime_put(dev); 440 440 pm_runtime_disable(dev); 441 - 442 - return 0; 443 441 } 444 442 445 443 static void rcar_gen3_hwmon_action(void *data) ··· 592 594 .of_match_table = rcar_gen3_thermal_dt_ids, 593 595 }, 594 596 .probe = rcar_gen3_thermal_probe, 595 - .remove = rcar_gen3_thermal_remove, 597 + .remove_new = rcar_gen3_thermal_remove, 596 598 }; 597 599 module_platform_driver(rcar_gen3_thermal_driver); 598 600
+2 -4
drivers/thermal/rcar_thermal.c
··· 371 371 /* 372 372 * platform functions 373 373 */ 374 - static int rcar_thermal_remove(struct platform_device *pdev) 374 + static void rcar_thermal_remove(struct platform_device *pdev) 375 375 { 376 376 struct rcar_thermal_common *common = platform_get_drvdata(pdev); 377 377 struct device *dev = &pdev->dev; ··· 388 388 389 389 pm_runtime_put(dev); 390 390 pm_runtime_disable(dev); 391 - 392 - return 0; 393 391 } 394 392 395 393 static int rcar_thermal_probe(struct platform_device *pdev) ··· 579 581 .of_match_table = rcar_thermal_dt_ids, 580 582 }, 581 583 .probe = rcar_thermal_probe, 582 - .remove = rcar_thermal_remove, 584 + .remove_new = rcar_thermal_remove, 583 585 }; 584 586 module_platform_driver(rcar_thermal_driver); 585 587
+2 -4
drivers/thermal/rockchip_thermal.c
··· 1601 1601 return 0; 1602 1602 } 1603 1603 1604 - static int rockchip_thermal_remove(struct platform_device *pdev) 1604 + static void rockchip_thermal_remove(struct platform_device *pdev) 1605 1605 { 1606 1606 struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev); 1607 1607 int i; ··· 1614 1614 } 1615 1615 1616 1616 thermal->chip->control(thermal->regs, false); 1617 - 1618 - return 0; 1619 1617 } 1620 1618 1621 1619 static int __maybe_unused rockchip_thermal_suspend(struct device *dev) ··· 1689 1691 .of_match_table = of_rockchip_thermal_match, 1690 1692 }, 1691 1693 .probe = rockchip_thermal_probe, 1692 - .remove = rockchip_thermal_remove, 1694 + .remove_new = rockchip_thermal_remove, 1693 1695 }; 1694 1696 1695 1697 module_platform_driver(rockchip_thermal_driver);
+2 -4
drivers/thermal/rzg2l_thermal.c
··· 150 150 reset_control_assert(priv->rstc); 151 151 } 152 152 153 - static int rzg2l_thermal_remove(struct platform_device *pdev) 153 + static void rzg2l_thermal_remove(struct platform_device *pdev) 154 154 { 155 155 struct rzg2l_thermal_priv *priv = dev_get_drvdata(&pdev->dev); 156 156 157 157 thermal_remove_hwmon_sysfs(priv->zone); 158 158 rzg2l_thermal_reset_assert_pm_disable_put(pdev); 159 - 160 - return 0; 161 159 } 162 160 163 161 static int rzg2l_thermal_probe(struct platform_device *pdev) ··· 240 242 .of_match_table = rzg2l_thermal_dt_ids, 241 243 }, 242 244 .probe = rzg2l_thermal_probe, 243 - .remove = rzg2l_thermal_remove, 245 + .remove_new = rzg2l_thermal_remove, 244 246 }; 245 247 module_platform_driver(rzg2l_thermal_driver); 246 248
+2 -4
drivers/thermal/samsung/exynos_tmu.c
··· 1124 1124 return ret; 1125 1125 } 1126 1126 1127 - static int exynos_tmu_remove(struct platform_device *pdev) 1127 + static void exynos_tmu_remove(struct platform_device *pdev) 1128 1128 { 1129 1129 struct exynos_tmu_data *data = platform_get_drvdata(pdev); 1130 1130 ··· 1137 1137 1138 1138 if (!IS_ERR(data->regulator)) 1139 1139 regulator_disable(data->regulator); 1140 - 1141 - return 0; 1142 1140 } 1143 1141 1144 1142 #ifdef CONFIG_PM_SLEEP ··· 1171 1173 .of_match_table = exynos_tmu_match, 1172 1174 }, 1173 1175 .probe = exynos_tmu_probe, 1174 - .remove = exynos_tmu_remove, 1176 + .remove_new = exynos_tmu_remove, 1175 1177 }; 1176 1178 1177 1179 module_platform_driver(exynos_tmu_driver);
+2 -4
drivers/thermal/spear_thermal.c
··· 150 150 return ret; 151 151 } 152 152 153 - static int spear_thermal_exit(struct platform_device *pdev) 153 + static void spear_thermal_exit(struct platform_device *pdev) 154 154 { 155 155 unsigned int actual_mask = 0; 156 156 struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); ··· 163 163 writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base); 164 164 165 165 clk_disable(stdev->clk); 166 - 167 - return 0; 168 166 } 169 167 170 168 static const struct of_device_id spear_thermal_id_table[] = { ··· 173 175 174 176 static struct platform_driver spear_thermal_driver = { 175 177 .probe = spear_thermal_probe, 176 - .remove = spear_thermal_exit, 178 + .remove_new = spear_thermal_exit, 177 179 .driver = { 178 180 .name = "spear_thermal", 179 181 .pm = &spear_thermal_pm_ops,
+2 -3
drivers/thermal/sprd_thermal.c
··· 516 516 } 517 517 #endif 518 518 519 - static int sprd_thm_remove(struct platform_device *pdev) 519 + static void sprd_thm_remove(struct platform_device *pdev) 520 520 { 521 521 struct sprd_thermal_data *thm = platform_get_drvdata(pdev); 522 522 int i; ··· 528 528 } 529 529 530 530 clk_disable_unprepare(thm->clk); 531 - return 0; 532 531 } 533 532 534 533 static const struct of_device_id sprd_thermal_of_match[] = { ··· 542 543 543 544 static struct platform_driver sprd_thermal_driver = { 544 545 .probe = sprd_thm_probe, 545 - .remove = sprd_thm_remove, 546 + .remove_new = sprd_thm_remove, 546 547 .driver = { 547 548 .name = "sprd-thermal", 548 549 .pm = &sprd_thermal_pm_ops,
+2 -4
drivers/thermal/st/stm_thermal.c
··· 569 569 return ret; 570 570 } 571 571 572 - static int stm_thermal_remove(struct platform_device *pdev) 572 + static void stm_thermal_remove(struct platform_device *pdev) 573 573 { 574 574 struct stm_thermal_sensor *sensor = platform_get_drvdata(pdev); 575 575 576 576 stm_thermal_sensor_off(sensor); 577 577 thermal_remove_hwmon_sysfs(sensor->th_dev); 578 - 579 - return 0; 580 578 } 581 579 582 580 static struct platform_driver stm_thermal_driver = { ··· 584 586 .of_match_table = stm_thermal_of_match, 585 587 }, 586 588 .probe = stm_thermal_probe, 587 - .remove = stm_thermal_remove, 589 + .remove_new = stm_thermal_remove, 588 590 }; 589 591 module_platform_driver(stm_thermal_driver); 590 592
+2 -4
drivers/thermal/tegra/soctherm.c
··· 2219 2219 return err; 2220 2220 } 2221 2221 2222 - static int tegra_soctherm_remove(struct platform_device *pdev) 2222 + static void tegra_soctherm_remove(struct platform_device *pdev) 2223 2223 { 2224 2224 struct tegra_soctherm *tegra = platform_get_drvdata(pdev); 2225 2225 2226 2226 debugfs_remove_recursive(tegra->debugfs_dir); 2227 2227 2228 2228 soctherm_clk_enable(pdev, false); 2229 - 2230 - return 0; 2231 2229 } 2232 2230 2233 2231 static int __maybe_unused soctherm_suspend(struct device *dev) ··· 2272 2274 2273 2275 static struct platform_driver tegra_soctherm_driver = { 2274 2276 .probe = tegra_soctherm_probe, 2275 - .remove = tegra_soctherm_remove, 2277 + .remove_new = tegra_soctherm_remove, 2276 2278 .driver = { 2277 2279 .name = "tegra_soctherm", 2278 2280 .pm = &tegra_soctherm_pm,
+2 -4
drivers/thermal/tegra/tegra-bpmp-thermal.c
··· 300 300 return 0; 301 301 } 302 302 303 - static int tegra_bpmp_thermal_remove(struct platform_device *pdev) 303 + static void tegra_bpmp_thermal_remove(struct platform_device *pdev) 304 304 { 305 305 struct tegra_bpmp_thermal *tegra = platform_get_drvdata(pdev); 306 306 307 307 tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra); 308 - 309 - return 0; 310 308 } 311 309 312 310 static const struct of_device_id tegra_bpmp_thermal_of_match[] = { ··· 315 317 316 318 static struct platform_driver tegra_bpmp_thermal_driver = { 317 319 .probe = tegra_bpmp_thermal_probe, 318 - .remove = tegra_bpmp_thermal_remove, 320 + .remove_new = tegra_bpmp_thermal_remove, 319 321 .driver = { 320 322 .name = "tegra-bpmp-thermal", 321 323 .of_match_table = tegra_bpmp_thermal_of_match,
+1 -2
drivers/thermal/thermal_acpi.c
··· 8 8 */ 9 9 #include <linux/acpi.h> 10 10 #include <linux/units.h> 11 - 12 - #include "thermal_core.h" 11 + #include <linux/thermal.h> 13 12 14 13 /* 15 14 * Minimum temperature for full military grade is 218°K (-55°C) and
+63 -74
drivers/thermal/thermal_core.c
··· 307 307 thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies); 308 308 } 309 309 310 - static void handle_non_critical_trips(struct thermal_zone_device *tz, int trip) 310 + static void handle_non_critical_trips(struct thermal_zone_device *tz, 311 + const struct thermal_trip *trip) 311 312 { 312 313 tz->governor ? tz->governor->throttle(tz, trip) : 313 314 def_governor->throttle(tz, trip); ··· 330 329 EXPORT_SYMBOL(thermal_zone_device_critical); 331 330 332 331 static void handle_critical_trips(struct thermal_zone_device *tz, 333 - int trip, int trip_temp, enum thermal_trip_type trip_type) 332 + const struct thermal_trip *trip) 334 333 { 335 334 /* If we have not crossed the trip_temp, we do not care. */ 336 - if (trip_temp <= 0 || tz->temperature < trip_temp) 335 + if (trip->temperature <= 0 || tz->temperature < trip->temperature) 337 336 return; 338 337 339 - trace_thermal_zone_trip(tz, trip, trip_type); 338 + trace_thermal_zone_trip(tz, thermal_zone_trip_id(tz, trip), trip->type); 340 339 341 - if (trip_type == THERMAL_TRIP_HOT && tz->ops->hot) 342 - tz->ops->hot(tz); 343 - else if (trip_type == THERMAL_TRIP_CRITICAL) 340 + if (trip->type == THERMAL_TRIP_CRITICAL) 344 341 tz->ops->critical(tz); 342 + else if (tz->ops->hot) 343 + tz->ops->hot(tz); 345 344 } 346 345 347 - static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) 346 + static void handle_thermal_trip(struct thermal_zone_device *tz, 347 + const struct thermal_trip *trip) 348 348 { 349 - struct thermal_trip trip; 350 - 351 - /* Ignore disabled trip points */ 352 - if (test_bit(trip_id, &tz->trips_disabled)) 353 - return; 354 - 355 - __thermal_zone_get_trip(tz, trip_id, &trip); 356 - 357 - if (trip.temperature == THERMAL_TEMP_INVALID) 349 + if (trip->temperature == THERMAL_TEMP_INVALID) 358 350 return; 359 351 360 352 if (tz->last_temperature != THERMAL_TEMP_INVALID) { 361 - if (tz->last_temperature < trip.temperature && 362 - tz->temperature >= trip.temperature) 363 - thermal_notify_tz_trip_up(tz->id, trip_id, 353 + if (tz->last_temperature < trip->temperature && 354 + tz->temperature >= trip->temperature) 355 + thermal_notify_tz_trip_up(tz->id, 356 + thermal_zone_trip_id(tz, trip), 364 357 tz->temperature); 365 - if (tz->last_temperature >= trip.temperature && 366 - tz->temperature < (trip.temperature - trip.hysteresis)) 367 - thermal_notify_tz_trip_down(tz->id, trip_id, 358 + if (tz->last_temperature >= trip->temperature && 359 + tz->temperature < trip->temperature - trip->hysteresis) 360 + thermal_notify_tz_trip_down(tz->id, 361 + thermal_zone_trip_id(tz, trip), 368 362 tz->temperature); 369 363 } 370 364 371 - if (trip.type == THERMAL_TRIP_CRITICAL || trip.type == THERMAL_TRIP_HOT) 372 - handle_critical_trips(tz, trip_id, trip.temperature, trip.type); 365 + if (trip->type == THERMAL_TRIP_CRITICAL || trip->type == THERMAL_TRIP_HOT) 366 + handle_critical_trips(tz, trip); 373 367 else 374 - handle_non_critical_trips(tz, trip_id); 368 + handle_non_critical_trips(tz, trip); 375 369 } 376 370 377 371 static void update_temperature(struct thermal_zone_device *tz) ··· 403 407 void __thermal_zone_device_update(struct thermal_zone_device *tz, 404 408 enum thermal_notify_event event) 405 409 { 406 - int count; 410 + const struct thermal_trip *trip; 407 411 408 412 if (atomic_read(&in_suspend)) 409 413 return; ··· 422 426 423 427 tz->notify_event = event; 424 428 425 - for (count = 0; count < tz->num_trips; count++) 426 - handle_thermal_trip(tz, count); 429 + for_each_trip(tz, trip) 430 + handle_thermal_trip(tz, trip); 427 431 428 432 monitor_thermal_zone(tz); 429 433 } ··· 494 498 mutex_unlock(&tz->lock); 495 499 } 496 500 EXPORT_SYMBOL_GPL(thermal_zone_device_update); 497 - 498 - /** 499 - * thermal_zone_device_exec - Run a callback under the zone lock. 500 - * @tz: Thermal zone. 501 - * @cb: Callback to run. 502 - * @data: Data to pass to the callback. 503 - */ 504 - void thermal_zone_device_exec(struct thermal_zone_device *tz, 505 - void (*cb)(struct thermal_zone_device *, 506 - unsigned long), 507 - unsigned long data) 508 - { 509 - mutex_lock(&tz->lock); 510 - 511 - cb(tz, data); 512 - 513 - mutex_unlock(&tz->lock); 514 - } 515 - EXPORT_SYMBOL_GPL(thermal_zone_device_exec); 516 501 517 502 static void thermal_zone_device_check(struct work_struct *work) 518 503 { ··· 581 604 */ 582 605 583 606 /** 584 - * thermal_zone_bind_cooling_device() - bind a cooling device to a thermal zone 607 + * thermal_bind_cdev_to_trip - bind a cooling device to a thermal zone 585 608 * @tz: pointer to struct thermal_zone_device 586 - * @trip: indicates which trip point the cooling devices is 587 - * associated with in this thermal zone. 609 + * @trip: trip point the cooling devices is associated with in this zone. 588 610 * @cdev: pointer to struct thermal_cooling_device 589 611 * @upper: the Maximum cooling state for this trip point. 590 612 * THERMAL_NO_LIMIT means no upper limit, ··· 601 625 * 602 626 * Return: 0 on success, the proper error value otherwise. 603 627 */ 604 - int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 605 - int trip, 628 + int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, 629 + const struct thermal_trip *trip, 606 630 struct thermal_cooling_device *cdev, 607 631 unsigned long upper, unsigned long lower, 608 632 unsigned int weight) ··· 613 637 struct thermal_cooling_device *pos2; 614 638 bool upper_no_limit; 615 639 int result; 616 - 617 - if (trip >= tz->num_trips || trip < 0) 618 - return -EINVAL; 619 640 620 641 list_for_each_entry(pos1, &thermal_tz_list, node) { 621 642 if (pos1 == tz) ··· 662 689 if (result) 663 690 goto release_ida; 664 691 665 - sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); 692 + snprintf(dev->attr_name, sizeof(dev->attr_name), "cdev%d_trip_point", 693 + dev->id); 666 694 sysfs_attr_init(&dev->attr.attr); 667 695 dev->attr.attr.name = dev->attr_name; 668 696 dev->attr.attr.mode = 0444; ··· 672 698 if (result) 673 699 goto remove_symbol_link; 674 700 675 - sprintf(dev->weight_attr_name, "cdev%d_weight", dev->id); 701 + snprintf(dev->weight_attr_name, sizeof(dev->weight_attr_name), 702 + "cdev%d_weight", dev->id); 676 703 sysfs_attr_init(&dev->weight_attr.attr); 677 704 dev->weight_attr.attr.name = dev->weight_attr_name; 678 705 dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO; ··· 712 737 kfree(dev); 713 738 return result; 714 739 } 740 + EXPORT_SYMBOL_GPL(thermal_bind_cdev_to_trip); 741 + 742 + int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, 743 + int trip_index, 744 + struct thermal_cooling_device *cdev, 745 + unsigned long upper, unsigned long lower, 746 + unsigned int weight) 747 + { 748 + if (trip_index < 0 || trip_index >= tz->num_trips) 749 + return -EINVAL; 750 + 751 + return thermal_bind_cdev_to_trip(tz, &tz->trips[trip_index], cdev, 752 + upper, lower, weight); 753 + } 715 754 EXPORT_SYMBOL_GPL(thermal_zone_bind_cooling_device); 716 755 717 756 /** 718 - * thermal_zone_unbind_cooling_device() - unbind a cooling device from a 719 - * thermal zone. 757 + * thermal_unbind_cdev_from_trip - unbind a cooling device from a thermal zone. 720 758 * @tz: pointer to a struct thermal_zone_device. 721 - * @trip: indicates which trip point the cooling devices is 722 - * associated with in this thermal zone. 759 + * @trip: trip point the cooling devices is associated with in this zone. 723 760 * @cdev: pointer to a struct thermal_cooling_device. 724 761 * 725 762 * This interface function unbind a thermal cooling device from the certain ··· 740 753 * 741 754 * Return: 0 on success, the proper error value otherwise. 742 755 */ 743 - int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, 744 - int trip, 745 - struct thermal_cooling_device *cdev) 756 + int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, 757 + const struct thermal_trip *trip, 758 + struct thermal_cooling_device *cdev) 746 759 { 747 760 struct thermal_instance *pos, *next; 748 761 ··· 769 782 ida_free(&tz->ida, pos->id); 770 783 kfree(pos); 771 784 return 0; 785 + } 786 + EXPORT_SYMBOL_GPL(thermal_unbind_cdev_from_trip); 787 + 788 + int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, 789 + int trip_index, 790 + struct thermal_cooling_device *cdev) 791 + { 792 + if (trip_index < 0 || trip_index >= tz->num_trips) 793 + return -EINVAL; 794 + 795 + return thermal_unbind_cdev_from_trip(tz, &tz->trips[trip_index], cdev); 772 796 } 773 797 EXPORT_SYMBOL_GPL(thermal_zone_unbind_cooling_device); 774 798 ··· 1229 1231 struct thermal_zone_device *tz; 1230 1232 int id; 1231 1233 int result; 1232 - int count; 1233 1234 struct thermal_governor *governor; 1234 1235 1235 1236 if (!type || strlen(type) == 0) { ··· 1324 1327 result = device_register(&tz->device); 1325 1328 if (result) 1326 1329 goto release_device; 1327 - 1328 - for (count = 0; count < num_trips; count++) { 1329 - struct thermal_trip trip; 1330 - 1331 - result = thermal_zone_get_trip(tz, count, &trip); 1332 - if (result || !trip.temperature) 1333 - set_bit(count, &tz->trips_disabled); 1334 - } 1335 1330 1336 1331 /* Update 'this' zone's governor information */ 1337 1332 mutex_lock(&thermal_governor_lock);
+7 -2
drivers/thermal/thermal_core.h
··· 70 70 void thermal_cdev_update(struct thermal_cooling_device *); 71 71 void __thermal_cdev_update(struct thermal_cooling_device *cdev); 72 72 73 - int get_tz_trend(struct thermal_zone_device *tz, int trip_index); 73 + int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip); 74 74 75 75 struct thermal_instance * 76 76 get_thermal_instance(struct thermal_zone_device *tz, ··· 87 87 char name[THERMAL_NAME_LENGTH]; 88 88 struct thermal_zone_device *tz; 89 89 struct thermal_cooling_device *cdev; 90 - int trip; 90 + const struct thermal_trip *trip; 91 91 bool initialized; 92 92 unsigned long upper; /* Highest cooling state for this trip point */ 93 93 unsigned long lower; /* Lowest cooling state for this trip point */ ··· 116 116 enum thermal_notify_event event); 117 117 118 118 /* Helpers */ 119 + #define for_each_trip(__tz, __trip) \ 120 + for (__trip = __tz->trips; __trip - __tz->trips < __tz->num_trips; __trip++) 121 + 119 122 void __thermal_zone_set_trips(struct thermal_zone_device *tz); 120 123 int __thermal_zone_get_trip(struct thermal_zone_device *tz, int trip_id, 121 124 struct thermal_trip *trip); 125 + int thermal_zone_trip_id(struct thermal_zone_device *tz, 126 + const struct thermal_trip *trip); 122 127 int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp); 123 128 124 129 /* sysfs I/F */
+5 -3
drivers/thermal/thermal_helpers.c
··· 22 22 #include "thermal_core.h" 23 23 #include "thermal_trace.h" 24 24 25 - int get_tz_trend(struct thermal_zone_device *tz, int trip_index) 25 + int get_tz_trend(struct thermal_zone_device *tz, const struct thermal_trip *trip) 26 26 { 27 - struct thermal_trip *trip = tz->trips ? &tz->trips[trip_index] : NULL; 28 27 enum thermal_trend trend; 29 28 30 29 if (tz->emul_temperature || !tz->ops->get_trend || ··· 41 42 42 43 struct thermal_instance * 43 44 get_thermal_instance(struct thermal_zone_device *tz, 44 - struct thermal_cooling_device *cdev, int trip) 45 + struct thermal_cooling_device *cdev, int trip_index) 45 46 { 46 47 struct thermal_instance *pos = NULL; 47 48 struct thermal_instance *target_instance = NULL; 49 + const struct thermal_trip *trip; 48 50 49 51 mutex_lock(&tz->lock); 50 52 mutex_lock(&cdev->lock); 53 + 54 + trip = &tz->trips[trip_index]; 51 55 52 56 list_for_each_entry(pos, &tz->thermal_instances, tz_node) { 53 57 if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) {
+2 -1
drivers/thermal/thermal_sysfs.c
··· 943 943 instance = 944 944 container_of(attr, struct thermal_instance, attr); 945 945 946 - return sprintf(buf, "%d\n", instance->trip); 946 + return sprintf(buf, "%d\n", 947 + thermal_zone_trip_id(instance->tz, instance->trip)); 947 948 } 948 949 949 950 ssize_t
+45 -10
drivers/thermal/thermal_trip.c
··· 13 13 int (*cb)(struct thermal_trip *, void *), 14 14 void *data) 15 15 { 16 - int i, ret; 16 + struct thermal_trip *trip; 17 + int ret; 17 18 18 - lockdep_assert_held(&tz->lock); 19 - 20 - if (!tz->trips) 21 - return -ENODATA; 22 - 23 - for (i = 0; i < tz->num_trips; i++) { 24 - ret = cb(&tz->trips[i], data); 19 + for_each_trip(tz, trip) { 20 + ret = cb(trip, data); 25 21 if (ret) 26 22 return ret; 27 23 } ··· 25 29 return 0; 26 30 } 27 31 EXPORT_SYMBOL_GPL(for_each_thermal_trip); 32 + 33 + int thermal_zone_for_each_trip(struct thermal_zone_device *tz, 34 + int (*cb)(struct thermal_trip *, void *), 35 + void *data) 36 + { 37 + int ret; 38 + 39 + mutex_lock(&tz->lock); 40 + ret = for_each_thermal_trip(tz, cb, data); 41 + mutex_unlock(&tz->lock); 42 + 43 + return ret; 44 + } 45 + EXPORT_SYMBOL_GPL(thermal_zone_for_each_trip); 28 46 29 47 int thermal_zone_get_num_trips(struct thermal_zone_device *tz) 30 48 { ··· 65 55 { 66 56 struct thermal_trip trip; 67 57 int low = -INT_MAX, high = INT_MAX; 58 + bool same_trip = false; 68 59 int i, ret; 69 60 70 61 lockdep_assert_held(&tz->lock); ··· 74 63 return; 75 64 76 65 for (i = 0; i < tz->num_trips; i++) { 66 + bool low_set = false; 77 67 int trip_low; 78 68 79 69 ret = __thermal_zone_get_trip(tz, i , &trip); ··· 83 71 84 72 trip_low = trip.temperature - trip.hysteresis; 85 73 86 - if (trip_low < tz->temperature && trip_low > low) 74 + if (trip_low < tz->temperature && trip_low > low) { 87 75 low = trip_low; 76 + low_set = true; 77 + same_trip = false; 78 + } 88 79 89 80 if (trip.temperature > tz->temperature && 90 - trip.temperature < high) 81 + trip.temperature < high) { 91 82 high = trip.temperature; 83 + same_trip = low_set; 84 + } 92 85 } 93 86 94 87 /* No need to change trip points */ 95 88 if (tz->prev_low_trip == low && tz->prev_high_trip == high) 89 + return; 90 + 91 + /* 92 + * If "high" and "low" are the same, skip the change unless this is the 93 + * first time. 94 + */ 95 + if (same_trip && (tz->prev_low_trip != -INT_MAX || 96 + tz->prev_high_trip != INT_MAX)) 96 97 return; 97 98 98 99 tz->prev_low_trip = low; ··· 184 159 __thermal_zone_device_update(tz, THERMAL_TRIP_CHANGED); 185 160 186 161 return 0; 162 + } 163 + 164 + int thermal_zone_trip_id(struct thermal_zone_device *tz, 165 + const struct thermal_trip *trip) 166 + { 167 + /* 168 + * Assume the trip to be located within the bounds of the thermal 169 + * zone's trips[] table. 170 + */ 171 + return trip - tz->trips; 187 172 }
+2 -4
drivers/thermal/ti-soc-thermal/ti-bandgap.c
··· 1069 1069 } 1070 1070 1071 1071 static 1072 - int ti_bandgap_remove(struct platform_device *pdev) 1072 + void ti_bandgap_remove(struct platform_device *pdev) 1073 1073 { 1074 1074 struct ti_bandgap *bgp = platform_get_drvdata(pdev); 1075 1075 int i; ··· 1098 1098 1099 1099 if (TI_BANDGAP_HAS(bgp, TSHUT)) 1100 1100 free_irq(gpiod_to_irq(bgp->tshut_gpiod), NULL); 1101 - 1102 - return 0; 1103 1101 } 1104 1102 1105 1103 #ifdef CONFIG_PM_SLEEP ··· 1281 1283 1282 1284 static struct platform_driver ti_bandgap_sensor_driver = { 1283 1285 .probe = ti_bandgap_probe, 1284 - .remove = ti_bandgap_remove, 1286 + .remove_new = ti_bandgap_remove, 1285 1287 .driver = { 1286 1288 .name = "ti-soc-thermal", 1287 1289 .pm = DEV_PM_OPS,
+2 -4
drivers/thermal/uniphier_thermal.c
··· 317 317 return 0; 318 318 } 319 319 320 - static int uniphier_tm_remove(struct platform_device *pdev) 320 + static void uniphier_tm_remove(struct platform_device *pdev) 321 321 { 322 322 struct uniphier_tm_dev *tdev = platform_get_drvdata(pdev); 323 323 324 324 /* disable sensor */ 325 325 uniphier_tm_disable_sensor(tdev); 326 - 327 - return 0; 328 326 } 329 327 330 328 static const struct uniphier_tm_soc_data uniphier_pxs2_tm_data = { ··· 360 362 361 363 static struct platform_driver uniphier_tm_driver = { 362 364 .probe = uniphier_tm_probe, 363 - .remove = uniphier_tm_remove, 365 + .remove_new = uniphier_tm_remove, 364 366 .driver = { 365 367 .name = "uniphier-thermal", 366 368 .of_match_table = uniphier_tm_dt_ids,
+28
include/dt-bindings/thermal/mediatek,lvts-thermal.h
··· 7 7 #ifndef __MEDIATEK_LVTS_DT_H 8 8 #define __MEDIATEK_LVTS_DT_H 9 9 10 + #define MT7988_CPU_0 0 11 + #define MT7988_CPU_1 1 12 + #define MT7988_ETH2P5G_0 2 13 + #define MT7988_ETH2P5G_1 3 14 + #define MT7988_TOPS_0 4 15 + #define MT7988_TOPS_1 5 16 + #define MT7988_ETHWARP_0 6 17 + #define MT7988_ETHWARP_1 7 18 + 10 19 #define MT8195_MCU_BIG_CPU0 0 11 20 #define MT8195_MCU_BIG_CPU1 1 12 21 #define MT8195_MCU_BIG_CPU2 2 ··· 34 25 #define MT8195_AP_INFRA 14 35 26 #define MT8195_AP_CAM0 15 36 27 #define MT8195_AP_CAM1 16 28 + 29 + #define MT8192_MCU_BIG_CPU0 0 30 + #define MT8192_MCU_BIG_CPU1 1 31 + #define MT8192_MCU_BIG_CPU2 2 32 + #define MT8192_MCU_BIG_CPU3 3 33 + #define MT8192_MCU_LITTLE_CPU0 4 34 + #define MT8192_MCU_LITTLE_CPU1 5 35 + #define MT8192_MCU_LITTLE_CPU2 6 36 + #define MT8192_MCU_LITTLE_CPU3 7 37 + 38 + #define MT8192_AP_VPU0 8 39 + #define MT8192_AP_VPU1 9 40 + #define MT8192_AP_GPU0 10 41 + #define MT8192_AP_GPU1 11 42 + #define MT8192_AP_INFRA 12 43 + #define MT8192_AP_CAM 13 44 + #define MT8192_AP_MD0 14 45 + #define MT8192_AP_MD1 15 46 + #define MT8192_AP_MD2 16 37 47 38 48 #endif /* __MEDIATEK_LVTS_DT_H */
+13 -7
include/linux/thermal.h
··· 122 122 * @devdata: private pointer for device private data 123 123 * @trips: an array of struct thermal_trip 124 124 * @num_trips: number of trip points the thermal zone supports 125 - * @trips_disabled; bitmap for disabled trips 126 125 * @passive_delay_jiffies: number of jiffies to wait between polls when 127 126 * performing passive cooling. 128 127 * @polling_delay_jiffies: number of jiffies to wait between polls when ··· 162 163 void *devdata; 163 164 struct thermal_trip *trips; 164 165 int num_trips; 165 - unsigned long trips_disabled; /* bitmap for disabled trips */ 166 166 unsigned long passive_delay_jiffies; 167 167 unsigned long polling_delay_jiffies; 168 168 int temperature; ··· 199 201 char name[THERMAL_NAME_LENGTH]; 200 202 int (*bind_to_tz)(struct thermal_zone_device *tz); 201 203 void (*unbind_from_tz)(struct thermal_zone_device *tz); 202 - int (*throttle)(struct thermal_zone_device *tz, int trip); 204 + int (*throttle)(struct thermal_zone_device *tz, 205 + const struct thermal_trip *trip); 203 206 struct list_head governor_list; 204 207 }; 205 208 ··· 287 288 int for_each_thermal_trip(struct thermal_zone_device *tz, 288 289 int (*cb)(struct thermal_trip *, void *), 289 290 void *data); 291 + int thermal_zone_for_each_trip(struct thermal_zone_device *tz, 292 + int (*cb)(struct thermal_trip *, void *), 293 + void *data); 290 294 int thermal_zone_get_num_trips(struct thermal_zone_device *tz); 291 295 292 296 int thermal_zone_get_crit_temp(struct thermal_zone_device *tz, int *temp); ··· 324 322 int thermal_zone_device_id(struct thermal_zone_device *tzd); 325 323 struct device *thermal_zone_device(struct thermal_zone_device *tzd); 326 324 325 + int thermal_bind_cdev_to_trip(struct thermal_zone_device *tz, 326 + const struct thermal_trip *trip, 327 + struct thermal_cooling_device *cdev, 328 + unsigned long upper, unsigned long lower, 329 + unsigned int weight); 327 330 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, 328 331 struct thermal_cooling_device *, 329 332 unsigned long, unsigned long, 330 333 unsigned int); 334 + int thermal_unbind_cdev_from_trip(struct thermal_zone_device *tz, 335 + const struct thermal_trip *trip, 336 + struct thermal_cooling_device *cdev); 331 337 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, 332 338 struct thermal_cooling_device *); 333 339 void thermal_zone_device_update(struct thermal_zone_device *, 334 340 enum thermal_notify_event); 335 - void thermal_zone_device_exec(struct thermal_zone_device *tz, 336 - void (*cb)(struct thermal_zone_device *, 337 - unsigned long), 338 - unsigned long data); 339 341 340 342 struct thermal_cooling_device *thermal_cooling_device_register(const char *, 341 343 void *, const struct thermal_cooling_device_ops *);
+2
tools/testing/selftests/Makefile
··· 85 85 TARGETS += sysctl 86 86 TARGETS += tc-testing 87 87 TARGETS += tdx 88 + TARGETS += thermal/intel/power_floor 89 + TARGETS += thermal/intel/workload_hint 88 90 TARGETS += timens 89 91 ifneq (1, $(quicktest)) 90 92 TARGETS += timers
+12
tools/testing/selftests/thermal/intel/power_floor/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + ifndef CROSS_COMPILE 3 + uname_M := $(shell uname -m 2>/dev/null || echo not) 4 + ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) 5 + 6 + ifeq ($(ARCH),x86) 7 + TEST_GEN_PROGS := power_floor_test 8 + 9 + include ../../../lib.mk 10 + 11 + endif 12 + endif
+108
tools/testing/selftests/thermal/intel/power_floor/power_floor_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE 4 + 5 + #include <stdio.h> 6 + #include <string.h> 7 + #include <stdlib.h> 8 + #include <unistd.h> 9 + #include <fcntl.h> 10 + #include <poll.h> 11 + #include <signal.h> 12 + 13 + #define POWER_FLOOR_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_enable" 14 + #define POWER_FLOOR_STATUS_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/power_limits/power_floor_status" 15 + 16 + void power_floor_exit(int signum) 17 + { 18 + int fd; 19 + 20 + /* Disable feature via sysfs knob */ 21 + 22 + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); 23 + if (fd < 0) { 24 + perror("Unable to open power floor enable file\n"); 25 + exit(1); 26 + } 27 + 28 + if (write(fd, "0\n", 2) < 0) { 29 + perror("Can' disable power floor notifications\n"); 30 + exit(1); 31 + } 32 + 33 + printf("Disabled power floor notifications\n"); 34 + 35 + close(fd); 36 + } 37 + 38 + int main(int argc, char **argv) 39 + { 40 + struct pollfd ufd; 41 + char status_str[3]; 42 + int fd, ret; 43 + 44 + if (signal(SIGINT, power_floor_exit) == SIG_IGN) 45 + signal(SIGINT, SIG_IGN); 46 + if (signal(SIGHUP, power_floor_exit) == SIG_IGN) 47 + signal(SIGHUP, SIG_IGN); 48 + if (signal(SIGTERM, power_floor_exit) == SIG_IGN) 49 + signal(SIGTERM, SIG_IGN); 50 + 51 + /* Enable feature via sysfs knob */ 52 + fd = open(POWER_FLOOR_ENABLE_ATTRIBUTE, O_RDWR); 53 + if (fd < 0) { 54 + perror("Unable to open power floor enable file\n"); 55 + exit(1); 56 + } 57 + 58 + if (write(fd, "1\n", 2) < 0) { 59 + perror("Can' enable power floor notifications\n"); 60 + exit(1); 61 + } 62 + 63 + close(fd); 64 + 65 + printf("Enabled power floor notifications\n"); 66 + 67 + while (1) { 68 + fd = open(POWER_FLOOR_STATUS_ATTRIBUTE, O_RDONLY); 69 + if (fd < 0) { 70 + perror("Unable to power floor status file\n"); 71 + exit(1); 72 + } 73 + 74 + if ((lseek(fd, 0L, SEEK_SET)) < 0) { 75 + fprintf(stderr, "Failed to set pointer to beginning\n"); 76 + exit(1); 77 + } 78 + 79 + if (read(fd, status_str, sizeof(status_str)) < 0) { 80 + fprintf(stderr, "Failed to read from:%s\n", 81 + POWER_FLOOR_STATUS_ATTRIBUTE); 82 + exit(1); 83 + } 84 + 85 + ufd.fd = fd; 86 + ufd.events = POLLPRI; 87 + 88 + ret = poll(&ufd, 1, -1); 89 + if (ret < 0) { 90 + perror("poll error"); 91 + exit(1); 92 + } else if (ret == 0) { 93 + printf("Poll Timeout\n"); 94 + } else { 95 + if ((lseek(fd, 0L, SEEK_SET)) < 0) { 96 + fprintf(stderr, "Failed to set pointer to beginning\n"); 97 + exit(1); 98 + } 99 + 100 + if (read(fd, status_str, sizeof(status_str)) < 0) 101 + exit(0); 102 + 103 + printf("power floor status: %s\n", status_str); 104 + } 105 + 106 + close(fd); 107 + } 108 + }
+12
tools/testing/selftests/thermal/intel/workload_hint/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + ifndef CROSS_COMPILE 3 + uname_M := $(shell uname -m 2>/dev/null || echo not) 4 + ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) 5 + 6 + ifeq ($(ARCH),x86) 7 + TEST_GEN_PROGS := workload_hint_test 8 + 9 + include ../../../lib.mk 10 + 11 + endif 12 + endif
+157
tools/testing/selftests/thermal/intel/workload_hint/workload_hint_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #define _GNU_SOURCE 4 + 5 + #include <stdio.h> 6 + #include <string.h> 7 + #include <stdlib.h> 8 + #include <unistd.h> 9 + #include <fcntl.h> 10 + #include <poll.h> 11 + #include <signal.h> 12 + 13 + #define WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/notification_delay_ms" 14 + #define WORKLOAD_ENABLE_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_hint_enable" 15 + #define WORKLOAD_TYPE_INDEX_ATTRIBUTE "/sys/bus/pci/devices/0000:00:04.0/workload_hint/workload_type_index" 16 + 17 + static const char * const workload_types[] = { 18 + "idle", 19 + "battery_life", 20 + "sustained", 21 + "bursty", 22 + NULL 23 + }; 24 + 25 + #define WORKLOAD_TYPE_MAX_INDEX 3 26 + 27 + void workload_hint_exit(int signum) 28 + { 29 + int fd; 30 + 31 + /* Disable feature via sysfs knob */ 32 + 33 + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); 34 + if (fd < 0) { 35 + perror("Unable to open workload type feature enable file\n"); 36 + exit(1); 37 + } 38 + 39 + if (write(fd, "0\n", 2) < 0) { 40 + perror("Can' disable workload hints\n"); 41 + exit(1); 42 + } 43 + 44 + printf("Disabled workload type prediction\n"); 45 + 46 + close(fd); 47 + } 48 + 49 + int main(int argc, char **argv) 50 + { 51 + struct pollfd ufd; 52 + char index_str[4]; 53 + int fd, ret, index; 54 + char delay_str[64]; 55 + int delay = 0; 56 + 57 + printf("Usage: workload_hint_test [notification delay in milli seconds]\n"); 58 + 59 + if (argc > 1) { 60 + ret = sscanf(argv[1], "%d", &delay); 61 + if (ret < 0) { 62 + printf("Invalid delay\n"); 63 + exit(1); 64 + } 65 + 66 + printf("Setting notification delay to %d ms\n", delay); 67 + if (delay < 0) 68 + exit(1); 69 + 70 + sprintf(delay_str, "%s\n", argv[1]); 71 + 72 + sprintf(delay_str, "%s\n", argv[1]); 73 + fd = open(WORKLOAD_NOTIFICATION_DELAY_ATTRIBUTE, O_RDWR); 74 + if (fd < 0) { 75 + perror("Unable to open workload notification delay\n"); 76 + exit(1); 77 + } 78 + 79 + if (write(fd, delay_str, strlen(delay_str)) < 0) { 80 + perror("Can't set delay\n"); 81 + exit(1); 82 + } 83 + 84 + close(fd); 85 + } 86 + 87 + if (signal(SIGINT, workload_hint_exit) == SIG_IGN) 88 + signal(SIGINT, SIG_IGN); 89 + if (signal(SIGHUP, workload_hint_exit) == SIG_IGN) 90 + signal(SIGHUP, SIG_IGN); 91 + if (signal(SIGTERM, workload_hint_exit) == SIG_IGN) 92 + signal(SIGTERM, SIG_IGN); 93 + 94 + /* Enable feature via sysfs knob */ 95 + fd = open(WORKLOAD_ENABLE_ATTRIBUTE, O_RDWR); 96 + if (fd < 0) { 97 + perror("Unable to open workload type feature enable file\n"); 98 + exit(1); 99 + } 100 + 101 + if (write(fd, "1\n", 2) < 0) { 102 + perror("Can' enable workload hints\n"); 103 + exit(1); 104 + } 105 + 106 + close(fd); 107 + 108 + printf("Enabled workload type prediction\n"); 109 + 110 + while (1) { 111 + fd = open(WORKLOAD_TYPE_INDEX_ATTRIBUTE, O_RDONLY); 112 + if (fd < 0) { 113 + perror("Unable to open workload type file\n"); 114 + exit(1); 115 + } 116 + 117 + if ((lseek(fd, 0L, SEEK_SET)) < 0) { 118 + fprintf(stderr, "Failed to set pointer to beginning\n"); 119 + exit(1); 120 + } 121 + 122 + if (read(fd, index_str, sizeof(index_str)) < 0) { 123 + fprintf(stderr, "Failed to read from:%s\n", 124 + WORKLOAD_TYPE_INDEX_ATTRIBUTE); 125 + exit(1); 126 + } 127 + 128 + ufd.fd = fd; 129 + ufd.events = POLLPRI; 130 + 131 + ret = poll(&ufd, 1, -1); 132 + if (ret < 0) { 133 + perror("poll error"); 134 + exit(1); 135 + } else if (ret == 0) { 136 + printf("Poll Timeout\n"); 137 + } else { 138 + if ((lseek(fd, 0L, SEEK_SET)) < 0) { 139 + fprintf(stderr, "Failed to set pointer to beginning\n"); 140 + exit(1); 141 + } 142 + 143 + if (read(fd, index_str, sizeof(index_str)) < 0) 144 + exit(0); 145 + 146 + ret = sscanf(index_str, "%d", &index); 147 + if (ret < 0) 148 + break; 149 + if (index > WORKLOAD_TYPE_MAX_INDEX) 150 + printf("Invalid workload type index\n"); 151 + else 152 + printf("workload type:%s\n", workload_types[index]); 153 + } 154 + 155 + close(fd); 156 + } 157 + }
-16
tools/thermal/lib/mainloop.c
··· 9 9 #include "log.h" 10 10 11 11 static int epfd = -1; 12 - static unsigned short nrhandler; 13 12 static sig_atomic_t exit_mainloop; 14 13 15 14 struct mainloop_data { ··· 16 17 void *data; 17 18 int fd; 18 19 }; 19 - 20 - static struct mainloop_data **mds; 21 20 22 21 #define MAX_EVENTS 10 23 22 ··· 58 61 59 62 struct mainloop_data *md; 60 63 61 - if (fd >= nrhandler) { 62 - mds = realloc(mds, sizeof(*mds) * (fd + 1)); 63 - if (!mds) 64 - return -1; 65 - nrhandler = fd + 1; 66 - } 67 - 68 64 md = malloc(sizeof(*md)); 69 65 if (!md) 70 66 return -1; ··· 66 76 md->cb = cb; 67 77 md->fd = fd; 68 78 69 - mds[fd] = md; 70 79 ev.data.ptr = md; 71 80 72 81 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { ··· 78 89 79 90 int mainloop_del(int fd) 80 91 { 81 - if (fd >= nrhandler) 82 - return -1; 83 - 84 92 if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0) 85 93 return -1; 86 - 87 - free(mds[fd]); 88 94 89 95 return 0; 90 96 }