Re: [PATCH 12/13] iio: imu: inv_mpu6050: use runtime pm with autosuspend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 12 Feb 2020 18:40:47 +0100
Jean-Baptiste Maneyrol <jmaneyrol@xxxxxxxxxxxxxx> wrote:

> Use runtime power management for handling chip power and
> sensor engines on/off. Simplifies things a lot since pm
> runtime already has reference counter.
> Usage of autosuspend reduces the number of power on/off. This
> makes polling interface now usable to get data at low
> frequency.
> 
> Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@xxxxxxxxxxxxxx>

Looks good.  A couple of questions / suggestions inline.

> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 265 ++++++++++++------
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h     |   5 +-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c |  29 +-
>  3 files changed, 191 insertions(+), 108 deletions(-)
> 
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index f33fd04671cc..f698d2aa61f4 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -16,6 +16,8 @@
>  #include <linux/acpi.h>
>  #include <linux/platform_device.h>
>  #include <linux/regulator/consumer.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
>  #include "inv_mpu_iio.h"
>  #include "inv_mpu_magn.h"
>  
> @@ -400,26 +402,13 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
>  {
>  	int result;
>  
> -	if (power_on) {
> -		if (!st->powerup_count) {
> -			result = inv_mpu6050_pwr_mgmt_1_write(st, false, -1, -1);
> -			if (result)
> -				return result;
> -			usleep_range(INV_MPU6050_REG_UP_TIME_MIN,
> -				     INV_MPU6050_REG_UP_TIME_MAX);
> -		}
> -		st->powerup_count++;
> -	} else {
> -		if (st->powerup_count == 1) {
> -			result = inv_mpu6050_pwr_mgmt_1_write(st, true, -1, -1);
> -			if (result)
> -				return result;
> -		}
> -		st->powerup_count--;
> -	}
> +	result = inv_mpu6050_pwr_mgmt_1_write(st, !power_on, -1, -1);
> +	if (result)
> +		return result;
>  
> -	dev_dbg(regmap_get_device(st->map), "set power %d, count=%u\n",
> -		power_on, st->powerup_count);
> +	if (power_on)
> +		usleep_range(INV_MPU6050_REG_UP_TIME_MIN,
> +			     INV_MPU6050_REG_UP_TIME_MAX);
>  
>  	return 0;
>  }
> @@ -563,6 +552,7 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  					 int *val)
>  {
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
> +	struct device *pdev = regmap_get_device(st->map);
>  	unsigned int freq_hz, period_us, min_sleep_us, max_sleep_us;
>  	int result;
>  	int ret;
> @@ -571,92 +561,85 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev,
>  	freq_hz = INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
>  	period_us = 1000000 / freq_hz;
>  
> -	result = inv_mpu6050_set_power_itg(st, true);
> -	if (result)
> +	result = pm_runtime_get_sync(pdev);
> +	if (result < 0) {
> +		pm_runtime_put_noidle(pdev);
>  		return result;
> +	}
>  
>  	switch (chan->type) {
>  	case IIO_ANGL_VEL:
> -		result = inv_mpu6050_switch_engine(st, true,
> -				INV_MPU6050_SENSOR_GYRO);
> -		if (result)
> -			goto error_power_off;
> -		/* need to wait 2 periods to have first valid sample */
> -		min_sleep_us = 2 * period_us;
> -		max_sleep_us = 2 * (period_us + period_us / 2);
> -		usleep_range(min_sleep_us, max_sleep_us);
> +		if (!st->chip_config.gyro_en) {

Are these changes due to runtime pm?  Or do they make sense in general?

> +			result = inv_mpu6050_switch_engine(st, true,
> +					INV_MPU6050_SENSOR_GYRO);
> +			if (result)
> +				goto error_power_off;
> +			/* need to wait 2 periods to have first valid sample */
> +			min_sleep_us = 2 * period_us;
> +			max_sleep_us = 2 * (period_us + period_us / 2);
> +			usleep_range(min_sleep_us, max_sleep_us);
> +		}
>  		ret = inv_mpu6050_sensor_show(st, st->reg->raw_gyro,
>  					      chan->channel2, val);
> -		result = inv_mpu6050_switch_engine(st, false,
> -				INV_MPU6050_SENSOR_GYRO);
> -		if (result)
> -			goto error_power_off;
>  		break;
>  	case IIO_ACCEL:
> -		result = inv_mpu6050_switch_engine(st, true,
> -				INV_MPU6050_SENSOR_ACCL);
> -		if (result)
> -			goto error_power_off;
> -		/* wait 1 period for first sample availability */
> -		min_sleep_us = period_us;
> -		max_sleep_us = period_us + period_us / 2;
> -		usleep_range(min_sleep_us, max_sleep_us);
> +		if (!st->chip_config.accl_en) {
> +			result = inv_mpu6050_switch_engine(st, true,
> +					INV_MPU6050_SENSOR_ACCL);
> +			if (result)
> +				goto error_power_off;
> +			/* wait 1 period for first sample availability */
> +			min_sleep_us = period_us;
> +			max_sleep_us = period_us + period_us / 2;
> +			usleep_range(min_sleep_us, max_sleep_us);
> +		}
>  		ret = inv_mpu6050_sensor_show(st, st->reg->raw_accl,
>  					      chan->channel2, val);
> -		result = inv_mpu6050_switch_engine(st, false,
> -				INV_MPU6050_SENSOR_ACCL);
> -		if (result)
> -			goto error_power_off;
>  		break;
>  	case IIO_TEMP:
> -		result = inv_mpu6050_switch_engine(st, true,
> -				INV_MPU6050_SENSOR_TEMP);
> -		if (result)
> -			goto error_power_off;
> -		/* wait 1 period for first sample availability */
> -		min_sleep_us = period_us;
> -		max_sleep_us = period_us + period_us / 2;
> -		usleep_range(min_sleep_us, max_sleep_us);
> +		if (!st->chip_config.temp_en) {
> +			result = inv_mpu6050_switch_engine(st, true,
> +					INV_MPU6050_SENSOR_TEMP);
> +			if (result)
> +				goto error_power_off;
> +			/* wait 1 period for first sample availability */
> +			min_sleep_us = period_us;
> +			max_sleep_us = period_us + period_us / 2;
> +			usleep_range(min_sleep_us, max_sleep_us);
> +		}
>  		ret = inv_mpu6050_sensor_show(st, st->reg->temperature,
>  					      IIO_MOD_X, val);
> -		result = inv_mpu6050_switch_engine(st, false,
> -				INV_MPU6050_SENSOR_TEMP);
> -		if (result)
> -			goto error_power_off;
>  		break;
>  	case IIO_MAGN:
> -		result = inv_mpu6050_switch_engine(st, true,
> -				INV_MPU6050_SENSOR_MAGN);
> -		if (result)
> -			goto error_power_off;
> -		/* frequency is limited for magnetometer */
> -		if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {
> -			freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
> -			period_us = 1000000 / freq_hz;
> +		if (!st->chip_config.magn_en) {
> +			result = inv_mpu6050_switch_engine(st, true,
> +					INV_MPU6050_SENSOR_MAGN);
> +			if (result)
> +				goto error_power_off;
> +			/* frequency is limited for magnetometer */
> +			if (freq_hz > INV_MPU_MAGN_FREQ_HZ_MAX) {
> +				freq_hz = INV_MPU_MAGN_FREQ_HZ_MAX;
> +				period_us = 1000000 / freq_hz;
> +			}
> +			/* need to wait 2 periods to have first valid sample */
> +			min_sleep_us = 2 * period_us;
> +			max_sleep_us = 2 * (period_us + period_us / 2);
> +			usleep_range(min_sleep_us, max_sleep_us);
>  		}
> -		/* need to wait 2 periods to have first valid sample */
> -		min_sleep_us = 2 * period_us;
> -		max_sleep_us = 2 * (period_us + period_us / 2);
> -		usleep_range(min_sleep_us, max_sleep_us);
>  		ret = inv_mpu_magn_read(st, chan->channel2, val);
> -		result = inv_mpu6050_switch_engine(st, false,
> -				INV_MPU6050_SENSOR_MAGN);
> -		if (result)
> -			goto error_power_off;
>  		break;
>  	default:
>  		ret = -EINVAL;
>  		break;
>  	}
>  
> -	result = inv_mpu6050_set_power_itg(st, false);
> -	if (result)
> -		goto error_power_off;
> +	pm_runtime_mark_last_busy(pdev);
> +	pm_runtime_put_autosuspend(pdev);
>  
>  	return ret;
>  
>  error_power_off:
> -	inv_mpu6050_set_power_itg(st, false);
> +	pm_runtime_put_autosuspend(pdev);
>  	return result;
>  }
>  
> @@ -795,6 +778,7 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
>  				 int val, int val2, long mask)
>  {
>  	struct inv_mpu6050_state  *st = iio_priv(indio_dev);
> +	struct device *pdev = regmap_get_device(st->map);
>  	int result;
>  
>  	/*
> @@ -806,9 +790,11 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
>  		return result;
>  
>  	mutex_lock(&st->lock);
> -	result = inv_mpu6050_set_power_itg(st, true);
> -	if (result)
> +	result = pm_runtime_get_sync(pdev);
> +	if (result < 0) {
> +		pm_runtime_put_noidle(pdev);
>  		goto error_write_raw_unlock;
> +	}
>  
>  	switch (mask) {
>  	case IIO_CHAN_INFO_SCALE:
> @@ -846,7 +832,8 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
>  		break;
>  	}
>  
> -	result |= inv_mpu6050_set_power_itg(st, false);
> +	pm_runtime_mark_last_busy(pdev);
> +	pm_runtime_put_autosuspend(pdev);
>  error_write_raw_unlock:
>  	mutex_unlock(&st->lock);
>  	iio_device_release_direct_mode(indio_dev);
> @@ -903,6 +890,7 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
>  	int result;
>  	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
> +	struct device *pdev = regmap_get_device(st->map);
>  
>  	if (kstrtoint(buf, 10, &fifo_rate))
>  		return -EINVAL;
> @@ -920,9 +908,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
>  		result = 0;
>  		goto fifo_rate_fail_unlock;
>  	}
> -	result = inv_mpu6050_set_power_itg(st, true);
> -	if (result)
> +	result = pm_runtime_get_sync(pdev);
> +	if (result < 0) {
> +		pm_runtime_put_noidle(pdev);
>  		goto fifo_rate_fail_unlock;
> +	}
>  
>  	result = regmap_write(st->map, st->reg->sample_rate_div, d);
>  	if (result)
> @@ -938,8 +928,9 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
>  	if (result)
>  		goto fifo_rate_fail_power_off;
>  
> +	pm_runtime_mark_last_busy(pdev);
>  fifo_rate_fail_power_off:
> -	result |= inv_mpu6050_set_power_itg(st, false);
> +	pm_runtime_put_autosuspend(pdev);
>  fifo_rate_fail_unlock:
>  	mutex_unlock(&st->lock);
>  	if (result)
> @@ -1385,6 +1376,14 @@ static void inv_mpu_core_disable_regulator_action(void *_data)
>  	inv_mpu_core_disable_regulator_vddio(st);
>  }
>  
> +static void inv_mpu_pm_disable(void *data)
> +{
> +	struct device *dev = data;
> +
> +	pm_runtime_put_sync_suspend(dev);
> +	pm_runtime_disable(dev);
> +}
> +
>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  		int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
>  {
> @@ -1409,7 +1408,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  	st = iio_priv(indio_dev);
>  	mutex_init(&st->lock);
>  	st->chip_type = chip_type;
> -	st->powerup_count = 0;
>  	st->irq = irq;
>  	st->map = regmap;
>  
> @@ -1521,8 +1519,16 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
>  			goto error_power_off;
>  	}
>  
> -	/* chip init is done, turning off */
> -	result = inv_mpu6050_set_power_itg(st, false);
> +	/* chip init is done, turning on runtime power management */
> +	result = pm_runtime_set_active(dev);
> +	if (result)
> +		goto error_power_off;
> +	pm_runtime_get_noresume(dev);
> +	pm_runtime_enable(dev);
> +	pm_runtime_set_autosuspend_delay(dev, INV_MPU6050_SUSPEND_DELAY_MS);
> +	pm_runtime_use_autosuspend(dev);
> +	pm_runtime_put(dev);
> +	result = devm_add_action_or_reset(dev, inv_mpu_pm_disable, dev);
>  	if (result)
>  		return result;
>  
> @@ -1594,36 +1600,113 @@ EXPORT_SYMBOL_GPL(inv_mpu_core_probe);
>  
>  static int inv_mpu_resume(struct device *dev)
>  {
> -	struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  	int result;
>  
>  	mutex_lock(&st->lock);
> +
>  	result = inv_mpu_core_enable_regulator_vddio(st);
>  	if (result)
>  		goto out_unlock;
>  
>  	result = inv_mpu6050_set_power_itg(st, true);
> +	if (result)
> +		goto out_unlock;
> +
> +	result = inv_mpu6050_switch_engine(st, true, st->suspended_sensors);
> +	if (result)
> +		goto out_unlock;
> +
> +	if (iio_buffer_enabled(indio_dev))
> +		result = inv_mpu6050_prepare_fifo(st, true);
> +
>  out_unlock:
>  	mutex_unlock(&st->lock);
> -

Not keen on random white space tweaks in a complex patch like this.

>  	return result;
>  }
>  
>  static int inv_mpu_suspend(struct device *dev)
>  {
> -	struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +	struct inv_mpu6050_state *st = iio_priv(indio_dev);
>  	int result;
>  
>  	mutex_lock(&st->lock);
> +
> +	if (iio_buffer_enabled(indio_dev)) {
> +		result = inv_mpu6050_prepare_fifo(st, false);
> +		goto out_unlock;
> +	}
> +
> +	st->suspended_sensors = 0;
> +	if (st->chip_config.accl_en)
> +		st->suspended_sensors |= INV_MPU6050_SENSOR_ACCL;
> +	if (st->chip_config.gyro_en)
> +		st->suspended_sensors |= INV_MPU6050_SENSOR_GYRO;
> +	if (st->chip_config.temp_en)
> +		st->suspended_sensors |= INV_MPU6050_SENSOR_TEMP;
> +	if (st->chip_config.magn_en)
> +		st->suspended_sensors |= INV_MPU6050_SENSOR_MAGN;
> +	result = inv_mpu6050_switch_engine(st, false, st->suspended_sensors);
> +	if (result)
> +		goto out_unlock;
> +
>  	result = inv_mpu6050_set_power_itg(st, false);
> +	if (result)
> +		goto out_unlock;
> +
>  	inv_mpu_core_disable_regulator_vddio(st);
> -	mutex_unlock(&st->lock);
>  
> +out_unlock:
> +	mutex_unlock(&st->lock);
>  	return result;
>  }
>  #endif /* CONFIG_PM_SLEEP */
>  
> -SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
> +#ifdef CONFIG_PM

Preferred to avoid the ifdef fun and mark the functions __maybe_unused
instead.  Avoids weird build issues that tend to happen around the
CONFIG_PM options.  Same for the CONFIG_PM_SLEEP cases above.
Note this preference has changed over the years since this driver
was introduced so entirely reasonable that we might want to update
this now.

> +static int inv_mpu_runtime_suspend(struct device *dev)
> +{
> +	struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
> +	unsigned int sensors;
> +	int ret;
> +
> +	mutex_lock(&st->lock);
> +
> +	sensors = INV_MPU6050_SENSOR_ACCL | INV_MPU6050_SENSOR_GYRO |
> +			INV_MPU6050_SENSOR_TEMP | INV_MPU6050_SENSOR_MAGN;
> +	ret = inv_mpu6050_switch_engine(st, false, sensors);
> +	if (ret)
> +		goto out_unlock;
> +
> +	ret = inv_mpu6050_set_power_itg(st, false);
> +	if (ret)
> +		goto out_unlock;
> +
> +	inv_mpu_core_disable_regulator_vddio(st);
> +
> +out_unlock:
> +	mutex_unlock(&st->lock);
> +	return ret;
> +}
> +
> +static int inv_mpu_runtime_resume(struct device *dev)
> +{
> +	struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(dev));
> +	int ret;
> +
> +	ret = inv_mpu_core_enable_regulator_vddio(st);
> +	if (ret)
> +		return ret;
> +
> +	return inv_mpu6050_set_power_itg(st, true);
> +}
> +#endif
> +
> +const struct dev_pm_ops inv_mpu_pmops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(inv_mpu_suspend, inv_mpu_resume)
> +	SET_RUNTIME_PM_OPS(inv_mpu_runtime_suspend, inv_mpu_runtime_resume, NULL)
> +};
>  EXPORT_SYMBOL_GPL(inv_mpu_pmops);
>  
>  MODULE_AUTHOR("Invensense Corporation");
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index e328c98e362c..cd38b3fccc7b 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -164,6 +164,7 @@ struct inv_mpu6050_hw {
>   *  @magn_disabled:     magnetometer disabled for backward compatibility reason.
>   *  @magn_raw_to_gauss:	coefficient to convert mag raw value to Gauss.
>   *  @magn_orient:       magnetometer sensor chip orientation if available.
> + *  @suspended_sensors:	sensors mask of sensors turned off for suspend
>   */
>  struct inv_mpu6050_state {
>  	struct mutex lock;
> @@ -174,7 +175,6 @@ struct inv_mpu6050_state {
>  	enum   inv_devices chip_type;
>  	struct i2c_mux_core *muxc;
>  	struct i2c_client *mux_client;
> -	unsigned int powerup_count;
>  	struct inv_mpu6050_platform_data plat_data;
>  	struct iio_mount_matrix orientation;
>  	struct regmap *map;
> @@ -189,6 +189,7 @@ struct inv_mpu6050_state {
>  	bool magn_disabled;
>  	s32 magn_raw_to_gauss[3];
>  	struct iio_mount_matrix magn_orient;
> +	unsigned int suspended_sensors;
>  };
>  
>  /*register and associated bit definition*/
> @@ -312,6 +313,7 @@ struct inv_mpu6050_state {
>  #define INV_MPU6050_ACCEL_UP_TIME            20
>  #define INV_MPU6050_GYRO_UP_TIME             35
>  #define INV_MPU6050_GYRO_DOWN_TIME           150
> +#define INV_MPU6050_SUSPEND_DELAY_MS         2000
>  
>  /* delay time in microseconds */
>  #define INV_MPU6050_REG_UP_TIME_MIN          5000
> @@ -439,7 +441,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable);
>  int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en,
>  			      unsigned int mask);
>  int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
> -int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
>  int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
>  void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
>  int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> index f53f50d08b9e..9eab39042443 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> @@ -3,6 +3,7 @@
>  * Copyright (C) 2012 Invensense, Inc.
>  */
>  
> +#include <linux/pm_runtime.h>
>  #include "inv_mpu_iio.h"
>  
>  static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev)
> @@ -156,41 +157,39 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
>  static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
>  {
>  	struct inv_mpu6050_state *st = iio_priv(indio_dev);
> +	struct device *pdev = regmap_get_device(st->map);
>  	unsigned int scan;
>  	int result;
>  
> -	scan = inv_scan_query(indio_dev);
> -
>  	if (enable) {
> -		result = inv_mpu6050_set_power_itg(st, true);
> -		if (result)
> +		scan = inv_scan_query(indio_dev);
> +		result = pm_runtime_get_sync(pdev);
> +		if (result < 0) {
> +			pm_runtime_put_noidle(pdev);
>  			return result;
> +		}
> +		result = inv_mpu6050_switch_engine(st, false, ~scan);
> +		if (result)
> +			goto error_power_off;

I'd like a comment on this block.  I guess this off / on sequence is
now necessary as we were previously relying on the power having been
turned off?

>  		result = inv_mpu6050_switch_engine(st, true, scan);
>  		if (result)
>  			goto error_power_off;
>  		st->skip_samples = inv_compute_skip_samples(st);
>  		result = inv_mpu6050_prepare_fifo(st, true);
>  		if (result)
> -			goto error_sensors_off;
> +			goto error_power_off;
>  	} else {
>  		result = inv_mpu6050_prepare_fifo(st, false);
> -		if (result)
> -			goto error_sensors_off;
> -		result = inv_mpu6050_switch_engine(st, false, scan);
> -		if (result)
> -			goto error_power_off;
> -
> -		result = inv_mpu6050_set_power_itg(st, false);
>  		if (result)
>  			goto error_power_off;
> +		pm_runtime_mark_last_busy(pdev);
> +		pm_runtime_put_autosuspend(pdev);
>  	}
>  
>  	return 0;
>  
> -error_sensors_off:
> -	inv_mpu6050_switch_engine(st, false, scan);
>  error_power_off:
> -	inv_mpu6050_set_power_itg(st, false);
> +	pm_runtime_put_autosuspend(pdev);
>  	return result;
>  }
>  




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux