aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-27 20:17:49 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-10-27 20:17:49 -0400
commitdd6c26be3bb3e98d4811780f831bbc246dae54c8 (patch)
tree5b0cce644ee725386b2c4539afc91459e1913cd9
parentc0ced86d38f418448dce1ca8a825dfd16ee9a23a (diff)
parent33cf00e5708290f7e57d949219ef443a2aef34e0 (diff)
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
-rw-r--r--drivers/acpi/device_pm.c8
-rw-r--r--drivers/i2c/i2c-core.c5
-rw-r--r--drivers/spi/spi.c18
-rw-r--r--include/acpi/acpi_bus.h3
4 files changed, 28 insertions, 6 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index a94383d1f350..d42b2fb5a7e9 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
118 /* 118 /*
119 * If we were unsure about the device parent's power state up to this 119 * If we were unsure about the device parent's power state up to this
120 * point, the fact that the device is in D0 implies that the parent has 120 * point, the fact that the device is in D0 implies that the parent has
121 * to be in D0 too. 121 * to be in D0 too, except if ignore_parent is set.
122 */ 122 */
123 if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN 123 if (!device->power.flags.ignore_parent && device->parent
124 && device->parent->power.state == ACPI_STATE_UNKNOWN
124 && result == ACPI_STATE_D0) 125 && result == ACPI_STATE_D0)
125 device->parent->power.state = ACPI_STATE_D0; 126 device->parent->power.state = ACPI_STATE_D0;
126 127
@@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
177 acpi_power_state_string(state)); 178 acpi_power_state_string(state));
178 return -ENODEV; 179 return -ENODEV;
179 } 180 }
180 if (device->parent && (state < device->parent->power.state)) { 181 if (!device->power.flags.ignore_parent &&
182 device->parent && (state < device->parent->power.state)) {
181 dev_warn(&device->dev, 183 dev_warn(&device->dev,
182 "Cannot transition to power state %s for parent in %s\n", 184 "Cannot transition to power state %s for parent in %s\n",
183 acpi_power_state_string(state), 185 acpi_power_state_string(state),
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 3be58f89ac77..75ba8608383e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev)
254 client->flags & I2C_CLIENT_WAKE); 254 client->flags & I2C_CLIENT_WAKE);
255 dev_dbg(dev, "probe\n"); 255 dev_dbg(dev, "probe\n");
256 256
257 acpi_dev_pm_attach(&client->dev, true);
257 status = driver->probe(client, i2c_match_id(driver->id_table, client)); 258 status = driver->probe(client, i2c_match_id(driver->id_table, client));
258 if (status) { 259 if (status) {
259 client->driver = NULL; 260 client->driver = NULL;
260 i2c_set_clientdata(client, NULL); 261 i2c_set_clientdata(client, NULL);
262 acpi_dev_pm_detach(&client->dev, true);
261 } 263 }
262 return status; 264 return status;
263} 265}
@@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev)
283 client->driver = NULL; 285 client->driver = NULL;
284 i2c_set_clientdata(client, NULL); 286 i2c_set_clientdata(client, NULL);
285 } 287 }
288 acpi_dev_pm_detach(&client->dev, true);
286 return status; 289 return status;
287} 290}
288 291
@@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
1111 if (ret < 0 || !info.addr) 1114 if (ret < 0 || !info.addr)
1112 return AE_OK; 1115 return AE_OK;
1113 1116
1117 adev->power.flags.ignore_parent = true;
1114 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); 1118 strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
1115 if (!i2c_new_device(adapter, &info)) { 1119 if (!i2c_new_device(adapter, &info)) {
1120 adev->power.flags.ignore_parent = false;
1116 dev_err(&adapter->dev, 1121 dev_err(&adapter->dev,
1117 "failed to add I2C device %s from ACPI\n", 1122 "failed to add I2C device %s from ACPI\n",
1118 dev_name(&adev->dev)); 1123 dev_name(&adev->dev));
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9e039c60c068..740f9ddda227 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
240static int spi_drv_probe(struct device *dev) 240static int spi_drv_probe(struct device *dev)
241{ 241{
242 const struct spi_driver *sdrv = to_spi_driver(dev->driver); 242 const struct spi_driver *sdrv = to_spi_driver(dev->driver);
243 struct spi_device *spi = to_spi_device(dev);
244 int ret;
245
246 acpi_dev_pm_attach(&spi->dev, true);
247 ret = sdrv->probe(spi);
248 if (ret)
249 acpi_dev_pm_detach(&spi->dev, true);
243 250
244 return sdrv->probe(to_spi_device(dev)); 251 return ret;
245} 252}
246 253
247static int spi_drv_remove(struct device *dev) 254static int spi_drv_remove(struct device *dev)
248{ 255{
249 const struct spi_driver *sdrv = to_spi_driver(dev->driver); 256 const struct spi_driver *sdrv = to_spi_driver(dev->driver);
257 struct spi_device *spi = to_spi_device(dev);
258 int ret;
259
260 ret = sdrv->remove(spi);
261 acpi_dev_pm_detach(&spi->dev, true);
250 262
251 return sdrv->remove(to_spi_device(dev)); 263 return ret;
252} 264}
253 265
254static void spi_drv_shutdown(struct device *dev) 266static void spi_drv_shutdown(struct device *dev)
@@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
1025 return AE_OK; 1037 return AE_OK;
1026 } 1038 }
1027 1039
1040 adev->power.flags.ignore_parent = true;
1028 strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias)); 1041 strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
1029 if (spi_add_device(spi)) { 1042 if (spi_add_device(spi)) {
1043 adev->power.flags.ignore_parent = false;
1030 dev_err(&master->dev, "failed to add SPI device %s from ACPI\n", 1044 dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
1031 dev_name(&adev->dev)); 1045 dev_name(&adev->dev));
1032 spi_dev_put(spi); 1046 spi_dev_put(spi);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index d9019821aa60..15100f625e65 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -222,7 +222,8 @@ struct acpi_device_power_flags {
222 u32 power_resources:1; /* Power resources */ 222 u32 power_resources:1; /* Power resources */
223 u32 inrush_current:1; /* Serialize Dx->D0 */ 223 u32 inrush_current:1; /* Serialize Dx->D0 */
224 u32 power_removed:1; /* Optimize Dx->D0 */ 224 u32 power_removed:1; /* Optimize Dx->D0 */
225 u32 reserved:28; 225 u32 ignore_parent:1; /* Power is independent of parent power state */
226 u32 reserved:27;
226}; 227};
227 228
228struct acpi_device_power_state { 229struct acpi_device_power_state {