diff options
| -rw-r--r-- | drivers/acpi/processor_throttling.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 18a873a55256..86c790e9f4fc 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -68,7 +68,7 @@ static int acpi_processor_update_tsd_coord(void) | |||
| 68 | 68 | ||
| 69 | /* | 69 | /* |
| 70 | * Now that we have _TSD data from all CPUs, lets setup T-state | 70 | * Now that we have _TSD data from all CPUs, lets setup T-state |
| 71 | * coordination among all CPUs. | 71 | * coordination between all CPUs. |
| 72 | */ | 72 | */ |
| 73 | for_each_possible_cpu(i) { | 73 | for_each_possible_cpu(i) { |
| 74 | pr = processors[i]; | 74 | pr = processors[i]; |
| @@ -988,6 +988,11 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 988 | { | 988 | { |
| 989 | cpumask_t saved_mask; | 989 | cpumask_t saved_mask; |
| 990 | int ret; | 990 | int ret; |
| 991 | unsigned int i; | ||
| 992 | struct acpi_processor *match_pr; | ||
| 993 | struct acpi_processor_throttling *p_throttling; | ||
| 994 | struct throttling_tstate t_state; | ||
| 995 | cpumask_t online_throttling_cpus; | ||
| 991 | 996 | ||
| 992 | if (!pr) | 997 | if (!pr) |
| 993 | return -EINVAL; | 998 | return -EINVAL; |
| @@ -998,12 +1003,76 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 998 | if ((state < 0) || (state > (pr->throttling.state_count - 1))) | 1003 | if ((state < 0) || (state > (pr->throttling.state_count - 1))) |
| 999 | return -EINVAL; | 1004 | return -EINVAL; |
| 1000 | 1005 | ||
| 1006 | saved_mask = current->cpus_allowed; | ||
| 1007 | t_state.target_state = state; | ||
| 1008 | p_throttling = &(pr->throttling); | ||
| 1009 | cpus_and(online_throttling_cpus, cpu_online_map, | ||
| 1010 | p_throttling->shared_cpu_map); | ||
| 1001 | /* | 1011 | /* |
| 1002 | * Migrate task to the cpu pointed by pr. | 1012 | * The throttling notifier will be called for every |
| 1013 | * affected cpu in order to get one proper T-state. | ||
| 1014 | * The notifier event is THROTTLING_PRECHANGE. | ||
| 1003 | */ | 1015 | */ |
| 1004 | saved_mask = current->cpus_allowed; | 1016 | for_each_cpu_mask(i, online_throttling_cpus) { |
| 1005 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | 1017 | t_state.cpu = i; |
| 1006 | ret = pr->throttling.acpi_processor_set_throttling(pr, state); | 1018 | acpi_processor_throttling_notifier(THROTTLING_PRECHANGE, |
| 1019 | &t_state); | ||
| 1020 | } | ||
| 1021 | /* | ||
| 1022 | * The function of acpi_processor_set_throttling will be called | ||
| 1023 | * to switch T-state. If the coordination type is SW_ALL or HW_ALL, | ||
| 1024 | * it is necessary to call it for every affected cpu. Otherwise | ||
| 1025 | * it can be called only for the cpu pointed by pr. | ||
| 1026 | */ | ||
| 1027 | if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) { | ||
| 1028 | set_cpus_allowed(current, cpumask_of_cpu(pr->id)); | ||
| 1029 | ret = p_throttling->acpi_processor_set_throttling(pr, | ||
| 1030 | t_state.target_state); | ||
| 1031 | } else { | ||
| 1032 | /* | ||
| 1033 | * When the T-state coordination is SW_ALL or HW_ALL, | ||
| 1034 | * it is necessary to set T-state for every affected | ||
| 1035 | * cpus. | ||
| 1036 | */ | ||
| 1037 | for_each_cpu_mask(i, online_throttling_cpus) { | ||
| 1038 | match_pr = processors[i]; | ||
| 1039 | /* | ||
| 1040 | * If the pointer is invalid, we will report the | ||
| 1041 | * error message and continue. | ||
| 1042 | */ | ||
| 1043 | if (!match_pr) { | ||
| 1044 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 1045 | "Invalid Pointer for CPU %d\n", i)); | ||
| 1046 | continue; | ||
| 1047 | } | ||
| 1048 | /* | ||
| 1049 | * If the throttling control is unsupported on CPU i, | ||
| 1050 | * we will report the error message and continue. | ||
| 1051 | */ | ||
| 1052 | if (!match_pr->flags.throttling) { | ||
| 1053 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 1054 | "Throttling Controll is unsupported " | ||
| 1055 | "on CPU %d\n", i)); | ||
| 1056 | continue; | ||
| 1057 | } | ||
| 1058 | t_state.cpu = i; | ||
| 1059 | set_cpus_allowed(current, cpumask_of_cpu(i)); | ||
| 1060 | ret = match_pr->throttling. | ||
| 1061 | acpi_processor_set_throttling( | ||
| 1062 | match_pr, t_state.target_state); | ||
| 1063 | } | ||
| 1064 | } | ||
| 1065 | /* | ||
| 1066 | * After the set_throttling is called, the | ||
| 1067 | * throttling notifier is called for every | ||
| 1068 | * affected cpu to update the T-states. | ||
| 1069 | * The notifier event is THROTTLING_POSTCHANGE | ||
| 1070 | */ | ||
| 1071 | for_each_cpu_mask(i, online_throttling_cpus) { | ||
| 1072 | t_state.cpu = i; | ||
| 1073 | acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE, | ||
| 1074 | &t_state); | ||
| 1075 | } | ||
| 1007 | /* restore the previous state */ | 1076 | /* restore the previous state */ |
| 1008 | set_cpus_allowed(current, saved_mask); | 1077 | set_cpus_allowed(current, saved_mask); |
| 1009 | return ret; | 1078 | return ret; |
