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

thermal: intel: intel_soc_dts_iosf: Rework critical trip setup

Critical trip points appear in the DTS thermal zones only after those
thermal zones have been registered via intel_soc_dts_iosf_init().
Moreover, they are "created" by changing the type of an existing trip
point from THERMAL_TRIP_PASSIVE to THERMAL_TRIP_CRITICAL via
intel_soc_dts_iosf_add_read_only_critical_trip(), the caller of which
has to be careful enough to pass at least 1 as the number of read-only
trip points to intel_soc_dts_iosf_init() beforehand.

This is questionable, because user space may have started to use the
trips at the time when intel_soc_dts_iosf_add_read_only_critical_trip()
runs and there is no synchronization between it and sys_set_trip_temp().

To address it, use the observation that nonzero number of read-only
trip points is only passed to intel_soc_dts_iosf_init() when critical
trip points are going to be used, so in fact that function may get all
of the information regarding the critical trip points upfront and it
can configure them before registering the corresponding thermal zones.

Accordingly, replace the read_only_trip_count argument of
intel_soc_dts_iosf_init() with a pair of new arguments related to
critical trip points: a bool one indicating whether or not critical
trip points are to be used at all and an int one representing the
critical trip point temperature offset relative to Tj_max. Use these
arguments to configure the critical trip points before the registration
of the thermal zones and to compute the number of writeable trip points
in add_dts_thermal_zone().

Modify both callers of intel_soc_dts_iosf_init() to take these changes
into account and drop the intel_soc_dts_iosf_add_read_only_critical_trip()
call, that is not necessary any more, from intel_soc_thermal_init(),
which also allows it to return success right after requesting the IRQ.

Finally, drop intel_soc_dts_iosf_add_read_only_critical_trip()
altogether, because it does not have any more users.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Reviewed-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

+27 -51
+1 -1
drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c
··· 59 59 * ACPI/MSR. So we don't want to fail for auxiliary DTSs. 60 60 */ 61 61 proc_priv->soc_dts = intel_soc_dts_iosf_init( 62 - INTEL_SOC_DTS_INTERRUPT_MSI, 0); 62 + INTEL_SOC_DTS_INTERRUPT_MSI, false, 0); 63 63 64 64 if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) { 65 65 ret = pci_enable_msi(pdev);
+20 -31
drivers/thermal/intel/intel_soc_dts_iosf.c
··· 257 257 } 258 258 259 259 static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, 260 - int read_only_trip_cnt) 260 + bool critical_trip) 261 261 { 262 + int writable_trip_cnt = SOC_MAX_DTS_TRIPS; 262 263 char name[10]; 263 264 unsigned long trip; 264 - int writable_trip_cnt; 265 265 int trip_mask; 266 266 unsigned long ptps; 267 267 u32 store_ptps; ··· 276 276 277 277 dts->id = id; 278 278 279 - writable_trip_cnt = SOC_MAX_DTS_TRIPS - read_only_trip_cnt; 279 + if (critical_trip) 280 + writable_trip_cnt--; 281 + 280 282 trip_mask = GENMASK(writable_trip_cnt - 1, 0); 281 283 282 284 /* Check if the writable trip we provide is not used by BIOS */ ··· 316 314 err_ret: 317 315 return ret; 318 316 } 319 - 320 - int intel_soc_dts_iosf_add_read_only_critical_trip( 321 - struct intel_soc_dts_sensors *sensors, int critical_offset) 322 - { 323 - int i, j; 324 - 325 - for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 326 - struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i]; 327 - int temp = sensors->tj_max - critical_offset; 328 - unsigned long mask = entry->trip_mask; 329 - 330 - j = find_first_zero_bit(&mask, SOC_MAX_DTS_TRIPS); 331 - if (j < SOC_MAX_DTS_TRIPS) 332 - return configure_trip(entry, j, THERMAL_TRIP_CRITICAL, temp); 333 - } 334 - 335 - return -EINVAL; 336 - } 337 - EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip); 338 317 339 318 void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) 340 319 { ··· 358 375 configure_trip(&sensors->soc_dts[dts_index], 1, 0, 0); 359 376 } 360 377 361 - struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( 362 - enum intel_soc_dts_interrupt_type intr_type, int read_only_trip_count) 378 + struct intel_soc_dts_sensors * 379 + intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, 380 + bool critical_trip, int crit_offset) 363 381 { 364 382 struct intel_soc_dts_sensors *sensors; 365 383 int tj_max; ··· 369 385 370 386 if (!iosf_mbi_available()) 371 387 return ERR_PTR(-ENODEV); 372 - 373 - if (read_only_trip_count > SOC_MAX_DTS_TRIPS) 374 - return ERR_PTR(-EINVAL); 375 388 376 389 tj_max = intel_tcc_get_tjmax(-1); 377 390 if (tj_max < 0) ··· 384 403 sensors->tj_max = tj_max * 1000; 385 404 386 405 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 406 + enum thermal_trip_type trip_type; 407 + int temp; 408 + 387 409 sensors->soc_dts[i].sensors = sensors; 388 410 389 411 ret = configure_trip(&sensors->soc_dts[i], 0, ··· 394 410 if (ret) 395 411 goto err_reset_trips; 396 412 397 - ret = configure_trip(&sensors->soc_dts[i], 1, 398 - THERMAL_TRIP_PASSIVE, 0); 413 + if (critical_trip) { 414 + trip_type = THERMAL_TRIP_CRITICAL; 415 + temp = sensors->tj_max - crit_offset; 416 + } else { 417 + trip_type = THERMAL_TRIP_PASSIVE; 418 + temp = 0; 419 + } 420 + ret = configure_trip(&sensors->soc_dts[i], 1, trip_type, temp); 399 421 if (ret) 400 422 goto err_reset_trips; 401 423 } 402 424 403 425 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 404 - ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], 405 - read_only_trip_count); 426 + ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], critical_trip); 406 427 if (ret) 407 428 goto err_remove_zone; 408 429 }
+4 -4
drivers/thermal/intel/intel_soc_dts_iosf.h
··· 42 42 struct intel_soc_dts_sensor_entry soc_dts[SOC_MAX_DTS_SENSORS]; 43 43 }; 44 44 45 - struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( 46 - enum intel_soc_dts_interrupt_type intr_type, int read_only_trip_count); 45 + 46 + struct intel_soc_dts_sensors * 47 + intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, 48 + bool critical_trip, int crit_offset); 47 49 void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors); 48 50 void intel_soc_dts_iosf_interrupt_handler( 49 51 struct intel_soc_dts_sensors *sensors); 50 - int intel_soc_dts_iosf_add_read_only_critical_trip( 51 - struct intel_soc_dts_sensors *sensors, int critical_offset); 52 52 #endif
+2 -15
drivers/thermal/intel/intel_soc_dts_thermal.c
··· 51 51 return -ENODEV; 52 52 53 53 /* Create a zone with 2 trips with marked as read only */ 54 - soc_dts = intel_soc_dts_iosf_init(INTEL_SOC_DTS_INTERRUPT_APIC, 1); 54 + soc_dts = intel_soc_dts_iosf_init(INTEL_SOC_DTS_INTERRUPT_APIC, true, 55 + crit_offset); 55 56 if (IS_ERR(soc_dts)) { 56 57 err = PTR_ERR(soc_dts); 57 58 return err; ··· 89 88 } 90 89 } 91 90 92 - err = intel_soc_dts_iosf_add_read_only_critical_trip(soc_dts, 93 - crit_offset); 94 - if (err) 95 - goto error_trips; 96 - 97 91 return 0; 98 - 99 - error_trips: 100 - if (soc_dts_thres_irq) { 101 - free_irq(soc_dts_thres_irq, soc_dts); 102 - acpi_unregister_gsi(soc_dts_thres_gsi); 103 - } 104 - intel_soc_dts_iosf_exit(soc_dts); 105 - 106 - return err; 107 92 } 108 93 109 94 static void __exit intel_soc_thermal_exit(void)