Pull ACPI and power management fixes from Rafael J Wysocki: - Fix for a recent cpufreq regression related to acpi-cpufreq and suspend/resume from Viresh Kumar. - cpufreq stats reference counting fix from Viresh Kumar. - intel_pstate driver fixes from Dirk Brandewie and Konrad Rzeszutek Wilk. - New ACPI suspend blacklist entry for Sony Vaio VGN-FW21M from Fabio Valentini. - ACPI Platform Error Interface (APEI) fix from Chen Gong. - PCI root bridge hotplug locking fix from Yinghai Lu. * tag 'pm+acpi-3.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: PCI / ACPI: hold acpi_scan_lock during root bus hotplug ACPI / APEI: fix error status check condition for CPER ACPI / PM: fix suspend and resume on Sony Vaio VGN-FW21M cpufreq: acpi-cpufreq: Don't set policy->related_cpus from .init() cpufreq: stats: do cpufreq_cpu_put() corresponding to cpufreq_cpu_get() intel-pstate: Use #defines instead of hard-coded values. cpufreq / intel_pstate: Fix calculation of current frequency cpufreq / intel_pstate: Add function to check that all MSRs are valid
Unified · Split
| @@ -44,6 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | #define SNB_C1_AUTO_UNDEMOTE (1UL << 27) |
| 45 | 45 | #define SNB_C3_AUTO_UNDEMOTE (1UL << 28) |
| 46 | 46 | |
| 47 | +#define MSR_PLATFORM_INFO 0x000000ce | |
| 47 | 48 | #define MSR_MTRRcap 0x000000fe |
| 48 | 49 | #define MSR_IA32_BBL_CR_CTL 0x00000119 |
| 49 | 50 | #define MSR_IA32_BBL_CR_CTL3 0x0000011e |
| @@ -405,7 +405,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus) · 404 unmodified lines | ||
| 405 | 405 | return rc; |
| 406 | 406 | data_len = estatus->data_length; |
| 407 | 407 | gdata = (struct acpi_hest_generic_data *)(estatus + 1); |
| 408 | − while (data_len > sizeof(*gdata)) { | |
| 408 | + while (data_len >= sizeof(*gdata)) { | |
| 409 | 409 | gedata_len = gdata->error_data_length; |
| 410 | 410 | if (gedata_len > data_len - sizeof(*gdata)) |
| 411 | 411 | return -EINVAL; |
| @@ -646,6 +646,7 @@ static void handle_root_bridge_insertion(acpi_handle handle) · 645 unmodified lines | ||
| 646 | 646 | |
| 647 | 647 | static void handle_root_bridge_removal(struct acpi_device *device) |
| 648 | 648 | { |
| 649 | + acpi_status status; | |
| 649 | 650 | struct acpi_eject_event *ej_event; |
| 650 | 651 | |
| 651 | 652 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
| @@ -661,7 +662,9 @@ static void handle_root_bridge_removal(struct acpi_device *device) · 9 unmodified lines | ||
| 661 | 662 | ej_event->device = device; |
| 662 | 663 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; |
| 663 | 664 | |
| 664 | − acpi_bus_hot_remove_device(ej_event); | |
| 665 | + status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | |
| 666 | + if (ACPI_FAILURE(status)) | |
| 667 | + kfree(ej_event); | |
| 665 | 668 | } |
| 666 | 669 | |
| 667 | 670 | static void _handle_hotplug_event_root(struct work_struct *work) |
| @@ -676,8 +679,9 @@ static void _handle_hotplug_event_root(struct work_struct *work) · 8 unmodified lines | ||
| 676 | 679 | handle = hp_work->handle; |
| 677 | 680 | type = hp_work->type; |
| 678 | 681 | |
| 679 | − root = acpi_pci_find_root(handle); | |
| 682 | + acpi_scan_lock_acquire(); | |
| 680 | 683 | |
| 684 | + root = acpi_pci_find_root(handle); | |
| 681 | 685 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
| 682 | 686 | |
| 683 | 687 | switch (type) { |
| @@ -711,6 +715,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) · 27 unmodified lines | ||
| 711 | 715 | break; |
| 712 | 716 | } |
| 713 | 717 | |
| 718 | + acpi_scan_lock_release(); | |
| 714 | 719 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
| 715 | 720 | kfree(buffer.pointer); |
| 716 | 721 | } |
| @@ -193,6 +193,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { · 192 unmodified lines | ||
| 193 | 193 | }, |
| 194 | 194 | { |
| 195 | 195 | .callback = init_nvs_nosave, |
| 196 | + .ident = "Sony Vaio VGN-FW21M", | |
| 197 | + .matches = { | |
| 198 | + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | |
| 199 | + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"), | |
| 200 | + }, | |
| 201 | + }, | |
| 202 | + { | |
| 203 | + .callback = init_nvs_nosave, | |
| 196 | 204 | .ident = "Sony Vaio VPCEB17FX", |
| 197 | 205 | .matches = { |
| 198 | 206 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
| @@ -730,7 +730,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) · 729 unmodified lines | ||
| 730 | 730 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { |
| 731 | 731 | cpumask_copy(policy->cpus, perf->shared_cpu_map); |
| 732 | 732 | } |
| 733 | − cpumask_copy(policy->related_cpus, perf->shared_cpu_map); | |
| 734 | 733 | |
| 735 | 734 | #ifdef CONFIG_SMP |
| 736 | 735 | dmi_check_system(sw_any_bug_dmi_table); |
| @@ -742,7 +741,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) · 5 unmodified lines | ||
| 742 | 741 | if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { |
| 743 | 742 | cpumask_clear(policy->cpus); |
| 744 | 743 | cpumask_set_cpu(cpu, policy->cpus); |
| 745 | − cpumask_copy(policy->related_cpus, cpu_sibling_mask(cpu)); | |
| 746 | 744 | policy->shared_type = CPUFREQ_SHARED_TYPE_HW; |
| 747 | 745 | pr_info_once(PFX "overriding BIOS provided _PSD data\n"); |
| 748 | 746 | } |
| @@ -180,15 +180,19 @@ static void cpufreq_stats_free_sysfs(unsigned int cpu) · 179 unmodified lines | ||
| 180 | 180 | { |
| 181 | 181 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); |
| 182 | 182 | |
| 183 | − if (!cpufreq_frequency_get_table(cpu)) | |
| 183 | + if (!policy) | |
| 184 | 184 | return; |
| 185 | 185 | |
| 186 | − if (policy && !policy_is_shared(policy)) { | |
| 186 | + if (!cpufreq_frequency_get_table(cpu)) | |
| 187 | + goto put_ref; | |
| 188 | + | |
| 189 | + if (!policy_is_shared(policy)) { | |
| 187 | 190 | pr_debug("%s: Free sysfs stat\n", __func__); |
| 188 | 191 | sysfs_remove_group(&policy->kobj, &stats_attr_group); |
| 189 | 192 | } |
| 190 | − if (policy) | |
| 191 | − cpufreq_cpu_put(policy); | |
| 193 | + | |
| 194 | +put_ref: | |
| 195 | + cpufreq_cpu_put(policy); | |
| 192 | 196 | } |
| 193 | 197 | |
| 194 | 198 | static int cpufreq_stats_create_table(struct cpufreq_policy *policy, |
| @@ -358,14 +358,14 @@ static void intel_pstate_sysfs_expose_params(void) · 357 unmodified lines | ||
| 358 | 358 | static int intel_pstate_min_pstate(void) |
| 359 | 359 | { |
| 360 | 360 | u64 value; |
| 361 | − rdmsrl(0xCE, value); | |
| 361 | + rdmsrl(MSR_PLATFORM_INFO, value); | |
| 362 | 362 | return (value >> 40) & 0xFF; |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | 365 | static int intel_pstate_max_pstate(void) |
| 366 | 366 | { |
| 367 | 367 | u64 value; |
| 368 | − rdmsrl(0xCE, value); | |
| 368 | + rdmsrl(MSR_PLATFORM_INFO, value); | |
| 369 | 369 | return (value >> 8) & 0xFF; |
| 370 | 370 | } |
| 371 | 371 | |
| @@ -373,7 +373,7 @@ static int intel_pstate_turbo_pstate(void) · 1 unmodified line | ||
| 373 | 373 | { |
| 374 | 374 | u64 value; |
| 375 | 375 | int nont, ret; |
| 376 | − rdmsrl(0x1AD, value); | |
| 376 | + rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); | |
| 377 | 377 | nont = intel_pstate_max_pstate(); |
| 378 | 378 | ret = ((value) & 255); |
| 379 | 379 | if (ret <= nont) |
| @@ -454,7 +454,7 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, · 74 unmodified lines | ||
| 454 | 454 | sample->idletime_us * 100, |
| 455 | 455 | sample->duration_us); |
| 456 | 456 | core_pct = div64_u64(sample->aperf * 100, sample->mperf); |
| 457 | − sample->freq = cpu->pstate.turbo_pstate * core_pct * 1000; | |
| 457 | + sample->freq = cpu->pstate.max_pstate * core_pct * 1000; | |
| 458 | 458 | |
| 459 | 459 | sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct), |
| 460 | 460 | 100); |
| @@ -752,6 +752,29 @@ static struct cpufreq_driver intel_pstate_driver = { · 291 unmodified lines | ||
| 752 | 752 | |
| 753 | 753 | static int __initdata no_load; |
| 754 | 754 | |
| 755 | +static int intel_pstate_msrs_not_valid(void) | |
| 756 | +{ | |
| 757 | + /* Check that all the msr's we are using are valid. */ | |
| 758 | + u64 aperf, mperf, tmp; | |
| 759 | + | |
| 760 | + rdmsrl(MSR_IA32_APERF, aperf); | |
| 761 | + rdmsrl(MSR_IA32_MPERF, mperf); | |
| 762 | + | |
| 763 | + if (!intel_pstate_min_pstate() || | |
| 764 | + !intel_pstate_max_pstate() || | |
| 765 | + !intel_pstate_turbo_pstate()) | |
| 766 | + return -ENODEV; | |
| 767 | + | |
| 768 | + rdmsrl(MSR_IA32_APERF, tmp); | |
| 769 | + if (!(tmp - aperf)) | |
| 770 | + return -ENODEV; | |
| 771 | + | |
| 772 | + rdmsrl(MSR_IA32_MPERF, tmp); | |
| 773 | + if (!(tmp - mperf)) | |
| 774 | + return -ENODEV; | |
| 775 | + | |
| 776 | + return 0; | |
| 777 | +} | |
| 755 | 778 | static int __init intel_pstate_init(void) |
| 756 | 779 | { |
| 757 | 780 | int cpu, rc = 0; |
| @@ -764,6 +787,9 @@ static int __init intel_pstate_init(void) · 6 unmodified lines | ||
| 764 | 787 | if (!id) |
| 765 | 788 | return -ENODEV; |
| 766 | 789 | |
| 790 | + if (intel_pstate_msrs_not_valid()) | |
| 791 | + return -ENODEV; | |
| 792 | + | |
| 767 | 793 | pr_info("Intel P-state driver initializing.\n"); |
| 768 | 794 | |
| 769 | 795 | all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus()); |