aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-09-02 06:29:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-05 10:13:10 -0400
commit18f48d9e784339c954eb1641fef600e00c7a53c0 (patch)
tree141a32cb4ceff6ecb676fb9ed19cbd2c2f130901 /drivers/misc/mei
parentcb4af713f95f049056c25e0c18f652c3338c2bc7 (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/misc/mei')
-rw-r--r--drivers/misc/mei/bus.c5
-rw-r--r--drivers/misc/mei/client.h6
-rw-r--r--drivers/misc/mei/main.c11
3 files changed, 14 insertions, 8 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 9ecd49a7be1b..99cc0b07a713 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)
295 295
296 if (cl->reading_state != MEI_READ_COMPLETE && 296 if (cl->reading_state != MEI_READ_COMPLETE &&
297 !waitqueue_active(&cl->rx_wait)) { 297 !waitqueue_active(&cl->rx_wait)) {
298
298 mutex_unlock(&dev->device_lock); 299 mutex_unlock(&dev->device_lock);
299 300
300 if (wait_event_interruptible(cl->rx_wait, 301 if (wait_event_interruptible(cl->rx_wait,
301 (MEI_READ_COMPLETE == cl->reading_state))) { 302 cl->reading_state == MEI_READ_COMPLETE ||
303 mei_cl_is_transitioning(cl))) {
304
302 if (signal_pending(current)) 305 if (signal_pending(current))
303 return -EINTR; 306 return -EINTR;
304 return -ERESTARTSYS; 307 return -ERESTARTSYS;
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index cfdb144526aa..467d9dda97fa 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,
76 (cl1->host_client_id == cl2->host_client_id) && 76 (cl1->host_client_id == cl2->host_client_id) &&
77 (cl1->me_client_id == cl2->me_client_id); 77 (cl1->me_client_id == cl2->me_client_id);
78} 78}
79static inline bool mei_cl_is_transitioning(struct mei_cl *cl)
80{
81 return (MEI_FILE_INITIALIZING == cl->state ||
82 MEI_FILE_DISCONNECTED == cl->state ||
83 MEI_FILE_DISCONNECTING == cl->state);
84}
79 85
80 86
81int mei_cl_flow_ctrl_creds(struct mei_cl *cl); 87int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 053139f61086..701698de5ac7 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,
262 mutex_unlock(&dev->device_lock); 262 mutex_unlock(&dev->device_lock);
263 263
264 if (wait_event_interruptible(cl->rx_wait, 264 if (wait_event_interruptible(cl->rx_wait,
265 (MEI_READ_COMPLETE == cl->reading_state || 265 MEI_READ_COMPLETE == cl->reading_state ||
266 MEI_FILE_INITIALIZING == cl->state || 266 mei_cl_is_transitioning(cl))) {
267 MEI_FILE_DISCONNECTED == cl->state || 267
268 MEI_FILE_DISCONNECTING == cl->state))) {
269 if (signal_pending(current)) 268 if (signal_pending(current))
270 return -EINTR; 269 return -EINTR;
271 return -ERESTARTSYS; 270 return -ERESTARTSYS;
272 } 271 }
273 272
274 mutex_lock(&dev->device_lock); 273 mutex_lock(&dev->device_lock);
275 if (MEI_FILE_INITIALIZING == cl->state || 274 if (mei_cl_is_transitioning(cl)) {
276 MEI_FILE_DISCONNECTED == cl->state ||
277 MEI_FILE_DISCONNECTING == cl->state) {
278 rets = -EBUSY; 275 rets = -EBUSY;
279 goto out; 276 goto out;
280 } 277 }