mei: enqueue consecutive reads
authorAlexander Usyskin <alexander.usyskin@intel.com>
Mon, 25 Jul 2016 22:06:06 +0000 (01:06 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 Aug 2016 12:39:42 +0000 (14:39 +0200)
The FW supports only one pending read per host client, in order to
support  issuing of consecutive reads the driver  queues read requests
internally and send them to the firmware after pending one has
completed.

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/interrupt.c
drivers/misc/mei/main.c

index 36382d782e201cb6192120ba9429888a58500500..bf745e03f21e5a44a7d543f9df9de03c0cc3f28b 100644 (file)
@@ -209,6 +209,9 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
        int slots;
        int ret;
 
+       if (!list_empty(&cl->rd_pending))
+               return 0;
+
        msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
        slots = mei_hbuf_empty_slots(dev);
 
index d698ba32357c81bcdf745c795b559be1e378087d..650061b6ab9b265b03d0c2b4385c719faa97e166 100644 (file)
@@ -139,9 +139,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
        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;
@@ -177,25 +176,29 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
        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;
@@ -207,13 +210,9 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
                        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 */