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