summaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/bus.c
diff options
context:
space:
mode:
authorTomas Winkler2015-02-10 09:39:46 +0100
committerGreg Kroah-Hartman2015-03-02 04:37:00 +0100
commita9bed61053af13c0768f82c9d1c8793515dd067c (patch)
tree3beb3a01fbfc4c8cc1d73c18a220478ad5683cd8 /drivers/misc/mei/bus.c
parentmei: simplify io callback disposal (diff)
downloadkernel-qcow2-linux-a9bed61053af13c0768f82c9d1c8793515dd067c.tar.gz
kernel-qcow2-linux-a9bed61053af13c0768f82c9d1c8793515dd067c.tar.xz
kernel-qcow2-linux-a9bed61053af13c0768f82c9d1c8793515dd067c.zip
mei: allow read concurrency
Replace clunky read state machine with read stack implemented as per client read list, this is important mostly for mei drivers with unsolicited reads Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/bus.c')
-rw-r--r--drivers/misc/mei/bus.c36
1 files changed, 19 insertions, 17 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index b5385372693d..17ca7e20fb6a 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -288,19 +288,20 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
mutex_lock(&dev->device_lock);
- if (!cl->read_cb) {
- rets = mei_cl_read_start(cl, length, NULL);
- if (rets < 0)
- goto out;
- }
+ cb = mei_cl_read_cb(cl, NULL);
+ if (cb)
+ goto copy;
+
+ rets = mei_cl_read_start(cl, length, NULL);
+ if (rets && rets != -EBUSY)
+ goto out;
- if (cl->reading_state != MEI_READ_COMPLETE &&
- !waitqueue_active(&cl->rx_wait)) {
+ if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
mutex_unlock(&dev->device_lock);
if (wait_event_interruptible(cl->rx_wait,
- cl->reading_state == MEI_READ_COMPLETE ||
+ (!list_empty(&cl->rd_completed)) ||
mei_cl_is_transitioning(cl))) {
if (signal_pending(current))
@@ -309,15 +310,20 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
}
mutex_lock(&dev->device_lock);
- }
+ if (mei_cl_is_transitioning(cl)) {
+ rets = -EBUSY;
+ goto out;
+ }
+ }
- if (cl->reading_state != MEI_READ_COMPLETE) {
+ cb = mei_cl_read_cb(cl, NULL);
+ if (!cb) {
rets = 0;
goto out;
}
- cb = cl->read_cb;
+copy:
if (cb->status) {
rets = cb->status;
goto free;
@@ -329,9 +335,6 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
free:
mei_io_cb_free(cb);
- cl->read_cb = NULL;
- cl->reading_state = MEI_IDLE;
-
out:
mutex_unlock(&dev->device_lock);
@@ -443,7 +446,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
mutex_unlock(&dev->device_lock);
- if (device->event_cb && !cl->read_cb)
+ if (device->event_cb)
mei_cl_read_start(device->cl, 0, NULL);
if (!device->ops || !device->ops->enable)
@@ -485,8 +488,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
}
/* Flush queues and remove any pending read */
- mei_cl_flush_queues(cl);
- mei_io_cb_free(cl->read_cb);
+ mei_cl_flush_queues(cl, NULL);
device->event_cb = NULL;