diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2008-01-28 00:53:42 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-02-02 02:30:11 -0500 |
commit | 1180509f6b3ec3ac2505375a78ccd72d270f2169 (patch) | |
tree | f26bcf07eedae91cb43a84fb617d62beb2a3d123 | |
parent | 87654273ef63213f90c4243913987436495824f0 (diff) |
ACPI : Update T-state coordination after getting _TSD info
Accordint to ACPI spec, the _TSD object provides T-state control cross
logical processor dependency information to OSPM.
After the _TSD data for all cpus are obtained, OSPM will set up
the T-state coordination between CPUs.
Of course if the _TSD doesn't exist or _TSD data is incorrect , it is
assumed that there is no T-state coordination and T-state is changed
independently.
Now there is no proper solution to update T-state coordination after
one cpu is hotplugged. So this patch won't support hotplugged cpu very well.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/processor_core.c | 2 | ||||
-rw-r--r-- | drivers/acpi/processor_throttling.c | 180 | ||||
-rw-r--r-- | include/acpi/processor.h | 4 |
3 files changed, 184 insertions, 2 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e48ee4f8749f..b3b537342715 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -1061,6 +1061,8 @@ static int __init acpi_processor_init(void) | |||
1061 | 1061 | ||
1062 | acpi_processor_ppc_init(); | 1062 | acpi_processor_ppc_init(); |
1063 | 1063 | ||
1064 | acpi_processor_throttling_init(); | ||
1065 | |||
1064 | return 0; | 1066 | return 0; |
1065 | 1067 | ||
1066 | out_cpuidle: | 1068 | out_cpuidle: |
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. |
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 76411b1fc4fd..d90ad0d63c24 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
@@ -176,6 +176,8 @@ struct acpi_processor_throttling { | |||
176 | u32 address; | 176 | u32 address; |
177 | u8 duty_offset; | 177 | u8 duty_offset; |
178 | u8 duty_width; | 178 | u8 duty_width; |
179 | u8 tsd_valid_flag; | ||
180 | unsigned int shared_type; | ||
179 | struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; | 181 | struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; |
180 | }; | 182 | }; |
181 | 183 | ||
@@ -316,7 +318,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) | |||
316 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); | 318 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); |
317 | extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | 319 | extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); |
318 | extern struct file_operations acpi_processor_throttling_fops; | 320 | extern struct file_operations acpi_processor_throttling_fops; |
319 | 321 | extern void acpi_processor_throttling_init(void); | |
320 | /* in processor_idle.c */ | 322 | /* in processor_idle.c */ |
321 | int acpi_processor_power_init(struct acpi_processor *pr, | 323 | int acpi_processor_power_init(struct acpi_processor *pr, |
322 | struct acpi_device *device); | 324 | struct acpi_device *device); |