diff options
author | Thomas Renninger <trenn@suse.de> | 2004-09-16 11:07:00 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2005-11-30 22:51:04 -0500 |
commit | 1cbf4c563c0eaaf11c552a88b374e213181c6ddd (patch) | |
tree | 6ec08fedd46526c3dbed911026e1581c82d50531 /drivers/acpi | |
parent | d2149b542382bfc206cb28485108f6470c979566 (diff) |
[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>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_thermal.c | 38 | ||||
-rw-r--r-- | drivers/acpi/thermal.c | 163 |
2 files changed, 108 insertions, 93 deletions
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 37528c3b64b0..f37584015324 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -101,9 +101,7 @@ static unsigned int acpi_thermal_cpufreq_is_init = 0; | |||
101 | static int cpu_has_cpufreq(unsigned int cpu) | 101 | static int cpu_has_cpufreq(unsigned int cpu) |
102 | { | 102 | { |
103 | struct cpufreq_policy policy; | 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 | return -ENODEV; | ||
106 | if (!cpufreq_get_policy(&policy, cpu)) | ||
107 | return -ENODEV; | 105 | return -ENODEV; |
108 | return 0; | 106 | return 0; |
109 | } | 107 | } |
@@ -127,13 +125,13 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) | |||
127 | if (!cpu_has_cpufreq(cpu)) | 125 | if (!cpu_has_cpufreq(cpu)) |
128 | return -ENODEV; | 126 | return -ENODEV; |
129 | 127 | ||
130 | if (cpufreq_thermal_reduction_pctg[cpu] >= 20) { | 128 | if (cpufreq_thermal_reduction_pctg[cpu] > 20) |
131 | cpufreq_thermal_reduction_pctg[cpu] -= 20; | 129 | cpufreq_thermal_reduction_pctg[cpu] -= 20; |
132 | cpufreq_update_policy(cpu); | 130 | else |
133 | return 0; | 131 | cpufreq_thermal_reduction_pctg[cpu] = 0; |
134 | } | 132 | cpufreq_update_policy(cpu); |
135 | 133 | /* We reached max freq again and can leave passive mode */ | |
136 | return -ERANGE; | 134 | return !cpufreq_thermal_reduction_pctg[cpu]; |
137 | } | 135 | } |
138 | 136 | ||
139 | static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, | 137 | static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, |
@@ -200,7 +198,7 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) | |||
200 | int result = 0; | 198 | int result = 0; |
201 | struct acpi_processor *pr = NULL; | 199 | struct acpi_processor *pr = NULL; |
202 | struct acpi_device *device = NULL; | 200 | struct acpi_device *device = NULL; |
203 | int tx = 0; | 201 | int tx = 0, max_tx_px = 0; |
204 | 202 | ||
205 | ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); | 203 | ACPI_FUNCTION_TRACE("acpi_processor_set_thermal_limit"); |
206 | 204 | ||
@@ -259,19 +257,27 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) | |||
259 | /* if going down: T-states first, P-states later */ | 257 | /* if going down: T-states first, P-states later */ |
260 | 258 | ||
261 | if (pr->flags.throttling) { | 259 | if (pr->flags.throttling) { |
262 | if (tx == 0) | 260 | if (tx == 0) { |
261 | max_tx_px = 1; | ||
263 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 262 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
264 | "At minimum throttling state\n")); | 263 | "At minimum throttling state\n")); |
265 | else { | 264 | } else { |
266 | tx--; | 265 | tx--; |
267 | goto end; | 266 | goto end; |
268 | } | 267 | } |
269 | } | 268 | } |
270 | 269 | ||
271 | result = acpi_thermal_cpufreq_decrease(pr->id); | 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 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 276 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
274 | "At minimum performance state\n")); | 277 | "At minimum performance state\n")); |
278 | max_tx_px = 1; | ||
279 | } else | ||
280 | max_tx_px = 0; | ||
275 | 281 | ||
276 | break; | 282 | break; |
277 | } | 283 | } |
@@ -290,8 +296,10 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type) | |||
290 | pr->limit.thermal.px, pr->limit.thermal.tx)); | 296 | pr->limit.thermal.px, pr->limit.thermal.tx)); |
291 | } else | 297 | } else |
292 | result = 0; | 298 | result = 0; |
293 | 299 | if (max_tx_px) | |
294 | return_VALUE(result); | 300 | return_VALUE(1); |
301 | else | ||
302 | return_VALUE(result); | ||
295 | } | 303 | } |
296 | 304 | ||
297 | int acpi_processor_get_limit_info(struct acpi_processor *pr) | 305 | int acpi_processor_get_limit_info(struct acpi_processor *pr) |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index a24847c08f7f..19f3ea48475e 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -72,7 +72,7 @@ | |||
72 | #define _COMPONENT ACPI_THERMAL_COMPONENT | 72 | #define _COMPONENT ACPI_THERMAL_COMPONENT |
73 | ACPI_MODULE_NAME("acpi_thermal") | 73 | ACPI_MODULE_NAME("acpi_thermal") |
74 | 74 | ||
75 | MODULE_AUTHOR("Paul Diefenbaugh"); | 75 | MODULE_AUTHOR("Paul Diefenbaugh"); |
76 | MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); | 76 | MODULE_DESCRIPTION(ACPI_THERMAL_DRIVER_NAME); |
77 | MODULE_LICENSE("GPL"); | 77 | MODULE_LICENSE("GPL"); |
78 | 78 | ||
@@ -517,9 +517,9 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) | |||
517 | return_VALUE(0); | 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 | struct acpi_thermal_passive *passive = NULL; | 523 | struct acpi_thermal_passive *passive = NULL; |
524 | int trend = 0; | 524 | int trend = 0; |
525 | int i = 0; | 525 | int i = 0; |
@@ -527,7 +527,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) | |||
527 | ACPI_FUNCTION_TRACE("acpi_thermal_passive"); | 527 | ACPI_FUNCTION_TRACE("acpi_thermal_passive"); |
528 | 528 | ||
529 | if (!tz || !tz->trips.passive.flags.valid) | 529 | if (!tz || !tz->trips.passive.flags.valid) |
530 | return_VALUE(-EINVAL); | 530 | return; |
531 | 531 | ||
532 | passive = &(tz->trips.passive); | 532 | passive = &(tz->trips.passive); |
533 | 533 | ||
@@ -547,7 +547,7 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) | |||
547 | trend, passive->tc1, tz->temperature, | 547 | trend, passive->tc1, tz->temperature, |
548 | tz->last_temperature, passive->tc2, | 548 | tz->last_temperature, passive->tc2, |
549 | tz->temperature, passive->temperature)); | 549 | tz->temperature, passive->temperature)); |
550 | tz->trips.passive.flags.enabled = 1; | 550 | passive->flags.enabled = 1; |
551 | /* Heating up? */ | 551 | /* Heating up? */ |
552 | if (trend > 0) | 552 | if (trend > 0) |
553 | for (i = 0; i < passive->devices.count; i++) | 553 | for (i = 0; i < passive->devices.count; i++) |
@@ -556,12 +556,32 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) | |||
556 | handles[i], | 556 | handles[i], |
557 | ACPI_PROCESSOR_LIMIT_INCREMENT); | 557 | ACPI_PROCESSOR_LIMIT_INCREMENT); |
558 | /* Cooling off? */ | 558 | /* Cooling off? */ |
559 | else if (trend < 0) | 559 | else if (trend < 0) { |
560 | for (i = 0; i < passive->devices.count; i++) | 560 | for (i = 0; i < passive->devices.count; i++) |
561 | acpi_processor_set_thermal_limit(passive-> | 561 | /* |
562 | devices. | 562 | * assume that we are on highest |
563 | handles[i], | 563 | * freq/lowest thrott and can leave |
564 | ACPI_PROCESSOR_LIMIT_DECREMENT); | 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 | /* |
@@ -571,23 +591,21 @@ static int acpi_thermal_passive(struct acpi_thermal *tz) | |||
571 | * and avoid thrashing around the passive trip point. Note that we | 591 | * and avoid thrashing around the passive trip point. Note that we |
572 | * assume symmetry. | 592 | * assume symmetry. |
573 | */ | 593 | */ |
574 | else if (tz->trips.passive.flags.enabled) { | 594 | if (!passive->flags.enabled) |
575 | for (i = 0; i < passive->devices.count; i++) | 595 | return; |
576 | result = | 596 | for (i = 0; i < passive->devices.count; i++) |
577 | acpi_processor_set_thermal_limit(passive->devices. | 597 | if (!acpi_processor_set_thermal_limit |
578 | handles[i], | 598 | (passive->devices.handles[i], |
579 | ACPI_PROCESSOR_LIMIT_DECREMENT); | 599 | ACPI_PROCESSOR_LIMIT_DECREMENT)) |
580 | if (result == 1) { | 600 | result = 0; |
581 | tz->trips.passive.flags.enabled = 0; | 601 | if (result) { |
582 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 602 | passive->flags.enabled = 0; |
583 | "Disabling passive cooling (zone is cool)\n")); | 603 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
584 | } | 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 | int result = 0; | 610 | int result = 0; |
593 | struct acpi_thermal_active *active = NULL; | 611 | struct acpi_thermal_active *active = NULL; |
@@ -598,74 +616,66 @@ static int acpi_thermal_active(struct acpi_thermal *tz) | |||
598 | ACPI_FUNCTION_TRACE("acpi_thermal_active"); | 616 | ACPI_FUNCTION_TRACE("acpi_thermal_active"); |
599 | 617 | ||
600 | if (!tz) | 618 | if (!tz) |
601 | return_VALUE(-EINVAL); | 619 | return; |
602 | 620 | ||
603 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { | 621 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { |
604 | |||
605 | active = &(tz->trips.active[i]); | 622 | active = &(tz->trips.active[i]); |
606 | if (!active || !active->flags.valid) | 623 | if (!active || !active->flags.valid) |
607 | break; | 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 | if (tz->temperature >= active->temperature) { | 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 | if (active->temperature > maxtemp) | 632 | if (active->temperature > maxtemp) |
617 | tz->state.active_index = i, maxtemp = | 633 | tz->state.active_index = i; |
618 | active->temperature; | 634 | maxtemp = active->temperature; |
619 | if (!active->flags.enabled) { | 635 | if (active->flags.enabled) |
620 | for (j = 0; j < active->devices.count; j++) { | 636 | continue; |
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) { | ||
648 | for (j = 0; j < active->devices.count; j++) { | 637 | for (j = 0; j < active->devices.count; j++) { |
649 | result = | 638 | result = |
650 | acpi_bus_set_power(active->devices. | 639 | acpi_bus_set_power(active->devices. |
651 | handles[j], | 640 | handles[j], |
652 | ACPI_STATE_D3); | 641 | ACPI_STATE_D0); |
653 | if (result) { | 642 | if (result) { |
654 | ACPI_DEBUG_PRINT((ACPI_DB_WARN, | 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 | active->devices. | 645 | active->devices. |
657 | handles[j])); | 646 | handles[j])); |
658 | continue; | 647 | continue; |
659 | } | 648 | } |
660 | active->flags.enabled = 0; | 649 | active->flags.enabled = 1; |
661 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 650 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
662 | "Cooling device [%p] now 'off'\n", | 651 | "Cooling device [%p] now 'on'\n", |
663 | active->devices.handles[j])); | 652 | active->devices.handles[j])); |
664 | } | 653 | } |
654 | continue; | ||
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])); | ||
665 | } | 677 | } |
666 | } | 678 | } |
667 | |||
668 | return_VALUE(0); | ||
669 | } | 679 | } |
670 | 680 | ||
671 | static void acpi_thermal_check(void *context); | 681 | static void acpi_thermal_check(void *context); |
@@ -744,15 +754,12 @@ static void acpi_thermal_check(void *data) | |||
744 | * Again, separated from the above two to allow independent policy | 754 | * Again, separated from the above two to allow independent policy |
745 | * decisions. | 755 | * decisions. |
746 | */ | 756 | */ |
747 | if (tz->trips.critical.flags.enabled) | 757 | tz->state.critical = tz->trips.critical.flags.enabled; |
748 | tz->state.critical = 1; | 758 | tz->state.hot = tz->trips.hot.flags.enabled; |
749 | if (tz->trips.hot.flags.enabled) | 759 | tz->state.passive = tz->trips.passive.flags.enabled; |
750 | tz->state.hot = 1; | 760 | tz->state.active = 0; |
751 | if (tz->trips.passive.flags.enabled) | ||
752 | tz->state.passive = 1; | ||
753 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) | 761 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) |
754 | if (tz->trips.active[i].flags.enabled) | 762 | tz->state.active |= tz->trips.active[i].flags.enabled; |
755 | tz->state.active = 1; | ||
756 | 763 | ||
757 | /* | 764 | /* |
758 | * Calculate Sleep Time | 765 | * Calculate Sleep Time |