if (ret < 0)
                return ret;
 
-       ret = __mei_cl_recv(cldev->cl, buf, length);
+       ret = __mei_cl_recv(cldev->cl, buf, length, 0);
        if (ret < 0)
                return ret;
 
                return -ENOMEM;
 
        ret = 0;
-       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
+       bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0);
        if (bytes_recv < if_version_length) {
                dev_err(bus->dev, "Could not read IF version\n");
                ret = -EIO;
 
  * @cl: host client
  * @buf: buffer to receive
  * @length: buffer length
+ * @mode: io mode
  *
  * Return: read size in bytes of < 0 on error
  */
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+                     unsigned int mode)
 {
        struct mei_device *bus;
        struct mei_cl_cb *cb;
        size_t r_length;
        ssize_t rets;
+       bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
 
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
        if (rets && rets != -EBUSY)
                goto out;
 
+       if (nonblock) {
+               rets = -EAGAIN;
+               goto out;
+       }
+
        /* wait on event only if there is no other waiter */
        /* synchronized under device mutex */
        if (!waitqueue_active(&cl->rx_wait)) {
 }
 EXPORT_SYMBOL_GPL(mei_cldev_send);
 
+/**
+ * mei_cldev_recv_nonblock - non block client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to receive
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ *         -EAGAIN if function will block.
+ */
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+                               size_t length)
+{
+       struct mei_cl *cl = cldev->cl;
+
+       return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
+
 /**
  * mei_cldev_recv - client receive (read)
  *
 {
        struct mei_cl *cl = cldev->cl;
 
-       return __mei_cl_recv(cl, buf, length);
+       return __mei_cl_recv(cl, buf, length, 0);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_recv);
 
 
  *
  * @MEI_CL_IO_TX_BLOCKING: send is blocking
  * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW
+ *
+ * @MEI_CL_IO_RX_NONBLOCK: recv is non-blocking
  */
 enum mei_cl_io_mode {
        MEI_CL_IO_TX_BLOCKING = BIT(0),
        MEI_CL_IO_TX_INTERNAL = BIT(1),
+
+       MEI_CL_IO_RX_NONBLOCK = BIT(2),
 };
 
 /*
 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);
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+                     unsigned int mode);
 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);
 
 /**
  * module_mei_cl_driver - Helper macro for registering mei cl driver
  *
- * @__mei_cldrv mei_cl_driver structure
+ * @__mei_cldrv: mei_cl_driver structure
  *
  *  Helper macro for mei cl drivers which do not do anything special in module
  *  init/exit, for eliminating a boilerplate code.
                      mei_cldev_driver_unregister)
 
 ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
-ssize_t  mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
+ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+                               size_t length);
 
 int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
 int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,