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

thermal: power_allocator: relax the requirement of two passive trip points

The power allocator governor currently requires that the thermal zone
has at least two passive trip points. If there aren't, the governor
refuses to bind to the thermal zone.

This commit relaxes that requirement. Now the governor will bind to all
thermal zones regardless of how many trip points they have.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Signed-off-by: Javi Merino <javi.merino@arm.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>

authored by

Javi Merino and committed by
Eduardo Valentin
8b7b390f e055bb0f

+58 -45
+1 -1
Documentation/thermal/power_allocator.txt
··· 4 4 Trip points 5 5 ----------- 6 6 7 - The governor requires the following two passive trip points: 7 + The governor works optimally with the following two passive trip points: 8 8 9 9 1. "switch on" trip point: temperature above which the governor 10 10 control loop starts operating. This is the first passive trip
+57 -44
drivers/thermal/power_allocator.c
··· 24 24 25 25 #include "thermal_core.h" 26 26 27 + #define INVALID_TRIP -1 28 + 27 29 #define FRAC_BITS 10 28 30 #define int_to_frac(x) ((x) << FRAC_BITS) 29 31 #define frac_to_int(x) ((x) >> FRAC_BITS) ··· 63 61 * Used to calculate the derivative term. 64 62 * @trip_switch_on: first passive trip point of the thermal zone. The 65 63 * governor switches on when this trip point is crossed. 64 + * If the thermal zone only has one passive trip point, 65 + * @trip_switch_on should be INVALID_TRIP. 66 66 * @trip_max_desired_temperature: last passive trip point of the thermal 67 67 * zone. The temperature we are 68 68 * controlling for. ··· 436 432 return ret; 437 433 } 438 434 439 - static int get_governor_trips(struct thermal_zone_device *tz, 440 - struct power_allocator_params *params) 435 + /** 436 + * get_governor_trips() - get the number of the two trip points that are key for this governor 437 + * @tz: thermal zone to operate on 438 + * @params: pointer to private data for this governor 439 + * 440 + * The power allocator governor works optimally with two trips points: 441 + * a "switch on" trip point and a "maximum desired temperature". These 442 + * are defined as the first and last passive trip points. 443 + * 444 + * If there is only one trip point, then that's considered to be the 445 + * "maximum desired temperature" trip point and the governor is always 446 + * on. If there are no passive or active trip points, then the 447 + * governor won't do anything. In fact, its throttle function 448 + * won't be called at all. 449 + */ 450 + static void get_governor_trips(struct thermal_zone_device *tz, 451 + struct power_allocator_params *params) 441 452 { 442 - int i, ret, last_passive; 453 + int i, last_active, last_passive; 443 454 bool found_first_passive; 444 455 445 456 found_first_passive = false; 446 - last_passive = -1; 447 - ret = -EINVAL; 457 + last_active = INVALID_TRIP; 458 + last_passive = INVALID_TRIP; 448 459 449 460 for (i = 0; i < tz->trips; i++) { 450 461 enum thermal_trip_type type; 462 + int ret; 451 463 452 464 ret = tz->ops->get_trip_type(tz, i, &type); 453 - if (ret) 454 - return ret; 465 + if (ret) { 466 + dev_warn(&tz->device, 467 + "Failed to get trip point %d type: %d\n", i, 468 + ret); 469 + continue; 470 + } 455 471 456 - if (!found_first_passive) { 457 - if (type == THERMAL_TRIP_PASSIVE) { 472 + if (type == THERMAL_TRIP_PASSIVE) { 473 + if (!found_first_passive) { 458 474 params->trip_switch_on = i; 459 475 found_first_passive = true; 476 + } else { 477 + last_passive = i; 460 478 } 461 - } else if (type == THERMAL_TRIP_PASSIVE) { 462 - last_passive = i; 479 + } else if (type == THERMAL_TRIP_ACTIVE) { 480 + last_active = i; 463 481 } else { 464 482 break; 465 483 } 466 484 } 467 485 468 - if (last_passive != -1) { 486 + if (last_passive != INVALID_TRIP) { 469 487 params->trip_max_desired_temperature = last_passive; 470 - ret = 0; 488 + } else if (found_first_passive) { 489 + params->trip_max_desired_temperature = params->trip_switch_on; 490 + params->trip_switch_on = INVALID_TRIP; 471 491 } else { 472 - ret = -EINVAL; 492 + params->trip_switch_on = INVALID_TRIP; 493 + params->trip_max_desired_temperature = last_active; 473 494 } 474 - 475 - return ret; 476 495 } 477 496 478 497 static void reset_pid_controller(struct power_allocator_params *params) ··· 524 497 * power_allocator_bind() - bind the power_allocator governor to a thermal zone 525 498 * @tz: thermal zone to bind it to 526 499 * 527 - * Check that the thermal zone is valid for this governor, that is, it 528 - * has two thermal trips. If so, initialize the PID controller 529 - * parameters and bind it to the thermal zone. 500 + * Initialize the PID controller parameters and bind it to the thermal 501 + * zone. 530 502 * 531 - * Return: 0 on success, -EINVAL if the trips were invalid or -ENOMEM 503 + * Return: 0 on success, -EINVAL if the thermal zone doesn't have tzp or -ENOMEM 532 504 * if we ran out of memory. 533 505 */ 534 506 static int power_allocator_bind(struct thermal_zone_device *tz) ··· 546 520 if (!tz->tzp->sustainable_power) 547 521 dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n"); 548 522 549 - ret = get_governor_trips(tz, params); 550 - if (ret) { 551 - dev_err(&tz->device, 552 - "thermal zone %s has wrong trip setup for power allocator\n", 553 - tz->type); 554 - goto free; 523 + get_governor_trips(tz, params); 524 + 525 + if (tz->trips > 0) { 526 + ret = tz->ops->get_trip_temp(tz, 527 + params->trip_max_desired_temperature, 528 + &control_temp); 529 + if (!ret) 530 + estimate_pid_constants(tz, tz->tzp->sustainable_power, 531 + params->trip_switch_on, 532 + control_temp, false); 555 533 } 556 534 557 - ret = tz->ops->get_trip_temp(tz, params->trip_max_desired_temperature, 558 - &control_temp); 559 - if (ret) 560 - goto free; 561 - 562 - estimate_pid_constants(tz, tz->tzp->sustainable_power, 563 - params->trip_switch_on, control_temp, false); 564 535 reset_pid_controller(params); 565 536 566 537 tz->governor_data = params; 567 538 568 539 return 0; 569 - 570 - free: 571 - kfree(params); 572 - return ret; 573 540 } 574 541 575 542 static void power_allocator_unbind(struct thermal_zone_device *tz) ··· 593 574 594 575 ret = tz->ops->get_trip_temp(tz, params->trip_switch_on, 595 576 &switch_on_temp); 596 - if (ret) { 597 - dev_warn(&tz->device, 598 - "Failed to get switch on temperature: %d\n", ret); 599 - return ret; 600 - } 601 - 602 - if (current_temp < switch_on_temp) { 577 + if (!ret && (current_temp < switch_on_temp)) { 603 578 tz->passive = 0; 604 579 reset_pid_controller(params); 605 580 allow_maximum_power(tz);