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;
 
  * @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;
 
                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);
 {
        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);
 
 {
        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);
 
 
 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);