]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'acpi-3.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Jun 2013 16:31:10 +0000 (06:31 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Jun 2013 16:31:10 +0000 (06:31 -1000)
Pull ACPI fixes from Rafael Wysocki:

 - Fix for a regression causing a failure to turn on some devices on
   some systems during initialization introduced by a recent revert of
   an ACPI PM change that broke something else.  Fortunately, we know
   exactly what devices are affected, so we can add a fix just for them
   leaving everyone else alone.

 - ACPI power resources initialization fix preventing a NULL pointer
   from being dereferenced in the acpi_add_power_resource() error code
   path.

 - ACPI dock station driver fix that adds missing locking to
   write_undock().

 - ACPI resources allocation fix changing the scope of an old workaround
   so that it doesn't affect systems that aren't actually buggy.  This
   was reported a couple of days ago to fix DMA problems on some new
   platforms so we need it in -stable.  From Mika Westerberg.

* tag 'acpi-3.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / LPSS: Power up LPSS devices during enumeration
  ACPI / PM: Fix error code path for power resources initialization
  ACPI / dock: Take ACPI scan lock in write_undock()
  ACPI / resources: call acpi_get_override_irq() only for legacy IRQ resources

drivers/acpi/acpi_lpss.c
drivers/acpi/device_pm.c
drivers/acpi/dock.c
drivers/acpi/power.c
drivers/acpi/resource.c
include/acpi/acpi_bus.h

index 652fd5ce303c4a9efdbfa3f6d4eb330fba42a5bd..cab13f2fc28e3033aaed24adbbf618199473bb28 100644 (file)
@@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
        if (dev_desc->clk_required) {
                ret = register_device_clock(adev, pdata);
                if (ret) {
-                       /*
-                        * Skip the device, but don't terminate the namespace
-                        * scan.
-                        */
-                       kfree(pdata);
-                       return 0;
+                       /* Skip the device, but continue the namespace scan. */
+                       ret = 0;
+                       goto err_out;
                }
        }
 
+       /*
+        * This works around a known issue in ACPI tables where LPSS devices
+        * have _PS0 and _PS3 without _PSC (and no power resources), so
+        * acpi_bus_init_power() will assume that the BIOS has put them into D0.
+        */
+       ret = acpi_device_fix_up_power(adev);
+       if (ret) {
+               /* Skip the device, but continue the namespace scan. */
+               ret = 0;
+               goto err_out;
+       }
+
        adev->driver_data = pdata;
        ret = acpi_create_platform_device(adev, id);
        if (ret > 0)
index 318fa32a141ec41c70c273b1f57f966f38fd55dc..31c217a42839dce40ee2039cd38f36d935bda543 100644 (file)
@@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device)
        return 0;
 }
 
+/**
+ * acpi_device_fix_up_power - Force device with missing _PSC into D0.
+ * @device: Device object whose power state is to be fixed up.
+ *
+ * Devices without power resources and _PSC, but having _PS0 and _PS3 defined,
+ * are assumed to be put into D0 by the BIOS.  However, in some cases that may
+ * not be the case and this function should be used then.
+ */
+int acpi_device_fix_up_power(struct acpi_device *device)
+{
+       int ret = 0;
+
+       if (!device->power.flags.power_resources
+           && !device->power.flags.explicit_get
+           && device->power.state == ACPI_STATE_D0)
+               ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0);
+
+       return ret;
+}
+
 int acpi_bus_update_power(acpi_handle handle, int *state_p)
 {
        struct acpi_device *device;
index 4fdea381ef21e07017a87b94ae16ce0f8860fb75..ec117c6c996cc0e2c25bd63c7c47897b2546492a 100644 (file)
@@ -868,8 +868,10 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
        if (!count)
                return -EINVAL;
 
+       acpi_scan_lock_acquire();
        begin_undock(dock_station);
        ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
+       acpi_scan_lock_release();
        return ret ? ret: count;
 }
 static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
index f962047c6c85591762893ada0a73549913b03d85..288bb270f8edc11cb0d92e23f7b759619e35e660 100644 (file)
@@ -885,6 +885,7 @@ int acpi_add_power_resource(acpi_handle handle)
                                ACPI_STA_DEFAULT);
        mutex_init(&resource->resource_lock);
        INIT_LIST_HEAD(&resource->dependent);
+       INIT_LIST_HEAD(&resource->list_node);
        resource->name = device->pnp.bus_id;
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
index a3868f6c222abfc65541a5a599035e18145108f9..3322b47ab7cae22dc08520b6cec9a3b1df981b84 100644 (file)
@@ -304,7 +304,8 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
 }
 
 static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
-                                    u8 triggering, u8 polarity, u8 shareable)
+                                    u8 triggering, u8 polarity, u8 shareable,
+                                    bool legacy)
 {
        int irq, p, t;
 
@@ -317,14 +318,19 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
         * In IO-APIC mode, use overrided attribute. Two reasons:
         * 1. BIOS bug in DSDT
         * 2. BIOS uses IO-APIC mode Interrupt Source Override
+        *
+        * We do this only if we are dealing with IRQ() or IRQNoFlags()
+        * resource (the legacy ISA resources). With modern ACPI 5 devices
+        * using extended IRQ descriptors we take the IRQ configuration
+        * from _CRS directly.
         */
-       if (!acpi_get_override_irq(gsi, &t, &p)) {
+       if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
                u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
                u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
 
                if (triggering != trig || polarity != pol) {
                        pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
-                                  t ? "edge" : "level", p ? "low" : "high");
+                                  t ? "level" : "edge", p ? "low" : "high");
                        triggering = trig;
                        polarity = pol;
                }
@@ -373,7 +379,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
                }
                acpi_dev_get_irqresource(res, irq->interrupts[index],
                                         irq->triggering, irq->polarity,
-                                        irq->sharable);
+                                        irq->sharable, true);
                break;
        case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
                ext_irq = &ares->data.extended_irq;
@@ -383,7 +389,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
                }
                acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
                                         ext_irq->triggering, ext_irq->polarity,
-                                        ext_irq->sharable);
+                                        ext_irq->sharable, false);
                break;
        default:
                return false;
index 636c59f2003a315c264777eccd0e3abfbdd8045f..c13c919ab99e9803b2ebe18d36eb93ab98bf6076 100644 (file)
@@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state);
 int acpi_device_get_power(struct acpi_device *device, int *state);
 int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_init_power(struct acpi_device *device);
+int acpi_device_fix_up_power(struct acpi_device *device);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);