diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/platform/x86/intel_ips.c | 122 |
1 files changed, 90 insertions, 32 deletions
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 9024480a8228..c44a5e8b8b82 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
| @@ -51,7 +51,6 @@ | |||
| 51 | * TODO: | 51 | * TODO: |
| 52 | * - handle CPU hotplug | 52 | * - handle CPU hotplug |
| 53 | * - provide turbo enable/disable api | 53 | * - provide turbo enable/disable api |
| 54 | * - make sure we can write turbo enable/disable reg based on MISC_EN | ||
| 55 | * | 54 | * |
| 56 | * Related documents: | 55 | * Related documents: |
| 57 | * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 | 56 | * - CDI 403777, 403778 - Auburndale EDS vol 1 & 2 |
| @@ -230,7 +229,7 @@ | |||
| 230 | #define THM_TC2 0xac | 229 | #define THM_TC2 0xac |
| 231 | #define THM_DTV 0xb0 | 230 | #define THM_DTV 0xb0 |
| 232 | #define THM_ITV 0xd8 | 231 | #define THM_ITV 0xd8 |
| 233 | #define ITV_ME_SEQNO_MASK 0x000f0000 /* ME should update every ~200ms */ | 232 | #define ITV_ME_SEQNO_MASK 0x00ff0000 /* ME should update every ~200ms */ |
| 234 | #define ITV_ME_SEQNO_SHIFT (16) | 233 | #define ITV_ME_SEQNO_SHIFT (16) |
| 235 | #define ITV_MCH_TEMP_MASK 0x0000ff00 | 234 | #define ITV_MCH_TEMP_MASK 0x0000ff00 |
| 236 | #define ITV_MCH_TEMP_SHIFT (8) | 235 | #define ITV_MCH_TEMP_SHIFT (8) |
| @@ -325,6 +324,7 @@ struct ips_driver { | |||
| 325 | bool gpu_preferred; | 324 | bool gpu_preferred; |
| 326 | bool poll_turbo_status; | 325 | bool poll_turbo_status; |
| 327 | bool second_cpu; | 326 | bool second_cpu; |
| 327 | bool turbo_toggle_allowed; | ||
| 328 | struct ips_mcp_limits *limits; | 328 | struct ips_mcp_limits *limits; |
| 329 | 329 | ||
| 330 | /* Optional MCH interfaces for if i915 is in use */ | 330 | /* Optional MCH interfaces for if i915 is in use */ |
| @@ -415,7 +415,7 @@ static void ips_cpu_lower(struct ips_driver *ips) | |||
| 415 | new_limit = cur_limit - 8; /* 1W decrease */ | 415 | new_limit = cur_limit - 8; /* 1W decrease */ |
| 416 | 416 | ||
| 417 | /* Clamp to SKU TDP limit */ | 417 | /* Clamp to SKU TDP limit */ |
| 418 | if (((new_limit * 10) / 8) < (ips->orig_turbo_limit & TURBO_TDP_MASK)) | 418 | if (new_limit < (ips->orig_turbo_limit & TURBO_TDP_MASK)) |
| 419 | new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; | 419 | new_limit = ips->orig_turbo_limit & TURBO_TDP_MASK; |
| 420 | 420 | ||
| 421 | thm_writew(THM_MPCPC, (new_limit * 10) / 8); | 421 | thm_writew(THM_MPCPC, (new_limit * 10) / 8); |
| @@ -461,7 +461,8 @@ static void ips_enable_cpu_turbo(struct ips_driver *ips) | |||
| 461 | if (ips->__cpu_turbo_on) | 461 | if (ips->__cpu_turbo_on) |
| 462 | return; | 462 | return; |
| 463 | 463 | ||
| 464 | on_each_cpu(do_enable_cpu_turbo, ips, 1); | 464 | if (ips->turbo_toggle_allowed) |
| 465 | on_each_cpu(do_enable_cpu_turbo, ips, 1); | ||
| 465 | 466 | ||
| 466 | ips->__cpu_turbo_on = true; | 467 | ips->__cpu_turbo_on = true; |
| 467 | } | 468 | } |
| @@ -498,7 +499,8 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips) | |||
| 498 | if (!ips->__cpu_turbo_on) | 499 | if (!ips->__cpu_turbo_on) |
| 499 | return; | 500 | return; |
| 500 | 501 | ||
| 501 | on_each_cpu(do_disable_cpu_turbo, ips, 1); | 502 | if (ips->turbo_toggle_allowed) |
| 503 | on_each_cpu(do_disable_cpu_turbo, ips, 1); | ||
| 502 | 504 | ||
| 503 | ips->__cpu_turbo_on = false; | 505 | ips->__cpu_turbo_on = false; |
| 504 | } | 506 | } |
| @@ -598,17 +600,29 @@ static bool mcp_exceeded(struct ips_driver *ips) | |||
| 598 | { | 600 | { |
| 599 | unsigned long flags; | 601 | unsigned long flags; |
| 600 | bool ret = false; | 602 | bool ret = false; |
| 603 | u32 temp_limit; | ||
| 604 | u32 avg_power; | ||
| 605 | const char *msg = "MCP limit exceeded: "; | ||
| 601 | 606 | ||
| 602 | spin_lock_irqsave(&ips->turbo_status_lock, flags); | 607 | spin_lock_irqsave(&ips->turbo_status_lock, flags); |
| 603 | if (ips->mcp_avg_temp > (ips->mcp_temp_limit * 100)) | 608 | |
| 604 | ret = true; | 609 | temp_limit = ips->mcp_temp_limit * 100; |
| 605 | if (ips->cpu_avg_power + ips->mch_avg_power > ips->mcp_power_limit) | 610 | if (ips->mcp_avg_temp > temp_limit) { |
| 611 | dev_info(&ips->dev->dev, | ||
| 612 | "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp, | ||
| 613 | temp_limit); | ||
| 606 | ret = true; | 614 | ret = true; |
| 607 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); | 615 | } |
| 608 | 616 | ||
| 609 | if (ret) | 617 | avg_power = ips->cpu_avg_power + ips->mch_avg_power; |
| 618 | if (avg_power > ips->mcp_power_limit) { | ||
| 610 | dev_info(&ips->dev->dev, | 619 | dev_info(&ips->dev->dev, |
| 611 | "MCP power or thermal limit exceeded\n"); | 620 | "%sAvg power %u, limit %u\n", msg, avg_power, |
| 621 | ips->mcp_power_limit); | ||
| 622 | ret = true; | ||
| 623 | } | ||
| 624 | |||
| 625 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); | ||
| 612 | 626 | ||
| 613 | return ret; | 627 | return ret; |
| 614 | } | 628 | } |
| @@ -663,6 +677,27 @@ static bool mch_exceeded(struct ips_driver *ips) | |||
| 663 | } | 677 | } |
| 664 | 678 | ||
| 665 | /** | 679 | /** |
| 680 | * verify_limits - verify BIOS provided limits | ||
| 681 | * @ips: IPS structure | ||
| 682 | * | ||
| 683 | * BIOS can optionally provide non-default limits for power and temp. Check | ||
| 684 | * them here and use the defaults if the BIOS values are not provided or | ||
| 685 | * are otherwise unusable. | ||
| 686 | */ | ||
| 687 | static void verify_limits(struct ips_driver *ips) | ||
| 688 | { | ||
| 689 | if (ips->mcp_power_limit < ips->limits->mcp_power_limit || | ||
| 690 | ips->mcp_power_limit > 35000) | ||
| 691 | ips->mcp_power_limit = ips->limits->mcp_power_limit; | ||
| 692 | |||
| 693 | if (ips->mcp_temp_limit < ips->limits->core_temp_limit || | ||
| 694 | ips->mcp_temp_limit < ips->limits->mch_temp_limit || | ||
| 695 | ips->mcp_temp_limit > 150) | ||
| 696 | ips->mcp_temp_limit = min(ips->limits->core_temp_limit, | ||
| 697 | ips->limits->mch_temp_limit); | ||
| 698 | } | ||
| 699 | |||
| 700 | /** | ||
| 666 | * update_turbo_limits - get various limits & settings from regs | 701 | * update_turbo_limits - get various limits & settings from regs |
| 667 | * @ips: IPS driver struct | 702 | * @ips: IPS driver struct |
| 668 | * | 703 | * |
| @@ -680,12 +715,21 @@ static void update_turbo_limits(struct ips_driver *ips) | |||
| 680 | u32 hts = thm_readl(THM_HTS); | 715 | u32 hts = thm_readl(THM_HTS); |
| 681 | 716 | ||
| 682 | ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); | 717 | ips->cpu_turbo_enabled = !(hts & HTS_PCTD_DIS); |
| 683 | ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); | 718 | /* |
| 719 | * Disable turbo for now, until we can figure out why the power figures | ||
| 720 | * are wrong | ||
| 721 | */ | ||
| 722 | ips->cpu_turbo_enabled = false; | ||
| 723 | |||
| 724 | if (ips->gpu_busy) | ||
| 725 | ips->gpu_turbo_enabled = !(hts & HTS_GTD_DIS); | ||
| 726 | |||
| 684 | ips->core_power_limit = thm_readw(THM_MPCPC); | 727 | ips->core_power_limit = thm_readw(THM_MPCPC); |
| 685 | ips->mch_power_limit = thm_readw(THM_MMGPC); | 728 | ips->mch_power_limit = thm_readw(THM_MMGPC); |
| 686 | ips->mcp_temp_limit = thm_readw(THM_PTL); | 729 | ips->mcp_temp_limit = thm_readw(THM_PTL); |
| 687 | ips->mcp_power_limit = thm_readw(THM_MPPC); | 730 | ips->mcp_power_limit = thm_readw(THM_MPPC); |
| 688 | 731 | ||
| 732 | verify_limits(ips); | ||
| 689 | /* Ignore BIOS CPU vs GPU pref */ | 733 | /* Ignore BIOS CPU vs GPU pref */ |
| 690 | } | 734 | } |
| 691 | 735 | ||
| @@ -858,7 +902,7 @@ static u32 get_cpu_power(struct ips_driver *ips, u32 *last, int period) | |||
| 858 | ret = (ret * 1000) / 65535; | 902 | ret = (ret * 1000) / 65535; |
| 859 | *last = val; | 903 | *last = val; |
| 860 | 904 | ||
| 861 | return ret; | 905 | return 0; |
| 862 | } | 906 | } |
| 863 | 907 | ||
| 864 | static const u16 temp_decay_factor = 2; | 908 | static const u16 temp_decay_factor = 2; |
| @@ -940,7 +984,6 @@ static int ips_monitor(void *data) | |||
| 940 | kfree(mch_samples); | 984 | kfree(mch_samples); |
| 941 | kfree(cpu_samples); | 985 | kfree(cpu_samples); |
| 942 | kfree(mchp_samples); | 986 | kfree(mchp_samples); |
| 943 | kthread_stop(ips->adjust); | ||
| 944 | return -ENOMEM; | 987 | return -ENOMEM; |
| 945 | } | 988 | } |
| 946 | 989 | ||
| @@ -948,7 +991,7 @@ static int ips_monitor(void *data) | |||
| 948 | ITV_ME_SEQNO_SHIFT; | 991 | ITV_ME_SEQNO_SHIFT; |
| 949 | seqno_timestamp = get_jiffies_64(); | 992 | seqno_timestamp = get_jiffies_64(); |
| 950 | 993 | ||
| 951 | old_cpu_power = thm_readl(THM_CEC) / 65535; | 994 | old_cpu_power = thm_readl(THM_CEC); |
| 952 | schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); | 995 | schedule_timeout_interruptible(msecs_to_jiffies(IPS_SAMPLE_PERIOD)); |
| 953 | 996 | ||
| 954 | /* Collect an initial average */ | 997 | /* Collect an initial average */ |
| @@ -1150,11 +1193,18 @@ static irqreturn_t ips_irq_handler(int irq, void *arg) | |||
| 1150 | STS_GPL_SHIFT; | 1193 | STS_GPL_SHIFT; |
| 1151 | /* ignore EC CPU vs GPU pref */ | 1194 | /* ignore EC CPU vs GPU pref */ |
| 1152 | ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); | 1195 | ips->cpu_turbo_enabled = !(sts & STS_PCTD_DIS); |
| 1153 | ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); | 1196 | /* |
| 1197 | * Disable turbo for now, until we can figure | ||
| 1198 | * out why the power figures are wrong | ||
| 1199 | */ | ||
| 1200 | ips->cpu_turbo_enabled = false; | ||
| 1201 | if (ips->gpu_busy) | ||
| 1202 | ips->gpu_turbo_enabled = !(sts & STS_GTD_DIS); | ||
| 1154 | ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> | 1203 | ips->mcp_temp_limit = (sts & STS_PTL_MASK) >> |
| 1155 | STS_PTL_SHIFT; | 1204 | STS_PTL_SHIFT; |
| 1156 | ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> | 1205 | ips->mcp_power_limit = (tc1 & STS_PPL_MASK) >> |
| 1157 | STS_PPL_SHIFT; | 1206 | STS_PPL_SHIFT; |
| 1207 | verify_limits(ips); | ||
| 1158 | spin_unlock(&ips->turbo_status_lock); | 1208 | spin_unlock(&ips->turbo_status_lock); |
| 1159 | 1209 | ||
| 1160 | thm_writeb(THM_SEC, SEC_ACK); | 1210 | thm_writeb(THM_SEC, SEC_ACK); |
| @@ -1333,8 +1383,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) | |||
| 1333 | * turbo manually or we'll get an illegal MSR access, even though | 1383 | * turbo manually or we'll get an illegal MSR access, even though |
| 1334 | * turbo will still be available. | 1384 | * turbo will still be available. |
| 1335 | */ | 1385 | */ |
| 1336 | if (!(misc_en & IA32_MISC_TURBO_EN)) | 1386 | if (misc_en & IA32_MISC_TURBO_EN) |
| 1337 | ; /* add turbo MSR write allowed flag if necessary */ | 1387 | ips->turbo_toggle_allowed = true; |
| 1388 | else | ||
| 1389 | ips->turbo_toggle_allowed = false; | ||
| 1338 | 1390 | ||
| 1339 | if (strstr(boot_cpu_data.x86_model_id, "CPU M")) | 1391 | if (strstr(boot_cpu_data.x86_model_id, "CPU M")) |
| 1340 | limits = &ips_sv_limits; | 1392 | limits = &ips_sv_limits; |
| @@ -1351,9 +1403,10 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) | |||
| 1351 | tdp = turbo_power & TURBO_TDP_MASK; | 1403 | tdp = turbo_power & TURBO_TDP_MASK; |
| 1352 | 1404 | ||
| 1353 | /* Sanity check TDP against CPU */ | 1405 | /* Sanity check TDP against CPU */ |
| 1354 | if (limits->mcp_power_limit != (tdp / 8) * 1000) { | 1406 | if (limits->core_power_limit != (tdp / 8) * 1000) { |
| 1355 | dev_warn(&ips->dev->dev, "Warning: CPU TDP doesn't match expected value (found %d, expected %d)\n", | 1407 | dev_info(&ips->dev->dev, "CPU TDP doesn't match expected value (found %d, expected %d)\n", |
| 1356 | tdp / 8, limits->mcp_power_limit / 1000); | 1408 | tdp / 8, limits->core_power_limit / 1000); |
| 1409 | limits->core_power_limit = (tdp / 8) * 1000; | ||
| 1357 | } | 1410 | } |
| 1358 | 1411 | ||
| 1359 | out: | 1412 | out: |
| @@ -1390,7 +1443,7 @@ static bool ips_get_i915_syms(struct ips_driver *ips) | |||
| 1390 | return true; | 1443 | return true; |
| 1391 | 1444 | ||
| 1392 | out_put_busy: | 1445 | out_put_busy: |
| 1393 | symbol_put(i915_gpu_turbo_disable); | 1446 | symbol_put(i915_gpu_busy); |
| 1394 | out_put_lower: | 1447 | out_put_lower: |
| 1395 | symbol_put(i915_gpu_lower); | 1448 | symbol_put(i915_gpu_lower); |
| 1396 | out_put_raise: | 1449 | out_put_raise: |
| @@ -1532,22 +1585,27 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1532 | /* Save turbo limits & ratios */ | 1585 | /* Save turbo limits & ratios */ |
| 1533 | rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); | 1586 | rdmsrl(TURBO_POWER_CURRENT_LIMIT, ips->orig_turbo_limit); |
| 1534 | 1587 | ||
| 1535 | ips_enable_cpu_turbo(ips); | 1588 | ips_disable_cpu_turbo(ips); |
| 1536 | ips->cpu_turbo_enabled = true; | 1589 | ips->cpu_turbo_enabled = false; |
| 1537 | 1590 | ||
| 1538 | /* Set up the work queue and monitor/adjust threads */ | 1591 | /* Create thermal adjust thread */ |
| 1539 | ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); | 1592 | ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); |
| 1540 | if (IS_ERR(ips->monitor)) { | 1593 | if (IS_ERR(ips->adjust)) { |
| 1541 | dev_err(&dev->dev, | 1594 | dev_err(&dev->dev, |
| 1542 | "failed to create thermal monitor thread, aborting\n"); | 1595 | "failed to create thermal adjust thread, aborting\n"); |
| 1543 | ret = -ENOMEM; | 1596 | ret = -ENOMEM; |
| 1544 | goto error_free_irq; | 1597 | goto error_free_irq; |
| 1598 | |||
| 1545 | } | 1599 | } |
| 1546 | 1600 | ||
| 1547 | ips->adjust = kthread_create(ips_adjust, ips, "ips-adjust"); | 1601 | /* |
| 1548 | if (IS_ERR(ips->adjust)) { | 1602 | * Set up the work queue and monitor thread. The monitor thread |
| 1603 | * will wake up ips_adjust thread. | ||
| 1604 | */ | ||
| 1605 | ips->monitor = kthread_run(ips_monitor, ips, "ips-monitor"); | ||
| 1606 | if (IS_ERR(ips->monitor)) { | ||
| 1549 | dev_err(&dev->dev, | 1607 | dev_err(&dev->dev, |
| 1550 | "failed to create thermal adjust thread, aborting\n"); | 1608 | "failed to create thermal monitor thread, aborting\n"); |
| 1551 | ret = -ENOMEM; | 1609 | ret = -ENOMEM; |
| 1552 | goto error_thread_cleanup; | 1610 | goto error_thread_cleanup; |
| 1553 | } | 1611 | } |
| @@ -1566,7 +1624,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 1566 | return ret; | 1624 | return ret; |
| 1567 | 1625 | ||
| 1568 | error_thread_cleanup: | 1626 | error_thread_cleanup: |
| 1569 | kthread_stop(ips->monitor); | 1627 | kthread_stop(ips->adjust); |
| 1570 | error_free_irq: | 1628 | error_free_irq: |
| 1571 | free_irq(ips->dev->irq, ips); | 1629 | free_irq(ips->dev->irq, ips); |
| 1572 | error_unmap: | 1630 | error_unmap: |
