提交 dd6c26be 编写于 作者: R Rafael J. Wysocki

Merge branch 'acpi-pm'

* acpi-pm:
  spi: attach/detach SPI device to the ACPI power domain
  i2c: attach/detach I2C client device to the ACPI power domain
  ACPI / PM: allow child devices to ignore parent power state
...@@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state) ...@@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
/* /*
* If we were unsure about the device parent's power state up to this * If we were unsure about the device parent's power state up to this
* point, the fact that the device is in D0 implies that the parent has * point, the fact that the device is in D0 implies that the parent has
* to be in D0 too. * to be in D0 too, except if ignore_parent is set.
*/ */
if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN if (!device->power.flags.ignore_parent && device->parent
&& device->parent->power.state == ACPI_STATE_UNKNOWN
&& result == ACPI_STATE_D0) && result == ACPI_STATE_D0)
device->parent->power.state = ACPI_STATE_D0; device->parent->power.state = ACPI_STATE_D0;
...@@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state) ...@@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
acpi_power_state_string(state)); acpi_power_state_string(state));
return -ENODEV; return -ENODEV;
} }
if (device->parent && (state < device->parent->power.state)) { if (!device->power.flags.ignore_parent &&
device->parent && (state < device->parent->power.state)) {
dev_warn(&device->dev, dev_warn(&device->dev,
"Cannot transition to power state %s for parent in %s\n", "Cannot transition to power state %s for parent in %s\n",
acpi_power_state_string(state), acpi_power_state_string(state),
......
...@@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev) ...@@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev)
client->flags & I2C_CLIENT_WAKE); client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n"); dev_dbg(dev, "probe\n");
acpi_dev_pm_attach(&client->dev, true);
status = driver->probe(client, i2c_match_id(driver->id_table, client)); status = driver->probe(client, i2c_match_id(driver->id_table, client));
if (status) { if (status) {
client->driver = NULL; client->driver = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
acpi_dev_pm_detach(&client->dev, true);
} }
return status; return status;
} }
...@@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev) ...@@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev)
client->driver = NULL; client->driver = NULL;
i2c_set_clientdata(client, NULL); i2c_set_clientdata(client, NULL);
} }
acpi_dev_pm_detach(&client->dev, true);
return status; return status;
} }
...@@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, ...@@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
if (ret < 0 || !info.addr) if (ret < 0 || !info.addr)
return AE_OK; return AE_OK;
adev->power.flags.ignore_parent = true;
strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
if (!i2c_new_device(adapter, &info)) { if (!i2c_new_device(adapter, &info)) {
adev->power.flags.ignore_parent = false;
dev_err(&adapter->dev, dev_err(&adapter->dev,
"failed to add I2C device %s from ACPI\n", "failed to add I2C device %s from ACPI\n",
dev_name(&adev->dev)); dev_name(&adev->dev));
......
...@@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type); ...@@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
static int spi_drv_probe(struct device *dev) static int spi_drv_probe(struct device *dev)
{ {
const struct spi_driver *sdrv = to_spi_driver(dev->driver); const struct spi_driver *sdrv = to_spi_driver(dev->driver);
struct spi_device *spi = to_spi_device(dev);
int ret;
return sdrv->probe(to_spi_device(dev)); acpi_dev_pm_attach(&spi->dev, true);
ret = sdrv->probe(spi);
if (ret)
acpi_dev_pm_detach(&spi->dev, true);
return ret;
} }
static int spi_drv_remove(struct device *dev) static int spi_drv_remove(struct device *dev)
{ {
const struct spi_driver *sdrv = to_spi_driver(dev->driver); const struct spi_driver *sdrv = to_spi_driver(dev->driver);
struct spi_device *spi = to_spi_device(dev);
int ret;
return sdrv->remove(to_spi_device(dev)); ret = sdrv->remove(spi);
acpi_dev_pm_detach(&spi->dev, true);
return ret;
} }
static void spi_drv_shutdown(struct device *dev) static void spi_drv_shutdown(struct device *dev)
...@@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, ...@@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
return AE_OK; return AE_OK;
} }
adev->power.flags.ignore_parent = true;
strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias)); strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
if (spi_add_device(spi)) { if (spi_add_device(spi)) {
adev->power.flags.ignore_parent = false;
dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
dev_name(&adev->dev)); dev_name(&adev->dev));
spi_dev_put(spi); spi_dev_put(spi);
......
...@@ -222,7 +222,8 @@ struct acpi_device_power_flags { ...@@ -222,7 +222,8 @@ struct acpi_device_power_flags {
u32 power_resources:1; /* Power resources */ u32 power_resources:1; /* Power resources */
u32 inrush_current:1; /* Serialize Dx->D0 */ u32 inrush_current:1; /* Serialize Dx->D0 */
u32 power_removed:1; /* Optimize Dx->D0 */ u32 power_removed:1; /* Optimize Dx->D0 */
u32 reserved:28; u32 ignore_parent:1; /* Power is independent of parent power state */
u32 reserved:27;
}; };
struct acpi_device_power_state { struct acpi_device_power_state {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册