Merge tag 'pm+acpi-3.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Feb 2014 20:12:21 +0000 (12:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Feb 2014 20:12:21 +0000 (12:12 -0800)
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

drivers/acpi/battery.c
drivers/acpi/proc.c
drivers/acpi/scan.c
drivers/acpi/utils.c
drivers/acpi/video_detect.c
drivers/cpufreq/intel_pstate.c
drivers/pci/hotplug/acpiphp_glue.c

index 470e7542bf31a3c2d571385e9b418de0a28eb140..018a4288370630cb40203ecd43cc2809851288ae 100644 (file)
@@ -549,7 +549,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 {
        unsigned long x;
        struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev));
-       if (sscanf(buf, "%ld\n", &x) == 1)
+       if (sscanf(buf, "%lu\n", &x) == 1)
                battery->alarm = x/1000;
        if (acpi_battery_present(battery))
                acpi_battery_set_alarm(battery);
index 50fe34ffe932fbdc9b1e9166c551fb025754853e..75c28eae88604903ac518fc0fe4ebe83f2e2669e 100644 (file)
@@ -60,7 +60,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
                                seq_printf(seq, "%c%-8s  %s:%s\n",
                                        dev->wakeup.flags.run_wake ? '*' : ' ',
                                        (device_may_wakeup(&dev->dev) ||
-                                       (ldev && device_may_wakeup(ldev))) ?
+                                       device_may_wakeup(ldev)) ?
                                        "enabled" : "disabled",
                                        ldev->bus ? ldev->bus->name :
                                        "no-bus", dev_name(ldev));
index 7384158c7f8770ddc4cd78d1570171a4cce9aae9..57b053f424d13e23ef2dd4b43a191c0d9dda09da 100644 (file)
@@ -484,7 +484,6 @@ static void acpi_device_hotplug(void *data, u32 src)
 static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
 {
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;
-       struct acpi_scan_handler *handler = data;
        struct acpi_device *adev;
        acpi_status status;
 
@@ -500,7 +499,10 @@ static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data)
                break;
        case ACPI_NOTIFY_EJECT_REQUEST:
                acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n");
-               if (!handler->hotplug.enabled) {
+               if (!adev->handler)
+                       goto err_out;
+
+               if (!adev->handler->hotplug.enabled) {
                        acpi_handle_err(handle, "Eject disabled\n");
                        ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
                        goto err_out;
index 0347a37eb4389dcbd5c497ca6833e867618acbf5..85e3b612bdc0d49f7df07d056b0d9c14f8aca89e 100644 (file)
@@ -99,10 +99,6 @@ acpi_extract_package(union acpi_object *package,
 
                union acpi_object *element = &(package->package.elements[i]);
 
-               if (!element) {
-                       return AE_BAD_DATA;
-               }
-
                switch (element->type) {
 
                case ACPI_TYPE_INTEGER:
index f0447d3daf2c433fce6ad97a981c378a2d8c38ae..a697b77b8865a163cd23fe591db0242631ca742f 100644 (file)
@@ -170,6 +170,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
        },
        {
        .callback = video_detect_force_vendor,
+       .ident = "HP EliteBook Revolve 810",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Revolve 810 G1"),
+               },
+       },
+       {
+       .callback = video_detect_force_vendor,
        .ident = "Lenovo Yoga 13",
        .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
index 7e257b2336025c3b2afd6faff9c0ae091fc7228f..79606f473f481b516069f66ce3c8a17ee60b053c 100644 (file)
@@ -57,6 +57,7 @@ struct sample {
        int32_t core_pct_busy;
        u64 aperf;
        u64 mperf;
+       unsigned long long tsc;
        int freq;
 };
 
@@ -96,6 +97,7 @@ struct cpudata {
 
        u64     prev_aperf;
        u64     prev_mperf;
+       unsigned long long prev_tsc;
        int     sample_ptr;
        struct sample samples[SAMPLE_COUNT];
 };
@@ -548,30 +550,41 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        struct sample *sample)
 {
        u64 core_pct;
-       core_pct = div64_u64(int_tofp(sample->aperf * 100),
-                            sample->mperf);
-       sample->freq = fp_toint(cpu->pstate.max_pstate * core_pct * 1000);
+       u64 c0_pct;
 
-       sample->core_pct_busy = core_pct;
+       core_pct = div64_u64(sample->aperf * 100, sample->mperf);
+
+       c0_pct = div64_u64(sample->mperf * 100, sample->tsc);
+       sample->freq = fp_toint(
+               mul_fp(int_tofp(cpu->pstate.max_pstate),
+                       int_tofp(core_pct * 1000)));
+
+       sample->core_pct_busy = mul_fp(int_tofp(core_pct),
+                               div_fp(int_tofp(c0_pct + 1), int_tofp(100)));
 }
 
 static inline void intel_pstate_sample(struct cpudata *cpu)
 {
        u64 aperf, mperf;
+       unsigned long long tsc;
 
        rdmsrl(MSR_IA32_APERF, aperf);
        rdmsrl(MSR_IA32_MPERF, mperf);
+       tsc = native_read_tsc();
 
        cpu->sample_ptr = (cpu->sample_ptr + 1) % SAMPLE_COUNT;
        cpu->samples[cpu->sample_ptr].aperf = aperf;
        cpu->samples[cpu->sample_ptr].mperf = mperf;
+       cpu->samples[cpu->sample_ptr].tsc = tsc;
        cpu->samples[cpu->sample_ptr].aperf -= cpu->prev_aperf;
        cpu->samples[cpu->sample_ptr].mperf -= cpu->prev_mperf;
+       cpu->samples[cpu->sample_ptr].tsc -= cpu->prev_tsc;
 
        intel_pstate_calc_busy(cpu, &cpu->samples[cpu->sample_ptr]);
 
        cpu->prev_aperf = aperf;
        cpu->prev_mperf = mperf;
+       cpu->prev_tsc = tsc;
 }
 
 static inline void intel_pstate_set_sample_time(struct cpudata *cpu)
index cd929aed3613314068ed7a4baf2bb6e5c6cb9f1f..e2a783fdb98fdc6be6cb24f52a9a828ba48f2ba6 100644 (file)
@@ -210,10 +210,29 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
        }
 }
 
+static void dock_event(acpi_handle handle, u32 type, void *data)
+{
+       struct acpiphp_context *context;
+
+       mutex_lock(&acpiphp_context_lock);
+       context = acpiphp_get_context(handle);
+       if (!context || WARN_ON(context->handle != handle)
+           || context->func.parent->is_going_away) {
+               mutex_unlock(&acpiphp_context_lock);
+               return;
+       }
+       get_bridge(context->func.parent);
+       acpiphp_put_context(context);
+       mutex_unlock(&acpiphp_context_lock);
+
+       hotplug_event(handle, type, data);
+
+       put_bridge(context->func.parent);
+}
 
 static const struct acpi_dock_ops acpiphp_dock_ops = {
        .fixup = post_dock_fixups,
-       .handler = hotplug_event,
+       .handler = dock_event,
 };
 
 /* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -441,7 +460,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
        list_del(&bridge->list);
        mutex_unlock(&bridge_mutex);
 
+       mutex_lock(&acpiphp_context_lock);
        bridge->is_going_away = true;
+       mutex_unlock(&acpiphp_context_lock);
 }
 
 /**
@@ -742,7 +763,7 @@ static void trim_stale_devices(struct pci_dev *dev)
 
                /* The device is a bridge. so check the bus below it. */
                pm_runtime_get_sync(&dev->dev);
-               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
+               list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
                        trim_stale_devices(child);
 
                pm_runtime_put(&dev->dev);
@@ -773,8 +794,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
                        ; /* do nothing */
                } else if (get_slot_status(slot) == ACPI_STA_ALL) {
                        /* remove stale devices if any */
-                       list_for_each_entry_safe(dev, tmp, &bus->devices,
-                                                bus_list)
+                       list_for_each_entry_safe_reverse(dev, tmp,
+                                                        &bus->devices, bus_list)
                                if (PCI_SLOT(dev->devfn) == slot->device)
                                        trim_stale_devices(dev);
 
@@ -805,7 +826,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
        int i;
        unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
 
-       list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
+       list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
                for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
                        struct resource *res = &dev->resource[i];
                        if ((res->flags & type_mask) && !res->start &&
@@ -829,7 +850,11 @@ void acpiphp_check_host_bridge(acpi_handle handle)
 
        bridge = acpiphp_handle_to_bridge(handle);
        if (bridge) {
+               pci_lock_rescan_remove();
+
                acpiphp_check_bridge(bridge);
+
+               pci_unlock_rescan_remove();
                put_bridge(bridge);
        }
 }
@@ -852,6 +877,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
 
        mutex_unlock(&acpiphp_context_lock);
 
+       pci_lock_rescan_remove();
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
        switch (type) {
@@ -905,6 +931,7 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
                break;
        }
 
+       pci_unlock_rescan_remove();
        if (bridge)
                put_bridge(bridge);
 }
@@ -915,11 +942,9 @@ static void hotplug_event_work(void *data, u32 type)
        acpi_handle handle = context->handle;
 
        acpi_scan_lock_acquire();
-       pci_lock_rescan_remove();
 
        hotplug_event(handle, type, context);
 
-       pci_unlock_rescan_remove();
        acpi_scan_lock_release();
        acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL);
        put_bridge(context->func.parent);
@@ -937,6 +962,7 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 {
        struct acpiphp_context *context;
        u32 ost_code = ACPI_OST_SC_SUCCESS;
+       acpi_status status;
 
        switch (type) {
        case ACPI_NOTIFY_BUS_CHECK:
@@ -972,13 +998,20 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
 
        mutex_lock(&acpiphp_context_lock);
        context = acpiphp_get_context(handle);
-       if (context && !WARN_ON(context->handle != handle)) {
-               get_bridge(context->func.parent);
-               acpiphp_put_context(context);
-               acpi_hotplug_execute(hotplug_event_work, context, type);
+       if (!context || WARN_ON(context->handle != handle)
+           || context->func.parent->is_going_away)
+               goto err_out;
+
+       get_bridge(context->func.parent);
+       acpiphp_put_context(context);
+       status = acpi_hotplug_execute(hotplug_event_work, context, type);
+       if (ACPI_SUCCESS(status)) {
                mutex_unlock(&acpiphp_context_lock);
                return;
        }
+       put_bridge(context->func.parent);
+
+ err_out:
        mutex_unlock(&acpiphp_context_lock);
        ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE;