summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattis fjallstrom <mattis@acm.org>2015-10-02 17:59:11 -0700
committermattis fjallstrom <mattis@acm.org>2015-10-02 17:59:11 -0700
commitb291034eef47ffdd9a486dd6b41c0c76c4d33353 (patch)
tree1d8585e20cd2683893bee839bedcfbced2637a9c
parentcf37981b4c9c4bfceab735aa210e2a8531c86954 (diff)
downloadolio-linux-3.10-b291034eef47ffdd9a486dd6b41c0c76c4d33353.tar.xz
olio-linux-3.10-b291034eef47ffdd9a486dd6b41c0c76c4d33353.zip
Improved wakeup performance.
Change-Id: Idd79c715744046d50736e08b07e0c937d4ff7318
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c1
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c35
-rw-r--r--drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c110
3 files changed, 132 insertions, 14 deletions
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c
index f28fa07270f..75d3e3aaca2 100644
--- a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_buffer.c
@@ -8,7 +8,6 @@
* Licensed under the GPL-2.
*/
-/* #define DEBUG */
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c
index b0df8009aa8..aca1924a38b 100644
--- a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_core.c
@@ -7,7 +7,7 @@
*
* Licensed under the GPL-2.
*/
-
+//#define DEBUG
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -1841,6 +1841,34 @@ ssize_t st_lsm6ds3_sysfs_get_irq_src(struct device *dev,
}
+static ssize_t st_lsm6ds3_sysfs_ack_wakeup_irq(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int ret;
+ struct lsm6ds3_sensor_data *sdata = iio_priv(dev_get_drvdata(dev));
+ uint32_t i;
+ struct timespec ts;
+ s64 ack_time;
+
+ ret = sscanf(buf, "%i", &i);
+ if(ret != 1 || i != 1){
+ dev_err(sdata->cdata->dev,"error, write 1 to ack");
+ return -EINVAL;
+ }
+
+ mutex_lock(&sdata->cdata->fifo_lock);
+#define ACK_TIME_DEBUG 1
+#if ACK_TIME_DEBUG
+ get_monotonic_boottime(&ts);
+ ack_time = timespec_to_ns(&ts);
+ dev_info(sdata->cdata->dev, "IRQ acked from android@%lld", ack_time);
+#endif
+ wake_unlock(&sdata->cdata->tap_wlock);
+
+ mutex_unlock(&sdata->cdata->fifo_lock);
+ return size;
+}
+
static ssize_t st_lsm6ds3_sysfs_write_reg(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
@@ -1971,6 +1999,8 @@ static IIO_DEVICE_ATTR(irq_source, S_IRUGO,
static IIO_DEVICE_ATTR(write_reg, S_IWUSR,
NULL, st_lsm6ds3_sysfs_write_reg, 0);
+static IIO_DEVICE_ATTR(ack_wakeup_irq, S_IWUSR,
+ NULL, st_lsm6ds3_sysfs_ack_wakeup_irq, 0);
static IIO_DEVICE_ATTR(read_reg, S_IRUGO | S_IWUSR,
st_lsm6ds3_sysfs_read_reg_get,
@@ -1997,6 +2027,7 @@ static struct attribute *st_lsm6ds3_accel_attributes[] = {
&iio_dev_attr_read_reg.dev_attr.attr,
&iio_dev_attr_sixd_wake_mask.dev_attr.attr,
&iio_dev_attr_suspend_samples.dev_attr.attr,
+ &iio_dev_attr_ack_wakeup_irq.dev_attr.attr,
NULL,
};
@@ -2149,7 +2180,7 @@ int st_lsm6ds3_common_probe(struct lsm6ds3_data *cdata, int irq)
dev_info(cdata->dev, "driver use DRDY int pin 1\n");
}
- cdata->sixd_mask = SIXD_MASK_VALID_BITS;
+ cdata->sixd_mask = 0x21;
cdata->indio_dev[ST_INDIO_DEV_ACCEL]->name =
kasprintf(GFP_KERNEL, "%s_%s", cdata->name,
diff --git a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c
index d4106ad5071..d5f6ed5fcf4 100644
--- a/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c
+++ b/drivers/iio/imu/st_lsm6ds3/st_lsm6ds3_trigger.c
@@ -7,9 +7,8 @@
*
* Licensed under the GPL-2.
*/
-
-/* #define DEBUG */
-
+//#define WAKE_STATS_DEBUG_INFO
+//#define DEBUG
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
@@ -38,7 +37,7 @@
#define ST_LSM6DS3_TAP_SRC_Z_AXIS_MASK (1<<0)
#define ST_LSM6DS3_6D_SRC_ADDR 0x1d
-
+#define ST_LSM6DS3_6D_SRC_DETECTED_MASK (1<<6)
static struct workqueue_struct *st_lsm6ds3_wq;
@@ -63,6 +62,82 @@ irqreturn_t st_lsm6ds3_save_timestamp(int irq, void *private)
return IRQ_HANDLED;
}
+#ifdef WAKE_STATS_DEBUG_INFO
+static int wakeup_irq_count = 0;
+static int wakeup_irq_stayawake_count = 0;
+static int wakeup_irq_keepawake_count = 0;
+#define MAX_ORIENTATIONS 6
+static int wake_up_orient_count[MAX_ORIENTATIONS] = {0};
+static long wake_up_orient_times[MAX_ORIENTATIONS] = {0};
+s64 last_orient_change_time_ns = 0;
+int last_orient;
+
+
+static void update_orient_stats(u8 d6d_src_reg, s64 ctime_ns)
+{
+ return;
+ s64 delta = 0;
+ int orient_val;
+ d6d_src_reg &= SIXD_MASK_VALID_BITS;
+ orient_val = __ffs(d6d_src_reg);
+ if( orient_val >= MAX_ORIENTATIONS){
+ return;
+ }
+
+ wake_up_orient_count[orient_val]++;
+ if(last_orient_change_time_ns != 0){
+ delta = ctime_ns - last_orient_change_time_ns;
+ do_div(delta, 1E6); //down to milliseconds
+ wake_up_orient_times[last_orient] += delta;
+ }
+ last_orient_change_time_ns = ctime_ns;
+ last_orient = orient_val;
+}
+
+static void print_wake_stats(struct lsm6ds3_data *cdata)
+{
+ struct timespec monotonic, boot, misc;
+ s64 mon_ns, boot_ns, misc_ns, tot_ms=0;
+ int i;
+
+ get_monotonic_boottime(&monotonic);
+ ktime_get_ts(&boot);
+ getnstimeofday(&misc);
+ mon_ns = timespec_to_ns(&monotonic);
+ boot_ns = timespec_to_ns(&boot);
+ misc_ns = timespec_to_ns(&misc);
+ do_div(mon_ns,1E9);
+ do_div(boot_ns,1E9);
+ do_div(misc_ns,1E9);
+
+ dev_info(cdata->dev, "wkstat: unignored/total/keepawake: \t%i\t%i\t%i", wakeup_irq_stayawake_count, wakeup_irq_count,
+ wakeup_irq_keepawake_count);
+ dev_info(cdata->dev, "wkstat times: tot:\t%lld\tawake:\t%lld", mon_ns, boot_ns);
+ dev_info(cdata->dev, "wkstat all orient count: 5-0 %i\t%i\t%i\t%i\t%i\t%i",
+ wake_up_orient_count[5],
+ wake_up_orient_count[4],
+ wake_up_orient_count[3],
+ wake_up_orient_count[2],
+ wake_up_orient_count[1],
+ wake_up_orient_count[0]);
+
+ for(i=0; i<MAX_ORIENTATIONS; i++)
+ tot_ms += wake_up_orient_times[i];
+
+ dev_info(cdata->dev, "wkstat orient times(uS): 5-0 %ld\t%ld\t%ld\t%ld\t%ld\t%ld\ttot:%lld",
+ wake_up_orient_times[5],
+ wake_up_orient_times[4],
+ wake_up_orient_times[3],
+ wake_up_orient_times[2],
+ wake_up_orient_times[1],
+ wake_up_orient_times[0], tot_ms);
+
+}
+#endif /* WAKE_STATS_DEBUG_INFO */
+
+
+
+
static void st_lsm6ds3_irq_management(struct work_struct *data_work)
{
struct lsm6ds3_data *cdata;
@@ -73,13 +148,10 @@ static void st_lsm6ds3_irq_management(struct work_struct *data_work)
int wake_irq;
int ignore_event = 0;
-
-
cdata = container_of((struct work_struct *)data_work,
struct lsm6ds3_data, data_work);
wake_irq = last_wakeup_reason_test(cdata->irq);
-
mutex_lock(&cdata->fifo_lock);
cdata->tf->read(cdata, ST_LSM6DS3_6D_SRC_ADDR, 1, &d6d_src_reg, true);
cdata->tf->read(cdata, ST_LSM6DS3_TAP_SRC_ADDR, 1, &tap_src_reg, true);
@@ -89,7 +161,10 @@ static void st_lsm6ds3_irq_management(struct work_struct *data_work)
dev_dbg(cdata->dev, "ST irq start :src_value, 6d, tap:%x %x %x",src_value, d6d_src_reg, tap_src_reg);
- if(d6d_src_reg & (1<<6)){
+ if(d6d_src_reg & ST_LSM6DS3_6D_SRC_DETECTED_MASK){
+#ifdef WAKE_STATS_DEBUG_INFO
+ update_orient_stats(d6d_src_reg, cdata->timestamp);
+#endif
dev_info(cdata->dev, "D6D IRQ val:0x%x mask:0x%x", SIXD_MASK_VALID_BITS & d6d_src_reg, cdata->sixd_mask);
if(cdata->sixd_mask & d6d_src_reg){
d6d_event = 1;
@@ -113,7 +188,9 @@ static void st_lsm6ds3_irq_management(struct work_struct *data_work)
}
}
if(cdata->first_irq_from_resume && wake_irq){
- dev_info(cdata->dev, "First IRQ from a RESUME");
+#ifdef WAKE_STATS_DEBUG_INFO
+ wakeup_irq_count++;
+#endif
if(!d6d_event && !tap_event && !ignore_event){
dev_info(cdata->dev, "No event from first resume, assuming lost TAP");
tap_event = 1;
@@ -124,8 +201,16 @@ static void st_lsm6ds3_irq_management(struct work_struct *data_work)
}
if(!ignore_event && (tap_event || d6d_event) && cdata->first_irq_from_resume){
- dev_info(cdata->dev, "Setting wake lock");
- wake_lock_timeout(&cdata->tap_wlock,msecs_to_jiffies(1500));
+ wake_lock_timeout(&cdata->tap_wlock,msecs_to_jiffies(500));
+#ifdef WAKE_STATS_DEBUG_INFO
+ wakeup_irq_stayawake_count++;
+#endif
+ }
+ else if(d6d_event && !ignore_event){//negative roll
+ wake_lock_timeout(&cdata->tap_wlock,msecs_to_jiffies(200));
+#ifdef WAKE_STATS_DEBUG_INFO
+ wakeup_irq_keepawake_count++;
+#endif
}
//significant motion event processing
if(tap_event){
@@ -179,6 +264,9 @@ static void st_lsm6ds3_irq_management(struct work_struct *data_work)
if(cdata->first_irq_from_resume){
cdata->first_irq_from_resume = 0;
st_lsm6ds3_reconfigure_fifo(cdata, false);
+#ifdef WAKE_STATS_DEBUG_INFO
+ print_wake_stats(cdata);
+#endif
}
enable_irq(cdata->irq);
return;