Skip to content

Commit 64a2f30

Browse files
committed
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
2 parents 9d0be54 + b9e95fc commit 64a2f30

File tree

6 files changed

+50
-11
lines changed

6 files changed

+50
-11
lines changed

drivers/acpi/acpi_lpss.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,24 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
164164
if (dev_desc->clk_required) {
165165
ret = register_device_clock(adev, pdata);
166166
if (ret) {
167-
/*
168-
* Skip the device, but don't terminate the namespace
169-
* scan.
170-
*/
171-
kfree(pdata);
172-
return 0;
167+
/* Skip the device, but continue the namespace scan. */
168+
ret = 0;
169+
goto err_out;
173170
}
174171
}
175172

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+
176185
adev->driver_data = pdata;
177186
ret = acpi_create_platform_device(adev, id);
178187
if (ret > 0)

drivers/acpi/device_pm.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,26 @@ int acpi_bus_init_power(struct acpi_device *device)
290290
return 0;
291291
}
292292

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+
293313
int acpi_bus_update_power(acpi_handle handle, int *state_p)
294314
{
295315
struct acpi_device *device;

drivers/acpi/dock.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,10 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
868868
if (!count)
869869
return -EINVAL;
870870

871+
acpi_scan_lock_acquire();
871872
begin_undock(dock_station);
872873
ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
874+
acpi_scan_lock_release();
873875
return ret ? ret: count;
874876
}
875877
static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);

drivers/acpi/power.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ int acpi_add_power_resource(acpi_handle handle)
885885
ACPI_STA_DEFAULT);
886886
mutex_init(&resource->resource_lock);
887887
INIT_LIST_HEAD(&resource->dependent);
888+
INIT_LIST_HEAD(&resource->list_node);
888889
resource->name = device->pnp.bus_id;
889890
strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
890891
strcpy(acpi_device_class(device), ACPI_POWER_CLASS);

drivers/acpi/resource.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
304304
}
305305

306306
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)
308309
{
309310
int irq, p, t;
310311

@@ -317,14 +318,19 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
317318
* In IO-APIC mode, use overrided attribute. Two reasons:
318319
* 1. BIOS bug in DSDT
319320
* 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.
320326
*/
321-
if (!acpi_get_override_irq(gsi, &t, &p)) {
327+
if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
322328
u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
323329
u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
324330

325331
if (triggering != trig || polarity != pol) {
326332
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");
328334
triggering = trig;
329335
polarity = pol;
330336
}
@@ -373,7 +379,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
373379
}
374380
acpi_dev_get_irqresource(res, irq->interrupts[index],
375381
irq->triggering, irq->polarity,
376-
irq->sharable);
382+
irq->sharable, true);
377383
break;
378384
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
379385
ext_irq = &ares->data.extended_irq;
@@ -383,7 +389,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
383389
}
384390
acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
385391
ext_irq->triggering, ext_irq->polarity,
386-
ext_irq->sharable);
392+
ext_irq->sharable, false);
387393
break;
388394
default:
389395
return false;

include/acpi/acpi_bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ const char *acpi_power_state_string(int state);
382382
int acpi_device_get_power(struct acpi_device *device, int *state);
383383
int acpi_device_set_power(struct acpi_device *device, int state);
384384
int acpi_bus_init_power(struct acpi_device *device);
385+
int acpi_device_fix_up_power(struct acpi_device *device);
385386
int acpi_bus_update_power(acpi_handle handle, int *state_p);
386387
bool acpi_bus_power_manageable(acpi_handle handle);
387388

0 commit comments

Comments
 (0)