mei: iamthif: use regular client read functions
[linux-2.6-block.git] / drivers / misc / mei / client.c
CommitLineData
ab841160
OW
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
733ba91c 4 * Copyright (c) 2003-2012, Intel Corporation.
ab841160
OW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
ab841160 17#include <linux/sched.h>
9ca9050b
TW
18#include <linux/wait.h>
19#include <linux/delay.h>
1f180359 20#include <linux/slab.h>
04bb139a 21#include <linux/pm_runtime.h>
ab841160 22
4f3afe1d 23#include <linux/mei.h>
47a73801
TW
24
25#include "mei_dev.h"
0edb23fc 26#include "hbm.h"
90e0b5f1
TW
27#include "client.h"
28
79563db9
TW
29/**
30 * mei_me_cl_init - initialize me client
31 *
32 * @me_cl: me client
33 */
34void mei_me_cl_init(struct mei_me_client *me_cl)
35{
36 INIT_LIST_HEAD(&me_cl->list);
37 kref_init(&me_cl->refcnt);
38}
39
40/**
41 * mei_me_cl_get - increases me client refcount
42 *
43 * @me_cl: me client
44 *
45 * Locking: called under "dev->device_lock" lock
46 *
47 * Return: me client or NULL
48 */
49struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)
50{
b7d88514
TW
51 if (me_cl && kref_get_unless_zero(&me_cl->refcnt))
52 return me_cl;
79563db9 53
b7d88514 54 return NULL;
79563db9
TW
55}
56
57/**
b7d88514 58 * mei_me_cl_release - free me client
79563db9
TW
59 *
60 * Locking: called under "dev->device_lock" lock
61 *
62 * @ref: me_client refcount
63 */
64static void mei_me_cl_release(struct kref *ref)
65{
66 struct mei_me_client *me_cl =
67 container_of(ref, struct mei_me_client, refcnt);
b7d88514 68
79563db9
TW
69 kfree(me_cl);
70}
b7d88514 71
79563db9
TW
72/**
73 * mei_me_cl_put - decrease me client refcount and free client if necessary
74 *
75 * Locking: called under "dev->device_lock" lock
76 *
77 * @me_cl: me client
78 */
79void mei_me_cl_put(struct mei_me_client *me_cl)
80{
81 if (me_cl)
82 kref_put(&me_cl->refcnt, mei_me_cl_release);
83}
84
90e0b5f1 85/**
b7d88514
TW
86 * __mei_me_cl_del - delete me client form the list and decrease
87 * reference counter
88 *
89 * @dev: mei device
90 * @me_cl: me client
91 *
92 * Locking: dev->me_clients_rwsem
93 */
94static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
95{
96 if (!me_cl)
97 return;
98
99 list_del(&me_cl->list);
100 mei_me_cl_put(me_cl);
101}
102
103/**
104 * mei_me_cl_add - add me client to the list
105 *
106 * @dev: mei device
107 * @me_cl: me client
108 */
109void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
110{
111 down_write(&dev->me_clients_rwsem);
112 list_add(&me_cl->list, &dev->me_clients);
113 up_write(&dev->me_clients_rwsem);
114}
115
116/**
117 * __mei_me_cl_by_uuid - locate me client by uuid
79563db9 118 * increases ref count
90e0b5f1
TW
119 *
120 * @dev: mei device
a8605ea2 121 * @uuid: me client uuid
a27a76d3 122 *
a8605ea2 123 * Return: me client or NULL if not found
b7d88514
TW
124 *
125 * Locking: dev->me_clients_rwsem
90e0b5f1 126 */
b7d88514 127static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
d320832f 128 const uuid_le *uuid)
90e0b5f1 129{
5ca2d388 130 struct mei_me_client *me_cl;
b7d88514 131 const uuid_le *pn;
90e0b5f1 132
b7d88514
TW
133 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
134
135 list_for_each_entry(me_cl, &dev->me_clients, list) {
136 pn = &me_cl->props.protocol_name;
137 if (uuid_le_cmp(*uuid, *pn) == 0)
79563db9 138 return mei_me_cl_get(me_cl);
b7d88514 139 }
90e0b5f1 140
d320832f 141 return NULL;
90e0b5f1
TW
142}
143
b7d88514
TW
144/**
145 * mei_me_cl_by_uuid - locate me client by uuid
146 * increases ref count
147 *
148 * @dev: mei device
149 * @uuid: me client uuid
150 *
151 * Return: me client or NULL if not found
152 *
153 * Locking: dev->me_clients_rwsem
154 */
155struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
156 const uuid_le *uuid)
157{
158 struct mei_me_client *me_cl;
159
160 down_read(&dev->me_clients_rwsem);
161 me_cl = __mei_me_cl_by_uuid(dev, uuid);
162 up_read(&dev->me_clients_rwsem);
163
164 return me_cl;
165}
166
90e0b5f1 167/**
a8605ea2 168 * mei_me_cl_by_id - locate me client by client id
79563db9 169 * increases ref count
90e0b5f1
TW
170 *
171 * @dev: the device structure
172 * @client_id: me client id
173 *
a8605ea2 174 * Return: me client or NULL if not found
b7d88514
TW
175 *
176 * Locking: dev->me_clients_rwsem
90e0b5f1 177 */
d320832f 178struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
90e0b5f1 179{
a27a76d3 180
b7d88514
TW
181 struct mei_me_client *__me_cl, *me_cl = NULL;
182
183 down_read(&dev->me_clients_rwsem);
184 list_for_each_entry(__me_cl, &dev->me_clients, list) {
185 if (__me_cl->client_id == client_id) {
186 me_cl = mei_me_cl_get(__me_cl);
187 break;
188 }
189 }
190 up_read(&dev->me_clients_rwsem);
191
192 return me_cl;
193}
194
195/**
196 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
197 * increases ref count
198 *
199 * @dev: the device structure
200 * @uuid: me client uuid
201 * @client_id: me client id
202 *
203 * Return: me client or null if not found
204 *
205 * Locking: dev->me_clients_rwsem
206 */
207static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
208 const uuid_le *uuid, u8 client_id)
209{
5ca2d388 210 struct mei_me_client *me_cl;
b7d88514
TW
211 const uuid_le *pn;
212
213 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
90e0b5f1 214
b7d88514
TW
215 list_for_each_entry(me_cl, &dev->me_clients, list) {
216 pn = &me_cl->props.protocol_name;
217 if (uuid_le_cmp(*uuid, *pn) == 0 &&
218 me_cl->client_id == client_id)
79563db9 219 return mei_me_cl_get(me_cl);
b7d88514 220 }
79563db9 221
d320832f 222 return NULL;
90e0b5f1 223}
ab841160 224
b7d88514 225
a8605ea2
AU
226/**
227 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
79563db9 228 * increases ref count
a8605ea2
AU
229 *
230 * @dev: the device structure
231 * @uuid: me client uuid
232 * @client_id: me client id
233 *
b7d88514 234 * Return: me client or null if not found
a8605ea2 235 */
d880f329
TW
236struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
237 const uuid_le *uuid, u8 client_id)
238{
239 struct mei_me_client *me_cl;
240
b7d88514
TW
241 down_read(&dev->me_clients_rwsem);
242 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);
243 up_read(&dev->me_clients_rwsem);
79563db9 244
b7d88514 245 return me_cl;
d880f329
TW
246}
247
25ca6472 248/**
79563db9 249 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid
25ca6472
TW
250 *
251 * @dev: the device structure
252 * @uuid: me client uuid
79563db9
TW
253 *
254 * Locking: called under "dev->device_lock" lock
25ca6472 255 */
79563db9 256void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
25ca6472 257{
b7d88514 258 struct mei_me_client *me_cl;
25ca6472 259
79563db9 260 dev_dbg(dev->dev, "remove %pUl\n", uuid);
b7d88514
TW
261
262 down_write(&dev->me_clients_rwsem);
263 me_cl = __mei_me_cl_by_uuid(dev, uuid);
264 __mei_me_cl_del(dev, me_cl);
265 up_write(&dev->me_clients_rwsem);
79563db9
TW
266}
267
268/**
269 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id
270 *
271 * @dev: the device structure
272 * @uuid: me client uuid
273 * @id: me client id
274 *
275 * Locking: called under "dev->device_lock" lock
276 */
277void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
278{
b7d88514 279 struct mei_me_client *me_cl;
79563db9
TW
280
281 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);
b7d88514
TW
282
283 down_write(&dev->me_clients_rwsem);
284 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
285 __mei_me_cl_del(dev, me_cl);
286 up_write(&dev->me_clients_rwsem);
25ca6472
TW
287}
288
79563db9
TW
289/**
290 * mei_me_cl_rm_all - remove all me clients
291 *
292 * @dev: the device structure
293 *
294 * Locking: called under "dev->device_lock" lock
295 */
296void mei_me_cl_rm_all(struct mei_device *dev)
297{
298 struct mei_me_client *me_cl, *next;
299
b7d88514 300 down_write(&dev->me_clients_rwsem);
79563db9 301 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
b7d88514
TW
302 __mei_me_cl_del(dev, me_cl);
303 up_write(&dev->me_clients_rwsem);
79563db9
TW
304}
305
9ca9050b 306/**
cc99ecfd 307 * mei_cl_cmp_id - tells if the clients are the same
9ca9050b 308 *
cc99ecfd
TW
309 * @cl1: host client 1
310 * @cl2: host client 2
311 *
a8605ea2 312 * Return: true - if the clients has same host and me ids
cc99ecfd
TW
313 * false - otherwise
314 */
315static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
316 const struct mei_cl *cl2)
317{
318 return cl1 && cl2 &&
319 (cl1->host_client_id == cl2->host_client_id) &&
320 (cl1->me_client_id == cl2->me_client_id);
321}
322
323/**
3908be6f 324 * __mei_io_list_flush - removes and frees cbs belonging to cl.
cc99ecfd
TW
325 *
326 * @list: an instance of our list structure
327 * @cl: host client, can be NULL for flushing the whole list
328 * @free: whether to free the cbs
9ca9050b 329 */
cc99ecfd
TW
330static void __mei_io_list_flush(struct mei_cl_cb *list,
331 struct mei_cl *cl, bool free)
9ca9050b
TW
332{
333 struct mei_cl_cb *cb;
334 struct mei_cl_cb *next;
335
cc99ecfd 336 /* enable removing everything if no cl is specified */
9ca9050b 337 list_for_each_entry_safe(cb, next, &list->list, list) {
140c7553 338 if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
9ca9050b 339 list_del(&cb->list);
cc99ecfd
TW
340 if (free)
341 mei_io_cb_free(cb);
342 }
9ca9050b
TW
343 }
344}
345
cc99ecfd
TW
346/**
347 * mei_io_list_flush - removes list entry belonging to cl.
348 *
349 * @list: An instance of our list structure
350 * @cl: host client
351 */
5456796b 352void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
cc99ecfd
TW
353{
354 __mei_io_list_flush(list, cl, false);
355}
356
357
358/**
359 * mei_io_list_free - removes cb belonging to cl and free them
360 *
361 * @list: An instance of our list structure
362 * @cl: host client
363 */
364static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
365{
366 __mei_io_list_flush(list, cl, true);
367}
368
601a1efa
TW
369/**
370 * mei_io_cb_free - free mei_cb_private related memory
371 *
372 * @cb: mei callback struct
373 */
374void mei_io_cb_free(struct mei_cl_cb *cb)
375{
376 if (cb == NULL)
377 return;
378
379 kfree(cb->request_buffer.data);
380 kfree(cb->response_buffer.data);
381 kfree(cb);
382}
9ca9050b 383
664df38b
TW
384/**
385 * mei_io_cb_init - allocate and initialize io callback
386 *
a8605ea2 387 * @cl: mei client
393b148f 388 * @fp: pointer to file structure
664df38b 389 *
a8605ea2 390 * Return: mei_cl_cb pointer or NULL;
664df38b
TW
391 */
392struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
393{
394 struct mei_cl_cb *cb;
395
396 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
397 if (!cb)
398 return NULL;
399
400 mei_io_list_init(cb);
401
402 cb->file_object = fp;
db3ed431 403 cb->cl = cl;
664df38b
TW
404 cb->buf_idx = 0;
405 return cb;
406}
407
664df38b
TW
408/**
409 * mei_io_cb_alloc_req_buf - allocate request buffer
410 *
393b148f
MI
411 * @cb: io callback structure
412 * @length: size of the buffer
664df38b 413 *
a8605ea2 414 * Return: 0 on success
664df38b
TW
415 * -EINVAL if cb is NULL
416 * -ENOMEM if allocation failed
417 */
418int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
419{
420 if (!cb)
421 return -EINVAL;
422
423 if (length == 0)
424 return 0;
425
426 cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
427 if (!cb->request_buffer.data)
428 return -ENOMEM;
429 cb->request_buffer.size = length;
430 return 0;
431}
432/**
83ce0741 433 * mei_io_cb_alloc_resp_buf - allocate response buffer
664df38b 434 *
393b148f
MI
435 * @cb: io callback structure
436 * @length: size of the buffer
664df38b 437 *
a8605ea2 438 * Return: 0 on success
664df38b
TW
439 * -EINVAL if cb is NULL
440 * -ENOMEM if allocation failed
441 */
442int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
443{
444 if (!cb)
445 return -EINVAL;
446
447 if (length == 0)
448 return 0;
449
450 cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
451 if (!cb->response_buffer.data)
452 return -ENOMEM;
453 cb->response_buffer.size = length;
454 return 0;
455}
456
601a1efa 457
9ca9050b
TW
458
459/**
460 * mei_cl_flush_queues - flushes queue lists belonging to cl.
461 *
9ca9050b 462 * @cl: host client
ce23139c
AU
463 *
464 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
9ca9050b
TW
465 */
466int mei_cl_flush_queues(struct mei_cl *cl)
467{
c0abffbd
AU
468 struct mei_device *dev;
469
90e0b5f1 470 if (WARN_ON(!cl || !cl->dev))
9ca9050b
TW
471 return -EINVAL;
472
c0abffbd
AU
473 dev = cl->dev;
474
475 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
9ca9050b 476 mei_io_list_flush(&cl->dev->read_list, cl);
cc99ecfd
TW
477 mei_io_list_free(&cl->dev->write_list, cl);
478 mei_io_list_free(&cl->dev->write_waiting_list, cl);
9ca9050b
TW
479 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
480 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
481 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
482 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
483 return 0;
484}
485
ab841160 486
9ca9050b 487/**
83ce0741 488 * mei_cl_init - initializes cl.
9ca9050b
TW
489 *
490 * @cl: host client to be initialized
491 * @dev: mei device
492 */
493void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
494{
495 memset(cl, 0, sizeof(struct mei_cl));
496 init_waitqueue_head(&cl->wait);
497 init_waitqueue_head(&cl->rx_wait);
498 init_waitqueue_head(&cl->tx_wait);
499 INIT_LIST_HEAD(&cl->link);
a7b71bc0 500 INIT_LIST_HEAD(&cl->device_link);
9ca9050b
TW
501 cl->reading_state = MEI_IDLE;
502 cl->writing_state = MEI_IDLE;
503 cl->dev = dev;
504}
505
506/**
507 * mei_cl_allocate - allocates cl structure and sets it up.
508 *
509 * @dev: mei device
a8605ea2 510 * Return: The allocated file or NULL on failure
9ca9050b
TW
511 */
512struct mei_cl *mei_cl_allocate(struct mei_device *dev)
513{
514 struct mei_cl *cl;
515
516 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
517 if (!cl)
518 return NULL;
519
520 mei_cl_init(cl, dev);
521
522 return cl;
523}
524
90e0b5f1
TW
525/**
526 * mei_cl_find_read_cb - find this cl's callback in the read list
527 *
393b148f
MI
528 * @cl: host client
529 *
a8605ea2 530 * Return: cb on success, NULL on error
90e0b5f1
TW
531 */
532struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
533{
534 struct mei_device *dev = cl->dev;
31f88f57 535 struct mei_cl_cb *cb;
90e0b5f1 536
31f88f57 537 list_for_each_entry(cb, &dev->read_list.list, list)
90e0b5f1
TW
538 if (mei_cl_cmp_id(cl, cb->cl))
539 return cb;
540 return NULL;
541}
542
3908be6f
AU
543/**
544 * mei_cl_link - allocate host id in the host map
9ca9050b 545 *
3908be6f
AU
546 * @cl: host client
547 * @id: fixed host id or -1 for generic one
393b148f 548 *
a8605ea2 549 * Return: 0 on success
9ca9050b
TW
550 * -EINVAL on incorrect values
551 * -ENONET if client not found
552 */
781d0d89 553int mei_cl_link(struct mei_cl *cl, int id)
9ca9050b 554{
90e0b5f1 555 struct mei_device *dev;
22f96a0e 556 long open_handle_count;
9ca9050b 557
781d0d89 558 if (WARN_ON(!cl || !cl->dev))
9ca9050b
TW
559 return -EINVAL;
560
90e0b5f1
TW
561 dev = cl->dev;
562
83ce0741 563 /* If Id is not assigned get one*/
781d0d89
TW
564 if (id == MEI_HOST_CLIENT_ID_ANY)
565 id = find_first_zero_bit(dev->host_clients_map,
566 MEI_CLIENTS_MAX);
9ca9050b 567
781d0d89 568 if (id >= MEI_CLIENTS_MAX) {
2bf94cab 569 dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX);
e036cc57
TW
570 return -EMFILE;
571 }
572
22f96a0e
TW
573 open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
574 if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
2bf94cab 575 dev_err(dev->dev, "open_handle_count exceeded %d",
e036cc57
TW
576 MEI_MAX_OPEN_HANDLE_COUNT);
577 return -EMFILE;
9ca9050b
TW
578 }
579
781d0d89
TW
580 dev->open_handle_count++;
581
582 cl->host_client_id = id;
583 list_add_tail(&cl->link, &dev->file_list);
584
585 set_bit(id, dev->host_clients_map);
586
587 cl->state = MEI_FILE_INITIALIZING;
588
c0abffbd 589 cl_dbg(dev, cl, "link cl\n");
781d0d89 590 return 0;
9ca9050b 591}
781d0d89 592
9ca9050b 593/**
90e0b5f1 594 * mei_cl_unlink - remove me_cl from the list
9ca9050b 595 *
393b148f 596 * @cl: host client
ce23139c
AU
597 *
598 * Return: always 0
9ca9050b 599 */
90e0b5f1 600int mei_cl_unlink(struct mei_cl *cl)
9ca9050b 601{
90e0b5f1 602 struct mei_device *dev;
90e0b5f1 603
781d0d89
TW
604 /* don't shout on error exit path */
605 if (!cl)
606 return 0;
607
8e9a4a9a
TW
608 /* wd and amthif might not be initialized */
609 if (!cl->dev)
610 return 0;
90e0b5f1
TW
611
612 dev = cl->dev;
613
a14c44d8
TW
614 cl_dbg(dev, cl, "unlink client");
615
22f96a0e
TW
616 if (dev->open_handle_count > 0)
617 dev->open_handle_count--;
618
619 /* never clear the 0 bit */
620 if (cl->host_client_id)
621 clear_bit(cl->host_client_id, dev->host_clients_map);
622
623 list_del_init(&cl->link);
624
625 cl->state = MEI_FILE_INITIALIZING;
626
90e0b5f1 627 return 0;
9ca9050b
TW
628}
629
630
631void mei_host_client_init(struct work_struct *work)
632{
b7d88514
TW
633 struct mei_device *dev =
634 container_of(work, struct mei_device, init_work);
5ca2d388 635 struct mei_me_client *me_cl;
9ca9050b
TW
636
637 mutex_lock(&dev->device_lock);
638
9ca9050b 639
b7d88514
TW
640 me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
641 if (me_cl)
642 mei_amthif_host_init(dev);
643
644 me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
645 if (me_cl)
646 mei_wd_host_init(dev);
647
648 me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
649 if (me_cl)
650 mei_nfc_host_init(dev);
59fcd7c6 651
9ca9050b
TW
652
653 dev->dev_state = MEI_DEV_ENABLED;
6adb8efb 654 dev->reset_count = 0;
9ca9050b 655 mutex_unlock(&dev->device_lock);
04bb139a 656
2bf94cab
TW
657 pm_runtime_mark_last_busy(dev->dev);
658 dev_dbg(dev->dev, "rpm: autosuspend\n");
659 pm_runtime_autosuspend(dev->dev);
9ca9050b
TW
660}
661
6aae48ff 662/**
a8605ea2 663 * mei_hbuf_acquire - try to acquire host buffer
6aae48ff
TW
664 *
665 * @dev: the device structure
a8605ea2 666 * Return: true if host buffer was acquired
6aae48ff
TW
667 */
668bool mei_hbuf_acquire(struct mei_device *dev)
669{
04bb139a
TW
670 if (mei_pg_state(dev) == MEI_PG_ON ||
671 dev->pg_event == MEI_PG_EVENT_WAIT) {
2bf94cab 672 dev_dbg(dev->dev, "device is in pg\n");
04bb139a
TW
673 return false;
674 }
675
6aae48ff 676 if (!dev->hbuf_is_ready) {
2bf94cab 677 dev_dbg(dev->dev, "hbuf is not ready\n");
6aae48ff
TW
678 return false;
679 }
680
681 dev->hbuf_is_ready = false;
682
683 return true;
684}
9ca9050b
TW
685
686/**
83ce0741 687 * mei_cl_disconnect - disconnect host client from the me one
9ca9050b 688 *
90e0b5f1 689 * @cl: host client
9ca9050b
TW
690 *
691 * Locking: called under "dev->device_lock" lock
692 *
a8605ea2 693 * Return: 0 on success, <0 on failure.
9ca9050b 694 */
90e0b5f1 695int mei_cl_disconnect(struct mei_cl *cl)
9ca9050b 696{
90e0b5f1 697 struct mei_device *dev;
9ca9050b 698 struct mei_cl_cb *cb;
fe2f17eb 699 int rets;
9ca9050b 700
90e0b5f1 701 if (WARN_ON(!cl || !cl->dev))
9ca9050b
TW
702 return -ENODEV;
703
90e0b5f1
TW
704 dev = cl->dev;
705
c0abffbd
AU
706 cl_dbg(dev, cl, "disconnecting");
707
9ca9050b
TW
708 if (cl->state != MEI_FILE_DISCONNECTING)
709 return 0;
710
2bf94cab 711 rets = pm_runtime_get(dev->dev);
04bb139a 712 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 713 pm_runtime_put_noidle(dev->dev);
04bb139a
TW
714 cl_err(dev, cl, "rpm: get failed %d\n", rets);
715 return rets;
716 }
717
9ca9050b 718 cb = mei_io_cb_init(cl, NULL);
04bb139a
TW
719 if (!cb) {
720 rets = -ENOMEM;
721 goto free;
722 }
9ca9050b 723
5a8373fb
TW
724 cb->fop_type = MEI_FOP_DISCONNECT;
725
6aae48ff 726 if (mei_hbuf_acquire(dev)) {
9ca9050b
TW
727 if (mei_hbm_cl_disconnect_req(dev, cl)) {
728 rets = -ENODEV;
c0abffbd 729 cl_err(dev, cl, "failed to disconnect.\n");
9ca9050b
TW
730 goto free;
731 }
22b987a3 732 cl->timer_count = MEI_CONNECT_TIMEOUT;
9ca9050b
TW
733 mdelay(10); /* Wait for hardware disconnection ready */
734 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
735 } else {
c0abffbd 736 cl_dbg(dev, cl, "add disconnect cb to control write list\n");
9ca9050b
TW
737 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
738
739 }
740 mutex_unlock(&dev->device_lock);
741
12f45ed4 742 wait_event_timeout(cl->wait,
9ca9050b
TW
743 MEI_FILE_DISCONNECTED == cl->state,
744 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
745
746 mutex_lock(&dev->device_lock);
fe2f17eb 747
9ca9050b
TW
748 if (MEI_FILE_DISCONNECTED == cl->state) {
749 rets = 0;
c0abffbd 750 cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
9ca9050b 751 } else {
fe2f17eb
AU
752 cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");
753 rets = -ETIME;
9ca9050b
TW
754 }
755
756 mei_io_list_flush(&dev->ctrl_rd_list, cl);
757 mei_io_list_flush(&dev->ctrl_wr_list, cl);
758free:
04bb139a 759 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
760 pm_runtime_mark_last_busy(dev->dev);
761 pm_runtime_put_autosuspend(dev->dev);
04bb139a 762
9ca9050b
TW
763 mei_io_cb_free(cb);
764 return rets;
765}
766
767
768/**
90e0b5f1
TW
769 * mei_cl_is_other_connecting - checks if other
770 * client with the same me client id is connecting
9ca9050b 771 *
9ca9050b
TW
772 * @cl: private data of the file object
773 *
a8605ea2 774 * Return: true if other client is connected, false - otherwise.
9ca9050b 775 */
90e0b5f1 776bool mei_cl_is_other_connecting(struct mei_cl *cl)
9ca9050b 777{
90e0b5f1 778 struct mei_device *dev;
31f88f57 779 struct mei_cl *ocl; /* the other client */
9ca9050b 780
90e0b5f1
TW
781 if (WARN_ON(!cl || !cl->dev))
782 return false;
783
784 dev = cl->dev;
785
31f88f57
TW
786 list_for_each_entry(ocl, &dev->file_list, link) {
787 if (ocl->state == MEI_FILE_CONNECTING &&
788 ocl != cl &&
789 cl->me_client_id == ocl->me_client_id)
90e0b5f1 790 return true;
9ca9050b
TW
791
792 }
90e0b5f1
TW
793
794 return false;
9ca9050b
TW
795}
796
9f81abda 797/**
83ce0741 798 * mei_cl_connect - connect host client to the me one
9f81abda
TW
799 *
800 * @cl: host client
a8605ea2 801 * @file: pointer to file structure
9f81abda
TW
802 *
803 * Locking: called under "dev->device_lock" lock
804 *
a8605ea2 805 * Return: 0 on success, <0 on failure.
9f81abda
TW
806 */
807int mei_cl_connect(struct mei_cl *cl, struct file *file)
808{
809 struct mei_device *dev;
810 struct mei_cl_cb *cb;
9f81abda
TW
811 int rets;
812
813 if (WARN_ON(!cl || !cl->dev))
814 return -ENODEV;
815
816 dev = cl->dev;
817
2bf94cab 818 rets = pm_runtime_get(dev->dev);
04bb139a 819 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 820 pm_runtime_put_noidle(dev->dev);
04bb139a
TW
821 cl_err(dev, cl, "rpm: get failed %d\n", rets);
822 return rets;
823 }
824
9f81abda
TW
825 cb = mei_io_cb_init(cl, file);
826 if (!cb) {
827 rets = -ENOMEM;
828 goto out;
829 }
830
02a7eecc 831 cb->fop_type = MEI_FOP_CONNECT;
9f81abda 832
6aae48ff
TW
833 /* run hbuf acquire last so we don't have to undo */
834 if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
e4d8270e 835 cl->state = MEI_FILE_CONNECTING;
9f81abda
TW
836 if (mei_hbm_cl_connect_req(dev, cl)) {
837 rets = -ENODEV;
838 goto out;
839 }
840 cl->timer_count = MEI_CONNECT_TIMEOUT;
841 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
842 } else {
73ab4232 843 cl->state = MEI_FILE_INITIALIZING;
9f81abda
TW
844 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
845 }
846
847 mutex_unlock(&dev->device_lock);
12f45ed4 848 wait_event_timeout(cl->wait,
285e2996
AU
849 (cl->state == MEI_FILE_CONNECTED ||
850 cl->state == MEI_FILE_DISCONNECTED),
851 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
9f81abda
TW
852 mutex_lock(&dev->device_lock);
853
854 if (cl->state != MEI_FILE_CONNECTED) {
3e37ebb7 855 cl->state = MEI_FILE_DISCONNECTED;
285e2996
AU
856 /* something went really wrong */
857 if (!cl->status)
858 cl->status = -EFAULT;
9f81abda
TW
859
860 mei_io_list_flush(&dev->ctrl_rd_list, cl);
861 mei_io_list_flush(&dev->ctrl_wr_list, cl);
9f81abda
TW
862 }
863
864 rets = cl->status;
865
866out:
04bb139a 867 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
868 pm_runtime_mark_last_busy(dev->dev);
869 pm_runtime_put_autosuspend(dev->dev);
04bb139a 870
9f81abda
TW
871 mei_io_cb_free(cb);
872 return rets;
873}
874
9ca9050b 875/**
90e0b5f1 876 * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
9ca9050b 877 *
9ca9050b
TW
878 * @cl: private data of the file object
879 *
a8605ea2 880 * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
9ca9050b
TW
881 * -ENOENT if mei_cl is not present
882 * -EINVAL if single_recv_buf == 0
883 */
90e0b5f1 884int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
9ca9050b 885{
90e0b5f1 886 struct mei_device *dev;
12d00665 887 struct mei_me_client *me_cl;
79563db9 888 int rets = 0;
9ca9050b 889
90e0b5f1
TW
890 if (WARN_ON(!cl || !cl->dev))
891 return -EINVAL;
892
893 dev = cl->dev;
894
9ca9050b
TW
895 if (cl->mei_flow_ctrl_creds > 0)
896 return 1;
897
2e5df413 898 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
d320832f 899 if (!me_cl) {
12d00665 900 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
d320832f 901 return -ENOENT;
9ca9050b 902 }
12d00665 903
79563db9
TW
904 if (me_cl->mei_flow_ctrl_creds > 0) {
905 rets = 1;
12d00665 906 if (WARN_ON(me_cl->props.single_recv_buf == 0))
79563db9 907 rets = -EINVAL;
12d00665 908 }
79563db9
TW
909 mei_me_cl_put(me_cl);
910 return rets;
9ca9050b
TW
911}
912
913/**
90e0b5f1 914 * mei_cl_flow_ctrl_reduce - reduces flow_control.
9ca9050b 915 *
9ca9050b 916 * @cl: private data of the file object
393b148f 917 *
a8605ea2 918 * Return:
9ca9050b
TW
919 * 0 on success
920 * -ENOENT when me client is not found
921 * -EINVAL when ctrl credits are <= 0
922 */
90e0b5f1 923int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
9ca9050b 924{
90e0b5f1 925 struct mei_device *dev;
12d00665 926 struct mei_me_client *me_cl;
79563db9 927 int rets;
9ca9050b 928
90e0b5f1
TW
929 if (WARN_ON(!cl || !cl->dev))
930 return -EINVAL;
931
932 dev = cl->dev;
933
2e5df413 934 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
d320832f 935 if (!me_cl) {
12d00665 936 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
d320832f 937 return -ENOENT;
12d00665 938 }
9ca9050b 939
d320832f 940 if (me_cl->props.single_recv_buf) {
79563db9
TW
941 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0)) {
942 rets = -EINVAL;
943 goto out;
944 }
12d00665
AU
945 me_cl->mei_flow_ctrl_creds--;
946 } else {
79563db9
TW
947 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0)) {
948 rets = -EINVAL;
949 goto out;
950 }
12d00665 951 cl->mei_flow_ctrl_creds--;
9ca9050b 952 }
79563db9
TW
953 rets = 0;
954out:
955 mei_me_cl_put(me_cl);
956 return rets;
9ca9050b
TW
957}
958
ab841160 959/**
393b148f 960 * mei_cl_read_start - the start read client message function.
ab841160 961 *
90e0b5f1 962 * @cl: host client
ce23139c 963 * @length: number of bytes to read
ab841160 964 *
a8605ea2 965 * Return: 0 on success, <0 on failure.
ab841160 966 */
fcb136e1 967int mei_cl_read_start(struct mei_cl *cl, size_t length)
ab841160 968{
90e0b5f1 969 struct mei_device *dev;
ab841160 970 struct mei_cl_cb *cb;
d320832f 971 struct mei_me_client *me_cl;
664df38b 972 int rets;
ab841160 973
90e0b5f1
TW
974 if (WARN_ON(!cl || !cl->dev))
975 return -ENODEV;
976
977 dev = cl->dev;
978
b950ac1d 979 if (!mei_cl_is_connected(cl))
ab841160
OW
980 return -ENODEV;
981
d91aaed3 982 if (cl->read_cb) {
c0abffbd 983 cl_dbg(dev, cl, "read is pending.\n");
ab841160
OW
984 return -EBUSY;
985 }
d880f329 986 me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
d320832f 987 if (!me_cl) {
c0abffbd 988 cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
7ca96aa2 989 return -ENOTTY;
664df38b 990 }
79563db9
TW
991 /* always allocate at least client max message */
992 length = max_t(size_t, length, me_cl->props.max_msg_length);
993 mei_me_cl_put(me_cl);
ab841160 994
2bf94cab 995 rets = pm_runtime_get(dev->dev);
04bb139a 996 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 997 pm_runtime_put_noidle(dev->dev);
04bb139a
TW
998 cl_err(dev, cl, "rpm: get failed %d\n", rets);
999 return rets;
1000 }
1001
664df38b 1002 cb = mei_io_cb_init(cl, NULL);
04bb139a
TW
1003 if (!cb) {
1004 rets = -ENOMEM;
1005 goto out;
1006 }
ab841160 1007
fcb136e1 1008 rets = mei_io_cb_alloc_resp_buf(cb, length);
664df38b 1009 if (rets)
04bb139a 1010 goto out;
ab841160 1011
4b8960b4 1012 cb->fop_type = MEI_FOP_READ;
6aae48ff 1013 if (mei_hbuf_acquire(dev)) {
86113500
AU
1014 rets = mei_hbm_cl_flow_control_req(dev, cl);
1015 if (rets < 0)
04bb139a 1016 goto out;
04bb139a 1017
fb601adb 1018 list_add_tail(&cb->list, &dev->read_list.list);
ab841160 1019 } else {
fb601adb 1020 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
ab841160 1021 }
accb884b
CB
1022
1023 cl->read_cb = cb;
1024
04bb139a
TW
1025out:
1026 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
1027 pm_runtime_mark_last_busy(dev->dev);
1028 pm_runtime_put_autosuspend(dev->dev);
04bb139a
TW
1029
1030 if (rets)
1031 mei_io_cb_free(cb);
1032
ab841160
OW
1033 return rets;
1034}
1035
21767546 1036/**
9d098192 1037 * mei_cl_irq_write - write a message to device
21767546
TW
1038 * from the interrupt thread context
1039 *
1040 * @cl: client
1041 * @cb: callback block.
21767546
TW
1042 * @cmpl_list: complete list.
1043 *
a8605ea2 1044 * Return: 0, OK; otherwise error.
21767546 1045 */
9d098192
TW
1046int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
1047 struct mei_cl_cb *cmpl_list)
21767546 1048{
136698e5
TW
1049 struct mei_device *dev;
1050 struct mei_msg_data *buf;
21767546 1051 struct mei_msg_hdr mei_hdr;
136698e5
TW
1052 size_t len;
1053 u32 msg_slots;
9d098192 1054 int slots;
2ebf8c94 1055 int rets;
21767546 1056
136698e5
TW
1057 if (WARN_ON(!cl || !cl->dev))
1058 return -ENODEV;
1059
1060 dev = cl->dev;
1061
1062 buf = &cb->request_buffer;
1063
1064 rets = mei_cl_flow_ctrl_creds(cl);
1065 if (rets < 0)
1066 return rets;
1067
1068 if (rets == 0) {
04bb139a 1069 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
136698e5
TW
1070 return 0;
1071 }
1072
9d098192 1073 slots = mei_hbuf_empty_slots(dev);
136698e5
TW
1074 len = buf->size - cb->buf_idx;
1075 msg_slots = mei_data2slots(len);
1076
21767546
TW
1077 mei_hdr.host_addr = cl->host_client_id;
1078 mei_hdr.me_addr = cl->me_client_id;
1079 mei_hdr.reserved = 0;
479327fc 1080 mei_hdr.internal = cb->internal;
21767546 1081
9d098192 1082 if (slots >= msg_slots) {
21767546
TW
1083 mei_hdr.length = len;
1084 mei_hdr.msg_complete = 1;
1085 /* Split the message only if we can write the whole host buffer */
9d098192
TW
1086 } else if (slots == dev->hbuf_depth) {
1087 msg_slots = slots;
1088 len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
21767546
TW
1089 mei_hdr.length = len;
1090 mei_hdr.msg_complete = 0;
1091 } else {
1092 /* wait for next time the host buffer is empty */
1093 return 0;
1094 }
1095
c0abffbd 1096 cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
21767546 1097 cb->request_buffer.size, cb->buf_idx);
21767546 1098
136698e5 1099 rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
2ebf8c94
TW
1100 if (rets) {
1101 cl->status = rets;
21767546 1102 list_move_tail(&cb->list, &cmpl_list->list);
2ebf8c94 1103 return rets;
21767546
TW
1104 }
1105
1106 cl->status = 0;
4dfaa9f7 1107 cl->writing_state = MEI_WRITING;
21767546 1108 cb->buf_idx += mei_hdr.length;
8660172e 1109 cb->completed = mei_hdr.msg_complete == 1;
4dfaa9f7 1110
21767546
TW
1111 if (mei_hdr.msg_complete) {
1112 if (mei_cl_flow_ctrl_reduce(cl))
2ebf8c94 1113 return -EIO;
21767546
TW
1114 list_move_tail(&cb->list, &dev->write_waiting_list.list);
1115 }
1116
1117 return 0;
1118}
1119
4234a6de
TW
1120/**
1121 * mei_cl_write - submit a write cb to mei device
a8605ea2 1122 * assumes device_lock is locked
4234a6de
TW
1123 *
1124 * @cl: host client
a8605ea2 1125 * @cb: write callback with filled data
ce23139c 1126 * @blocking: block until completed
4234a6de 1127 *
a8605ea2 1128 * Return: number of bytes sent on success, <0 on failure.
4234a6de
TW
1129 */
1130int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
1131{
1132 struct mei_device *dev;
1133 struct mei_msg_data *buf;
1134 struct mei_msg_hdr mei_hdr;
1135 int rets;
1136
1137
1138 if (WARN_ON(!cl || !cl->dev))
1139 return -ENODEV;
1140
1141 if (WARN_ON(!cb))
1142 return -EINVAL;
1143
1144 dev = cl->dev;
1145
1146
1147 buf = &cb->request_buffer;
1148
0a01e974 1149 cl_dbg(dev, cl, "size=%d\n", buf->size);
4234a6de 1150
2bf94cab 1151 rets = pm_runtime_get(dev->dev);
04bb139a 1152 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 1153 pm_runtime_put_noidle(dev->dev);
04bb139a
TW
1154 cl_err(dev, cl, "rpm: get failed %d\n", rets);
1155 return rets;
1156 }
4234a6de
TW
1157
1158 cb->fop_type = MEI_FOP_WRITE;
6aae48ff
TW
1159 cb->buf_idx = 0;
1160 cl->writing_state = MEI_IDLE;
1161
1162 mei_hdr.host_addr = cl->host_client_id;
1163 mei_hdr.me_addr = cl->me_client_id;
1164 mei_hdr.reserved = 0;
1165 mei_hdr.msg_complete = 0;
1166 mei_hdr.internal = cb->internal;
4234a6de
TW
1167
1168 rets = mei_cl_flow_ctrl_creds(cl);
1169 if (rets < 0)
1170 goto err;
1171
6aae48ff
TW
1172 if (rets == 0) {
1173 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
1174 rets = buf->size;
1175 goto out;
1176 }
1177 if (!mei_hbuf_acquire(dev)) {
1178 cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
4234a6de
TW
1179 rets = buf->size;
1180 goto out;
1181 }
4234a6de
TW
1182
1183 /* Check for a maximum length */
1184 if (buf->size > mei_hbuf_max_len(dev)) {
1185 mei_hdr.length = mei_hbuf_max_len(dev);
1186 mei_hdr.msg_complete = 0;
1187 } else {
1188 mei_hdr.length = buf->size;
1189 mei_hdr.msg_complete = 1;
1190 }
1191
2ebf8c94
TW
1192 rets = mei_write_message(dev, &mei_hdr, buf->data);
1193 if (rets)
4234a6de 1194 goto err;
4234a6de
TW
1195
1196 cl->writing_state = MEI_WRITING;
1197 cb->buf_idx = mei_hdr.length;
8660172e 1198 cb->completed = mei_hdr.msg_complete == 1;
4234a6de 1199
4234a6de
TW
1200out:
1201 if (mei_hdr.msg_complete) {
7ca96aa2
AU
1202 rets = mei_cl_flow_ctrl_reduce(cl);
1203 if (rets < 0)
4234a6de 1204 goto err;
7ca96aa2 1205
4234a6de
TW
1206 list_add_tail(&cb->list, &dev->write_waiting_list.list);
1207 } else {
1208 list_add_tail(&cb->list, &dev->write_list.list);
1209 }
1210
1211
1212 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
1213
1214 mutex_unlock(&dev->device_lock);
7ca96aa2
AU
1215 rets = wait_event_interruptible(cl->tx_wait,
1216 cl->writing_state == MEI_WRITE_COMPLETE);
4234a6de 1217 mutex_lock(&dev->device_lock);
7ca96aa2
AU
1218 /* wait_event_interruptible returns -ERESTARTSYS */
1219 if (rets) {
1220 if (signal_pending(current))
1221 rets = -EINTR;
1222 goto err;
1223 }
4234a6de 1224 }
7ca96aa2
AU
1225
1226 rets = buf->size;
4234a6de 1227err:
04bb139a 1228 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
1229 pm_runtime_mark_last_busy(dev->dev);
1230 pm_runtime_put_autosuspend(dev->dev);
04bb139a 1231
4234a6de
TW
1232 return rets;
1233}
1234
1235
db086fa9
TW
1236/**
1237 * mei_cl_complete - processes completed operation for a client
1238 *
1239 * @cl: private data of the file object.
1240 * @cb: callback block.
1241 */
1242void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
1243{
1244 if (cb->fop_type == MEI_FOP_WRITE) {
1245 mei_io_cb_free(cb);
1246 cb = NULL;
1247 cl->writing_state = MEI_WRITE_COMPLETE;
1248 if (waitqueue_active(&cl->tx_wait))
1249 wake_up_interruptible(&cl->tx_wait);
1250
1251 } else if (cb->fop_type == MEI_FOP_READ &&
1252 MEI_READING == cl->reading_state) {
1253 cl->reading_state = MEI_READ_COMPLETE;
1254 if (waitqueue_active(&cl->rx_wait))
1255 wake_up_interruptible(&cl->rx_wait);
1256 else
1257 mei_cl_bus_rx_event(cl);
1258
1259 }
1260}
1261
4234a6de 1262
074b4c01
TW
1263/**
1264 * mei_cl_all_disconnect - disconnect forcefully all connected clients
1265 *
a8605ea2 1266 * @dev: mei device
074b4c01
TW
1267 */
1268
1269void mei_cl_all_disconnect(struct mei_device *dev)
1270{
31f88f57 1271 struct mei_cl *cl;
074b4c01 1272
31f88f57 1273 list_for_each_entry(cl, &dev->file_list, link) {
074b4c01
TW
1274 cl->state = MEI_FILE_DISCONNECTED;
1275 cl->mei_flow_ctrl_creds = 0;
074b4c01
TW
1276 cl->timer_count = 0;
1277 }
1278}
1279
1280
1281/**
5290801c 1282 * mei_cl_all_wakeup - wake up all readers and writers they can be interrupted
074b4c01 1283 *
a8605ea2 1284 * @dev: mei device
074b4c01 1285 */
5290801c 1286void mei_cl_all_wakeup(struct mei_device *dev)
074b4c01 1287{
31f88f57 1288 struct mei_cl *cl;
92db1555 1289
31f88f57 1290 list_for_each_entry(cl, &dev->file_list, link) {
074b4c01 1291 if (waitqueue_active(&cl->rx_wait)) {
c0abffbd 1292 cl_dbg(dev, cl, "Waking up reading client!\n");
074b4c01
TW
1293 wake_up_interruptible(&cl->rx_wait);
1294 }
5290801c 1295 if (waitqueue_active(&cl->tx_wait)) {
c0abffbd 1296 cl_dbg(dev, cl, "Waking up writing client!\n");
5290801c
TW
1297 wake_up_interruptible(&cl->tx_wait);
1298 }
074b4c01
TW
1299 }
1300}
1301
1302/**
1303 * mei_cl_all_write_clear - clear all pending writes
a8605ea2
AU
1304 *
1305 * @dev: mei device
074b4c01
TW
1306 */
1307void mei_cl_all_write_clear(struct mei_device *dev)
1308{
cc99ecfd
TW
1309 mei_io_list_free(&dev->write_list, NULL);
1310 mei_io_list_free(&dev->write_waiting_list, NULL);
074b4c01
TW
1311}
1312
1313