aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-wiimote.h
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-05-05 23:12:50 +0200
committerJiri Kosina <jkosina@suse.cz>2013-06-03 11:07:00 +0200
commitd758b1f0c527aedc5e83a565a0737d9ac21ea46a (patch)
tree20707221091b2e594df2e18a164d94ccf2e05490 /drivers/hid/hid-wiimote.h
parentHID: wiimote: use cached battery values on I/O failure (diff)
downloadlinux-dev-d758b1f0c527aedc5e83a565a0737d9ac21ea46a.tar.xz
linux-dev-d758b1f0c527aedc5e83a565a0737d9ac21ea46a.zip
HID: wiimote: wake up if output queue failed
Our output queue is asynchronous but synchronous reports may wait for a response to their request. Therefore, wake them up unconditionally if an output report couldn't be sent. But keep the report ID intact so we don't incorrectly assume our request succeeded. Note that the underlying connection is required to be reliable and does retransmission itself. So it is safe to assume that if the transmission fails, the device is in inconsistent state. Hence, we abort every request if any output report fails. No need to verify which report failed. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-wiimote.h')
-rw-r--r--drivers/hid/hid-wiimote.h19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index 301607da7715..34417021606e 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -195,6 +195,16 @@ static inline void wiimote_cmd_complete(struct wiimote_data *wdata)
complete(&wdata->state.ready);
}
+/* requires the state.lock spinlock to be held */
+static inline void wiimote_cmd_abort(struct wiimote_data *wdata)
+{
+ /* Abort synchronous request by waking up the sleeping caller. But
+ * reset the state.cmd field to an invalid value so no further event
+ * handlers will work with it. */
+ wdata->state.cmd = WIIPROTO_REQ_MAX;
+ complete(&wdata->state.ready);
+}
+
static inline int wiimote_cmd_acquire(struct wiimote_data *wdata)
{
return mutex_lock_interruptible(&wdata->state.sync) ? -ERESTARTSYS : 0;
@@ -223,11 +233,17 @@ static inline int wiimote_cmd_wait(struct wiimote_data *wdata)
{
int ret;
+ /* The completion acts as implicit memory barrier so we can safely
+ * assume that state.cmd is set on success/failure and isn't accessed
+ * by any other thread, anymore. */
+
ret = wait_for_completion_interruptible_timeout(&wdata->state.ready, HZ);
if (ret < 0)
return -ERESTARTSYS;
else if (ret == 0)
return -EIO;
+ else if (wdata->state.cmd != WIIPROTO_REQ_NULL)
+ return -EIO;
else
return 0;
}
@@ -236,9 +252,12 @@ static inline int wiimote_cmd_wait_noint(struct wiimote_data *wdata)
{
unsigned long ret;
+ /* no locking needed; see wiimote_cmd_wait() */
ret = wait_for_completion_timeout(&wdata->state.ready, HZ);
if (!ret)
return -EIO;
+ else if (wdata->state.cmd != WIIPROTO_REQ_NULL)
+ return -EIO;
else
return 0;
}