aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-02-10 03:39:46 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-01 22:37:00 -0500
commita9bed61053af13c0768f82c9d1c8793515dd067c (patch)
tree3beb3a01fbfc4c8cc1d73c18a220478ad5683cd8 /drivers/misc
parent928fa6664b362aad70c16f04483414f60743e15e (diff)
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')
-rw-r--r--drivers/misc/mei/bus.c36
-rw-r--r--drivers/misc/mei/client.c84
-rw-r--r--drivers/misc/mei/client.h7
-rw-r--r--drivers/misc/mei/debugfs.c2
-rw-r--r--drivers/misc/mei/init.c1
-rw-r--r--drivers/misc/mei/interrupt.c35
-rw-r--r--drivers/misc/mei/main.c42
-rw-r--r--drivers/misc/mei/mei_dev.h10
8 files changed, 98 insertions, 119 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)
288 288
289 mutex_lock(&dev->device_lock); 289 mutex_lock(&dev->device_lock);
290 290
291 if (!cl->read_cb) { 291 cb = mei_cl_read_cb(cl, NULL);
292 rets = mei_cl_read_start(cl, length, NULL); 292 if (cb)
293 if (rets < 0) 293 goto copy;
294 goto out; 294
295 } 295 rets = mei_cl_read_start(cl, length, NULL);
296 if (rets && rets != -EBUSY)
297 goto out;
296 298
297 if (cl->reading_state != MEI_READ_COMPLETE && 299 if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
298 !waitqueue_active(&cl->rx_wait)) {
299 300
300 mutex_unlock(&dev->device_lock); 301 mutex_unlock(&dev->device_lock);
301 302
302 if (wait_event_interruptible(cl->rx_wait, 303 if (wait_event_interruptible(cl->rx_wait,
303 cl->reading_state == MEI_READ_COMPLETE || 304 (!list_empty(&cl->rd_completed)) ||
304 mei_cl_is_transitioning(cl))) { 305 mei_cl_is_transitioning(cl))) {
305 306
306 if (signal_pending(current)) 307 if (signal_pending(current))
@@ -309,15 +310,20 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
309 } 310 }
310 311
311 mutex_lock(&dev->device_lock); 312 mutex_lock(&dev->device_lock);
312 }
313 313
314 if (mei_cl_is_transitioning(cl)) {
315 rets = -EBUSY;
316 goto out;
317 }
318 }
314 319
315 if (cl->reading_state != MEI_READ_COMPLETE) { 320 cb = mei_cl_read_cb(cl, NULL);
321 if (!cb) {
316 rets = 0; 322 rets = 0;
317 goto out; 323 goto out;
318 } 324 }
319 325
320 cb = cl->read_cb; 326copy:
321 if (cb->status) { 327 if (cb->status) {
322 rets = cb->status; 328 rets = cb->status;
323 goto free; 329 goto free;
@@ -329,9 +335,6 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
329 335
330free: 336free:
331 mei_io_cb_free(cb); 337 mei_io_cb_free(cb);
332 cl->read_cb = NULL;
333 cl->reading_state = MEI_IDLE;
334
335out: 338out:
336 mutex_unlock(&dev->device_lock); 339 mutex_unlock(&dev->device_lock);
337 340
@@ -443,7 +446,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
443 446
444 mutex_unlock(&dev->device_lock); 447 mutex_unlock(&dev->device_lock);
445 448
446 if (device->event_cb && !cl->read_cb) 449 if (device->event_cb)
447 mei_cl_read_start(device->cl, 0, NULL); 450 mei_cl_read_start(device->cl, 0, NULL);
448 451
449 if (!device->ops || !device->ops->enable) 452 if (!device->ops || !device->ops->enable)
@@ -485,8 +488,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
485 } 488 }
486 489
487 /* Flush queues and remove any pending read */ 490 /* Flush queues and remove any pending read */
488 mei_cl_flush_queues(cl); 491 mei_cl_flush_queues(cl, NULL);
489 mei_io_cb_free(cl->read_cb);
490 492
491 device->event_cb = NULL; 493 device->event_cb = NULL;
492 494
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 624bf0182a50..98a5363e1e8a 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -458,13 +458,55 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
458} 458}
459 459
460/** 460/**
461 * mei_cl_read_cb - find this cl's callback in the read list
462 * for a specific file
463 *
464 * @cl: host client
465 * @fp: file pointer (matching cb file object), may be NULL
466 *
467 * Return: cb on success, NULL if cb is not found
468 */
469struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
470{
471 struct mei_cl_cb *cb;
472
473 list_for_each_entry(cb, &cl->rd_completed, list)
474 if (!fp || fp == cb->file_object)
475 return cb;
476
477 return NULL;
478}
479
480/**
481 * mei_cl_read_cb_flush - free client's read pending and completed cbs
482 * for a specific file
483 *
484 * @cl: host client
485 * @fp: file pointer (matching cb file object), may be NULL
486 */
487void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp)
488{
489 struct mei_cl_cb *cb, *next;
490
491 list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
492 if (!fp || fp == cb->file_object)
493 mei_io_cb_free(cb);
494
495
496 list_for_each_entry_safe(cb, next, &cl->rd_pending, list)
497 if (!fp || fp == cb->file_object)
498 mei_io_cb_free(cb);
499}
500
501/**
461 * mei_cl_flush_queues - flushes queue lists belonging to cl. 502 * mei_cl_flush_queues - flushes queue lists belonging to cl.
462 * 503 *
463 * @cl: host client 504 * @cl: host client
505 * @fp: file pointer (matching cb file object), may be NULL
464 * 506 *
465 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL. 507 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
466 */ 508 */
467int mei_cl_flush_queues(struct mei_cl *cl) 509int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
468{ 510{
469 struct mei_device *dev; 511 struct mei_device *dev;
470 512
@@ -474,13 +516,15 @@ int mei_cl_flush_queues(struct mei_cl *cl)
474 dev = cl->dev; 516 dev = cl->dev;
475 517
476 cl_dbg(dev, cl, "remove list entry belonging to cl\n"); 518 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
477 mei_io_list_flush(&cl->dev->read_list, cl);
478 mei_io_list_free(&cl->dev->write_list, cl); 519 mei_io_list_free(&cl->dev->write_list, cl);
479 mei_io_list_free(&cl->dev->write_waiting_list, cl); 520 mei_io_list_free(&cl->dev->write_waiting_list, cl);
480 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 521 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
481 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 522 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
482 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); 523 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
483 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); 524 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
525
526 mei_cl_read_cb_flush(cl, fp);
527
484 return 0; 528 return 0;
485} 529}
486 530
@@ -497,9 +541,10 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
497 init_waitqueue_head(&cl->wait); 541 init_waitqueue_head(&cl->wait);
498 init_waitqueue_head(&cl->rx_wait); 542 init_waitqueue_head(&cl->rx_wait);
499 init_waitqueue_head(&cl->tx_wait); 543 init_waitqueue_head(&cl->tx_wait);
544 INIT_LIST_HEAD(&cl->rd_completed);
545 INIT_LIST_HEAD(&cl->rd_pending);
500 INIT_LIST_HEAD(&cl->link); 546 INIT_LIST_HEAD(&cl->link);
501 INIT_LIST_HEAD(&cl->device_link); 547 INIT_LIST_HEAD(&cl->device_link);
502 cl->reading_state = MEI_IDLE;
503 cl->writing_state = MEI_IDLE; 548 cl->writing_state = MEI_IDLE;
504 cl->dev = dev; 549 cl->dev = dev;
505} 550}
@@ -524,24 +569,6 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
524} 569}
525 570
526/** 571/**
527 * mei_cl_find_read_cb - find this cl's callback in the read list
528 *
529 * @cl: host client
530 *
531 * Return: cb on success, NULL on error
532 */
533struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
534{
535 struct mei_device *dev = cl->dev;
536 struct mei_cl_cb *cb;
537
538 list_for_each_entry(cb, &dev->read_list.list, list)
539 if (mei_cl_cmp_id(cl, cb->cl))
540 return cb;
541 return NULL;
542}
543
544/**
545 * mei_cl_link - allocate host id in the host map 572 * mei_cl_link - allocate host id in the host map
546 * 573 *
547 * @cl: host client 574 * @cl: host client
@@ -1006,10 +1033,10 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
1006 if (!mei_cl_is_connected(cl)) 1033 if (!mei_cl_is_connected(cl))
1007 return -ENODEV; 1034 return -ENODEV;
1008 1035
1009 if (cl->read_cb) { 1036 /* HW currently supports only one pending read */
1010 cl_dbg(dev, cl, "read is pending.\n"); 1037 if (!list_empty(&cl->rd_pending))
1011 return -EBUSY; 1038 return -EBUSY;
1012 } 1039
1013 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id); 1040 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
1014 if (!me_cl) { 1041 if (!me_cl) {
1015 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id); 1042 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
@@ -1036,13 +1063,11 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
1036 if (rets < 0) 1063 if (rets < 0)
1037 goto out; 1064 goto out;
1038 1065
1039 list_add_tail(&cb->list, &dev->read_list.list); 1066 list_add_tail(&cb->list, &cl->rd_pending);
1040 } else { 1067 } else {
1041 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 1068 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
1042 } 1069 }
1043 1070
1044 cl->read_cb = cb;
1045
1046out: 1071out:
1047 cl_dbg(dev, cl, "rpm: autosuspend\n"); 1072 cl_dbg(dev, cl, "rpm: autosuspend\n");
1048 pm_runtime_mark_last_busy(dev->dev); 1073 pm_runtime_mark_last_busy(dev->dev);
@@ -1268,9 +1293,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
1268 if (waitqueue_active(&cl->tx_wait)) 1293 if (waitqueue_active(&cl->tx_wait))
1269 wake_up_interruptible(&cl->tx_wait); 1294 wake_up_interruptible(&cl->tx_wait);
1270 1295
1271 } else if (cb->fop_type == MEI_FOP_READ && 1296 } else if (cb->fop_type == MEI_FOP_READ) {
1272 MEI_READING == cl->reading_state) { 1297 list_add_tail(&cb->list, &cl->rd_completed);
1273 cl->reading_state = MEI_READ_COMPLETE;
1274 if (waitqueue_active(&cl->rx_wait)) 1298 if (waitqueue_active(&cl->rx_wait))
1275 wake_up_interruptible(&cl->rx_wait); 1299 wake_up_interruptible(&cl->rx_wait);
1276 else 1300 else
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index c3d0e200a642..eb02f34b2fe0 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -77,11 +77,12 @@ int mei_cl_unlink(struct mei_cl *cl);
77 77
78struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id); 78struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id);
79 79
80int mei_cl_flush_queues(struct mei_cl *cl); 80struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl,
81struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl); 81 const struct file *fp);
82 82void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp);
83struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, 83struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
84 enum mei_cb_file_ops type, struct file *fp); 84 enum mei_cb_file_ops type, struct file *fp);
85int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp);
85 86
86int mei_cl_flow_ctrl_creds(struct mei_cl *cl); 87int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
87 88
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 50fc6635fab1..d9cd7e6ee484 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -117,7 +117,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
117 pos += scnprintf(buf + pos, bufsz - pos, 117 pos += scnprintf(buf + pos, bufsz - pos,
118 "%2d|%2d|%4d|%5d|%2d|%2d|\n", 118 "%2d|%2d|%4d|%5d|%2d|%2d|\n",
119 i, cl->me_client_id, cl->host_client_id, cl->state, 119 i, cl->me_client_id, cl->host_client_id, cl->state,
120 cl->reading_state, cl->writing_state); 120 !list_empty(&cl->rd_completed), cl->writing_state);
121 i++; 121 i++;
122 } 122 }
123out: 123out:
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 106c054f573f..4596401888e5 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -395,7 +395,6 @@ void mei_device_init(struct mei_device *dev,
395 dev->dev_state = MEI_DEV_INITIALIZING; 395 dev->dev_state = MEI_DEV_INITIALIZING;
396 dev->reset_count = 0; 396 dev->reset_count = 0;
397 397
398 mei_io_list_init(&dev->read_list);
399 mei_io_list_init(&dev->write_list); 398 mei_io_list_init(&dev->write_list);
400 mei_io_list_init(&dev->write_waiting_list); 399 mei_io_list_init(&dev->write_waiting_list);
401 mei_io_list_init(&dev->ctrl_wr_list); 400 mei_io_list_init(&dev->ctrl_wr_list);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 1e2f3c774853..3f23629759db 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -68,18 +68,6 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
68 return cl->host_client_id == mei_hdr->host_addr && 68 return cl->host_client_id == mei_hdr->host_addr &&
69 cl->me_client_id == mei_hdr->me_addr; 69 cl->me_client_id == mei_hdr->me_addr;
70} 70}
71/**
72 * mei_cl_is_reading - checks if the client is in reading state
73 *
74 * @cl: mei client
75 *
76 * Return: true if the client is reading
77 */
78static bool mei_cl_is_reading(struct mei_cl *cl)
79{
80 return cl->state == MEI_FILE_CONNECTED &&
81 cl->reading_state != MEI_READ_COMPLETE;
82}
83 71
84/** 72/**
85 * mei_irq_discard_msg - discard received message 73 * mei_irq_discard_msg - discard received message
@@ -116,24 +104,18 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
116 struct mei_cl_cb *cb; 104 struct mei_cl_cb *cb;
117 unsigned char *buffer = NULL; 105 unsigned char *buffer = NULL;
118 106
119 list_for_each_entry(cb, &dev->read_list.list, list) { 107 cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
120 if (cl == cb->cl) 108 if (!cb) {
121 break; 109 cl_err(dev, cl, "pending read cb not found\n");
122 }
123
124 if (&cb->list == &dev->read_list.list) {
125 dev_err(dev->dev, "no reader found\n");
126 goto out; 110 goto out;
127 } 111 }
128 112
129 if (!mei_cl_is_reading(cl)) { 113 if (cl->state != MEI_FILE_CONNECTED) {
130 cl_err(dev, cl, "cl is not reading state=%d reading state=%d\n", 114 cl_dbg(dev, cl, "not connected\n");
131 cl->state, cl->reading_state); 115 cb->status = -ENODEV;
132 goto out; 116 goto out;
133 } 117 }
134 118
135 cl->reading_state = MEI_READING;
136
137 if (cb->buf.size == 0 || cb->buf.data == NULL) { 119 if (cb->buf.size == 0 || cb->buf.data == NULL) {
138 cl_err(dev, cl, "response buffer is not allocated.\n"); 120 cl_err(dev, cl, "response buffer is not allocated.\n");
139 list_move_tail(&cb->list, &complete_list->list); 121 list_move_tail(&cb->list, &complete_list->list);
@@ -163,8 +145,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
163 145
164 if (mei_hdr->msg_complete) { 146 if (mei_hdr->msg_complete) {
165 cb->read_time = jiffies; 147 cb->read_time = jiffies;
166 cl_dbg(dev, cl, "completed read length = %lu\n", 148 cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
167 cb->buf_idx);
168 list_move_tail(&cb->list, &complete_list->list); 149 list_move_tail(&cb->list, &complete_list->list);
169 } 150 }
170 151
@@ -281,7 +262,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
281 return ret; 262 return ret;
282 } 263 }
283 264
284 list_move_tail(&cb->list, &dev->read_list.list); 265 list_move_tail(&cb->list, &cl->rd_pending);
285 266
286 return 0; 267 return 0;
287} 268}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index c34853be963f..d80867e0d803 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -112,14 +112,11 @@ static int mei_release(struct inode *inode, struct file *file)
112 cl_dbg(dev, cl, "disconnecting\n"); 112 cl_dbg(dev, cl, "disconnecting\n");
113 rets = mei_cl_disconnect(cl); 113 rets = mei_cl_disconnect(cl);
114 } 114 }
115 mei_cl_flush_queues(cl); 115 mei_cl_flush_queues(cl, file);
116 cl_dbg(dev, cl, "removing\n"); 116 cl_dbg(dev, cl, "removing\n");
117 117
118 mei_cl_unlink(cl); 118 mei_cl_unlink(cl);
119 119
120 mei_io_cb_free(cl->read_cb);
121 cl->read_cb = NULL;
122
123 file->private_data = NULL; 120 file->private_data = NULL;
124 121
125 kfree(cl); 122 kfree(cl);
@@ -143,8 +140,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
143 size_t length, loff_t *offset) 140 size_t length, loff_t *offset)
144{ 141{
145 struct mei_cl *cl = file->private_data; 142 struct mei_cl *cl = file->private_data;
146 struct mei_cl_cb *cb = NULL;
147 struct mei_device *dev; 143 struct mei_device *dev;
144 struct mei_cl_cb *cb = NULL;
148 int rets; 145 int rets;
149 int err; 146 int err;
150 147
@@ -171,7 +168,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
171 goto out; 168 goto out;
172 } 169 }
173 170
174 cb = cl->read_cb; 171 cb = mei_cl_read_cb(cl, file);
175 if (cb) { 172 if (cb) {
176 /* read what left */ 173 /* read what left */
177 if (cb->buf_idx > *offset) 174 if (cb->buf_idx > *offset)
@@ -196,9 +193,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
196 goto out; 193 goto out;
197 } 194 }
198 195
199 if (MEI_READ_COMPLETE != cl->reading_state && 196 if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
200 !waitqueue_active(&cl->rx_wait)) {
201
202 if (file->f_flags & O_NONBLOCK) { 197 if (file->f_flags & O_NONBLOCK) {
203 rets = -EAGAIN; 198 rets = -EAGAIN;
204 goto out; 199 goto out;
@@ -207,7 +202,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
207 mutex_unlock(&dev->device_lock); 202 mutex_unlock(&dev->device_lock);
208 203
209 if (wait_event_interruptible(cl->rx_wait, 204 if (wait_event_interruptible(cl->rx_wait,
210 MEI_READ_COMPLETE == cl->reading_state || 205 (!list_empty(&cl->rd_completed)) ||
211 mei_cl_is_transitioning(cl))) { 206 mei_cl_is_transitioning(cl))) {
212 207
213 if (signal_pending(current)) 208 if (signal_pending(current))
@@ -222,14 +217,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
222 } 217 }
223 } 218 }
224 219
225 cb = cl->read_cb; 220 cb = mei_cl_read_cb(cl, file);
226
227 if (!cb) { 221 if (!cb) {
228 rets = -ENODEV;
229 goto out;
230 }
231
232 if (cl->reading_state != MEI_READ_COMPLETE) {
233 rets = 0; 222 rets = 0;
234 goto out; 223 goto out;
235 } 224 }
@@ -266,9 +255,7 @@ copy_buffer:
266 255
267free: 256free:
268 mei_io_cb_free(cb); 257 mei_io_cb_free(cb);
269 cl->read_cb = NULL;
270 258
271 cl->reading_state = MEI_IDLE;
272out: 259out:
273 dev_dbg(dev->dev, "end mei read rets= %d\n", rets); 260 dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
274 mutex_unlock(&dev->device_lock); 261 mutex_unlock(&dev->device_lock);
@@ -335,8 +322,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
335 timeout = write_cb->read_time + 322 timeout = write_cb->read_time +
336 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); 323 mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
337 324
338 if (time_after(jiffies, timeout) || 325 if (time_after(jiffies, timeout)) {
339 cl->reading_state == MEI_READ_COMPLETE) {
340 *offset = 0; 326 *offset = 0;
341 mei_io_cb_free(write_cb); 327 mei_io_cb_free(write_cb);
342 write_cb = NULL; 328 write_cb = NULL;
@@ -344,19 +330,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
344 } 330 }
345 } 331 }
346 332
347 /* free entry used in read */ 333 *offset = 0;
348 if (cl->reading_state == MEI_READ_COMPLETE) {
349 *offset = 0;
350 write_cb = mei_cl_find_read_cb(cl);
351 if (write_cb) {
352 mei_io_cb_free(write_cb);
353 write_cb = NULL;
354 cl->read_cb = NULL;
355 cl->reading_state = MEI_IDLE;
356 }
357 } else if (cl->reading_state == MEI_IDLE)
358 *offset = 0;
359
360 write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file); 334 write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
361 if (!write_cb) { 335 if (!write_cb) {
362 rets = -ENOMEM; 336 rets = -ENOMEM;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 1a0f6e9588b6..f066ecd71939 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -231,9 +231,9 @@ struct mei_cl_cb {
231 * @me_client_id: me/fw id 231 * @me_client_id: me/fw id
232 * @mei_flow_ctrl_creds: transmit flow credentials 232 * @mei_flow_ctrl_creds: transmit flow credentials
233 * @timer_count: watchdog timer for operation completion 233 * @timer_count: watchdog timer for operation completion
234 * @reading_state: state of the rx
235 * @writing_state: state of the tx 234 * @writing_state: state of the tx
236 * @read_cb: current pending reading callback 235 * @rd_pending: pending read credits
236 * @rd_completed: completed read
237 * 237 *
238 * @device: device on the mei client bus 238 * @device: device on the mei client bus
239 * @device_link: link to bus clients 239 * @device_link: link to bus clients
@@ -251,9 +251,9 @@ struct mei_cl {
251 u8 me_client_id; 251 u8 me_client_id;
252 u8 mei_flow_ctrl_creds; 252 u8 mei_flow_ctrl_creds;
253 u8 timer_count; 253 u8 timer_count;
254 enum mei_file_transaction_states reading_state;
255 enum mei_file_transaction_states writing_state; 254 enum mei_file_transaction_states writing_state;
256 struct mei_cl_cb *read_cb; 255 struct list_head rd_pending;
256 struct list_head rd_completed;
257 257
258 /* MEI CL bus data */ 258 /* MEI CL bus data */
259 struct mei_cl_device *device; 259 struct mei_cl_device *device;
@@ -425,7 +425,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
425 * @cdev : character device 425 * @cdev : character device
426 * @minor : minor number allocated for device 426 * @minor : minor number allocated for device
427 * 427 *
428 * @read_list : read completion list
429 * @write_list : write pending list 428 * @write_list : write pending list
430 * @write_waiting_list : write completion list 429 * @write_waiting_list : write completion list
431 * @ctrl_wr_list : pending control write list 430 * @ctrl_wr_list : pending control write list
@@ -501,7 +500,6 @@ struct mei_device {
501 struct cdev cdev; 500 struct cdev cdev;
502 int minor; 501 int minor;
503 502
504 struct mei_cl_cb read_list;
505 struct mei_cl_cb write_list; 503 struct mei_cl_cb write_list;
506 struct mei_cl_cb write_waiting_list; 504 struct mei_cl_cb write_waiting_list;
507 struct mei_cl_cb ctrl_wr_list; 505 struct mei_cl_cb ctrl_wr_list;