mei: add optional timeout to internal bus recv
authorAlexander Usyskin <alexander.usyskin@intel.com>
Sun, 24 Jun 2018 21:11:40 +0000 (00:11 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 3 Jul 2018 11:11:20 +0000 (13:11 +0200)
Add optional timeout to internal bus recv function to
enable break out of internal flows in case of no answer from FW.

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>
drivers/misc/mei/bus-fixup.c
drivers/misc/mei/bus.c
drivers/misc/mei/mei_dev.h

index 0208c4b..b17c46a 100644 (file)
@@ -266,7 +266,7 @@ static int mei_nfc_if_version(struct mei_cl *cl,
                return -ENOMEM;
 
        ret = 0;
-       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0);
+       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0);
        if (bytes_recv < if_version_length) {
                dev_err(bus->dev, "Could not read IF version\n");
                ret = -EIO;
index b113373..7bba62a 100644 (file)
@@ -116,11 +116,12 @@ out:
  * @buf: buffer to receive
  * @length: buffer length
  * @mode: io mode
+ * @timeout: recv timeout, 0 for infinite timeout
  *
  * Return: read size in bytes of < 0 on error
  */
 ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
-                     unsigned int mode)
+                     unsigned int mode, unsigned long timeout)
 {
        struct mei_device *bus;
        struct mei_cl_cb *cb;
@@ -158,13 +159,28 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
 
                mutex_unlock(&bus->device_lock);
 
-               if (wait_event_interruptible(cl->rx_wait,
-                               (!list_empty(&cl->rd_completed)) ||
-                               (!mei_cl_is_connected(cl)))) {
-
-                       if (signal_pending(current))
-                               return -EINTR;
-                       return -ERESTARTSYS;
+               if (timeout) {
+                       rets = wait_event_interruptible_timeout
+                                       (cl->rx_wait,
+                                       (!list_empty(&cl->rd_completed)) ||
+                                       (!mei_cl_is_connected(cl)),
+                                       msecs_to_jiffies(timeout));
+                       if (rets == 0)
+                               return -ETIME;
+                       if (rets < 0) {
+                               if (signal_pending(current))
+                                       return -EINTR;
+                               return -ERESTARTSYS;
+                       }
+               } else {
+                       if (wait_event_interruptible
+                                       (cl->rx_wait,
+                                       (!list_empty(&cl->rd_completed)) ||
+                                       (!mei_cl_is_connected(cl)))) {
+                               if (signal_pending(current))
+                                       return -EINTR;
+                               return -ERESTARTSYS;
+                       }
                }
 
                mutex_lock(&bus->device_lock);
@@ -231,7 +247,7 @@ ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
 {
        struct mei_cl *cl = cldev->cl;
 
-       return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
+       return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
 
@@ -248,7 +264,7 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
 {
        struct mei_cl *cl = cldev->cl;
 
-       return __mei_cl_recv(cl, buf, length, 0);
+       return __mei_cl_recv(cl, buf, length, 0, 0);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_recv);
 
index be9c484..4058ab5 100644 (file)
@@ -317,7 +317,7 @@ void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
                      unsigned int mode);
 ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
-                     unsigned int mode);
+                     unsigned int mode, unsigned long timeout);
 bool mei_cl_bus_rx_event(struct mei_cl *cl);
 bool mei_cl_bus_notify_event(struct mei_cl *cl);
 void mei_cl_bus_remove_devices(struct mei_device *bus);