Commit 1cbf4c563c0eaaf11c552a88b374e213181c6ddd
Committed by
Len Brown
1 parent
d2149b5423
Exists in
master
and in
7 other branches
[ACPI] Allow return to active cooling mode once passive mode is entered
http://bugzilla.kernel.org/show_bug.cgi?id=3410 https://bugzilla.novell.com/show_bug.cgi?id=131543 Signed-off-by: Thomas Renninger <trenn@suse.de> Signed-off-by: Konstantin Karasyov <konstantin.a.karasyov@intel.com> Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> Signed-off-by: Yu Luming <luming.yu@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org>
Showing 2 changed files with 108 additions and 93 deletions Side-by-side Diff
drivers/acpi/processor_thermal.c
... | ... | @@ -101,10 +101,8 @@ |
101 | 101 | static int cpu_has_cpufreq(unsigned int cpu) |
102 | 102 | { |
103 | 103 | struct cpufreq_policy policy; |
104 | - if (!acpi_thermal_cpufreq_is_init) | |
104 | + if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu)) | |
105 | 105 | return -ENODEV; |
106 | - if (!cpufreq_get_policy(&policy, cpu)) | |
107 | - return -ENODEV; | |
108 | 106 | return 0; |
109 | 107 | } |
110 | 108 | |
111 | 109 | |
... | ... | @@ -127,13 +125,13 @@ |
127 | 125 | if (!cpu_has_cpufreq(cpu)) |
128 | 126 | return -ENODEV; |
129 | 127 | |
130 | - if (cpufreq_thermal_reduction_pctg[cpu] >= 20) { | |
128 | + if (cpufreq_thermal_reduction_pctg[cpu] > 20) | |
131 | 129 | cpufreq_thermal_reduction_pctg[cpu] -= 20; |
132 | - cpufreq_update_policy(cpu); | |
133 | - return 0; | |
134 | - } | |
135 | - | |
136 | - return -ERANGE; | |
130 | + else | |
131 | + cpufreq_thermal_reduction_pctg[cpu] = 0; | |
132 | + cpufreq_update_policy(cpu); | |
133 | + /* We reached max freq again and can leave passive mode */ | |
134 | + return !cpufreq_thermal_reduction_pctg[cpu]; | |
137 | 135 | } |
138 | 136 | |
139 | 137 | static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, |
... | ... | @@ -200,7 +198,7 @@ |
200 | 198 | int result = 0; |
201 | 199 | struct acpi_processor *pr = NULL; |
202 | 200 | struct acpi_device *device = NULL; |
203 | - int tx = 0; | |
201 | + int tx = 0, max_tx_px = 0; | |
204 | 202 | |
205 | 203 | ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); |
206 | 204 | |
207 | 205 | |
208 | 206 | |
209 | 207 | |
... | ... | @@ -259,19 +257,27 @@ |
259 | 257 | /* if going down: T-states first, P-states later */ |
260 | 258 | |
261 | 259 | if (pr->flags.throttling) { |
262 | - if (tx == 0) | |
260 | + if (tx == 0) { | |
261 | + max_tx_px = 1; | |
263 | 262 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
264 | 263 | "At minimum throttling state\n")); |
265 | - else { | |
264 | + } else { | |
266 | 265 | tx--; |
267 | 266 | goto end; |
268 | 267 | } |
269 | 268 | } |
270 | 269 | |
271 | 270 | result = acpi_thermal_cpufreq_decrease(pr->id); |
272 | - if (result == -ERANGE) | |
271 | + if (result) { | |
272 | + /* | |
273 | + * We only could get -ERANGE, 1 or 0. | |
274 | + * In the first two cases we reached max freq again. | |
275 | + */ | |
273 | 276 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
274 | 277 | "At minimum performance state\n")); |
278 | + max_tx_px = 1; | |
279 | + } else | |
280 | + max_tx_px = 0; | |
275 | 281 | |
276 | 282 | break; |
277 | 283 | } |
... | ... | @@ -290,8 +296,10 @@ |
290 | 296 | pr->limit.thermal.px, pr->limit.thermal.tx)); |
291 | 297 | } else |
292 | 298 | result = 0; |
293 | - | |
294 | - return_VALUE(result); | |
299 | + if (max_tx_px) | |
300 | + return_VALUE(1); | |
301 | + else | |
302 | + return_VALUE(result); | |
295 | 303 | } |
296 | 304 | |
297 | 305 | int acpi_processor_get_limit_info(struct acpi_processor *pr) |
drivers/acpi/thermal.c
... | ... | @@ -72,7 +72,7 @@ |
72 | 72 | #define _COMPONENT ACPI_THERMAL_COMPONENT |
73 | 73 | ACPI_MODULE_NAME("acpi_thermal") |
74 | 74 | |
75 | - MODULE_AUTHOR("Paul Diefenbaugh"); | |
75 | +MODULE_AUTHOR("Paul Diefenbaugh"); | |
76 | 76 | MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); |
77 | 77 | MODULE_LICENSE("GPL"); |
78 | 78 | |
79 | 79 | |
... | ... | @@ -517,9 +517,9 @@ |
517 | 517 | return_VALUE(0); |
518 | 518 | } |
519 | 519 | |
520 | -static int acpi_thermal_passive(struct acpi_thermal *tz) | |
520 | +static void acpi_thermal_passive(struct acpi_thermal *tz) | |
521 | 521 | { |
522 | - int result = 0; | |
522 | + int result = 1; | |
523 | 523 | struct acpi_thermal_passive *passive = NULL; |
524 | 524 | int trend = 0; |
525 | 525 | int i = 0; |
... | ... | @@ -527,7 +527,7 @@ |
527 | 527 | ACPI_FUNCTION_TRACE("acpi_thermal_passive"); |
528 | 528 | |
529 | 529 | if (!tz || !tz->trips.passive.flags.valid) |
530 | - return_VALUE(-EINVAL); | |
530 | + return; | |
531 | 531 | |
532 | 532 | passive = &(tz->trips.passive); |
533 | 533 | |
... | ... | @@ -547,7 +547,7 @@ |
547 | 547 | trend, passive->tc1, tz->temperature, |
548 | 548 | tz->last_temperature, passive->tc2, |
549 | 549 | tz->temperature, passive->temperature)); |
550 | - tz->trips.passive.flags.enabled = 1; | |
550 | + passive->flags.enabled = 1; | |
551 | 551 | /* Heating up? */ |
552 | 552 | if (trend > 0) |
553 | 553 | for (i = 0; i < passive->devices.count; i++) |
554 | 554 | |
... | ... | @@ -556,12 +556,32 @@ |
556 | 556 | handles[i], |
557 | 557 | ACPI_PROCESSOR_LIMIT_INCREMENT); |
558 | 558 | /* Cooling off? */ |
559 | - else if (trend < 0) | |
559 | + else if (trend < 0) { | |
560 | 560 | for (i = 0; i < passive->devices.count; i++) |
561 | - acpi_processor_set_thermal_limit(passive-> | |
562 | - devices. | |
563 | - handles[i], | |
564 | - ACPI_PROCESSOR_LIMIT_DECREMENT); | |
561 | + /* | |
562 | + * assume that we are on highest | |
563 | + * freq/lowest thrott and can leave | |
564 | + * passive mode, even in error case | |
565 | + */ | |
566 | + if (!acpi_processor_set_thermal_limit | |
567 | + (passive->devices.handles[i], | |
568 | + ACPI_PROCESSOR_LIMIT_DECREMENT)) | |
569 | + result = 0; | |
570 | + /* | |
571 | + * Leave cooling mode, even if the temp might | |
572 | + * higher than trip point This is because some | |
573 | + * machines might have long thermal polling | |
574 | + * frequencies (tsp) defined. We will fall back | |
575 | + * into passive mode in next cycle (probably quicker) | |
576 | + */ | |
577 | + if (result) { | |
578 | + passive->flags.enabled = 0; | |
579 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
580 | + "Disabling passive cooling, still above threshold," | |
581 | + " but we are cooling down\n")); | |
582 | + } | |
583 | + } | |
584 | + return; | |
565 | 585 | } |
566 | 586 | |
567 | 587 | /* |
568 | 588 | |
569 | 589 | |
... | ... | @@ -571,23 +591,21 @@ |
571 | 591 | * and avoid thrashing around the passive trip point. Note that we |
572 | 592 | * assume symmetry. |
573 | 593 | */ |
574 | - else if (tz->trips.passive.flags.enabled) { | |
575 | - for (i = 0; i < passive->devices.count; i++) | |
576 | - result = | |
577 | - acpi_processor_set_thermal_limit(passive->devices. | |
578 | - handles[i], | |
579 | - ACPI_PROCESSOR_LIMIT_DECREMENT); | |
580 | - if (result == 1) { | |
581 | - tz->trips.passive.flags.enabled = 0; | |
582 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
583 | - "Disabling passive cooling (zone is cool)\n")); | |
584 | - } | |
594 | + if (!passive->flags.enabled) | |
595 | + return; | |
596 | + for (i = 0; i < passive->devices.count; i++) | |
597 | + if (!acpi_processor_set_thermal_limit | |
598 | + (passive->devices.handles[i], | |
599 | + ACPI_PROCESSOR_LIMIT_DECREMENT)) | |
600 | + result = 0; | |
601 | + if (result) { | |
602 | + passive->flags.enabled = 0; | |
603 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
604 | + "Disabling passive cooling (zone is cool)\n")); | |
585 | 605 | } |
586 | - | |
587 | - return_VALUE(0); | |
588 | 606 | } |
589 | 607 | |
590 | -static int acpi_thermal_active(struct acpi_thermal *tz) | |
608 | +static void acpi_thermal_active(struct acpi_thermal *tz) | |
591 | 609 | { |
592 | 610 | int result = 0; |
593 | 611 | struct acpi_thermal_active *active = NULL; |
594 | 612 | |
595 | 613 | |
596 | 614 | |
597 | 615 | |
598 | 616 | |
599 | 617 | |
600 | 618 | |
601 | 619 | |
602 | 620 | |
603 | 621 | |
604 | 622 | |
... | ... | @@ -598,74 +616,66 @@ |
598 | 616 | ACPI_FUNCTION_TRACE("acpi_thermal_active"); |
599 | 617 | |
600 | 618 | if (!tz) |
601 | - return_VALUE(-EINVAL); | |
619 | + return; | |
602 | 620 | |
603 | 621 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { |
604 | - | |
605 | 622 | active = &(tz->trips.active[i]); |
606 | 623 | if (!active || !active->flags.valid) |
607 | 624 | break; |
608 | - | |
609 | - /* | |
610 | - * Above Threshold? | |
611 | - * ---------------- | |
612 | - * If not already enabled, turn ON all cooling devices | |
613 | - * associated with this active threshold. | |
614 | - */ | |
615 | 625 | if (tz->temperature >= active->temperature) { |
626 | + /* | |
627 | + * Above Threshold? | |
628 | + * ---------------- | |
629 | + * If not already enabled, turn ON all cooling devices | |
630 | + * associated with this active threshold. | |
631 | + */ | |
616 | 632 | if (active->temperature > maxtemp) |
617 | - tz->state.active_index = i, maxtemp = | |
618 | - active->temperature; | |
619 | - if (!active->flags.enabled) { | |
620 | - for (j = 0; j < active->devices.count; j++) { | |
621 | - result = | |
622 | - acpi_bus_set_power(active->devices. | |
623 | - handles[j], | |
624 | - ACPI_STATE_D0); | |
625 | - if (result) { | |
626 | - ACPI_DEBUG_PRINT((ACPI_DB_WARN, | |
627 | - "Unable to turn cooling device [%p] 'on'\n", | |
628 | - active-> | |
629 | - devices. | |
630 | - handles[j])); | |
631 | - continue; | |
632 | - } | |
633 | - active->flags.enabled = 1; | |
634 | - ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
635 | - "Cooling device [%p] now 'on'\n", | |
636 | - active->devices. | |
637 | - handles[j])); | |
638 | - } | |
639 | - } | |
640 | - } | |
641 | - /* | |
642 | - * Below Threshold? | |
643 | - * ---------------- | |
644 | - * Turn OFF all cooling devices associated with this | |
645 | - * threshold. | |
646 | - */ | |
647 | - else if (active->flags.enabled) { | |
633 | + tz->state.active_index = i; | |
634 | + maxtemp = active->temperature; | |
635 | + if (active->flags.enabled) | |
636 | + continue; | |
648 | 637 | for (j = 0; j < active->devices.count; j++) { |
649 | 638 | result = |
650 | 639 | acpi_bus_set_power(active->devices. |
651 | 640 | handles[j], |
652 | - ACPI_STATE_D3); | |
641 | + ACPI_STATE_D0); | |
653 | 642 | if (result) { |
654 | 643 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, |
655 | - "Unable to turn cooling device [%p] 'off'\n", | |
644 | + "Unable to turn cooling device [%p] 'on'\n", | |
656 | 645 | active->devices. |
657 | 646 | handles[j])); |
658 | 647 | continue; |
659 | 648 | } |
660 | - active->flags.enabled = 0; | |
649 | + active->flags.enabled = 1; | |
661 | 650 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
662 | - "Cooling device [%p] now 'off'\n", | |
651 | + "Cooling device [%p] now 'on'\n", | |
663 | 652 | active->devices.handles[j])); |
664 | 653 | } |
654 | + continue; | |
665 | 655 | } |
656 | + if (!active->flags.enabled) | |
657 | + continue; | |
658 | + /* | |
659 | + * Below Threshold? | |
660 | + * ---------------- | |
661 | + * Turn OFF all cooling devices associated with this | |
662 | + * threshold. | |
663 | + */ | |
664 | + for (j = 0; j < active->devices.count; j++) { | |
665 | + result = acpi_bus_set_power(active->devices.handles[j], | |
666 | + ACPI_STATE_D3); | |
667 | + if (result) { | |
668 | + ACPI_DEBUG_PRINT((ACPI_DB_WARN, | |
669 | + "Unable to turn cooling device [%p] 'off'\n", | |
670 | + active->devices.handles[j])); | |
671 | + continue; | |
672 | + } | |
673 | + active->flags.enabled = 0; | |
674 | + ACPI_DEBUG_PRINT((ACPI_DB_INFO, | |
675 | + "Cooling device [%p] now 'off'\n", | |
676 | + active->devices.handles[j])); | |
677 | + } | |
666 | 678 | } |
667 | - | |
668 | - return_VALUE(0); | |
669 | 679 | } |
670 | 680 | |
671 | 681 | static void acpi_thermal_check(void *context); |
672 | 682 | |
... | ... | @@ -744,15 +754,12 @@ |
744 | 754 | * Again, separated from the above two to allow independent policy |
745 | 755 | * decisions. |
746 | 756 | */ |
747 | - if (tz->trips.critical.flags.enabled) | |
748 | - tz->state.critical = 1; | |
749 | - if (tz->trips.hot.flags.enabled) | |
750 | - tz->state.hot = 1; | |
751 | - if (tz->trips.passive.flags.enabled) | |
752 | - tz->state.passive = 1; | |
757 | + tz->state.critical = tz->trips.critical.flags.enabled; | |
758 | + tz->state.hot = tz->trips.hot.flags.enabled; | |
759 | + tz->state.passive = tz->trips.passive.flags.enabled; | |
760 | + tz->state.active = 0; | |
753 | 761 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) |
754 | - if (tz->trips.active[i].flags.enabled) | |
755 | - tz->state.active = 1; | |
762 | + tz->state.active |= tz->trips.active[i].flags.enabled; | |
756 | 763 | |
757 | 764 | /* |
758 | 765 | * Calculate Sleep Time |