Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI: add ACPI 3.0 _TPC _TSS _PTC throttling support

adds _TPC _TSS _PTC -- Throttling Present Capabilities

Signed-off-by: Luming Yu <luming.yu@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Luming Yu and committed by
Len Brown
01854e69 f285e3d3

+423 -9
+6
drivers/acpi/processor_core.c
··· 66 66 #define ACPI_PROCESSOR_FILE_LIMIT "limit" 67 67 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 68 68 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 69 + #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 69 70 70 71 #define ACPI_PROCESSOR_LIMIT_USER 0 71 72 #define ACPI_PROCESSOR_LIMIT_THERMAL 1 ··· 85 84 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); 86 85 static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); 87 86 static int acpi_processor_handle_eject(struct acpi_processor *pr); 87 + extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); 88 + 88 89 89 90 static struct acpi_driver acpi_processor_driver = { 90 91 .name = "processor", ··· 702 699 acpi_processor_cst_has_changed(pr); 703 700 acpi_bus_generate_event(device, event, 0); 704 701 break; 702 + case ACPI_PROCESSOR_NOTIFY_THROTTLING: 703 + acpi_processor_tstate_has_changed(pr); 704 + acpi_bus_generate_event(device, event, 0); 705 705 default: 706 706 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 707 707 "Unsupported event [0x%x]\n", event));
+374 -6
drivers/acpi/processor_throttling.c
··· 44 44 #define _COMPONENT ACPI_PROCESSOR_COMPONENT 45 45 ACPI_MODULE_NAME("processor_throttling"); 46 46 47 + static int acpi_processor_get_throttling (struct acpi_processor *pr); 48 + int acpi_processor_set_throttling (struct acpi_processor *pr, int state); 49 + 50 + static int acpi_processor_get_platform_limit(struct acpi_processor *pr) 51 + { 52 + acpi_status status = 0; 53 + unsigned long tpc = 0; 54 + 55 + if(!pr) 56 + return -EINVAL; 57 + status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc); 58 + if(ACPI_FAILURE(status) && status != AE_NOT_FOUND){ 59 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); 60 + return -ENODEV; 61 + } 62 + pr->throttling_platform_limit = (int)tpc; 63 + return 0; 64 + } 65 + 66 + int acpi_processor_tstate_has_changed(struct acpi_processor *pr) 67 + { 68 + return acpi_processor_get_platform_limit(pr); 69 + } 70 + 71 + /* -------------------------------------------------------------------------- 72 + _PTC, _TSS, _TSD support 73 + -------------------------------------------------------------------------- */ 74 + static int acpi_processor_get_throttling_control(struct acpi_processor *pr) 75 + { 76 + int result = 0; 77 + acpi_status status = 0; 78 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 79 + union acpi_object *ptc = NULL; 80 + union acpi_object obj = { 0 }; 81 + 82 + status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); 83 + if (ACPI_FAILURE(status)) { 84 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); 85 + return -ENODEV; 86 + } 87 + 88 + ptc = (union acpi_object *)buffer.pointer; 89 + if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE) 90 + || (ptc->package.count != 2)) { 91 + printk(KERN_ERR PREFIX "Invalid _PTC data\n"); 92 + result = -EFAULT; 93 + goto end; 94 + } 95 + 96 + /* 97 + * control_register 98 + */ 99 + 100 + obj = ptc->package.elements[0]; 101 + 102 + if ((obj.type != ACPI_TYPE_BUFFER) 103 + || (obj.buffer.length < sizeof(struct acpi_ptc_register)) 104 + || (obj.buffer.pointer == NULL)) { 105 + printk(KERN_ERR PREFIX "Invalid _PTC data (control_register)\n"); 106 + result = -EFAULT; 107 + goto end; 108 + } 109 + memcpy(&pr->throttling.control_register, obj.buffer.pointer, 110 + sizeof(struct acpi_ptc_register)); 111 + 112 + /* 113 + * status_register 114 + */ 115 + 116 + obj = ptc->package.elements[1]; 117 + 118 + if ((obj.type != ACPI_TYPE_BUFFER) 119 + || (obj.buffer.length < sizeof(struct acpi_ptc_register)) 120 + || (obj.buffer.pointer == NULL)) { 121 + printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n"); 122 + result = -EFAULT; 123 + goto end; 124 + } 125 + 126 + memcpy(&pr->throttling.status_register, obj.buffer.pointer, 127 + sizeof(struct acpi_ptc_register)); 128 + 129 + end: 130 + kfree(buffer.pointer); 131 + 132 + return result; 133 + } 134 + static int acpi_processor_get_throttling_states(struct acpi_processor *pr) 135 + { 136 + int result = 0; 137 + acpi_status status = AE_OK; 138 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 139 + struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; 140 + struct acpi_buffer state = { 0, NULL }; 141 + union acpi_object *tss = NULL; 142 + int i; 143 + 144 + status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer); 145 + if (ACPI_FAILURE(status)) { 146 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); 147 + return -ENODEV; 148 + } 149 + 150 + tss = buffer.pointer; 151 + if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) { 152 + printk(KERN_ERR PREFIX "Invalid _TSS data\n"); 153 + result = -EFAULT; 154 + goto end; 155 + } 156 + 157 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", 158 + tss->package.count)); 159 + 160 + pr->throttling.state_count = tss->package.count; 161 + pr->throttling.states_tss = 162 + kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count, 163 + GFP_KERNEL); 164 + if (!pr->throttling.states_tss) { 165 + result = -ENOMEM; 166 + goto end; 167 + } 168 + 169 + for (i = 0; i < pr->throttling.state_count; i++) { 170 + 171 + struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *) &(pr->throttling.states_tss[i]); 172 + 173 + state.length = sizeof(struct acpi_processor_tx_tss); 174 + state.pointer = tx; 175 + 176 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); 177 + 178 + status = acpi_extract_package(&(tss->package.elements[i]), 179 + &format, &state); 180 + if (ACPI_FAILURE(status)) { 181 + ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data")); 182 + result = -EFAULT; 183 + kfree(pr->throttling.states_tss); 184 + goto end; 185 + } 186 + 187 + if (!tx->freqpercentage) { 188 + printk(KERN_ERR PREFIX 189 + "Invalid _TSS data: freq is zero\n"); 190 + result = -EFAULT; 191 + kfree(pr->throttling.states_tss); 192 + goto end; 193 + } 194 + } 195 + 196 + end: 197 + kfree(buffer.pointer); 198 + 199 + return result; 200 + } 201 + static int acpi_processor_get_tsd(struct acpi_processor *pr) 202 + { 203 + int result = 0; 204 + acpi_status status = AE_OK; 205 + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 206 + struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; 207 + struct acpi_buffer state = {0, NULL}; 208 + union acpi_object *tsd = NULL; 209 + struct acpi_tsd_package *pdomain; 210 + 211 + status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); 212 + if (ACPI_FAILURE(status)) { 213 + return -ENODEV; 214 + } 215 + 216 + tsd = buffer.pointer; 217 + if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { 218 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 219 + result = -EFAULT; 220 + goto end; 221 + } 222 + 223 + if (tsd->package.count != 1) { 224 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 225 + result = -EFAULT; 226 + goto end; 227 + } 228 + 229 + pdomain = &(pr->throttling.domain_info); 230 + 231 + state.length = sizeof(struct acpi_tsd_package); 232 + state.pointer = pdomain; 233 + 234 + status = acpi_extract_package(&(tsd->package.elements[0]), 235 + &format, &state); 236 + if (ACPI_FAILURE(status)) { 237 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 238 + result = -EFAULT; 239 + goto end; 240 + } 241 + 242 + if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { 243 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n")); 244 + result = -EFAULT; 245 + goto end; 246 + } 247 + 248 + if (pdomain->revision != ACPI_TSD_REV0_REVISION) { 249 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n")); 250 + result = -EFAULT; 251 + goto end; 252 + } 253 + 254 + end: 255 + kfree(buffer.pointer); 256 + return result; 257 + } 258 + 47 259 /* -------------------------------------------------------------------------- 48 260 Throttling Control 49 261 -------------------------------------------------------------------------- */ 50 - static int acpi_processor_get_throttling(struct acpi_processor *pr) 262 + static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) 51 263 { 52 264 int state = 0; 53 265 u32 value = 0; ··· 306 94 return 0; 307 95 } 308 96 309 - int acpi_processor_set_throttling(struct acpi_processor *pr, int state) 97 + static int acpi_read_throttling_status(struct acpi_processor_throttling *throttling) 98 + { 99 + int value = -1; 100 + switch (throttling->status_register.space_id) { 101 + case ACPI_ADR_SPACE_SYSTEM_IO: 102 + acpi_os_read_port((acpi_io_address)throttling->status_register.address, 103 + &value, 104 + (u32)throttling->status_register.bit_width*8); 105 + break; 106 + case ACPI_ADR_SPACE_FIXED_HARDWARE: 107 + printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); 108 + break; 109 + default: 110 + printk(KERN_ERR PREFIX "Unknown addr space %d\n", 111 + (u32) (throttling->status_register.space_id)); 112 + } 113 + return value; 114 + } 115 + 116 + static int acpi_write_throttling_state(struct acpi_processor_throttling *throttling,int value) 117 + { 118 + int ret = -1; 119 + 120 + switch (throttling->control_register.space_id) { 121 + case ACPI_ADR_SPACE_SYSTEM_IO: 122 + acpi_os_write_port((acpi_io_address)throttling->control_register.address, 123 + value, 124 + (u32)throttling->control_register.bit_width*8); 125 + ret = 0; 126 + break; 127 + case ACPI_ADR_SPACE_FIXED_HARDWARE: 128 + printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet\n"); 129 + break; 130 + default: 131 + printk(KERN_ERR PREFIX "Unknown addr space %d\n", 132 + (u32) (throttling->control_register.space_id)); 133 + } 134 + return ret; 135 + } 136 + 137 + static int acpi_get_throttling_state(struct acpi_processor *pr,int value) 138 + { 139 + int i; 140 + 141 + for (i = 0; i < pr->throttling.state_count; i++) { 142 + struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *) &(pr->throttling.states_tss[i]); 143 + if(tx->control == value) 144 + break; 145 + } 146 + if(i > pr->throttling.state_count) 147 + i=-1; 148 + return i; 149 + } 150 + 151 + static int acpi_get_throttling_value(struct acpi_processor *pr,int state) 152 + { 153 + int value = -1; 154 + if(state >=0 && state <= pr->throttling.state_count){ 155 + struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *) &(pr->throttling.states_tss[state]); 156 + value = tx->control; 157 + } 158 + return value; 159 + } 160 + 161 + static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) 162 + { 163 + int state = 0; 164 + u32 value = 0; 165 + 166 + 167 + if (!pr) 168 + return -EINVAL; 169 + 170 + if (!pr->flags.throttling) 171 + return -ENODEV; 172 + 173 + pr->throttling.state = 0; 174 + local_irq_disable(); 175 + value = acpi_read_throttling_status(&pr->throttling); 176 + if(value >= 0){ 177 + state = acpi_get_throttling_state(pr,value); 178 + pr->throttling.state = state; 179 + } 180 + local_irq_enable(); 181 + 182 + return 0; 183 + } 184 + 185 + 186 + static int acpi_processor_get_throttling(struct acpi_processor *pr) 187 + { 188 + return pr->throttling.acpi_processor_get_throttling(pr); 189 + } 190 + 191 + int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, int state) 310 192 { 311 193 u32 value = 0; 312 194 u32 duty_mask = 0; ··· 419 113 if (state == pr->throttling.state) 420 114 return 0; 421 115 116 + if (state < pr->throttling_platform_limit) 117 + return -EPERM; 422 118 /* 423 119 * Calculate the duty_value and duty_mask. 424 120 */ ··· 473 165 return 0; 474 166 } 475 167 168 + int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, int state) 169 + { 170 + u32 value = 0; 171 + 172 + if (!pr) 173 + return -EINVAL; 174 + 175 + if ((state < 0) || (state > (pr->throttling.state_count - 1))) 176 + return -EINVAL; 177 + 178 + if (!pr->flags.throttling) 179 + return -ENODEV; 180 + 181 + if (state == pr->throttling.state) 182 + return 0; 183 + 184 + if (state < pr->throttling_platform_limit) 185 + return -EPERM; 186 + 187 + local_irq_disable(); 188 + 189 + value = acpi_get_throttling_value(pr,state); 190 + if(value >=0){ 191 + acpi_write_throttling_state(&pr->throttling,value); 192 + pr->throttling.state = state; 193 + } 194 + local_irq_enable(); 195 + 196 + return 0; 197 + } 198 + 199 + int acpi_processor_set_throttling(struct acpi_processor *pr, int state) 200 + { 201 + return pr->throttling.acpi_processor_set_throttling(pr,state); 202 + } 203 + 476 204 int acpi_processor_get_throttling_info(struct acpi_processor *pr) 477 205 { 478 206 int result = 0; 479 207 int step = 0; 480 208 int i = 0; 209 + int no_ptc = 0; 210 + int no_tss = 0; 211 + int no_tsd = 0; 481 212 482 213 483 214 ACPI_DEBUG_PRINT((ACPI_DB_INFO, ··· 529 182 return -EINVAL; 530 183 531 184 /* TBD: Support ACPI 2.0 objects */ 185 + no_ptc = acpi_processor_get_throttling_control(pr); 186 + no_tss = acpi_processor_get_throttling_states(pr); 187 + no_tsd = acpi_processor_get_tsd(pr); 188 + 189 + if(no_ptc || no_tss) { 190 + pr->throttling.acpi_processor_get_throttling = &acpi_processor_get_throttling_fadt; 191 + pr->throttling.acpi_processor_set_throttling = &acpi_processor_set_throttling_fadt; 192 + } else { 193 + pr->throttling.acpi_processor_get_throttling = &acpi_processor_get_throttling_ptc; 194 + pr->throttling.acpi_processor_set_throttling = &acpi_processor_set_throttling_ptc; 195 + } 532 196 533 197 if (!pr->throttling.address) { 534 198 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); ··· 638 280 } 639 281 640 282 seq_printf(seq, "state count: %d\n" 641 - "active state: T%d\n", 642 - pr->throttling.state_count, pr->throttling.state); 283 + "active state: T%d\n" 284 + "state available: T%d to T%d\n", 285 + pr->throttling.state_count, pr->throttling.state, 286 + pr->throttling_platform_limit, 287 + pr->throttling.state_count-1); 643 288 644 289 seq_puts(seq, "states:\n"); 645 - for (i = 0; i < pr->throttling.state_count; i++) 646 - seq_printf(seq, " %cT%d: %02d%%\n", 290 + if(acpi_processor_get_throttling == acpi_processor_get_throttling_fadt) 291 + for (i = 0; i < pr->throttling.state_count; i++) 292 + seq_printf(seq, " %cT%d: %02d%%\n", 647 293 (i == pr->throttling.state ? '*' : ' '), i, 648 294 (pr->throttling.states[i].performance ? pr-> 649 295 throttling.states[i].performance / 10 : 0)); 296 + else 297 + for (i = 0; i < pr->throttling.state_count; i++) 298 + seq_printf(seq, " %cT%d: %02d%%\n", 299 + (i == pr->throttling.state ? '*' : ' '), i, 300 + (int)pr->throttling.states_tss[i].freqpercentage); 301 + 650 302 651 303 end: 652 304 return 0;
+43 -3
include/acpi/processor.h
··· 21 21 #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ 22 22 #define ACPI_PSD_REV0_ENTRIES 5 23 23 24 + #define ACPI_TSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ 25 + #define ACPI_TSD_REV0_ENTRIES 5 24 26 /* 25 27 * Types of coordination defined in ACPI 3.0. Same macros can be used across 26 28 * P, C and T states ··· 127 125 128 126 /* Throttling Control */ 129 127 128 + struct acpi_tsd_package { 129 + acpi_integer num_entries; 130 + acpi_integer revision; 131 + acpi_integer domain; 132 + acpi_integer coord_type; 133 + acpi_integer num_processors; 134 + } __attribute__ ((packed)); 135 + 136 + struct acpi_ptc_register { 137 + u8 descriptor; 138 + u16 length; 139 + u8 space_id; 140 + u8 bit_width; 141 + u8 bit_offset; 142 + u8 reserved; 143 + u64 address; 144 + } __attribute__ ((packed)); 145 + 146 + struct acpi_processor_tx_tss { 147 + acpi_integer freqpercentage; /* */ 148 + acpi_integer power; /* milliWatts */ 149 + acpi_integer transition_latency; /* microseconds */ 150 + acpi_integer control; /* control value */ 151 + acpi_integer status; /* success indicator */ 152 + }; 130 153 struct acpi_processor_tx { 131 154 u16 power; 132 155 u16 performance; 133 156 }; 134 157 158 + struct acpi_processor; 135 159 struct acpi_processor_throttling { 136 - int state; 160 + unsigned int state; 161 + unsigned int platform_limit; 162 + struct acpi_pct_register control_register; 163 + struct acpi_pct_register status_register; 164 + unsigned int state_count; 165 + struct acpi_processor_tx_tss *states_tss; 166 + struct acpi_tsd_package domain_info; 167 + cpumask_t shared_cpu_map; 168 + int (*acpi_processor_get_throttling) (struct acpi_processor *pr); 169 + int (*acpi_processor_set_throttling) (struct acpi_processor *pr, int state); 170 + 137 171 u32 address; 138 172 u8 duty_offset; 139 173 u8 duty_width; 140 - int state_count; 141 174 struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; 142 175 }; 143 176 ··· 206 169 u32 id; 207 170 u32 pblk; 208 171 int performance_platform_limit; 172 + int throttling_platform_limit; 173 + /*0 - states 0..n-th satte available*/ 174 + 209 175 struct acpi_processor_flags flags; 210 176 struct acpi_processor_power power; 211 177 struct acpi_processor_performance *performance; ··· 310 270 311 271 /* in processor_throttling.c */ 312 272 int acpi_processor_get_throttling_info(struct acpi_processor *pr); 313 - int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 273 + extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 314 274 extern struct file_operations acpi_processor_throttling_fops; 315 275 316 276 /* in processor_idle.c */