diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-21 12:31:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-06-21 12:31:10 -0400 |
commit | 64a2f30a89a3c26a5152b09f4d390b9d91cab0cc (patch) | |
tree | c6823ceef71ee0e031ce81932dd3b3b0ab504d2c | |
parent | 9d0be540d73dc8256e8eff85285bd3b682e3c1d1 (diff) | |
parent | b9e95fc65ededbec083aa91b4faa58ad992c0891 (diff) |
Merge tag 'acpi-3.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
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
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 21 | ||||
-rw-r--r-- | drivers/acpi/device_pm.c | 20 | ||||
-rw-r--r-- | drivers/acpi/dock.c | 2 | ||||
-rw-r--r-- | drivers/acpi/power.c | 1 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 16 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 1 |
6 files changed, 50 insertions, 11 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 652fd5ce303c..cab13f2fc28e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
164 | if (dev_desc->clk_required) { | 164 | if (dev_desc->clk_required) { |
165 | ret = register_device_clock(adev, pdata); | 165 | ret = register_device_clock(adev, pdata); |
166 | if (ret) { | 166 | if (ret) { |
167 | /* | 167 | /* Skip the device, but continue the namespace scan. */ |
168 | * Skip the device, but don't terminate the namespace | 168 | ret = 0; |
169 | * scan. | 169 | goto err_out; |
170 | */ | ||
171 | kfree(pdata); | ||
172 | return 0; | ||
173 | } | 170 | } |
174 | } | 171 | } |
175 | 172 | ||
173 | /* | ||
174 | * This works around a known issue in ACPI tables where LPSS devices | ||
175 | * have _PS0 and _PS3 without _PSC (and no power resources), so | ||
176 | * acpi_bus_init_power() will assume that the BIOS has put them into D0. | ||
177 | */ | ||
178 | ret = acpi_device_fix_up_power(adev); | ||
179 | if (ret) { | ||
180 | /* Skip the device, but continue the namespace scan. */ | ||
181 | ret = 0; | ||
182 | goto err_out; | ||
183 | } | ||
184 | |||
176 | adev->driver_data = pdata; | 185 | adev->driver_data = pdata; |
177 | ret = acpi_create_platform_device(adev, id); | 186 | ret = acpi_create_platform_device(adev, id); |
178 | if (ret > 0) | 187 | if (ret > 0) |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 318fa32a141e..31c217a42839 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
@@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device) | |||
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
292 | 292 | ||
293 | /** | ||
294 | * acpi_device_fix_up_power - Force device with missing _PSC into D0. | ||
295 | * @device: Device object whose power state is to be fixed up. | ||
296 | * | ||
297 | * Devices without power resources and _PSC, but having _PS0 and _PS3 defined, | ||
298 | * are assumed to be put into D0 by the BIOS. However, in some cases that may | ||
299 | * not be the case and this function should be used then. | ||
300 | */ | ||
301 | int acpi_device_fix_up_power(struct acpi_device *device) | ||
302 | { | ||
303 | int ret = 0; | ||
304 | |||
305 | if (!device->power.flags.power_resources | ||
306 | && !device->power.flags.explicit_get | ||
307 | && device->power.state == ACPI_STATE_D0) | ||
308 | ret = acpi_dev_pm_explicit_set(device, ACPI_STATE_D0); | ||
309 | |||
310 | return ret; | ||
311 | } | ||
312 | |||
293 | int acpi_bus_update_power(acpi_handle handle, int *state_p) | 313 | int acpi_bus_update_power(acpi_handle handle, int *state_p) |
294 | { | 314 | { |
295 | struct acpi_device *device; | 315 | struct acpi_device *device; |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4fdea381ef21..ec117c6c996c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
@@ -868,8 +868,10 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | |||
868 | if (!count) | 868 | if (!count) |
869 | return -EINVAL; | 869 | return -EINVAL; |
870 | 870 | ||
871 | acpi_scan_lock_acquire(); | ||
871 | begin_undock(dock_station); | 872 | begin_undock(dock_station); |
872 | ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); | 873 | ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST); |
874 | acpi_scan_lock_release(); | ||
873 | return ret ? ret: count; | 875 | return ret ? ret: count; |
874 | } | 876 | } |
875 | static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); | 877 | static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index f962047c6c85..288bb270f8ed 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -885,6 +885,7 @@ int acpi_add_power_resource(acpi_handle handle) | |||
885 | ACPI_STA_DEFAULT); | 885 | ACPI_STA_DEFAULT); |
886 | mutex_init(&resource->resource_lock); | 886 | mutex_init(&resource->resource_lock); |
887 | INIT_LIST_HEAD(&resource->dependent); | 887 | INIT_LIST_HEAD(&resource->dependent); |
888 | INIT_LIST_HEAD(&resource->list_node); | ||
888 | resource->name = device->pnp.bus_id; | 889 | resource->name = device->pnp.bus_id; |
889 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); | 890 | strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); |
890 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); | 891 | strcpy(acpi_device_class(device), ACPI_POWER_CLASS); |
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index a3868f6c222a..3322b47ab7ca 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
@@ -304,7 +304,8 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) | |||
304 | } | 304 | } |
305 | 305 | ||
306 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | 306 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, |
307 | u8 triggering, u8 polarity, u8 shareable) | 307 | u8 triggering, u8 polarity, u8 shareable, |
308 | bool legacy) | ||
308 | { | 309 | { |
309 | int irq, p, t; | 310 | int irq, p, t; |
310 | 311 | ||
@@ -317,14 +318,19 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | |||
317 | * In IO-APIC mode, use overrided attribute. Two reasons: | 318 | * In IO-APIC mode, use overrided attribute. Two reasons: |
318 | * 1. BIOS bug in DSDT | 319 | * 1. BIOS bug in DSDT |
319 | * 2. BIOS uses IO-APIC mode Interrupt Source Override | 320 | * 2. BIOS uses IO-APIC mode Interrupt Source Override |
321 | * | ||
322 | * We do this only if we are dealing with IRQ() or IRQNoFlags() | ||
323 | * resource (the legacy ISA resources). With modern ACPI 5 devices | ||
324 | * using extended IRQ descriptors we take the IRQ configuration | ||
325 | * from _CRS directly. | ||
320 | */ | 326 | */ |
321 | if (!acpi_get_override_irq(gsi, &t, &p)) { | 327 | if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { |
322 | u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; | 328 | u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; |
323 | u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | 329 | u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; |
324 | 330 | ||
325 | if (triggering != trig || polarity != pol) { | 331 | if (triggering != trig || polarity != pol) { |
326 | pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, | 332 | pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi, |
327 | t ? "edge" : "level", p ? "low" : "high"); | 333 | t ? "level" : "edge", p ? "low" : "high"); |
328 | triggering = trig; | 334 | triggering = trig; |
329 | polarity = pol; | 335 | polarity = pol; |
330 | } | 336 | } |
@@ -373,7 +379,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | |||
373 | } | 379 | } |
374 | acpi_dev_get_irqresource(res, irq->interrupts[index], | 380 | acpi_dev_get_irqresource(res, irq->interrupts[index], |
375 | irq->triggering, irq->polarity, | 381 | irq->triggering, irq->polarity, |
376 | irq->sharable); | 382 | irq->sharable, true); |
377 | break; | 383 | break; |
378 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 384 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
379 | ext_irq = &ares->data.extended_irq; | 385 | ext_irq = &ares->data.extended_irq; |
@@ -383,7 +389,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | |||
383 | } | 389 | } |
384 | acpi_dev_get_irqresource(res, ext_irq->interrupts[index], | 390 | acpi_dev_get_irqresource(res, ext_irq->interrupts[index], |
385 | ext_irq->triggering, ext_irq->polarity, | 391 | ext_irq->triggering, ext_irq->polarity, |
386 | ext_irq->sharable); | 392 | ext_irq->sharable, false); |
387 | break; | 393 | break; |
388 | default: | 394 | default: |
389 | return false; | 395 | return false; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 636c59f2003a..c13c919ab99e 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state); | |||
382 | int acpi_device_get_power(struct acpi_device *device, int *state); | 382 | int acpi_device_get_power(struct acpi_device *device, int *state); |
383 | int acpi_device_set_power(struct acpi_device *device, int state); | 383 | int acpi_device_set_power(struct acpi_device *device, int state); |
384 | int acpi_bus_init_power(struct acpi_device *device); | 384 | int acpi_bus_init_power(struct acpi_device *device); |
385 | int acpi_device_fix_up_power(struct acpi_device *device); | ||
385 | int acpi_bus_update_power(acpi_handle handle, int *state_p); | 386 | int acpi_bus_update_power(acpi_handle handle, int *state_p); |
386 | bool acpi_bus_power_manageable(acpi_handle handle); | 387 | bool acpi_bus_power_manageable(acpi_handle handle); |
387 | 388 | ||