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

Reply via email to