aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-04-20 11:03:55 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-04-30 17:08:08 -0400
commit7ff4bdd45448936363dc6dc6c851112b5c08e209 (patch)
tree93a8e1621ef6d07fe36431413a31351e9ee485a8 /drivers/misc
parent4a8eaa96d8eebf5818ddf1aca92e775a2c2d3f7e (diff)
mei: fix waiting for wr_ctrl for corner cases.
A control message reply may not be received if either a link reset has occurred or disconnection is initiated by the FW. In the both cases the client state will be set straight to DISCONNECTED and the driver will wait till timeout. Adding DISCONNECTED state in the waiting condition will release the client from the stall. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/client.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 85ae11d410cc..eed254da63a8 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -727,6 +727,11 @@ static void mei_cl_wake_all(struct mei_cl *cl)
727 cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); 727 cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
728 wake_up_interruptible(&cl->ev_wait); 728 wake_up_interruptible(&cl->ev_wait);
729 } 729 }
730 /* synchronized under device mutex */
731 if (waitqueue_active(&cl->wait)) {
732 cl_dbg(dev, cl, "Waking up ctrl write clients!\n");
733 wake_up_interruptible(&cl->wait);
734 }
730} 735}
731 736
732/** 737/**
@@ -879,12 +884,15 @@ static int __mei_cl_disconnect(struct mei_cl *cl)
879 } 884 }
880 885
881 mutex_unlock(&dev->device_lock); 886 mutex_unlock(&dev->device_lock);
882 wait_event_timeout(cl->wait, cl->state == MEI_FILE_DISCONNECT_REPLY, 887 wait_event_timeout(cl->wait,
888 cl->state == MEI_FILE_DISCONNECT_REPLY ||
889 cl->state == MEI_FILE_DISCONNECTED,
883 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); 890 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
884 mutex_lock(&dev->device_lock); 891 mutex_lock(&dev->device_lock);
885 892
886 rets = cl->status; 893 rets = cl->status;
887 if (cl->state != MEI_FILE_DISCONNECT_REPLY) { 894 if (cl->state != MEI_FILE_DISCONNECT_REPLY &&
895 cl->state != MEI_FILE_DISCONNECTED) {
888 cl_dbg(dev, cl, "timeout on disconnect from FW client.\n"); 896 cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");
889 rets = -ETIME; 897 rets = -ETIME;
890 } 898 }
@@ -1085,6 +1093,7 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
1085 mutex_unlock(&dev->device_lock); 1093 mutex_unlock(&dev->device_lock);
1086 wait_event_timeout(cl->wait, 1094 wait_event_timeout(cl->wait,
1087 (cl->state == MEI_FILE_CONNECTED || 1095 (cl->state == MEI_FILE_CONNECTED ||
1096 cl->state == MEI_FILE_DISCONNECTED ||
1088 cl->state == MEI_FILE_DISCONNECT_REQUIRED || 1097 cl->state == MEI_FILE_DISCONNECT_REQUIRED ||
1089 cl->state == MEI_FILE_DISCONNECT_REPLY), 1098 cl->state == MEI_FILE_DISCONNECT_REPLY),
1090 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); 1099 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
@@ -1333,8 +1342,9 @@ int mei_cl_notify_request(struct mei_cl *cl,
1333 } 1342 }
1334 1343
1335 mutex_unlock(&dev->device_lock); 1344 mutex_unlock(&dev->device_lock);
1336 wait_event_timeout(cl->wait, cl->notify_en == request, 1345 wait_event_timeout(cl->wait,
1337 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); 1346 cl->notify_en == request || !mei_cl_is_connected(cl),
1347 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
1338 mutex_lock(&dev->device_lock); 1348 mutex_lock(&dev->device_lock);
1339 1349
1340 if (cl->notify_en != request && !cl->status) 1350 if (cl->notify_en != request && !cl->status)