diff options
Diffstat (limited to 'drivers/acpi/processor_throttling.c')
-rw-r--r-- | drivers/acpi/processor_throttling.c | 180 |
1 files changed, 179 insertions, 1 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 5d2eae207886..d6780f41d28c 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -48,6 +48,154 @@ ACPI_MODULE_NAME("processor_throttling"); | |||
48 | static int acpi_processor_get_throttling(struct acpi_processor *pr); | 48 | static int acpi_processor_get_throttling(struct acpi_processor *pr); |
49 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | 49 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); |
50 | 50 | ||
51 | static int acpi_processor_update_tsd_coord(void) | ||
52 | { | ||
53 | int count, count_target; | ||
54 | int retval = 0; | ||
55 | unsigned int i, j; | ||
56 | cpumask_t covered_cpus; | ||
57 | struct acpi_processor *pr, *match_pr; | ||
58 | struct acpi_tsd_package *pdomain, *match_pdomain; | ||
59 | struct acpi_processor_throttling *pthrottling, *match_pthrottling; | ||
60 | |||
61 | /* | ||
62 | * Now that we have _TSD data from all CPUs, lets setup T-state | ||
63 | * coordination among all CPUs. | ||
64 | */ | ||
65 | for_each_possible_cpu(i) { | ||
66 | pr = processors[i]; | ||
67 | if (!pr) | ||
68 | continue; | ||
69 | |||
70 | /* Basic validity check for domain info */ | ||
71 | pthrottling = &(pr->throttling); | ||
72 | |||
73 | /* | ||
74 | * If tsd package for one cpu is invalid, the coordination | ||
75 | * among all CPUs is thought as invalid. | ||
76 | * Maybe it is ugly. | ||
77 | */ | ||
78 | if (!pthrottling->tsd_valid_flag) { | ||
79 | retval = -EINVAL; | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | if (retval) | ||
84 | goto err_ret; | ||
85 | |||
86 | cpus_clear(covered_cpus); | ||
87 | for_each_possible_cpu(i) { | ||
88 | pr = processors[i]; | ||
89 | if (!pr) | ||
90 | continue; | ||
91 | |||
92 | if (cpu_isset(i, covered_cpus)) | ||
93 | continue; | ||
94 | pthrottling = &pr->throttling; | ||
95 | |||
96 | pdomain = &(pthrottling->domain_info); | ||
97 | cpu_set(i, pthrottling->shared_cpu_map); | ||
98 | cpu_set(i, covered_cpus); | ||
99 | /* | ||
100 | * If the number of processor in the TSD domain is 1, it is | ||
101 | * unnecessary to parse the coordination for this CPU. | ||
102 | */ | ||
103 | if (pdomain->num_processors <= 1) | ||
104 | continue; | ||
105 | |||
106 | /* Validate the Domain info */ | ||
107 | count_target = pdomain->num_processors; | ||
108 | count = 1; | ||
109 | |||
110 | for_each_possible_cpu(j) { | ||
111 | if (i == j) | ||
112 | continue; | ||
113 | |||
114 | match_pr = processors[j]; | ||
115 | if (!match_pr) | ||
116 | continue; | ||
117 | |||
118 | match_pthrottling = &(match_pr->throttling); | ||
119 | match_pdomain = &(match_pthrottling->domain_info); | ||
120 | if (match_pdomain->domain != pdomain->domain) | ||
121 | continue; | ||
122 | |||
123 | /* Here i and j are in the same domain. | ||
124 | * If two TSD packages have the same domain, they | ||
125 | * should have the same num_porcessors and | ||
126 | * coordination type. Otherwise it will be regarded | ||
127 | * as illegal. | ||
128 | */ | ||
129 | if (match_pdomain->num_processors != count_target) { | ||
130 | retval = -EINVAL; | ||
131 | goto err_ret; | ||
132 | } | ||
133 | |||
134 | if (pdomain->coord_type != match_pdomain->coord_type) { | ||
135 | retval = -EINVAL; | ||
136 | goto err_ret; | ||
137 | } | ||
138 | |||
139 | cpu_set(j, covered_cpus); | ||
140 | cpu_set(j, pthrottling->shared_cpu_map); | ||
141 | count++; | ||
142 | } | ||
143 | for_each_possible_cpu(j) { | ||
144 | if (i == j) | ||
145 | continue; | ||
146 | |||
147 | match_pr = processors[j]; | ||
148 | if (!match_pr) | ||
149 | continue; | ||
150 | |||
151 | match_pthrottling = &(match_pr->throttling); | ||
152 | match_pdomain = &(match_pthrottling->domain_info); | ||
153 | if (match_pdomain->domain != pdomain->domain) | ||
154 | continue; | ||
155 | |||
156 | /* | ||
157 | * If some CPUS have the same domain, they | ||
158 | * will have the same shared_cpu_map. | ||
159 | */ | ||
160 | match_pthrottling->shared_cpu_map = | ||
161 | pthrottling->shared_cpu_map; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | err_ret: | ||
166 | for_each_possible_cpu(i) { | ||
167 | pr = processors[i]; | ||
168 | if (!pr) | ||
169 | continue; | ||
170 | |||
171 | /* | ||
172 | * Assume no coordination on any error parsing domain info. | ||
173 | * The coordination type will be forced as SW_ALL. | ||
174 | */ | ||
175 | if (retval) { | ||
176 | pthrottling = &(pr->throttling); | ||
177 | cpus_clear(pthrottling->shared_cpu_map); | ||
178 | cpu_set(i, pthrottling->shared_cpu_map); | ||
179 | pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL; | ||
180 | } | ||
181 | } | ||
182 | |||
183 | return retval; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Update the T-state coordination after the _TSD | ||
188 | * data for all cpus is obtained. | ||
189 | */ | ||
190 | void acpi_processor_throttling_init(void) | ||
191 | { | ||
192 | if (acpi_processor_update_tsd_coord()) | ||
193 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
194 | "Assume no T-state coordination\n")); | ||
195 | |||
196 | return; | ||
197 | } | ||
198 | |||
51 | /* | 199 | /* |
52 | * _TPC - Throttling Present Capabilities | 200 | * _TPC - Throttling Present Capabilities |
53 | */ | 201 | */ |
@@ -293,6 +441,10 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) | |||
293 | struct acpi_buffer state = { 0, NULL }; | 441 | struct acpi_buffer state = { 0, NULL }; |
294 | union acpi_object *tsd = NULL; | 442 | union acpi_object *tsd = NULL; |
295 | struct acpi_tsd_package *pdomain; | 443 | struct acpi_tsd_package *pdomain; |
444 | struct acpi_processor_throttling *pthrottling; | ||
445 | |||
446 | pthrottling = &pr->throttling; | ||
447 | pthrottling->tsd_valid_flag = 0; | ||
296 | 448 | ||
297 | status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); | 449 | status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); |
298 | if (ACPI_FAILURE(status)) { | 450 | if (ACPI_FAILURE(status)) { |
@@ -340,6 +492,22 @@ static int acpi_processor_get_tsd(struct acpi_processor *pr) | |||
340 | goto end; | 492 | goto end; |
341 | } | 493 | } |
342 | 494 | ||
495 | pthrottling = &pr->throttling; | ||
496 | pthrottling->tsd_valid_flag = 1; | ||
497 | pthrottling->shared_type = pdomain->coord_type; | ||
498 | cpu_set(pr->id, pthrottling->shared_cpu_map); | ||
499 | /* | ||
500 | * If the coordination type is not defined in ACPI spec, | ||
501 | * the tsd_valid_flag will be clear and coordination type | ||
502 | * will be forecd as DOMAIN_COORD_TYPE_SW_ALL. | ||
503 | */ | ||
504 | if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && | ||
505 | pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && | ||
506 | pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { | ||
507 | pthrottling->tsd_valid_flag = 0; | ||
508 | pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL; | ||
509 | } | ||
510 | |||
343 | end: | 511 | end: |
344 | kfree(buffer.pointer); | 512 | kfree(buffer.pointer); |
345 | return result; | 513 | return result; |
@@ -772,6 +940,7 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
772 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) | 940 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
773 | { | 941 | { |
774 | int result = 0; | 942 | int result = 0; |
943 | struct acpi_processor_throttling *pthrottling; | ||
775 | 944 | ||
776 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 945 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
777 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", | 946 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", |
@@ -803,7 +972,16 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
803 | &acpi_processor_set_throttling_ptc; | 972 | &acpi_processor_set_throttling_ptc; |
804 | } | 973 | } |
805 | 974 | ||
806 | acpi_processor_get_tsd(pr); | 975 | /* |
976 | * If TSD package for one CPU can't be parsed successfully, it means | ||
977 | * that this CPU will have no coordination with other CPUs. | ||
978 | */ | ||
979 | if (acpi_processor_get_tsd(pr)) { | ||
980 | pthrottling = &pr->throttling; | ||
981 | pthrottling->tsd_valid_flag = 0; | ||
982 | cpu_set(pr->id, pthrottling->shared_cpu_map); | ||
983 | pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL; | ||
984 | } | ||
807 | 985 | ||
808 | /* | 986 | /* |
809 | * PIIX4 Errata: We don't support throttling on the original PIIX4. | 987 | * PIIX4 Errata: We don't support throttling on the original PIIX4. |