diff options
| author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-22 20:50:22 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-22 20:50:22 -0400 |
| commit | 2ee8099f2c2bc74a7c2fac7f83e12a5d651681d3 (patch) | |
| tree | 433ebb87a3d5d02e7df3700c846ac9af632c55f3 | |
| parent | c03efdb202a4882f426ce49766859af4058c9b8a (diff) | |
| parent | 24669f7d00d387799fc6a39452ab22d7f078f043 (diff) | |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq
* master.kernel.org:/pub/scm/linux/kernel/git/davej/cpufreq:
[CPUFREQ] sw_any_bug_dmi_table can be used on resume, so it isn't initdata
[CPUFREQ] Fix some more CPU hotplug locking.
[CPUFREQ] Workaround for BIOS bug in software coordination of frequency
[CPUFREQ] Longhaul - Add voltage scaling to driver
[CPUFREQ] Fix sparse warning in ondemand
[CPUFREQ] make drivers/cpufreq/cpufreq_ondemand.c:powersave_bias_target() static
[CPUFREQ] Longhaul - Add ignore_latency option
[CPUFREQ] Longhaul - Disable arbiter
[CPUFREQ][2/2] ondemand: updated add powersave_bias tunable
[CPUFREQ][1/2] ondemand: updated tune for hardware coordination
[CPUFREQ] Fix typo.
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 39 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 186 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.h | 48 | ||||
| -rw-r--r-- | arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | 42 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq.c | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq_ondemand.c | 173 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq_stats.c | 2 |
7 files changed, 391 insertions, 101 deletions
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index e6ea00edcb54..ea19d091fd41 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
| 33 | #include <linux/compiler.h> | 33 | #include <linux/compiler.h> |
| 34 | #include <linux/sched.h> /* current */ | 34 | #include <linux/sched.h> /* current */ |
| 35 | #include <linux/dmi.h> | ||
| 35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
| 36 | #include <asm/delay.h> | 37 | #include <asm/delay.h> |
| 37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| @@ -387,6 +388,33 @@ static int acpi_cpufreq_early_init_acpi(void) | |||
| 387 | return acpi_processor_preregister_performance(acpi_perf_data); | 388 | return acpi_processor_preregister_performance(acpi_perf_data); |
| 388 | } | 389 | } |
| 389 | 390 | ||
| 391 | /* | ||
| 392 | * Some BIOSes do SW_ANY coordination internally, either set it up in hw | ||
| 393 | * or do it in BIOS firmware and won't inform about it to OS. If not | ||
| 394 | * detected, this has a side effect of making CPU run at a different speed | ||
| 395 | * than OS intended it to run at. Detect it and handle it cleanly. | ||
| 396 | */ | ||
| 397 | static int bios_with_sw_any_bug; | ||
| 398 | |||
| 399 | static int __init sw_any_bug_found(struct dmi_system_id *d) | ||
| 400 | { | ||
| 401 | bios_with_sw_any_bug = 1; | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static struct dmi_system_id __initdata sw_any_bug_dmi_table[] = { | ||
| 406 | { | ||
| 407 | .callback = sw_any_bug_found, | ||
| 408 | .ident = "Supermicro Server X6DLP", | ||
| 409 | .matches = { | ||
| 410 | DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), | ||
| 411 | DMI_MATCH(DMI_BIOS_VERSION, "080010"), | ||
| 412 | DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), | ||
| 413 | }, | ||
| 414 | }, | ||
| 415 | { } | ||
| 416 | }; | ||
| 417 | |||
| 390 | static int | 418 | static int |
| 391 | acpi_cpufreq_cpu_init ( | 419 | acpi_cpufreq_cpu_init ( |
| 392 | struct cpufreq_policy *policy) | 420 | struct cpufreq_policy *policy) |
| @@ -422,8 +450,17 @@ acpi_cpufreq_cpu_init ( | |||
| 422 | * coordination is required. | 450 | * coordination is required. |
| 423 | */ | 451 | */ |
| 424 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || | 452 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || |
| 425 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) | 453 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { |
| 426 | policy->cpus = perf->shared_cpu_map; | 454 | policy->cpus = perf->shared_cpu_map; |
| 455 | } | ||
| 456 | |||
| 457 | #ifdef CONFIG_SMP | ||
| 458 | dmi_check_system(sw_any_bug_dmi_table); | ||
| 459 | if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) { | ||
| 460 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
| 461 | policy->cpus = cpu_core_map[cpu]; | ||
| 462 | } | ||
| 463 | #endif | ||
| 427 | 464 | ||
| 428 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { | 465 | if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { |
| 429 | acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; | 466 | acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; |
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 4f2c3aeef724..f5cc9f5c9bab 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/moduleparam.h> | 27 | #include <linux/moduleparam.h> |
| 28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
| 29 | #include <linux/cpufreq.h> | 29 | #include <linux/cpufreq.h> |
| 30 | #include <linux/pci.h> | ||
| 30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 31 | #include <linux/string.h> | 32 | #include <linux/string.h> |
| 32 | 33 | ||
| @@ -52,18 +53,26 @@ | |||
| 52 | #define CPU_NEHEMIAH 5 | 53 | #define CPU_NEHEMIAH 5 |
| 53 | 54 | ||
| 54 | static int cpu_model; | 55 | static int cpu_model; |
| 55 | static unsigned int numscales=16, numvscales; | 56 | static unsigned int numscales=16; |
| 56 | static unsigned int fsb; | 57 | static unsigned int fsb; |
| 57 | static int minvid, maxvid; | 58 | |
| 59 | static struct mV_pos *vrm_mV_table; | ||
| 60 | static unsigned char *mV_vrm_table; | ||
| 61 | struct f_msr { | ||
| 62 | unsigned char vrm; | ||
| 63 | }; | ||
| 64 | static struct f_msr f_msr_table[32]; | ||
| 65 | |||
| 66 | static unsigned int highest_speed, lowest_speed; /* kHz */ | ||
| 58 | static unsigned int minmult, maxmult; | 67 | static unsigned int minmult, maxmult; |
| 59 | static int can_scale_voltage; | 68 | static int can_scale_voltage; |
| 60 | static int vrmrev; | ||
| 61 | static struct acpi_processor *pr = NULL; | 69 | static struct acpi_processor *pr = NULL; |
| 62 | static struct acpi_processor_cx *cx = NULL; | 70 | static struct acpi_processor_cx *cx = NULL; |
| 71 | static int port22_en; | ||
| 63 | 72 | ||
| 64 | /* Module parameters */ | 73 | /* Module parameters */ |
| 65 | static int dont_scale_voltage; | 74 | static int scale_voltage; |
| 66 | 75 | static int ignore_latency; | |
| 67 | 76 | ||
| 68 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) | 77 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) |
| 69 | 78 | ||
| @@ -71,7 +80,6 @@ static int dont_scale_voltage; | |||
| 71 | /* Clock ratios multiplied by 10 */ | 80 | /* Clock ratios multiplied by 10 */ |
| 72 | static int clock_ratio[32]; | 81 | static int clock_ratio[32]; |
| 73 | static int eblcr_table[32]; | 82 | static int eblcr_table[32]; |
| 74 | static int voltage_table[32]; | ||
| 75 | static unsigned int highest_speed, lowest_speed; /* kHz */ | 83 | static unsigned int highest_speed, lowest_speed; /* kHz */ |
| 76 | static int longhaul_version; | 84 | static int longhaul_version; |
| 77 | static struct cpufreq_frequency_table *longhaul_table; | 85 | static struct cpufreq_frequency_table *longhaul_table; |
| @@ -124,10 +132,9 @@ static int longhaul_get_cpu_mult(void) | |||
| 124 | 132 | ||
| 125 | /* For processor with BCR2 MSR */ | 133 | /* For processor with BCR2 MSR */ |
| 126 | 134 | ||
| 127 | static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) | 135 | static void do_longhaul1(unsigned int clock_ratio_index) |
| 128 | { | 136 | { |
| 129 | union msr_bcr2 bcr2; | 137 | union msr_bcr2 bcr2; |
| 130 | u32 t; | ||
| 131 | 138 | ||
| 132 | rdmsrl(MSR_VIA_BCR2, bcr2.val); | 139 | rdmsrl(MSR_VIA_BCR2, bcr2.val); |
| 133 | /* Enable software clock multiplier */ | 140 | /* Enable software clock multiplier */ |
| @@ -136,13 +143,11 @@ static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) | |||
| 136 | 143 | ||
| 137 | /* Sync to timer tick */ | 144 | /* Sync to timer tick */ |
| 138 | safe_halt(); | 145 | safe_halt(); |
| 139 | ACPI_FLUSH_CPU_CACHE(); | ||
| 140 | /* Change frequency on next halt or sleep */ | 146 | /* Change frequency on next halt or sleep */ |
| 141 | wrmsrl(MSR_VIA_BCR2, bcr2.val); | 147 | wrmsrl(MSR_VIA_BCR2, bcr2.val); |
| 142 | /* Invoke C3 */ | 148 | /* Invoke transition */ |
| 143 | inb(cx_address); | 149 | ACPI_FLUSH_CPU_CACHE(); |
| 144 | /* Dummy op - must do something useless after P_LVL3 read */ | 150 | halt(); |
| 145 | t = inl(acpi_fadt.xpm_tmr_blk.address); | ||
| 146 | 151 | ||
| 147 | /* Disable software clock multiplier */ | 152 | /* Disable software clock multiplier */ |
| 148 | local_irq_disable(); | 153 | local_irq_disable(); |
| @@ -164,11 +169,16 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
| 164 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | 169 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; |
| 165 | longhaul.bits.EnableSoftBusRatio = 1; | 170 | longhaul.bits.EnableSoftBusRatio = 1; |
| 166 | 171 | ||
| 172 | if (can_scale_voltage) { | ||
| 173 | longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm; | ||
| 174 | longhaul.bits.EnableSoftVID = 1; | ||
| 175 | } | ||
| 176 | |||
| 167 | /* Sync to timer tick */ | 177 | /* Sync to timer tick */ |
| 168 | safe_halt(); | 178 | safe_halt(); |
| 169 | ACPI_FLUSH_CPU_CACHE(); | ||
| 170 | /* Change frequency on next halt or sleep */ | 179 | /* Change frequency on next halt or sleep */ |
| 171 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 180 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
| 181 | ACPI_FLUSH_CPU_CACHE(); | ||
| 172 | /* Invoke C3 */ | 182 | /* Invoke C3 */ |
| 173 | inb(cx_address); | 183 | inb(cx_address); |
| 174 | /* Dummy op - must do something useless after P_LVL3 read */ | 184 | /* Dummy op - must do something useless after P_LVL3 read */ |
| @@ -227,10 +237,13 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
| 227 | outb(0xFF,0xA1); /* Overkill */ | 237 | outb(0xFF,0xA1); /* Overkill */ |
| 228 | outb(0xFE,0x21); /* TMR0 only */ | 238 | outb(0xFE,0x21); /* TMR0 only */ |
| 229 | 239 | ||
| 230 | /* Disable bus master arbitration */ | 240 | if (pr->flags.bm_control) { |
| 231 | if (pr->flags.bm_check) { | 241 | /* Disable bus master arbitration */ |
| 232 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, | 242 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, |
| 233 | ACPI_MTX_DO_NOT_LOCK); | 243 | ACPI_MTX_DO_NOT_LOCK); |
| 244 | } else if (port22_en) { | ||
| 245 | /* Disable AGP and PCI arbiters */ | ||
| 246 | outb(3, 0x22); | ||
| 234 | } | 247 | } |
| 235 | 248 | ||
| 236 | switch (longhaul_version) { | 249 | switch (longhaul_version) { |
| @@ -244,7 +257,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
| 244 | */ | 257 | */ |
| 245 | case TYPE_LONGHAUL_V1: | 258 | case TYPE_LONGHAUL_V1: |
| 246 | case TYPE_LONGHAUL_V2: | 259 | case TYPE_LONGHAUL_V2: |
| 247 | do_longhaul1(cx->address, clock_ratio_index); | 260 | do_longhaul1(clock_ratio_index); |
| 248 | break; | 261 | break; |
| 249 | 262 | ||
| 250 | /* | 263 | /* |
| @@ -259,14 +272,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
| 259 | * to work in practice. | 272 | * to work in practice. |
| 260 | */ | 273 | */ |
| 261 | case TYPE_POWERSAVER: | 274 | case TYPE_POWERSAVER: |
| 275 | /* Don't allow wakeup */ | ||
| 276 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, | ||
| 277 | ACPI_MTX_DO_NOT_LOCK); | ||
| 262 | do_powersaver(cx->address, clock_ratio_index); | 278 | do_powersaver(cx->address, clock_ratio_index); |
| 263 | break; | 279 | break; |
| 264 | } | 280 | } |
| 265 | 281 | ||
| 266 | /* Enable bus master arbitration */ | 282 | if (pr->flags.bm_control) { |
| 267 | if (pr->flags.bm_check) { | 283 | /* Enable bus master arbitration */ |
| 268 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, | 284 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, |
| 269 | ACPI_MTX_DO_NOT_LOCK); | 285 | ACPI_MTX_DO_NOT_LOCK); |
| 286 | } else if (port22_en) { | ||
| 287 | /* Enable arbiters */ | ||
| 288 | outb(0, 0x22); | ||
| 270 | } | 289 | } |
| 271 | 290 | ||
| 272 | outb(pic2_mask,0xA1); /* restore mask */ | 291 | outb(pic2_mask,0xA1); /* restore mask */ |
| @@ -446,53 +465,57 @@ static int __init longhaul_get_ranges(void) | |||
| 446 | static void __init longhaul_setup_voltagescaling(void) | 465 | static void __init longhaul_setup_voltagescaling(void) |
| 447 | { | 466 | { |
| 448 | union msr_longhaul longhaul; | 467 | union msr_longhaul longhaul; |
| 468 | struct mV_pos minvid, maxvid; | ||
| 469 | unsigned int j, speed, pos, kHz_step, numvscales; | ||
| 449 | 470 | ||
| 450 | rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); | 471 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
| 451 | 472 | if (!(longhaul.bits.RevisionID & 1)) { | |
| 452 | if (!(longhaul.bits.RevisionID & 1)) | 473 | printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n"); |
| 453 | return; | 474 | return; |
| 475 | } | ||
| 476 | |||
| 477 | if (!longhaul.bits.VRMRev) { | ||
| 478 | printk (KERN_INFO PFX "VRM 8.5\n"); | ||
| 479 | vrm_mV_table = &vrm85_mV[0]; | ||
| 480 | mV_vrm_table = &mV_vrm85[0]; | ||
| 481 | } else { | ||
| 482 | printk (KERN_INFO PFX "Mobile VRM\n"); | ||
| 483 | vrm_mV_table = &mobilevrm_mV[0]; | ||
| 484 | mV_vrm_table = &mV_mobilevrm[0]; | ||
| 485 | } | ||
| 454 | 486 | ||
| 455 | minvid = longhaul.bits.MinimumVID; | 487 | minvid = vrm_mV_table[longhaul.bits.MinimumVID]; |
| 456 | maxvid = longhaul.bits.MaximumVID; | 488 | maxvid = vrm_mV_table[longhaul.bits.MaximumVID]; |
| 457 | vrmrev = longhaul.bits.VRMRev; | 489 | numvscales = maxvid.pos - minvid.pos + 1; |
| 490 | kHz_step = (highest_speed - lowest_speed) / numvscales; | ||
| 458 | 491 | ||
| 459 | if (minvid == 0 || maxvid == 0) { | 492 | if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) { |
| 460 | printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " | 493 | printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. " |
| 461 | "Voltage scaling disabled.\n", | 494 | "Voltage scaling disabled.\n", |
| 462 | minvid/1000, minvid%1000, maxvid/1000, maxvid%1000); | 495 | minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000); |
| 463 | return; | 496 | return; |
| 464 | } | 497 | } |
| 465 | 498 | ||
| 466 | if (minvid == maxvid) { | 499 | if (minvid.mV == maxvid.mV) { |
| 467 | printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are " | 500 | printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are " |
| 468 | "both %d.%03d. Voltage scaling disabled\n", | 501 | "both %d.%03d. Voltage scaling disabled\n", |
| 469 | maxvid/1000, maxvid%1000); | 502 | maxvid.mV/1000, maxvid.mV%1000); |
| 470 | return; | 503 | return; |
| 471 | } | 504 | } |
| 472 | 505 | ||
| 473 | if (vrmrev==0) { | 506 | printk(KERN_INFO PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n", |
| 474 | dprintk ("VRM 8.5\n"); | 507 | maxvid.mV/1000, maxvid.mV%1000, |
| 475 | memcpy (voltage_table, vrm85scales, sizeof(voltage_table)); | 508 | minvid.mV/1000, minvid.mV%1000, |
| 476 | numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25; | 509 | numvscales); |
| 477 | } else { | 510 | |
| 478 | dprintk ("Mobile VRM\n"); | 511 | j = 0; |
| 479 | memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table)); | 512 | while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { |
| 480 | numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5; | 513 | speed = longhaul_table[j].frequency; |
| 514 | pos = (speed - lowest_speed) / kHz_step + minvid.pos; | ||
| 515 | f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos]; | ||
| 516 | j++; | ||
| 481 | } | 517 | } |
| 482 | 518 | ||
| 483 | /* Current voltage isn't readable at first, so we need to | ||
| 484 | set it to a known value. The spec says to use maxvid */ | ||
| 485 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */ | ||
| 486 | longhaul.bits.EnableSoftVID = 1; | ||
| 487 | longhaul.bits.SoftVID = maxvid; | ||
| 488 | wrmsrl (MSR_VIA_LONGHAUL, longhaul.val); | ||
| 489 | |||
| 490 | minvid = voltage_table[minvid]; | ||
| 491 | maxvid = voltage_table[maxvid]; | ||
| 492 | |||
| 493 | dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n", | ||
| 494 | maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales); | ||
| 495 | |||
| 496 | can_scale_voltage = 1; | 519 | can_scale_voltage = 1; |
| 497 | } | 520 | } |
| 498 | 521 | ||
| @@ -540,21 +563,33 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle, | |||
| 540 | return 1; | 563 | return 1; |
| 541 | } | 564 | } |
| 542 | 565 | ||
| 566 | /* VIA don't support PM2 reg, but have something similar */ | ||
| 567 | static int enable_arbiter_disable(void) | ||
| 568 | { | ||
| 569 | struct pci_dev *dev; | ||
| 570 | u8 pci_cmd; | ||
| 571 | |||
| 572 | /* Find PLE133 host bridge */ | ||
| 573 | dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL); | ||
| 574 | if (dev != NULL) { | ||
| 575 | /* Enable access to port 0x22 */ | ||
| 576 | pci_read_config_byte(dev, 0x78, &pci_cmd); | ||
| 577 | if ( !(pci_cmd & 1<<7) ) { | ||
| 578 | pci_cmd |= 1<<7; | ||
| 579 | pci_write_config_byte(dev, 0x78, pci_cmd); | ||
| 580 | } | ||
| 581 | return 1; | ||
| 582 | } | ||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 543 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | 586 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) |
| 544 | { | 587 | { |
| 545 | struct cpuinfo_x86 *c = cpu_data; | 588 | struct cpuinfo_x86 *c = cpu_data; |
| 546 | char *cpuname=NULL; | 589 | char *cpuname=NULL; |
| 547 | int ret; | 590 | int ret; |
| 548 | 591 | ||
| 549 | /* Check ACPI support for C3 state */ | 592 | /* Check what we have on this motherboard */ |
| 550 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | ||
| 551 | &longhaul_walk_callback, NULL, (void *)&pr); | ||
| 552 | if (pr == NULL) goto err_acpi; | ||
| 553 | |||
| 554 | cx = &pr->power.states[ACPI_STATE_C3]; | ||
| 555 | if (cx->address == 0 || cx->latency > 1000) goto err_acpi; | ||
| 556 | |||
| 557 | /* Now check what we have on this motherboard */ | ||
| 558 | switch (c->x86_model) { | 593 | switch (c->x86_model) { |
| 559 | case 6: | 594 | case 6: |
| 560 | cpu_model = CPU_SAMUEL; | 595 | cpu_model = CPU_SAMUEL; |
| @@ -636,12 +671,36 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
| 636 | break; | 671 | break; |
| 637 | }; | 672 | }; |
| 638 | 673 | ||
| 674 | /* Find ACPI data for processor */ | ||
| 675 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | ||
| 676 | &longhaul_walk_callback, NULL, (void *)&pr); | ||
| 677 | if (pr == NULL) | ||
| 678 | goto err_acpi; | ||
| 679 | |||
| 680 | if (longhaul_version == TYPE_POWERSAVER) { | ||
| 681 | /* Check ACPI support for C3 state */ | ||
| 682 | cx = &pr->power.states[ACPI_STATE_C3]; | ||
| 683 | if (cx->address == 0 || | ||
| 684 | (cx->latency > 1000 && ignore_latency == 0) ) | ||
| 685 | goto err_acpi; | ||
| 686 | |||
| 687 | } else { | ||
| 688 | /* Check ACPI support for bus master arbiter disable */ | ||
| 689 | if (!pr->flags.bm_control) { | ||
| 690 | if (!enable_arbiter_disable()) { | ||
| 691 | printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n"); | ||
| 692 | return -ENODEV; | ||
| 693 | } else | ||
| 694 | port22_en = 1; | ||
| 695 | } | ||
| 696 | } | ||
| 697 | |||
| 639 | ret = longhaul_get_ranges(); | 698 | ret = longhaul_get_ranges(); |
| 640 | if (ret != 0) | 699 | if (ret != 0) |
| 641 | return ret; | 700 | return ret; |
| 642 | 701 | ||
| 643 | if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && | 702 | if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && |
| 644 | (dont_scale_voltage==0)) | 703 | (scale_voltage != 0)) |
| 645 | longhaul_setup_voltagescaling(); | 704 | longhaul_setup_voltagescaling(); |
| 646 | 705 | ||
| 647 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | 706 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; |
| @@ -729,8 +788,10 @@ static void __exit longhaul_exit(void) | |||
| 729 | kfree(longhaul_table); | 788 | kfree(longhaul_table); |
| 730 | } | 789 | } |
| 731 | 790 | ||
| 732 | module_param (dont_scale_voltage, int, 0644); | 791 | module_param (scale_voltage, int, 0644); |
| 733 | MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor"); | 792 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); |
| 793 | module_param(ignore_latency, int, 0644); | ||
| 794 | MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test"); | ||
| 734 | 795 | ||
| 735 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); | 796 | MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); |
| 736 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); | 797 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); |
| @@ -738,4 +799,3 @@ MODULE_LICENSE ("GPL"); | |||
| 738 | 799 | ||
| 739 | late_initcall(longhaul_init); | 800 | late_initcall(longhaul_init); |
| 740 | module_exit(longhaul_exit); | 801 | module_exit(longhaul_exit); |
| 741 | |||
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h index d3a95d77ee85..bc4682aad69b 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.h +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h | |||
| @@ -450,17 +450,45 @@ static int __initdata nehemiah_c_eblcr[32] = { | |||
| 450 | * Voltage scales. Div/Mod by 1000 to get actual voltage. | 450 | * Voltage scales. Div/Mod by 1000 to get actual voltage. |
| 451 | * Which scale to use depends on the VRM type in use. | 451 | * Which scale to use depends on the VRM type in use. |
| 452 | */ | 452 | */ |
| 453 | static int __initdata vrm85scales[32] = { | 453 | |
| 454 | 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, | 454 | struct mV_pos { |
| 455 | 1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300, | 455 | unsigned short mV; |
| 456 | 1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725, | 456 | unsigned short pos; |
| 457 | 1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325, | 457 | }; |
| 458 | |||
| 459 | static struct mV_pos __initdata vrm85_mV[32] = { | ||
| 460 | {1250, 8}, {1200, 6}, {1150, 4}, {1100, 2}, | ||
| 461 | {1050, 0}, {1800, 30}, {1750, 28}, {1700, 26}, | ||
| 462 | {1650, 24}, {1600, 22}, {1550, 20}, {1500, 18}, | ||
| 463 | {1450, 16}, {1400, 14}, {1350, 12}, {1300, 10}, | ||
| 464 | {1275, 9}, {1225, 7}, {1175, 5}, {1125, 3}, | ||
| 465 | {1075, 1}, {1825, 31}, {1775, 29}, {1725, 27}, | ||
| 466 | {1675, 25}, {1625, 23}, {1575, 21}, {1525, 19}, | ||
| 467 | {1475, 17}, {1425, 15}, {1375, 13}, {1325, 11} | ||
| 468 | }; | ||
| 469 | |||
| 470 | static unsigned char __initdata mV_vrm85[32] = { | ||
| 471 | 0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11, | ||
| 472 | 0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d, | ||
| 473 | 0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19, | ||
| 474 | 0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15 | ||
| 475 | }; | ||
| 476 | |||
| 477 | static struct mV_pos __initdata mobilevrm_mV[32] = { | ||
| 478 | {1750, 31}, {1700, 30}, {1650, 29}, {1600, 28}, | ||
| 479 | {1550, 27}, {1500, 26}, {1450, 25}, {1400, 24}, | ||
| 480 | {1350, 23}, {1300, 22}, {1250, 21}, {1200, 20}, | ||
| 481 | {1150, 19}, {1100, 18}, {1050, 17}, {1000, 16}, | ||
| 482 | {975, 15}, {950, 14}, {925, 13}, {900, 12}, | ||
| 483 | {875, 11}, {850, 10}, {825, 9}, {800, 8}, | ||
| 484 | {775, 7}, {750, 6}, {725, 5}, {700, 4}, | ||
| 485 | {675, 3}, {650, 2}, {625, 1}, {600, 0} | ||
| 458 | }; | 486 | }; |
| 459 | 487 | ||
| 460 | static int __initdata mobilevrmscales[32] = { | 488 | static unsigned char __initdata mV_mobilevrm[32] = { |
| 461 | 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650, | 489 | 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, |
| 462 | 1600, 1550, 1500, 1450, 1500, 1350, 1300, -1, | 490 | 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, |
| 463 | 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100, | 491 | 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, |
| 464 | 1075, 1050, 1025, 1000, 975, 950, 925, -1, | 492 | 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 |
| 465 | }; | 493 | }; |
| 466 | 494 | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index b77f1358bd79..7a9325349e94 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 24 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI |
| 25 | #include <linux/acpi.h> | 25 | #include <linux/acpi.h> |
| 26 | #include <linux/dmi.h> | ||
| 26 | #include <acpi/processor.h> | 27 | #include <acpi/processor.h> |
| 27 | #endif | 28 | #endif |
| 28 | 29 | ||
| @@ -377,6 +378,35 @@ static int centrino_cpu_early_init_acpi(void) | |||
| 377 | return 0; | 378 | return 0; |
| 378 | } | 379 | } |
| 379 | 380 | ||
| 381 | |||
| 382 | /* | ||
| 383 | * Some BIOSes do SW_ANY coordination internally, either set it up in hw | ||
| 384 | * or do it in BIOS firmware and won't inform about it to OS. If not | ||
| 385 | * detected, this has a side effect of making CPU run at a different speed | ||
| 386 | * than OS intended it to run at. Detect it and handle it cleanly. | ||
| 387 | */ | ||
| 388 | static int bios_with_sw_any_bug; | ||
| 389 | static int __init sw_any_bug_found(struct dmi_system_id *d) | ||
| 390 | { | ||
| 391 | bios_with_sw_any_bug = 1; | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 395 | |||
| 396 | static struct dmi_system_id sw_any_bug_dmi_table[] = { | ||
| 397 | { | ||
| 398 | .callback = sw_any_bug_found, | ||
| 399 | .ident = "Supermicro Server X6DLP", | ||
| 400 | .matches = { | ||
| 401 | DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), | ||
| 402 | DMI_MATCH(DMI_BIOS_VERSION, "080010"), | ||
| 403 | DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), | ||
| 404 | }, | ||
| 405 | }, | ||
| 406 | { } | ||
| 407 | }; | ||
| 408 | |||
| 409 | |||
| 380 | /* | 410 | /* |
| 381 | * centrino_cpu_init_acpi - register with ACPI P-States library | 411 | * centrino_cpu_init_acpi - register with ACPI P-States library |
| 382 | * | 412 | * |
| @@ -398,14 +428,24 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) | |||
| 398 | dprintk(PFX "obtaining ACPI data failed\n"); | 428 | dprintk(PFX "obtaining ACPI data failed\n"); |
| 399 | return -EIO; | 429 | return -EIO; |
| 400 | } | 430 | } |
| 431 | |||
| 401 | policy->shared_type = p->shared_type; | 432 | policy->shared_type = p->shared_type; |
| 402 | /* | 433 | /* |
| 403 | * Will let policy->cpus know about dependency only when software | 434 | * Will let policy->cpus know about dependency only when software |
| 404 | * coordination is required. | 435 | * coordination is required. |
| 405 | */ | 436 | */ |
| 406 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || | 437 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || |
| 407 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) | 438 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { |
| 408 | policy->cpus = p->shared_cpu_map; | 439 | policy->cpus = p->shared_cpu_map; |
| 440 | } | ||
| 441 | |||
| 442 | #ifdef CONFIG_SMP | ||
| 443 | dmi_check_system(sw_any_bug_dmi_table); | ||
| 444 | if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) { | ||
| 445 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
| 446 | policy->cpus = cpu_core_map[cpu]; | ||
| 447 | } | ||
| 448 | #endif | ||
| 409 | 449 | ||
| 410 | /* verify the acpi_data */ | 450 | /* verify the acpi_data */ |
| 411 | if (p->state_count <= 1) { | 451 | if (p->state_count <= 1) { |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b3df613ae4ec..d35a9f06ab7b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -32,7 +32,7 @@ | |||
| 32 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) | 32 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) |
| 33 | 33 | ||
| 34 | /** | 34 | /** |
| 35 | * The "cpufreq driver" - the arch- or hardware-dependend low | 35 | * The "cpufreq driver" - the arch- or hardware-dependent low |
| 36 | * level driver of CPUFreq support, and its spinlock. This lock | 36 | * level driver of CPUFreq support, and its spinlock. This lock |
| 37 | * also protects the cpufreq_cpu_data array. | 37 | * also protects the cpufreq_cpu_data array. |
| 38 | */ | 38 | */ |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 52cf1f021825..bf8aa45d4f01 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -55,6 +55,10 @@ struct cpu_dbs_info_s { | |||
| 55 | struct cpufreq_policy *cur_policy; | 55 | struct cpufreq_policy *cur_policy; |
| 56 | struct work_struct work; | 56 | struct work_struct work; |
| 57 | unsigned int enable; | 57 | unsigned int enable; |
| 58 | struct cpufreq_frequency_table *freq_table; | ||
| 59 | unsigned int freq_lo; | ||
| 60 | unsigned int freq_lo_jiffies; | ||
| 61 | unsigned int freq_hi_jiffies; | ||
| 58 | }; | 62 | }; |
| 59 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 63 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
| 60 | 64 | ||
| @@ -72,15 +76,15 @@ static DEFINE_MUTEX(dbs_mutex); | |||
| 72 | 76 | ||
| 73 | static struct workqueue_struct *kondemand_wq; | 77 | static struct workqueue_struct *kondemand_wq; |
| 74 | 78 | ||
| 75 | struct dbs_tuners { | 79 | static struct dbs_tuners { |
| 76 | unsigned int sampling_rate; | 80 | unsigned int sampling_rate; |
| 77 | unsigned int up_threshold; | 81 | unsigned int up_threshold; |
| 78 | unsigned int ignore_nice; | 82 | unsigned int ignore_nice; |
| 79 | }; | 83 | unsigned int powersave_bias; |
| 80 | 84 | } dbs_tuners_ins = { | |
| 81 | static struct dbs_tuners dbs_tuners_ins = { | ||
| 82 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 85 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
| 83 | .ignore_nice = 0, | 86 | .ignore_nice = 0, |
| 87 | .powersave_bias = 0, | ||
| 84 | }; | 88 | }; |
| 85 | 89 | ||
| 86 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu) | 90 | static inline cputime64_t get_cpu_idle_time(unsigned int cpu) |
| @@ -96,6 +100,70 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu) | |||
| 96 | return retval; | 100 | return retval; |
| 97 | } | 101 | } |
| 98 | 102 | ||
| 103 | /* | ||
| 104 | * Find right freq to be set now with powersave_bias on. | ||
| 105 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | ||
| 106 | * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. | ||
| 107 | */ | ||
| 108 | static unsigned int powersave_bias_target(struct cpufreq_policy *policy, | ||
| 109 | unsigned int freq_next, | ||
| 110 | unsigned int relation) | ||
| 111 | { | ||
| 112 | unsigned int freq_req, freq_reduc, freq_avg; | ||
| 113 | unsigned int freq_hi, freq_lo; | ||
| 114 | unsigned int index = 0; | ||
| 115 | unsigned int jiffies_total, jiffies_hi, jiffies_lo; | ||
| 116 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, policy->cpu); | ||
| 117 | |||
| 118 | if (!dbs_info->freq_table) { | ||
| 119 | dbs_info->freq_lo = 0; | ||
| 120 | dbs_info->freq_lo_jiffies = 0; | ||
| 121 | return freq_next; | ||
| 122 | } | ||
| 123 | |||
| 124 | cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, | ||
| 125 | relation, &index); | ||
| 126 | freq_req = dbs_info->freq_table[index].frequency; | ||
| 127 | freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000; | ||
| 128 | freq_avg = freq_req - freq_reduc; | ||
| 129 | |||
| 130 | /* Find freq bounds for freq_avg in freq_table */ | ||
| 131 | index = 0; | ||
| 132 | cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, | ||
| 133 | CPUFREQ_RELATION_H, &index); | ||
| 134 | freq_lo = dbs_info->freq_table[index].frequency; | ||
| 135 | index = 0; | ||
| 136 | cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, | ||
| 137 | CPUFREQ_RELATION_L, &index); | ||
| 138 | freq_hi = dbs_info->freq_table[index].frequency; | ||
| 139 | |||
| 140 | /* Find out how long we have to be in hi and lo freqs */ | ||
| 141 | if (freq_hi == freq_lo) { | ||
| 142 | dbs_info->freq_lo = 0; | ||
| 143 | dbs_info->freq_lo_jiffies = 0; | ||
| 144 | return freq_lo; | ||
| 145 | } | ||
| 146 | jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
| 147 | jiffies_hi = (freq_avg - freq_lo) * jiffies_total; | ||
| 148 | jiffies_hi += ((freq_hi - freq_lo) / 2); | ||
| 149 | jiffies_hi /= (freq_hi - freq_lo); | ||
| 150 | jiffies_lo = jiffies_total - jiffies_hi; | ||
| 151 | dbs_info->freq_lo = freq_lo; | ||
| 152 | dbs_info->freq_lo_jiffies = jiffies_lo; | ||
| 153 | dbs_info->freq_hi_jiffies = jiffies_hi; | ||
| 154 | return freq_hi; | ||
| 155 | } | ||
| 156 | |||
| 157 | static void ondemand_powersave_bias_init(void) | ||
| 158 | { | ||
| 159 | int i; | ||
| 160 | for_each_online_cpu(i) { | ||
| 161 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i); | ||
| 162 | dbs_info->freq_table = cpufreq_frequency_get_table(i); | ||
| 163 | dbs_info->freq_lo = 0; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 99 | /************************** sysfs interface ************************/ | 167 | /************************** sysfs interface ************************/ |
| 100 | static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) | 168 | static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) |
| 101 | { | 169 | { |
| @@ -124,6 +192,7 @@ static ssize_t show_##file_name \ | |||
| 124 | show_one(sampling_rate, sampling_rate); | 192 | show_one(sampling_rate, sampling_rate); |
| 125 | show_one(up_threshold, up_threshold); | 193 | show_one(up_threshold, up_threshold); |
| 126 | show_one(ignore_nice_load, ignore_nice); | 194 | show_one(ignore_nice_load, ignore_nice); |
| 195 | show_one(powersave_bias, powersave_bias); | ||
| 127 | 196 | ||
| 128 | static ssize_t store_sampling_rate(struct cpufreq_policy *unused, | 197 | static ssize_t store_sampling_rate(struct cpufreq_policy *unused, |
| 129 | const char *buf, size_t count) | 198 | const char *buf, size_t count) |
| @@ -198,6 +267,27 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, | |||
| 198 | return count; | 267 | return count; |
| 199 | } | 268 | } |
| 200 | 269 | ||
| 270 | static ssize_t store_powersave_bias(struct cpufreq_policy *unused, | ||
| 271 | const char *buf, size_t count) | ||
| 272 | { | ||
| 273 | unsigned int input; | ||
| 274 | int ret; | ||
| 275 | ret = sscanf(buf, "%u", &input); | ||
| 276 | |||
| 277 | if (ret != 1) | ||
| 278 | return -EINVAL; | ||
| 279 | |||
| 280 | if (input > 1000) | ||
| 281 | input = 1000; | ||
| 282 | |||
| 283 | mutex_lock(&dbs_mutex); | ||
| 284 | dbs_tuners_ins.powersave_bias = input; | ||
| 285 | ondemand_powersave_bias_init(); | ||
| 286 | mutex_unlock(&dbs_mutex); | ||
| 287 | |||
| 288 | return count; | ||
| 289 | } | ||
| 290 | |||
| 201 | #define define_one_rw(_name) \ | 291 | #define define_one_rw(_name) \ |
| 202 | static struct freq_attr _name = \ | 292 | static struct freq_attr _name = \ |
| 203 | __ATTR(_name, 0644, show_##_name, store_##_name) | 293 | __ATTR(_name, 0644, show_##_name, store_##_name) |
| @@ -205,6 +295,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name) | |||
| 205 | define_one_rw(sampling_rate); | 295 | define_one_rw(sampling_rate); |
| 206 | define_one_rw(up_threshold); | 296 | define_one_rw(up_threshold); |
| 207 | define_one_rw(ignore_nice_load); | 297 | define_one_rw(ignore_nice_load); |
| 298 | define_one_rw(powersave_bias); | ||
| 208 | 299 | ||
| 209 | static struct attribute * dbs_attributes[] = { | 300 | static struct attribute * dbs_attributes[] = { |
| 210 | &sampling_rate_max.attr, | 301 | &sampling_rate_max.attr, |
| @@ -212,6 +303,7 @@ static struct attribute * dbs_attributes[] = { | |||
| 212 | &sampling_rate.attr, | 303 | &sampling_rate.attr, |
| 213 | &up_threshold.attr, | 304 | &up_threshold.attr, |
| 214 | &ignore_nice_load.attr, | 305 | &ignore_nice_load.attr, |
| 306 | &powersave_bias.attr, | ||
| 215 | NULL | 307 | NULL |
| 216 | }; | 308 | }; |
| 217 | 309 | ||
| @@ -234,6 +326,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 234 | if (!this_dbs_info->enable) | 326 | if (!this_dbs_info->enable) |
| 235 | return; | 327 | return; |
| 236 | 328 | ||
| 329 | this_dbs_info->freq_lo = 0; | ||
| 237 | policy = this_dbs_info->cur_policy; | 330 | policy = this_dbs_info->cur_policy; |
| 238 | cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); | 331 | cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); |
| 239 | total_ticks = (unsigned int) cputime64_sub(cur_jiffies, | 332 | total_ticks = (unsigned int) cputime64_sub(cur_jiffies, |
| @@ -274,11 +367,18 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 274 | /* Check for frequency increase */ | 367 | /* Check for frequency increase */ |
| 275 | if (load > dbs_tuners_ins.up_threshold) { | 368 | if (load > dbs_tuners_ins.up_threshold) { |
| 276 | /* if we are already at full speed then break out early */ | 369 | /* if we are already at full speed then break out early */ |
| 277 | if (policy->cur == policy->max) | 370 | if (!dbs_tuners_ins.powersave_bias) { |
| 278 | return; | 371 | if (policy->cur == policy->max) |
| 279 | 372 | return; | |
| 280 | __cpufreq_driver_target(policy, policy->max, | 373 | |
| 281 | CPUFREQ_RELATION_H); | 374 | __cpufreq_driver_target(policy, policy->max, |
| 375 | CPUFREQ_RELATION_H); | ||
| 376 | } else { | ||
| 377 | int freq = powersave_bias_target(policy, policy->max, | ||
| 378 | CPUFREQ_RELATION_H); | ||
| 379 | __cpufreq_driver_target(policy, freq, | ||
| 380 | CPUFREQ_RELATION_L); | ||
| 381 | } | ||
| 282 | return; | 382 | return; |
| 283 | } | 383 | } |
| 284 | 384 | ||
| @@ -293,37 +393,64 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 293 | * policy. To be safe, we focus 10 points under the threshold. | 393 | * policy. To be safe, we focus 10 points under the threshold. |
| 294 | */ | 394 | */ |
| 295 | if (load < (dbs_tuners_ins.up_threshold - 10)) { | 395 | if (load < (dbs_tuners_ins.up_threshold - 10)) { |
| 296 | unsigned int freq_next; | 396 | unsigned int freq_next = (policy->cur * load) / |
| 297 | freq_next = (policy->cur * load) / | ||
| 298 | (dbs_tuners_ins.up_threshold - 10); | 397 | (dbs_tuners_ins.up_threshold - 10); |
| 299 | 398 | if (!dbs_tuners_ins.powersave_bias) { | |
| 300 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); | 399 | __cpufreq_driver_target(policy, freq_next, |
| 400 | CPUFREQ_RELATION_L); | ||
| 401 | } else { | ||
| 402 | int freq = powersave_bias_target(policy, freq_next, | ||
| 403 | CPUFREQ_RELATION_L); | ||
| 404 | __cpufreq_driver_target(policy, freq, | ||
| 405 | CPUFREQ_RELATION_L); | ||
| 406 | } | ||
| 301 | } | 407 | } |
| 302 | } | 408 | } |
| 303 | 409 | ||
| 410 | /* Sampling types */ | ||
| 411 | enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; | ||
| 412 | |||
| 304 | static void do_dbs_timer(void *data) | 413 | static void do_dbs_timer(void *data) |
| 305 | { | 414 | { |
| 306 | unsigned int cpu = smp_processor_id(); | 415 | unsigned int cpu = smp_processor_id(); |
| 307 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); | 416 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); |
| 417 | /* We want all CPUs to do sampling nearly on same jiffy */ | ||
| 418 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
| 419 | delay -= jiffies % delay; | ||
| 308 | 420 | ||
| 309 | if (!dbs_info->enable) | 421 | if (!dbs_info->enable) |
| 310 | return; | 422 | return; |
| 311 | 423 | /* Common NORMAL_SAMPLE setup */ | |
| 312 | lock_cpu_hotplug(); | 424 | INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE); |
| 313 | dbs_check_cpu(dbs_info); | 425 | if (!dbs_tuners_ins.powersave_bias || |
| 314 | unlock_cpu_hotplug(); | 426 | (unsigned long) data == DBS_NORMAL_SAMPLE) { |
| 315 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, | 427 | lock_cpu_hotplug(); |
| 316 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); | 428 | dbs_check_cpu(dbs_info); |
| 429 | unlock_cpu_hotplug(); | ||
| 430 | if (dbs_info->freq_lo) { | ||
| 431 | /* Setup timer for SUB_SAMPLE */ | ||
| 432 | INIT_WORK(&dbs_info->work, do_dbs_timer, | ||
| 433 | (void *)DBS_SUB_SAMPLE); | ||
| 434 | delay = dbs_info->freq_hi_jiffies; | ||
| 435 | } | ||
| 436 | } else { | ||
| 437 | __cpufreq_driver_target(dbs_info->cur_policy, | ||
| 438 | dbs_info->freq_lo, | ||
| 439 | CPUFREQ_RELATION_H); | ||
| 440 | } | ||
| 441 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); | ||
| 317 | } | 442 | } |
| 318 | 443 | ||
| 319 | static inline void dbs_timer_init(unsigned int cpu) | 444 | static inline void dbs_timer_init(unsigned int cpu) |
| 320 | { | 445 | { |
| 321 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); | 446 | struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); |
| 447 | /* We want all CPUs to do sampling nearly on same jiffy */ | ||
| 448 | int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | ||
| 449 | delay -= jiffies % delay; | ||
| 322 | 450 | ||
| 323 | INIT_WORK(&dbs_info->work, do_dbs_timer, 0); | 451 | ondemand_powersave_bias_init(); |
| 324 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, | 452 | INIT_WORK(&dbs_info->work, do_dbs_timer, NULL); |
| 325 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); | 453 | queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); |
| 326 | return; | ||
| 327 | } | 454 | } |
| 328 | 455 | ||
| 329 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | 456 | static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) |
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 25eee5394201..c2ecc599dc5f 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
| @@ -350,12 +350,10 @@ __init cpufreq_stats_init(void) | |||
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); | 352 | register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); |
| 353 | lock_cpu_hotplug(); | ||
| 354 | for_each_online_cpu(cpu) { | 353 | for_each_online_cpu(cpu) { |
| 355 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, | 354 | cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, |
| 356 | (void *)(long)cpu); | 355 | (void *)(long)cpu); |
| 357 | } | 356 | } |
| 358 | unlock_cpu_hotplug(); | ||
| 359 | return 0; | 357 | return 0; |
| 360 | } | 358 | } |
| 361 | static void | 359 | static void |
