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>
This commit is contained in:
Tomas Winkler
2015-02-10 10:39:46 +02:00
committato da Greg Kroah-Hartman
parent 928fa6664b
commit a9bed61053
8 ha cambiato i file con 98 aggiunte e 119 eliminazioni

Vedi File

@@ -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;
if (cl->reading_state != MEI_READ_COMPLETE &&
!waitqueue_active(&cl->rx_wait)) {
rets = mei_cl_read_start(cl, length, NULL);
if (rets && rets != -EBUSY)
goto out;
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;