diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-09-02 13:29:46 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-05 07:13:10 -0700 |
commit | 18f48d9e784339c954eb1641fef600e00c7a53c0 (patch) | |
tree | 141a32cb4ceff6ecb676fb9ed19cbd2c2f130901 /drivers | |
parent | cb4af713f95f049056c25e0c18f652c3338c2bc7 (diff) |
mei: bus: stop wait for read during cl state transition
commit e2b31644e999e8bfe3efce880fb32840299abf41 upstream.
Bus layer omitted check for client state transition while waiting
for read completion
The client state transition may occur for example as result
of firmware initiated reset
Add mei_cl_is_transitioning wrapper to reduce the code
repetition.:
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/mei/bus.c | 5 | ||||
-rw-r--r-- | drivers/misc/mei/client.h | 6 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 11 |
3 files changed, 14 insertions, 8 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 9ecd49a7be1..99cc0b07a71 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -295,10 +295,13 @@ int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) if (cl->reading_state != MEI_READ_COMPLETE && !waitqueue_active(&cl->rx_wait)) { + mutex_unlock(&dev->device_lock); if (wait_event_interruptible(cl->rx_wait, - (MEI_READ_COMPLETE == cl->reading_state))) { + cl->reading_state == MEI_READ_COMPLETE || + mei_cl_is_transitioning(cl))) { + if (signal_pending(current)) return -EINTR; return -ERESTARTSYS; diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index cfdb144526a..467d9dda97f 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -76,6 +76,12 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1, (cl1->host_client_id == cl2->host_client_id) && (cl1->me_client_id == cl2->me_client_id); } +static inline bool mei_cl_is_transitioning(struct mei_cl *cl) +{ + return (MEI_FILE_INITIALIZING == cl->state || + MEI_FILE_DISCONNECTED == cl->state || + MEI_FILE_DISCONNECTING == cl->state); +} int mei_cl_flow_ctrl_creds(struct mei_cl *cl); diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 053139f6108..701698de5ac 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -262,19 +262,16 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, mutex_unlock(&dev->device_lock); if (wait_event_interruptible(cl->rx_wait, - (MEI_READ_COMPLETE == cl->reading_state || - MEI_FILE_INITIALIZING == cl->state || - MEI_FILE_DISCONNECTED == cl->state || - MEI_FILE_DISCONNECTING == cl->state))) { + MEI_READ_COMPLETE == cl->reading_state || + mei_cl_is_transitioning(cl))) { + if (signal_pending(current)) return -EINTR; return -ERESTARTSYS; } mutex_lock(&dev->device_lock); - if (MEI_FILE_INITIALIZING == cl->state || - MEI_FILE_DISCONNECTED == cl->state || - MEI_FILE_DISCONNECTING == cl->state) { + if (mei_cl_is_transitioning(cl)) { rets = -EBUSY; goto out; } |