aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Pandruvada <srinivas.pandruvada@linux.intel.com>2017-10-11 12:35:01 -0400
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2017-10-14 14:29:50 -0400
commitad7532cefd11d11a0814a75fb814c205ee3d9d4c (patch)
treeee5da70a1f2f53961a27bb1e42b7924c1e4b7c1e
parent446b3217a96c456ab8796605fbb3ce379b03a504 (diff)
iio: hid-sensor-trigger: Don't touch sensors unless user space requests
One of the user complained that on his system Thinkpad Yoga S1, with commit f1664eaacec3 ("iio: hid-sensor-trigger: Fix the race with user space powering up sensors") causes the system to resume immediately on suspend (S3 operation). On this system the sensor hub is on USB and is a wake up device from S3. So if any sensor sends data on motion, the system will wake up. This can be a legitimate use case to wake up device motion, but that needs proper user space support to set right thresholds. In fact the above commit didn't cause this regression, but any operation which cause sensors to wake up would have caused the same issue. So if user reads the raw sensor data, same issue occurs, with or without this commit. Only difference is that the above commit by default will trigger a power up and power down of sensors as part of runtime pm enable (runtime enable will cause a runtime resume callback followed by runtime_suspend callback). Previously user has to do some action on sensors. On investigation it was observed that the current driver correctly changing the state of all sensors to power off but then also some sensor will still send some data. Only option is to never power up any sensor. Only good option is to: - Using sysfs interface disable USB as a wakeup device (This will not need any driver change) Since some user don't care about sensors. So for those users this change brings back old functionality. As long as they don't cause any operation to power up sensors (like raw read or start iio-sensor-proxy service), the sensors will not be to touched. This is done by delaying run time enable till user space does some operation with sensors. Link: https://bugzilla.kernel.org/show_bug.cgi?id=196853 Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c12
-rw-r--r--include/linux/hid-sensor-hub.h1
2 files changed, 10 insertions, 3 deletions
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 55dfd6288d18..cfb6588565ba 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -179,6 +179,10 @@ int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
179 int ret; 179 int ret;
180 180
181 atomic_set(&st->user_requested_state, state); 181 atomic_set(&st->user_requested_state, state);
182
183 if (atomic_add_unless(&st->runtime_pm_enable, 1, 1))
184 pm_runtime_enable(&st->pdev->dev);
185
182 if (state) 186 if (state)
183 ret = pm_runtime_get_sync(&st->pdev->dev); 187 ret = pm_runtime_get_sync(&st->pdev->dev);
184 else { 188 else {
@@ -221,7 +225,8 @@ static void hid_sensor_set_power_work(struct work_struct *work)
221 if (attrb->latency_ms > 0) 225 if (attrb->latency_ms > 0)
222 hid_sensor_set_report_latency(attrb, attrb->latency_ms); 226 hid_sensor_set_report_latency(attrb, attrb->latency_ms);
223 227
224 _hid_sensor_power_state(attrb, true); 228 if (atomic_read(&attrb->user_requested_state))
229 _hid_sensor_power_state(attrb, true);
225} 230}
226 231
227static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig, 232static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
@@ -232,7 +237,9 @@ static int hid_sensor_data_rdy_trigger_set_state(struct iio_trigger *trig,
232 237
233void hid_sensor_remove_trigger(struct hid_sensor_common *attrb) 238void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
234{ 239{
235 pm_runtime_disable(&attrb->pdev->dev); 240 if (atomic_read(&attrb->runtime_pm_enable))
241 pm_runtime_disable(&attrb->pdev->dev);
242
236 pm_runtime_set_suspended(&attrb->pdev->dev); 243 pm_runtime_set_suspended(&attrb->pdev->dev);
237 pm_runtime_put_noidle(&attrb->pdev->dev); 244 pm_runtime_put_noidle(&attrb->pdev->dev);
238 245
@@ -282,7 +289,6 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
282 INIT_WORK(&attrb->work, hid_sensor_set_power_work); 289 INIT_WORK(&attrb->work, hid_sensor_set_power_work);
283 290
284 pm_suspend_ignore_children(&attrb->pdev->dev, true); 291 pm_suspend_ignore_children(&attrb->pdev->dev, true);
285 pm_runtime_enable(&attrb->pdev->dev);
286 /* Default to 3 seconds, but can be changed from sysfs */ 292 /* Default to 3 seconds, but can be changed from sysfs */
287 pm_runtime_set_autosuspend_delay(&attrb->pdev->dev, 293 pm_runtime_set_autosuspend_delay(&attrb->pdev->dev,
288 3000); 294 3000);
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index fc7aae64dcde..331dc377c275 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -231,6 +231,7 @@ struct hid_sensor_common {
231 unsigned usage_id; 231 unsigned usage_id;
232 atomic_t data_ready; 232 atomic_t data_ready;
233 atomic_t user_requested_state; 233 atomic_t user_requested_state;
234 atomic_t runtime_pm_enable;
234 int poll_interval; 235 int poll_interval;
235 int raw_hystersis; 236 int raw_hystersis;
236 int latency_ms; 237 int latency_ms;