Dear Alan, I added two flags and autosuspend function in this patch. I have verified it on my developmental board. Is this patch fine to you? Thank you.
Joseph --- From: Joseph Lai <[email protected]> Subject: fix power control race and improve performance Add two flags in mpu3050 struct to avoid power control race, and add autosuspend function to improve the performance of this driver. This driver spends 100 milliseconds to wait for chip data ready every time when resuming the chip. It will impact the performance of sensorfw. So, I add the autosuspend function can keep the chip awake during the period of its data reading. The driver will suspend when the gyro data is not read after the autosuspend_delay. Signed-off-by: Joseph Lai <[email protected]> diff -urN a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c --- a/drivers/input/misc/mpu3050.c 2011-02-16 16:52:15.000000000 +0800 +++ b/drivers/input/misc/mpu3050.c 2011-02-16 20:38:41.000000000 +0800 @@ -61,6 +61,8 @@ struct device *dev; struct input_dev *idev; struct mutex lock; + int is_suspended; + int rpm_resume_is_used; }; /** @@ -158,6 +160,8 @@ mpu3050_set_power_mode(sensor->client, buf[0] == '1' ? 1 : 0); mutex_unlock(&sensor->lock); + sensor->is_suspended = (buf[0] == '1') ? 0 : 1; + return count; } static DEVICE_ATTR(power_mode, S_IRUGO | S_IWUSR, @@ -179,14 +183,21 @@ struct mpu3050_sensor *sensor = dev_get_drvdata(dev); struct axis_data data; - if (mpu3050_get_power_mode(sensor->client)) + if (sensor->is_suspended && !sensor->rpm_resume_is_used) { pm_runtime_get_sync(dev); + sensor->rpm_resume_is_used = 1; + } pm_runtime_mark_last_busy(dev); mutex_lock(&sensor->lock); mpu3050_read_xyz(sensor->client, &data); mutex_unlock(&sensor->lock); + if (!sensor->is_suspended && sensor->rpm_resume_is_used) { + pm_runtime_put_sync_autosuspend(dev); + sensor->rpm_resume_is_used = 0; + } + return sprintf(buf, "%d %d %d\n", data.x, data.y, data.z); } static DEVICE_ATTR(gyro_data, S_IRUGO, mpu3050_show_xyz, NULL); @@ -212,7 +223,10 @@ static int mpu3050_input_open(struct input_dev *input) { struct mpu3050_sensor *sensor = input_get_drvdata(input); - pm_runtime_get(sensor->dev); + if (sensor->is_suspended && !sensor->rpm_resume_is_used) { + pm_runtime_get(sensor->dev); + sensor->rpm_resume_is_used = 1; + } return 0; } @@ -226,7 +240,10 @@ static void mpu3050_input_close(struct input_dev *input) { struct mpu3050_sensor *sensor = input_get_drvdata(input); - pm_runtime_put(sensor->dev); + if (!sensor->is_suspended && sensor->rpm_resume_is_used) { + pm_runtime_put(sensor->dev); + sensor->rpm_resume_is_used = 0; + } } /** @@ -370,14 +387,16 @@ goto failed_free; } - pm_runtime_set_active(&client->dev); - ret = mpu3050_register_input_device(sensor); if (ret) dev_err(&client->dev, "only provide sysfs\n"); + pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); + pm_runtime_use_autosuspend(&client->dev); pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY); + sensor->is_suspended = 1; + sensor->rpm_resume_is_used = 0; dev_info(&client->dev, "%s registered\n", id->name); return 0; @@ -417,7 +436,9 @@ */ static int mpu3050_suspend(struct i2c_client *client, pm_message_t mesg) { + struct mpu3050_sensor *sensor = i2c_get_clientdata(client); mpu3050_set_power_mode(client, 0); + sensor->is_suspended = 1; return 0; } @@ -429,7 +450,9 @@ */ static int mpu3050_resume(struct i2c_client *client) { + struct mpu3050_sensor *sensor = i2c_get_clientdata(client); mpu3050_set_power_mode(client, 1); + sensor->is_suspended = 0; msleep(100); /* wait for gyro chip resume */ return 0; } @@ -443,6 +466,7 @@ { struct mpu3050_sensor *sensor = dev_get_drvdata(dev); mpu3050_set_power_mode(sensor->client, 0); + sensor->is_suspended = 1; return 0; } @@ -450,6 +474,7 @@ { struct mpu3050_sensor *sensor = dev_get_drvdata(dev); mpu3050_set_power_mode(sensor->client, 1); + sensor->is_suspended = 0; msleep(100); /* wait for gyro chip resume */ return 0; } _______________________________________________ MeeGo-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
