From: Alexander Usyskin <[email protected]>

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 <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
---
 drivers/misc/mei/bus-fixup.c |  2 +-
 drivers/misc/mei/bus.c       | 36 ++++++++++++++++++++++++++----------
 drivers/misc/mei/mei_dev.h   |  2 +-
 3 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 0208c4b027c5..b17c46a43812 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -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;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index b1133739fb4b..7bba62a72921 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -116,11 +116,12 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t 
length,
  * @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);
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index be9c48415da9..4058ab5ad2d8 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -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);
-- 
2.14.4

Reply via email to