struct mei_cl *cl = file->private_data;
        struct mei_device *dev;
        struct mei_cl_cb *cb = NULL;
+       bool nonblock = !!(file->f_flags & O_NONBLOCK);
        int rets;
-       int err;
-
 
        if (WARN_ON(!cl || !cl->dev))
                return -ENODEV;
        if (*offset > 0)
                *offset = 0;
 
-       err = mei_cl_read_start(cl, length, file);
-       if (err && err != -EBUSY) {
-               cl_dbg(dev, cl, "mei start read failure status = %d\n", err);
-               rets = err;
+       rets = mei_cl_read_start(cl, length, file);
+       if (rets && rets != -EBUSY) {
+               cl_dbg(dev, cl, "mei start read failure status = %d\n", rets);
                goto out;
        }
 
-       /* synchronized under device mutex */
-       if (!waitqueue_active(&cl->rx_wait)) {
-               if (file->f_flags & O_NONBLOCK) {
-                       rets = -EAGAIN;
-                       goto out;
-               }
+       if (nonblock) {
+               rets = -EAGAIN;
+               goto out;
+       }
+
+       if (rets == -EBUSY &&
+           !mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, file)) {
+               rets = -ENOMEM;
+               goto out;
+       }
 
+       do {
                mutex_unlock(&dev->device_lock);
 
                if (wait_event_interruptible(cl->rx_wait,
-                               (!list_empty(&cl->rd_completed)) ||
-                               (!mei_cl_is_connected(cl)))) {
+                                            (!list_empty(&cl->rd_completed)) ||
+                                            (!mei_cl_is_connected(cl)))) {
 
                        if (signal_pending(current))
                                return -EINTR;
                        rets = -ENODEV;
                        goto out;
                }
-       }
 
-       cb = mei_cl_read_cb(cl, file);
-       if (!cb) {
-               rets = 0;
-               goto out;
-       }
+               cb = mei_cl_read_cb(cl, file);
+       } while (!cb);
 
 copy_buffer:
        /* now copy the data to user space */