diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-07 15:12:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-07 15:12:21 -0500 |
commit | 22446d3f23dd250ed1922edc8cc8a003bcb2538e (patch) | |
tree | e13cb0713f382d27f5d932ac80cdfecf933a82e1 | |
parent | 9343224bfd4be6a02e6ae0c0d66426c955c7d76e (diff) | |
parent | a2ff34c433932e201ea3c5081335f3beeb2509bd (diff) |
Merge tag 'pm+acpi-3.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
"These include a fix for a recent ACPI hotplug regression, four
concurrency related fixes and one PCI device removal fix for
ACPI-based PCI hotplug (ACPIPHP), intel_pstate fix that should go into
stable, three simple ACPI cleanups and a new entry for the ACPI video
blacklist.
Specifics:
- Fix for a recent ACPI hotplug regression causing a NULL pointer
dereference to occur while handling ACPI eject notifications for
already ejected devices. From Toshi Kani.
- Four concurrency-related fixes for ACPIPHP. Two of them add
missing locking and the other two fix race conditions related to
reference counting.
- ACPIPHP fix to avoid NULL pointer dereferences during device
removal involving Virtual Funcions.
- intel_pstate fix to make it compute the percentage of time the CPU
is busy properly. From Dirk Brandewie.
- Removal of two unnecessary NULL pointer checks in ACPI code and a
fix for sscanf() format string from Dan Carpenter and Luis G.F.
- New ACPI video blacklist entry for HP EliteBook Revolve 810 from
Mika Westerberg"
* tag 'pm+acpi-3.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI / hotplug: Fix panic on eject to ejected device
ACPI / battery: Fix incorrect sscanf() string in acpi_battery_init_alarm()
ACPI / proc: remove unneeded NULL check
ACPI / utils: remove a pointless NULL check
ACPI / video: Add HP EliteBook Revolve 810 to the blacklist
intel_pstate: Take core C0 time into account for core busy calculation
ACPI / hotplug / PCI: Fix bridge removal race vs dock events
ACPI / hotplug / PCI: Fix bridge removal race in handle_hotplug_event()
ACPI / hotplug / PCI: Scan root bus under the PCI rescan-remove lock
ACPI / hotplug / PCI: Move PCI rescan-remove locking to hotplug_event()
ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order
-rw-r--r-- | drivers/acpi/battery.c | 2 | ||||
-rw-r--r-- | drivers/acpi/proc.c | 2 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 6 | ||||
-rw-r--r-- | drivers/acpi/utils.c | 4 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 8 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 21 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 55 |
7 files changed, 75 insertions, 23 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 470e7542bf31..018a42883706 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -549,7 +549,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, | |||
549 | { | 549 | { |
550 | unsigned long x; | 550 | unsigned long x; |
551 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); | 551 | struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); |
552 | if (sscanf(buf, "%ld\n", &x) == 1) | 552 | if (sscanf(buf, "%lu\n", &x) == 1) |
553 | battery->alarm = x/1000; | 553 | battery->alarm = x/1000; |
554 | if (acpi_battery_present(battery)) | 554 | if (acpi_battery_present(battery)) |
555 | acpi_battery_set_alarm(battery); | 555 | acpi_battery_set_alarm(battery); |
diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 50fe34ffe932..75c28eae8860 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c | |||
@@ -60,7 +60,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
60 | seq_printf(seq, "%c%-8s %s:%s\n", | 60 | seq_printf(seq, "%c%-8s %s:%s\n", |
61 | dev->wakeup.flags.run_wake ? '*' : ' ', | 61 | dev->wakeup.flags.run_wake ? '*' : ' ', |
62 | (device_may_wakeup(&dev->dev) || | 62 | (device_may_wakeup(&dev->dev) || |
63 | (ldev && device_may_wakeup(ldev))) ? | 63 | device_may_wakeup(ldev)) ? |
64 | "enabled" : "disabled", | 64 | "enabled" : "disabled", |
65 | ldev->bus ? ldev->bus->name : | 65 | ldev->bus ? ldev->bus->name : |
66 | "no-bus", dev_name(ldev)); | 66 | "no-bus", dev_name(ldev)); |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7384158c7f87..57b053f424d1 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -484,7 +484,6 @@ static void acpi_device_hotplug(void *data, u32 src) | |||
484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | 484 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) |
485 | { | 485 | { |
486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 486 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
487 | struct acpi_scan_handler *handler = data; | ||
488 | struct acpi_device *adev; | 487 | struct acpi_device *adev; |
489 | acpi_status status; | 488 | acpi_status status; |
490 | 489 | ||
@@ -500,7 +499,10 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | |||
500 | break; | 499 | break; |
501 | case ACPI_NOTIFY_EJECT_REQUEST: | 500 | case ACPI_NOTIFY_EJECT_REQUEST: |
502 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | 501 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); |
503 | if (!handler->hotplug.enabled) { | 502 | if (!adev->handler) |
503 | goto err_out; | ||
504 | |||
505 | if (!adev->handler->hotplug.enabled) { | ||
504 | acpi_handle_err(handle, "Eject disabled\n"); | 506 | acpi_handle_err(handle, "Eject disabled\n"); |
505 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | 507 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; |
506 | goto err_out; | 508 | goto err_out; |
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 0347a37eb438..85e3b612bdc0 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
@@ -99,10 +99,6 @@ acpi_extract_package(union acpi_object *package, | |||
99 | 99 | ||
100 | union acpi_object *element = &(package->package.elements[i]); | 100 | union acpi_object *element = &(package->package.elements[i]); |
101 | 101 | ||
102 | if (!element) { | ||
103 | return AE_BAD_DATA; | ||
104 | } | ||
105 | |||
106 | switch (element->type) { | 102 | switch (element->type) { |
107 | 103 | ||
108 | case ACPI_TYPE_INTEGER: | 104 | case ACPI_TYPE_INTEGER: |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index f0447d3daf2c..a697b77b8865 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -170,6 +170,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { | |||
170 | }, | 170 | }, |
171 | { | 171 | { |
172 | .callback = video_detect_force_vendor, | 172 | .callback = video_detect_force_vendor, |
173 | .ident = "HP EliteBook Revolve 810", | ||
174 | .matches = { | ||
175 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
176 | DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"), | ||
177 | }, | ||
178 | }, | ||
179 | { | ||
180 | .callback = video_detect_force_vendor, | ||
173 | .ident = "Lenovo Yoga 13", | 181 | .ident = "Lenovo Yoga 13", |
174 | .matches = { | 182 | .matches = { |
175 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 183 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7e257b233602..79606f473f48 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -57,6 +57,7 @@ struct sample { | |||
57 | int32_t core_pct_busy; | 57 | int32_t core_pct_busy; |
58 | u64 aperf; | 58 | u64 aperf; |
59 | u64 mperf; | 59 | u64 mperf; |
60 | unsigned long long tsc; | ||
60 | int freq; | 61 | int freq; |
61 | }; | 62 | }; |
62 | 63 | ||
@@ -96,6 +97,7 @@ struct cpudata { | |||
96 | 97 | ||
97 | u64 prev_aperf; | 98 | u64 prev_aperf; |
98 | u64 prev_mperf; | 99 | u64 prev_mperf; |
100 | unsigned long long prev_tsc; | ||
99 | int sample_ptr; | 101 | int sample_ptr; |
100 | struct sample samples[SAMPLE_COUNT]; | 102 | struct sample samples[SAMPLE_COUNT]; |
101 | }; | 103 | }; |
@@ -548,30 +550,41 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, | |||
548 | struct sample *sample) | 550 | struct sample *sample) |
549 | { | 551 | { |
550 | u64 core_pct; | 552 | u64 core_pct; |
551 | core_pct = div64_u64(int_tofp(sample->aperf * 100), | 553 | u64 c0_pct; |
552 | sample->mperf); | ||
553 | sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000); | ||
554 | 554 | ||
555 | sample->core_pct_busy = core_pct; | 555 | core_pct = div64_u64(sample->aperf * 100, sample->mperf); |
556 | |||
557 | c0_pct = div64_u64(sample->mperf * 100, sample->tsc); | ||
558 | sample->freq = fp_toint( | ||
559 | mul_fp(int_tofp(cpu->pstate.max_pstate), | ||
560 | int_tofp(core_pct * 1000))); | ||
561 | |||
562 | sample->core_pct_busy = mul_fp(int_tofp(core_pct), | ||
563 | div_fp(int_tofp(c0_pct + 1), int_tofp(100))); | ||
556 | } | 564 | } |
557 | 565 | ||
558 | static inline void intel_pstate_sample(struct cpudata *cpu) | 566 | static inline void intel_pstate_sample(struct cpudata *cpu) |
559 | { | 567 | { |
560 | u64 aperf, mperf; | 568 | u64 aperf, mperf; |
569 | unsigned long long tsc; | ||
561 | 570 | ||
562 | rdmsrl(MSR_IA32_APERF, aperf); | 571 | rdmsrl(MSR_IA32_APERF, aperf); |
563 | rdmsrl(MSR_IA32_MPERF, mperf); | 572 | rdmsrl(MSR_IA32_MPERF, mperf); |
573 | tsc = native_read_tsc(); | ||
564 | 574 | ||
565 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; | 575 | cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT; |
566 | cpu->samples[cpu->sample_ptr].aperf = aperf; | 576 | cpu->samples[cpu->sample_ptr].aperf = aperf; |
567 | cpu->samples[cpu->sample_ptr].mperf = mperf; | 577 | cpu->samples[cpu->sample_ptr].mperf = mperf; |
578 | cpu->samples[cpu->sample_ptr].tsc = tsc; | ||
568 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; | 579 | cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf; |
569 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; | 580 | cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf; |
581 | cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc; | ||
570 | 582 | ||
571 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); | 583 | intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]); |
572 | 584 | ||
573 | cpu->prev_aperf = aperf; | 585 | cpu->prev_aperf = aperf; |
574 | cpu->prev_mperf = mperf; | 586 | cpu->prev_mperf = mperf; |
587 | cpu->prev_tsc = tsc; | ||
575 | } | 588 | } |
576 | 589 | ||
577 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) | 590 | static inline void intel_pstate_set_sample_time(struct cpudata *cpu) |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index cd929aed3613..e2a783fdb98f 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -210,10 +210,29 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | |||
210 | } | 210 | } |
211 | } | 211 | } |
212 | 212 | ||
213 | static void dock_event(acpi_handle handle, u32 type, void *data) | ||
214 | { | ||
215 | struct acpiphp_context *context; | ||
216 | |||
217 | mutex_lock(&acpiphp_context_lock); | ||
218 | context = acpiphp_get_context(handle); | ||
219 | if (!context || WARN_ON(context->handle != handle) | ||
220 | || context->func.parent->is_going_away) { | ||
221 | mutex_unlock(&acpiphp_context_lock); | ||
222 | return; | ||
223 | } | ||
224 | get_bridge(context->func.parent); | ||
225 | acpiphp_put_context(context); | ||
226 | mutex_unlock(&acpiphp_context_lock); | ||
227 | |||
228 | hotplug_event(handle, type, data); | ||
229 | |||
230 | put_bridge(context->func.parent); | ||
231 | } | ||
213 | 232 | ||
214 | static const struct acpi_dock_ops acpiphp_dock_ops = { | 233 | static const struct acpi_dock_ops acpiphp_dock_ops = { |
215 | .fixup = post_dock_fixups, | 234 | .fixup = post_dock_fixups, |
216 | .handler = hotplug_event, | 235 | .handler = dock_event, |
217 | }; | 236 | }; |
218 | 237 | ||
219 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ | 238 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ |
@@ -441,7 +460,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
441 | list_del(&bridge->list); | 460 | list_del(&bridge->list); |
442 | mutex_unlock(&bridge_mutex); | 461 | mutex_unlock(&bridge_mutex); |
443 | 462 | ||
463 | mutex_lock(&acpiphp_context_lock); | ||
444 | bridge->is_going_away = true; | 464 | bridge->is_going_away = true; |
465 | mutex_unlock(&acpiphp_context_lock); | ||
445 | } | 466 | } |
446 | 467 | ||
447 | /** | 468 | /** |
@@ -742,7 +763,7 @@ static void trim_stale_devices(struct pci_dev *dev) | |||
742 | 763 | ||
743 | /* The device is a bridge. so check the bus below it. */ | 764 | /* The device is a bridge. so check the bus below it. */ |
744 | pm_runtime_get_sync(&dev->dev); | 765 | pm_runtime_get_sync(&dev->dev); |
745 | list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) | 766 | list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list) |
746 | trim_stale_devices(child); | 767 | trim_stale_devices(child); |
747 | 768 | ||
748 | pm_runtime_put(&dev->dev); | 769 | pm_runtime_put(&dev->dev); |
@@ -773,8 +794,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
773 | ; /* do nothing */ | 794 | ; /* do nothing */ |
774 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { | 795 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { |
775 | /* remove stale devices if any */ | 796 | /* remove stale devices if any */ |
776 | list_for_each_entry_safe(dev, tmp, &bus->devices, | 797 | list_for_each_entry_safe_reverse(dev, tmp, |
777 | bus_list) | 798 | &bus->devices, bus_list) |
778 | if (PCI_SLOT(dev->devfn) == slot->device) | 799 | if (PCI_SLOT(dev->devfn) == slot->device) |
779 | trim_stale_devices(dev); | 800 | trim_stale_devices(dev); |
780 | 801 | ||
@@ -805,7 +826,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
805 | int i; | 826 | int i; |
806 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 827 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
807 | 828 | ||
808 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { | 829 | list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) { |
809 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { | 830 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { |
810 | struct resource *res = &dev->resource[i]; | 831 | struct resource *res = &dev->resource[i]; |
811 | if ((res->flags & type_mask) && !res->start && | 832 | if ((res->flags & type_mask) && !res->start && |
@@ -829,7 +850,11 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
829 | 850 | ||
830 | bridge = acpiphp_handle_to_bridge(handle); | 851 | bridge = acpiphp_handle_to_bridge(handle); |
831 | if (bridge) { | 852 | if (bridge) { |
853 | pci_lock_rescan_remove(); | ||
854 | |||
832 | acpiphp_check_bridge(bridge); | 855 | acpiphp_check_bridge(bridge); |
856 | |||
857 | pci_unlock_rescan_remove(); | ||
833 | put_bridge(bridge); | 858 | put_bridge(bridge); |
834 | } | 859 | } |
835 | } | 860 | } |
@@ -852,6 +877,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
852 | 877 | ||
853 | mutex_unlock(&acpiphp_context_lock); | 878 | mutex_unlock(&acpiphp_context_lock); |
854 | 879 | ||
880 | pci_lock_rescan_remove(); | ||
855 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 881 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
856 | 882 | ||
857 | switch (type) { | 883 | switch (type) { |
@@ -905,6 +931,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
905 | break; | 931 | break; |
906 | } | 932 | } |
907 | 933 | ||
934 | pci_unlock_rescan_remove(); | ||
908 | if (bridge) | 935 | if (bridge) |
909 | put_bridge(bridge); | 936 | put_bridge(bridge); |
910 | } | 937 | } |
@@ -915,11 +942,9 @@ static void hotplug_event_work(void *data, u32 type) | |||
915 | acpi_handle handle = context->handle; | 942 | acpi_handle handle = context->handle; |
916 | 943 | ||
917 | acpi_scan_lock_acquire(); | 944 | acpi_scan_lock_acquire(); |
918 | pci_lock_rescan_remove(); | ||
919 | 945 | ||
920 | hotplug_event(handle, type, context); | 946 | hotplug_event(handle, type, context); |
921 | 947 | ||
922 | pci_unlock_rescan_remove(); | ||
923 | acpi_scan_lock_release(); | 948 | acpi_scan_lock_release(); |
924 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 949 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); |
925 | put_bridge(context->func.parent); | 950 | put_bridge(context->func.parent); |
@@ -937,6 +962,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
937 | { | 962 | { |
938 | struct acpiphp_context *context; | 963 | struct acpiphp_context *context; |
939 | u32 ost_code = ACPI_OST_SC_SUCCESS; | 964 | u32 ost_code = ACPI_OST_SC_SUCCESS; |
965 | acpi_status status; | ||
940 | 966 | ||
941 | switch (type) { | 967 | switch (type) { |
942 | case ACPI_NOTIFY_BUS_CHECK: | 968 | case ACPI_NOTIFY_BUS_CHECK: |
@@ -972,13 +998,20 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | |||
972 | 998 | ||
973 | mutex_lock(&acpiphp_context_lock); | 999 | mutex_lock(&acpiphp_context_lock); |
974 | context = acpiphp_get_context(handle); | 1000 | context = acpiphp_get_context(handle); |
975 | if (context && !WARN_ON(context->handle != handle)) { | 1001 | if (!context || WARN_ON(context->handle != handle) |
976 | get_bridge(context->func.parent); | 1002 | || context->func.parent->is_going_away) |
977 | acpiphp_put_context(context); | 1003 | goto err_out; |
978 | acpi_hotplug_execute(hotplug_event_work, context, type); | 1004 | |
1005 | get_bridge(context->func.parent); | ||
1006 | acpiphp_put_context(context); | ||
1007 | status = acpi_hotplug_execute(hotplug_event_work, context, type); | ||
1008 | if (ACPI_SUCCESS(status)) { | ||
979 | mutex_unlock(&acpiphp_context_lock); | 1009 | mutex_unlock(&acpiphp_context_lock); |
980 | return; | 1010 | return; |
981 | } | 1011 | } |
1012 | put_bridge(context->func.parent); | ||
1013 | |||
1014 | err_out: | ||
982 | mutex_unlock(&acpiphp_context_lock); | 1015 | mutex_unlock(&acpiphp_context_lock); |
983 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | 1016 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; |
984 | 1017 | ||