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; |