aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/processor_throttling.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/processor_throttling.c')
-rw-r--r--drivers/acpi/processor_throttling.c180
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");
48static int acpi_processor_get_throttling(struct acpi_processor *pr); 48static int acpi_processor_get_throttling(struct acpi_processor *pr);
49int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 49int acpi_processor_set_throttling(struct acpi_processor *pr, int state);
50 50
51static 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
165err_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 */
190void 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)
772int acpi_processor_get_throttling_info(struct acpi_processor *pr) 940int 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.