diff options
Diffstat (limited to 'drivers/hid/hid-wiimote.h')
-rw-r--r-- | drivers/hid/hid-wiimote.h | 19 |
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; } |