mei: amthif: allow the read completion after close
[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/**
d49ed64a 86 * __mei_me_cl_del - delete me client from the list and decrease
b7d88514
TW
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
d49ed64a 99 list_del_init(&me_cl->list);
b7d88514
TW
100 mei_me_cl_put(me_cl);
101}
102
d49ed64a
AU
103/**
104 * mei_me_cl_del - delete me client from the list and decrease
105 * reference counter
106 *
107 * @dev: mei device
108 * @me_cl: me client
109 */
110void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
111{
112 down_write(&dev->me_clients_rwsem);
113 __mei_me_cl_del(dev, me_cl);
114 up_write(&dev->me_clients_rwsem);
115}
116
b7d88514
TW
117/**
118 * mei_me_cl_add - add me client to the list
119 *
120 * @dev: mei device
121 * @me_cl: me client
122 */
123void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
124{
125 down_write(&dev->me_clients_rwsem);
126 list_add(&me_cl->list, &dev->me_clients);
127 up_write(&dev->me_clients_rwsem);
128}
129
130/**
131 * __mei_me_cl_by_uuid - locate me client by uuid
79563db9 132 * increases ref count
90e0b5f1
TW
133 *
134 * @dev: mei device
a8605ea2 135 * @uuid: me client uuid
a27a76d3 136 *
a8605ea2 137 * Return: me client or NULL if not found
b7d88514
TW
138 *
139 * Locking: dev->me_clients_rwsem
90e0b5f1 140 */
b7d88514 141static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
d320832f 142 const uuid_le *uuid)
90e0b5f1 143{
5ca2d388 144 struct mei_me_client *me_cl;
b7d88514 145 const uuid_le *pn;
90e0b5f1 146
b7d88514
TW
147 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
148
149 list_for_each_entry(me_cl, &dev->me_clients, list) {
150 pn = &me_cl->props.protocol_name;
151 if (uuid_le_cmp(*uuid, *pn) == 0)
79563db9 152 return mei_me_cl_get(me_cl);
b7d88514 153 }
90e0b5f1 154
d320832f 155 return NULL;
90e0b5f1
TW
156}
157
b7d88514
TW
158/**
159 * mei_me_cl_by_uuid - locate me client by uuid
160 * increases ref count
161 *
162 * @dev: mei device
163 * @uuid: me client uuid
164 *
165 * Return: me client or NULL if not found
166 *
167 * Locking: dev->me_clients_rwsem
168 */
169struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
170 const uuid_le *uuid)
171{
172 struct mei_me_client *me_cl;
173
174 down_read(&dev->me_clients_rwsem);
175 me_cl = __mei_me_cl_by_uuid(dev, uuid);
176 up_read(&dev->me_clients_rwsem);
177
178 return me_cl;
179}
180
90e0b5f1 181/**
a8605ea2 182 * mei_me_cl_by_id - locate me client by client id
79563db9 183 * increases ref count
90e0b5f1
TW
184 *
185 * @dev: the device structure
186 * @client_id: me client id
187 *
a8605ea2 188 * Return: me client or NULL if not found
b7d88514
TW
189 *
190 * Locking: dev->me_clients_rwsem
90e0b5f1 191 */
d320832f 192struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
90e0b5f1 193{
a27a76d3 194
b7d88514
TW
195 struct mei_me_client *__me_cl, *me_cl = NULL;
196
197 down_read(&dev->me_clients_rwsem);
198 list_for_each_entry(__me_cl, &dev->me_clients, list) {
199 if (__me_cl->client_id == client_id) {
200 me_cl = mei_me_cl_get(__me_cl);
201 break;
202 }
203 }
204 up_read(&dev->me_clients_rwsem);
205
206 return me_cl;
207}
208
209/**
210 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
211 * increases ref count
212 *
213 * @dev: the device structure
214 * @uuid: me client uuid
215 * @client_id: me client id
216 *
217 * Return: me client or null if not found
218 *
219 * Locking: dev->me_clients_rwsem
220 */
221static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
222 const uuid_le *uuid, u8 client_id)
223{
5ca2d388 224 struct mei_me_client *me_cl;
b7d88514
TW
225 const uuid_le *pn;
226
227 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
90e0b5f1 228
b7d88514
TW
229 list_for_each_entry(me_cl, &dev->me_clients, list) {
230 pn = &me_cl->props.protocol_name;
231 if (uuid_le_cmp(*uuid, *pn) == 0 &&
232 me_cl->client_id == client_id)
79563db9 233 return mei_me_cl_get(me_cl);
b7d88514 234 }
79563db9 235
d320832f 236 return NULL;
90e0b5f1 237}
ab841160 238
b7d88514 239
a8605ea2
AU
240/**
241 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
79563db9 242 * increases ref count
a8605ea2
AU
243 *
244 * @dev: the device structure
245 * @uuid: me client uuid
246 * @client_id: me client id
247 *
b7d88514 248 * Return: me client or null if not found
a8605ea2 249 */
d880f329
TW
250struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
251 const uuid_le *uuid, u8 client_id)
252{
253 struct mei_me_client *me_cl;
254
b7d88514
TW
255 down_read(&dev->me_clients_rwsem);
256 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);
257 up_read(&dev->me_clients_rwsem);
79563db9 258
b7d88514 259 return me_cl;
d880f329
TW
260}
261
25ca6472 262/**
79563db9 263 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid
25ca6472
TW
264 *
265 * @dev: the device structure
266 * @uuid: me client uuid
79563db9
TW
267 *
268 * Locking: called under "dev->device_lock" lock
25ca6472 269 */
79563db9 270void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
25ca6472 271{
b7d88514 272 struct mei_me_client *me_cl;
25ca6472 273
79563db9 274 dev_dbg(dev->dev, "remove %pUl\n", uuid);
b7d88514
TW
275
276 down_write(&dev->me_clients_rwsem);
277 me_cl = __mei_me_cl_by_uuid(dev, uuid);
278 __mei_me_cl_del(dev, me_cl);
279 up_write(&dev->me_clients_rwsem);
79563db9
TW
280}
281
282/**
283 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id
284 *
285 * @dev: the device structure
286 * @uuid: me client uuid
287 * @id: me client id
288 *
289 * Locking: called under "dev->device_lock" lock
290 */
291void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
292{
b7d88514 293 struct mei_me_client *me_cl;
79563db9
TW
294
295 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);
b7d88514
TW
296
297 down_write(&dev->me_clients_rwsem);
298 me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
299 __mei_me_cl_del(dev, me_cl);
300 up_write(&dev->me_clients_rwsem);
25ca6472
TW
301}
302
79563db9
TW
303/**
304 * mei_me_cl_rm_all - remove all me clients
305 *
306 * @dev: the device structure
307 *
308 * Locking: called under "dev->device_lock" lock
309 */
310void mei_me_cl_rm_all(struct mei_device *dev)
311{
312 struct mei_me_client *me_cl, *next;
313
b7d88514 314 down_write(&dev->me_clients_rwsem);
79563db9 315 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
b7d88514
TW
316 __mei_me_cl_del(dev, me_cl);
317 up_write(&dev->me_clients_rwsem);
79563db9
TW
318}
319
9ca9050b 320/**
cc99ecfd 321 * mei_cl_cmp_id - tells if the clients are the same
9ca9050b 322 *
cc99ecfd
TW
323 * @cl1: host client 1
324 * @cl2: host client 2
325 *
a8605ea2 326 * Return: true - if the clients has same host and me ids
cc99ecfd
TW
327 * false - otherwise
328 */
329static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
330 const struct mei_cl *cl2)
331{
332 return cl1 && cl2 &&
333 (cl1->host_client_id == cl2->host_client_id) &&
d49ed64a 334 (mei_cl_me_id(cl1) == mei_cl_me_id(cl2));
cc99ecfd
TW
335}
336
928fa666
TW
337/**
338 * mei_io_cb_free - free mei_cb_private related memory
339 *
340 * @cb: mei callback struct
341 */
342void mei_io_cb_free(struct mei_cl_cb *cb)
343{
344 if (cb == NULL)
345 return;
346
347 list_del(&cb->list);
348 kfree(cb->buf.data);
349 kfree(cb);
350}
351
352/**
353 * mei_io_cb_init - allocate and initialize io callback
354 *
355 * @cl: mei client
356 * @type: operation type
357 * @fp: pointer to file structure
358 *
359 * Return: mei_cl_cb pointer or NULL;
360 */
3030dc05
TW
361static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
362 enum mei_cb_file_ops type,
363 const struct file *fp)
928fa666
TW
364{
365 struct mei_cl_cb *cb;
366
367 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
368 if (!cb)
369 return NULL;
370
371 INIT_LIST_HEAD(&cb->list);
62e8e6ad 372 cb->fp = fp;
928fa666
TW
373 cb->cl = cl;
374 cb->buf_idx = 0;
375 cb->fop_type = type;
376 return cb;
377}
378
cc99ecfd 379/**
3908be6f 380 * __mei_io_list_flush - removes and frees cbs belonging to cl.
cc99ecfd
TW
381 *
382 * @list: an instance of our list structure
383 * @cl: host client, can be NULL for flushing the whole list
384 * @free: whether to free the cbs
9ca9050b 385 */
cc99ecfd
TW
386static void __mei_io_list_flush(struct mei_cl_cb *list,
387 struct mei_cl *cl, bool free)
9ca9050b 388{
928fa666 389 struct mei_cl_cb *cb, *next;
9ca9050b 390
cc99ecfd 391 /* enable removing everything if no cl is specified */
9ca9050b 392 list_for_each_entry_safe(cb, next, &list->list, list) {
140c7553 393 if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
928fa666 394 list_del_init(&cb->list);
cc99ecfd
TW
395 if (free)
396 mei_io_cb_free(cb);
397 }
9ca9050b
TW
398 }
399}
400
cc99ecfd
TW
401/**
402 * mei_io_list_flush - removes list entry belonging to cl.
403 *
404 * @list: An instance of our list structure
405 * @cl: host client
406 */
29fe7d59 407static inline void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
cc99ecfd
TW
408{
409 __mei_io_list_flush(list, cl, false);
410}
411
cc99ecfd
TW
412/**
413 * mei_io_list_free - removes cb belonging to cl and free them
414 *
415 * @list: An instance of our list structure
416 * @cl: host client
417 */
418static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
419{
420 __mei_io_list_flush(list, cl, true);
421}
422
bca67d68
TW
423/**
424 * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
425 *
426 * @cl: host client
427 * @length: size of the buffer
967b274e 428 * @fop_type: operation type
bca67d68
TW
429 * @fp: associated file pointer (might be NULL)
430 *
431 * Return: cb on success and NULL on failure
432 */
433struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
3030dc05 434 enum mei_cb_file_ops fop_type,
f23e2cc4 435 const struct file *fp)
bca67d68
TW
436{
437 struct mei_cl_cb *cb;
438
3030dc05 439 cb = mei_io_cb_init(cl, fop_type, fp);
bca67d68
TW
440 if (!cb)
441 return NULL;
442
aab3b1a3
AU
443 if (length == 0)
444 return cb;
445
446 cb->buf.data = kmalloc(length, GFP_KERNEL);
447 if (!cb->buf.data) {
bca67d68
TW
448 mei_io_cb_free(cb);
449 return NULL;
450 }
aab3b1a3 451 cb->buf.size = length;
bca67d68
TW
452
453 return cb;
454}
455
3030dc05
TW
456/**
457 * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating
458 * and enqueuing of the control commands cb
459 *
460 * @cl: host client
461 * @length: size of the buffer
967b274e 462 * @fop_type: operation type
3030dc05
TW
463 * @fp: associated file pointer (might be NULL)
464 *
465 * Return: cb on success and NULL on failure
466 * Locking: called under "dev->device_lock" lock
467 */
468struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
469 enum mei_cb_file_ops fop_type,
470 const struct file *fp)
471{
472 struct mei_cl_cb *cb;
473
474 /* for RX always allocate at least client's mtu */
475 if (length)
476 length = max_t(size_t, length, mei_cl_mtu(cl));
477
478 cb = mei_cl_alloc_cb(cl, length, fop_type, fp);
479 if (!cb)
480 return NULL;
481
482 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list.list);
483 return cb;
484}
485
a9bed610
TW
486/**
487 * mei_cl_read_cb - find this cl's callback in the read list
488 * for a specific file
489 *
490 * @cl: host client
491 * @fp: file pointer (matching cb file object), may be NULL
492 *
493 * Return: cb on success, NULL if cb is not found
494 */
495struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
496{
497 struct mei_cl_cb *cb;
498
499 list_for_each_entry(cb, &cl->rd_completed, list)
62e8e6ad 500 if (!fp || fp == cb->fp)
a9bed610
TW
501 return cb;
502
503 return NULL;
504}
505
506/**
507 * mei_cl_read_cb_flush - free client's read pending and completed cbs
508 * for a specific file
509 *
510 * @cl: host client
511 * @fp: file pointer (matching cb file object), may be NULL
512 */
513void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp)
514{
515 struct mei_cl_cb *cb, *next;
516
517 list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
62e8e6ad 518 if (!fp || fp == cb->fp)
a9bed610
TW
519 mei_io_cb_free(cb);
520
521
522 list_for_each_entry_safe(cb, next, &cl->rd_pending, list)
62e8e6ad 523 if (!fp || fp == cb->fp)
a9bed610
TW
524 mei_io_cb_free(cb);
525}
526
9ca9050b
TW
527/**
528 * mei_cl_flush_queues - flushes queue lists belonging to cl.
529 *
9ca9050b 530 * @cl: host client
a9bed610 531 * @fp: file pointer (matching cb file object), may be NULL
ce23139c
AU
532 *
533 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
9ca9050b 534 */
a9bed610 535int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
9ca9050b 536{
c0abffbd
AU
537 struct mei_device *dev;
538
90e0b5f1 539 if (WARN_ON(!cl || !cl->dev))
9ca9050b
TW
540 return -EINVAL;
541
c0abffbd
AU
542 dev = cl->dev;
543
544 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
cc99ecfd
TW
545 mei_io_list_free(&cl->dev->write_list, cl);
546 mei_io_list_free(&cl->dev->write_waiting_list, cl);
9ca9050b
TW
547 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
548 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
a9bed610
TW
549
550 mei_cl_read_cb_flush(cl, fp);
551
9ca9050b
TW
552 return 0;
553}
554
ab841160 555
9ca9050b 556/**
83ce0741 557 * mei_cl_init - initializes cl.
9ca9050b
TW
558 *
559 * @cl: host client to be initialized
560 * @dev: mei device
561 */
562void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
563{
564 memset(cl, 0, sizeof(struct mei_cl));
565 init_waitqueue_head(&cl->wait);
566 init_waitqueue_head(&cl->rx_wait);
567 init_waitqueue_head(&cl->tx_wait);
b38a362f 568 init_waitqueue_head(&cl->ev_wait);
a9bed610
TW
569 INIT_LIST_HEAD(&cl->rd_completed);
570 INIT_LIST_HEAD(&cl->rd_pending);
9ca9050b 571 INIT_LIST_HEAD(&cl->link);
9ca9050b 572 cl->writing_state = MEI_IDLE;
bd47b526 573 cl->state = MEI_FILE_UNINITIALIZED;
9ca9050b
TW
574 cl->dev = dev;
575}
576
577/**
578 * mei_cl_allocate - allocates cl structure and sets it up.
579 *
580 * @dev: mei device
a8605ea2 581 * Return: The allocated file or NULL on failure
9ca9050b
TW
582 */
583struct mei_cl *mei_cl_allocate(struct mei_device *dev)
584{
585 struct mei_cl *cl;
586
587 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
588 if (!cl)
589 return NULL;
590
591 mei_cl_init(cl, dev);
592
593 return cl;
594}
595
3908be6f
AU
596/**
597 * mei_cl_link - allocate host id in the host map
9ca9050b 598 *
3908be6f 599 * @cl: host client
393b148f 600 *
a8605ea2 601 * Return: 0 on success
9ca9050b 602 * -EINVAL on incorrect values
03b8d341 603 * -EMFILE if open count exceeded.
9ca9050b 604 */
7851e008 605int mei_cl_link(struct mei_cl *cl)
9ca9050b 606{
90e0b5f1 607 struct mei_device *dev;
22f96a0e 608 long open_handle_count;
7851e008 609 int id;
9ca9050b 610
781d0d89 611 if (WARN_ON(!cl || !cl->dev))
9ca9050b
TW
612 return -EINVAL;
613
90e0b5f1
TW
614 dev = cl->dev;
615
7851e008 616 id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
781d0d89 617 if (id >= MEI_CLIENTS_MAX) {
2bf94cab 618 dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX);
e036cc57
TW
619 return -EMFILE;
620 }
621
22f96a0e
TW
622 open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
623 if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
2bf94cab 624 dev_err(dev->dev, "open_handle_count exceeded %d",
e036cc57
TW
625 MEI_MAX_OPEN_HANDLE_COUNT);
626 return -EMFILE;
9ca9050b
TW
627 }
628
781d0d89
TW
629 dev->open_handle_count++;
630
631 cl->host_client_id = id;
632 list_add_tail(&cl->link, &dev->file_list);
633
634 set_bit(id, dev->host_clients_map);
635
636 cl->state = MEI_FILE_INITIALIZING;
637
c0abffbd 638 cl_dbg(dev, cl, "link cl\n");
781d0d89 639 return 0;
9ca9050b 640}
781d0d89 641
9ca9050b 642/**
d49ed64a 643 * mei_cl_unlink - remove host client from the list
9ca9050b 644 *
393b148f 645 * @cl: host client
ce23139c
AU
646 *
647 * Return: always 0
9ca9050b 648 */
90e0b5f1 649int mei_cl_unlink(struct mei_cl *cl)
9ca9050b 650{
90e0b5f1 651 struct mei_device *dev;
90e0b5f1 652
781d0d89
TW
653 /* don't shout on error exit path */
654 if (!cl)
655 return 0;
656
fdd9b865 657 /* amthif might not be initialized */
8e9a4a9a
TW
658 if (!cl->dev)
659 return 0;
90e0b5f1
TW
660
661 dev = cl->dev;
662
a14c44d8
TW
663 cl_dbg(dev, cl, "unlink client");
664
22f96a0e
TW
665 if (dev->open_handle_count > 0)
666 dev->open_handle_count--;
667
668 /* never clear the 0 bit */
669 if (cl->host_client_id)
670 clear_bit(cl->host_client_id, dev->host_clients_map);
671
672 list_del_init(&cl->link);
673
bd47b526 674 cl->state = MEI_FILE_UNINITIALIZED;
7c7a6077
AU
675 cl->writing_state = MEI_IDLE;
676
677 WARN_ON(!list_empty(&cl->rd_completed) ||
678 !list_empty(&cl->rd_pending) ||
679 !list_empty(&cl->link));
22f96a0e 680
90e0b5f1 681 return 0;
9ca9050b
TW
682}
683
025fb792 684void mei_host_client_init(struct mei_device *dev)
9ca9050b 685{
9ca9050b 686 dev->dev_state = MEI_DEV_ENABLED;
6adb8efb 687 dev->reset_count = 0;
04bb139a 688
025fb792 689 schedule_work(&dev->bus_rescan_work);
6009595a 690
2bf94cab
TW
691 pm_runtime_mark_last_busy(dev->dev);
692 dev_dbg(dev->dev, "rpm: autosuspend\n");
d5f8e166 693 pm_request_autosuspend(dev->dev);
9ca9050b
TW
694}
695
6aae48ff 696/**
a8605ea2 697 * mei_hbuf_acquire - try to acquire host buffer
6aae48ff
TW
698 *
699 * @dev: the device structure
a8605ea2 700 * Return: true if host buffer was acquired
6aae48ff
TW
701 */
702bool mei_hbuf_acquire(struct mei_device *dev)
703{
04bb139a 704 if (mei_pg_state(dev) == MEI_PG_ON ||
3dc196ea 705 mei_pg_in_transition(dev)) {
2bf94cab 706 dev_dbg(dev->dev, "device is in pg\n");
04bb139a
TW
707 return false;
708 }
709
6aae48ff 710 if (!dev->hbuf_is_ready) {
2bf94cab 711 dev_dbg(dev->dev, "hbuf is not ready\n");
6aae48ff
TW
712 return false;
713 }
714
715 dev->hbuf_is_ready = false;
716
717 return true;
718}
9ca9050b 719
a4307fe4
AU
720/**
721 * mei_cl_wake_all - wake up readers, writers and event waiters so
722 * they can be interrupted
723 *
724 * @cl: host client
725 */
726static void mei_cl_wake_all(struct mei_cl *cl)
727{
728 struct mei_device *dev = cl->dev;
729
730 /* synchronized under device mutex */
731 if (waitqueue_active(&cl->rx_wait)) {
732 cl_dbg(dev, cl, "Waking up reading client!\n");
733 wake_up_interruptible(&cl->rx_wait);
734 }
735 /* synchronized under device mutex */
736 if (waitqueue_active(&cl->tx_wait)) {
737 cl_dbg(dev, cl, "Waking up writing client!\n");
738 wake_up_interruptible(&cl->tx_wait);
739 }
740 /* synchronized under device mutex */
741 if (waitqueue_active(&cl->ev_wait)) {
742 cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
743 wake_up_interruptible(&cl->ev_wait);
744 }
7ff4bdd4
AU
745 /* synchronized under device mutex */
746 if (waitqueue_active(&cl->wait)) {
747 cl_dbg(dev, cl, "Waking up ctrl write clients!\n");
69f1804a 748 wake_up(&cl->wait);
7ff4bdd4 749 }
a4307fe4
AU
750}
751
3c666182
TW
752/**
753 * mei_cl_set_disconnected - set disconnected state and clear
754 * associated states and resources
755 *
756 * @cl: host client
757 */
669c256c 758static void mei_cl_set_disconnected(struct mei_cl *cl)
3c666182
TW
759{
760 struct mei_device *dev = cl->dev;
761
762 if (cl->state == MEI_FILE_DISCONNECTED ||
bd47b526 763 cl->state <= MEI_FILE_INITIALIZING)
3c666182
TW
764 return;
765
766 cl->state = MEI_FILE_DISCONNECTED;
a4307fe4
AU
767 mei_io_list_free(&dev->write_list, cl);
768 mei_io_list_free(&dev->write_waiting_list, cl);
3c666182
TW
769 mei_io_list_flush(&dev->ctrl_rd_list, cl);
770 mei_io_list_flush(&dev->ctrl_wr_list, cl);
6537ae2f 771 mei_io_list_free(&dev->amthif_cmd_list, cl);
a4307fe4 772 mei_cl_wake_all(cl);
46978ada 773 cl->rx_flow_ctrl_creds = 0;
4034b81b 774 cl->tx_flow_ctrl_creds = 0;
3c666182 775 cl->timer_count = 0;
d49ed64a 776
5d882460
AU
777 mei_cl_bus_module_put(cl);
778
a03d77f6
AU
779 if (!cl->me_cl)
780 return;
781
782 if (!WARN_ON(cl->me_cl->connect_count == 0))
783 cl->me_cl->connect_count--;
784
c241e9b1 785 if (cl->me_cl->connect_count == 0)
4034b81b 786 cl->me_cl->tx_flow_ctrl_creds = 0;
c241e9b1 787
d49ed64a
AU
788 mei_me_cl_put(cl->me_cl);
789 cl->me_cl = NULL;
3c666182
TW
790}
791
a03d77f6
AU
792static int mei_cl_set_connecting(struct mei_cl *cl, struct mei_me_client *me_cl)
793{
1df629ef 794 if (!mei_me_cl_get(me_cl))
a03d77f6
AU
795 return -ENOENT;
796
1df629ef
AU
797 /* only one connection is allowed for fixed address clients */
798 if (me_cl->props.fixed_address) {
799 if (me_cl->connect_count) {
800 mei_me_cl_put(me_cl);
801 return -EBUSY;
802 }
803 }
804
805 cl->me_cl = me_cl;
a03d77f6
AU
806 cl->state = MEI_FILE_CONNECTING;
807 cl->me_cl->connect_count++;
808
809 return 0;
810}
811
3c666182
TW
812/*
813 * mei_cl_send_disconnect - send disconnect request
814 *
815 * @cl: host client
816 * @cb: callback block
817 *
818 * Return: 0, OK; otherwise, error.
819 */
820static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)
821{
822 struct mei_device *dev;
823 int ret;
824
825 dev = cl->dev;
826
827 ret = mei_hbm_cl_disconnect_req(dev, cl);
828 cl->status = ret;
829 if (ret) {
830 cl->state = MEI_FILE_DISCONNECT_REPLY;
831 return ret;
832 }
833
834 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
835 cl->timer_count = MEI_CONNECT_TIMEOUT;
1892fc2e 836 mei_schedule_stall_timer(dev);
3c666182
TW
837
838 return 0;
839}
840
841/**
842 * mei_cl_irq_disconnect - processes close related operation from
843 * interrupt thread context - send disconnect request
844 *
845 * @cl: client
846 * @cb: callback block.
847 * @cmpl_list: complete list.
848 *
849 * Return: 0, OK; otherwise, error.
850 */
851int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
852 struct mei_cl_cb *cmpl_list)
853{
854 struct mei_device *dev = cl->dev;
855 u32 msg_slots;
856 int slots;
857 int ret;
858
859 msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
860 slots = mei_hbuf_empty_slots(dev);
861
862 if (slots < msg_slots)
863 return -EMSGSIZE;
864
865 ret = mei_cl_send_disconnect(cl, cb);
866 if (ret)
867 list_move_tail(&cb->list, &cmpl_list->list);
868
869 return ret;
870}
871
9ca9050b 872/**
18901357
AU
873 * __mei_cl_disconnect - disconnect host client from the me one
874 * internal function runtime pm has to be already acquired
9ca9050b 875 *
90e0b5f1 876 * @cl: host client
9ca9050b 877 *
a8605ea2 878 * Return: 0 on success, <0 on failure.
9ca9050b 879 */
18901357 880static int __mei_cl_disconnect(struct mei_cl *cl)
9ca9050b 881{
90e0b5f1 882 struct mei_device *dev;
9ca9050b 883 struct mei_cl_cb *cb;
fe2f17eb 884 int rets;
9ca9050b 885
90e0b5f1
TW
886 dev = cl->dev;
887
3c666182
TW
888 cl->state = MEI_FILE_DISCONNECTING;
889
3030dc05
TW
890 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT, NULL);
891 if (!cb) {
892 rets = -ENOMEM;
3c666182 893 goto out;
3030dc05 894 }
5a8373fb 895
6aae48ff 896 if (mei_hbuf_acquire(dev)) {
3c666182
TW
897 rets = mei_cl_send_disconnect(cl, cb);
898 if (rets) {
c0abffbd 899 cl_err(dev, cl, "failed to disconnect.\n");
3c666182 900 goto out;
9ca9050b 901 }
9ca9050b 902 }
9ca9050b 903
3c666182 904 mutex_unlock(&dev->device_lock);
7ff4bdd4
AU
905 wait_event_timeout(cl->wait,
906 cl->state == MEI_FILE_DISCONNECT_REPLY ||
907 cl->state == MEI_FILE_DISCONNECTED,
3c666182 908 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
9ca9050b 909 mutex_lock(&dev->device_lock);
fe2f17eb 910
3c666182 911 rets = cl->status;
7ff4bdd4
AU
912 if (cl->state != MEI_FILE_DISCONNECT_REPLY &&
913 cl->state != MEI_FILE_DISCONNECTED) {
fe2f17eb
AU
914 cl_dbg(dev, cl, "timeout on disconnect from FW client.\n");
915 rets = -ETIME;
9ca9050b
TW
916 }
917
3c666182
TW
918out:
919 /* we disconnect also on error */
920 mei_cl_set_disconnected(cl);
921 if (!rets)
922 cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
923
18901357
AU
924 mei_io_cb_free(cb);
925 return rets;
926}
927
928/**
929 * mei_cl_disconnect - disconnect host client from the me one
930 *
931 * @cl: host client
932 *
933 * Locking: called under "dev->device_lock" lock
934 *
935 * Return: 0 on success, <0 on failure.
936 */
937int mei_cl_disconnect(struct mei_cl *cl)
938{
939 struct mei_device *dev;
940 int rets;
941
942 if (WARN_ON(!cl || !cl->dev))
943 return -ENODEV;
944
945 dev = cl->dev;
946
947 cl_dbg(dev, cl, "disconnecting");
948
949 if (!mei_cl_is_connected(cl))
950 return 0;
951
952 if (mei_cl_is_fixed_address(cl)) {
953 mei_cl_set_disconnected(cl);
954 return 0;
955 }
956
957 rets = pm_runtime_get(dev->dev);
958 if (rets < 0 && rets != -EINPROGRESS) {
959 pm_runtime_put_noidle(dev->dev);
960 cl_err(dev, cl, "rpm: get failed %d\n", rets);
961 return rets;
962 }
963
964 rets = __mei_cl_disconnect(cl);
965
04bb139a 966 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
967 pm_runtime_mark_last_busy(dev->dev);
968 pm_runtime_put_autosuspend(dev->dev);
04bb139a 969
9ca9050b
TW
970 return rets;
971}
972
973
974/**
90e0b5f1
TW
975 * mei_cl_is_other_connecting - checks if other
976 * client with the same me client id is connecting
9ca9050b 977 *
9ca9050b
TW
978 * @cl: private data of the file object
979 *
a8605ea2 980 * Return: true if other client is connected, false - otherwise.
9ca9050b 981 */
0c53357c 982static bool mei_cl_is_other_connecting(struct mei_cl *cl)
9ca9050b 983{
90e0b5f1 984 struct mei_device *dev;
0c53357c 985 struct mei_cl_cb *cb;
90e0b5f1
TW
986
987 dev = cl->dev;
988
0c53357c
TW
989 list_for_each_entry(cb, &dev->ctrl_rd_list.list, list) {
990 if (cb->fop_type == MEI_FOP_CONNECT &&
d49ed64a 991 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl))
90e0b5f1 992 return true;
9ca9050b 993 }
90e0b5f1
TW
994
995 return false;
9ca9050b
TW
996}
997
0c53357c
TW
998/**
999 * mei_cl_send_connect - send connect request
1000 *
1001 * @cl: host client
1002 * @cb: callback block
1003 *
1004 * Return: 0, OK; otherwise, error.
1005 */
1006static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
1007{
1008 struct mei_device *dev;
1009 int ret;
1010
1011 dev = cl->dev;
1012
1013 ret = mei_hbm_cl_connect_req(dev, cl);
1014 cl->status = ret;
1015 if (ret) {
1016 cl->state = MEI_FILE_DISCONNECT_REPLY;
1017 return ret;
1018 }
1019
1020 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
1021 cl->timer_count = MEI_CONNECT_TIMEOUT;
1892fc2e 1022 mei_schedule_stall_timer(dev);
0c53357c
TW
1023 return 0;
1024}
1025
1026/**
1027 * mei_cl_irq_connect - send connect request in irq_thread context
1028 *
1029 * @cl: host client
1030 * @cb: callback block
1031 * @cmpl_list: complete list
1032 *
1033 * Return: 0, OK; otherwise, error.
1034 */
1035int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
1036 struct mei_cl_cb *cmpl_list)
1037{
1038 struct mei_device *dev = cl->dev;
1039 u32 msg_slots;
1040 int slots;
1041 int rets;
1042
1043 msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
1044 slots = mei_hbuf_empty_slots(dev);
1045
1046 if (mei_cl_is_other_connecting(cl))
1047 return 0;
1048
1049 if (slots < msg_slots)
1050 return -EMSGSIZE;
1051
1052 rets = mei_cl_send_connect(cl, cb);
1053 if (rets)
1054 list_move_tail(&cb->list, &cmpl_list->list);
1055
1056 return rets;
1057}
1058
9f81abda 1059/**
83ce0741 1060 * mei_cl_connect - connect host client to the me one
9f81abda
TW
1061 *
1062 * @cl: host client
d49ed64a 1063 * @me_cl: me client
3030dc05 1064 * @fp: pointer to file structure
9f81abda
TW
1065 *
1066 * Locking: called under "dev->device_lock" lock
1067 *
a8605ea2 1068 * Return: 0 on success, <0 on failure.
9f81abda 1069 */
d49ed64a 1070int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
3030dc05 1071 const struct file *fp)
9f81abda
TW
1072{
1073 struct mei_device *dev;
1074 struct mei_cl_cb *cb;
9f81abda
TW
1075 int rets;
1076
1df629ef 1077 if (WARN_ON(!cl || !cl->dev || !me_cl))
9f81abda
TW
1078 return -ENODEV;
1079
1080 dev = cl->dev;
1081
5d882460
AU
1082 if (!mei_cl_bus_module_get(cl))
1083 return -ENODEV;
1084
1df629ef
AU
1085 rets = mei_cl_set_connecting(cl, me_cl);
1086 if (rets)
5d882460 1087 goto nortpm;
1df629ef
AU
1088
1089 if (mei_cl_is_fixed_address(cl)) {
1090 cl->state = MEI_FILE_CONNECTED;
5d882460
AU
1091 rets = 0;
1092 goto nortpm;
1df629ef
AU
1093 }
1094
2bf94cab 1095 rets = pm_runtime_get(dev->dev);
04bb139a 1096 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 1097 pm_runtime_put_noidle(dev->dev);
04bb139a 1098 cl_err(dev, cl, "rpm: get failed %d\n", rets);
1df629ef 1099 goto nortpm;
04bb139a
TW
1100 }
1101
3030dc05
TW
1102 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_CONNECT, fp);
1103 if (!cb) {
1104 rets = -ENOMEM;
9f81abda 1105 goto out;
3030dc05 1106 }
0c53357c 1107
6aae48ff
TW
1108 /* run hbuf acquire last so we don't have to undo */
1109 if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
0c53357c
TW
1110 rets = mei_cl_send_connect(cl, cb);
1111 if (rets)
9f81abda 1112 goto out;
9f81abda
TW
1113 }
1114
1115 mutex_unlock(&dev->device_lock);
12f45ed4 1116 wait_event_timeout(cl->wait,
285e2996 1117 (cl->state == MEI_FILE_CONNECTED ||
7ff4bdd4 1118 cl->state == MEI_FILE_DISCONNECTED ||
18901357 1119 cl->state == MEI_FILE_DISCONNECT_REQUIRED ||
3c666182 1120 cl->state == MEI_FILE_DISCONNECT_REPLY),
285e2996 1121 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
9f81abda
TW
1122 mutex_lock(&dev->device_lock);
1123
f3de9b63 1124 if (!mei_cl_is_connected(cl)) {
18901357
AU
1125 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) {
1126 mei_io_list_flush(&dev->ctrl_rd_list, cl);
1127 mei_io_list_flush(&dev->ctrl_wr_list, cl);
1128 /* ignore disconnect return valuue;
1129 * in case of failure reset will be invoked
1130 */
1131 __mei_cl_disconnect(cl);
1132 rets = -EFAULT;
1133 goto out;
1134 }
1135
0c53357c 1136 /* timeout or something went really wrong */
285e2996
AU
1137 if (!cl->status)
1138 cl->status = -EFAULT;
9f81abda
TW
1139 }
1140
1141 rets = cl->status;
9f81abda 1142out:
04bb139a 1143 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
1144 pm_runtime_mark_last_busy(dev->dev);
1145 pm_runtime_put_autosuspend(dev->dev);
04bb139a 1146
9f81abda 1147 mei_io_cb_free(cb);
0c53357c 1148
1df629ef 1149nortpm:
0c53357c
TW
1150 if (!mei_cl_is_connected(cl))
1151 mei_cl_set_disconnected(cl);
1152
9f81abda
TW
1153 return rets;
1154}
1155
03b8d341
TW
1156/**
1157 * mei_cl_alloc_linked - allocate and link host client
1158 *
1159 * @dev: the device structure
03b8d341
TW
1160 *
1161 * Return: cl on success ERR_PTR on failure
1162 */
7851e008 1163struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev)
03b8d341
TW
1164{
1165 struct mei_cl *cl;
1166 int ret;
1167
1168 cl = mei_cl_allocate(dev);
1169 if (!cl) {
1170 ret = -ENOMEM;
1171 goto err;
1172 }
1173
7851e008 1174 ret = mei_cl_link(cl);
03b8d341
TW
1175 if (ret)
1176 goto err;
1177
1178 return cl;
1179err:
1180 kfree(cl);
1181 return ERR_PTR(ret);
1182}
1183
9ca9050b 1184/**
4034b81b 1185 * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.
9ca9050b 1186 *
06ee536b 1187 * @cl: host client
9ca9050b 1188 *
4034b81b 1189 * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.
9ca9050b 1190 */
4034b81b 1191static int mei_cl_tx_flow_ctrl_creds(struct mei_cl *cl)
9ca9050b 1192{
d49ed64a 1193 if (WARN_ON(!cl || !cl->me_cl))
90e0b5f1
TW
1194 return -EINVAL;
1195
4034b81b 1196 if (cl->tx_flow_ctrl_creds > 0)
9ca9050b
TW
1197 return 1;
1198
a808c80c 1199 if (mei_cl_is_fixed_address(cl))
1df629ef 1200 return 1;
1df629ef 1201
d49ed64a 1202 if (mei_cl_is_single_recv_buf(cl)) {
4034b81b 1203 if (cl->me_cl->tx_flow_ctrl_creds > 0)
d49ed64a 1204 return 1;
9ca9050b 1205 }
d49ed64a 1206 return 0;
9ca9050b
TW
1207}
1208
1209/**
4034b81b
TW
1210 * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits
1211 * for a client
9ca9050b 1212 *
4034b81b 1213 * @cl: host client
393b148f 1214 *
a8605ea2 1215 * Return:
9ca9050b 1216 * 0 on success
9ca9050b
TW
1217 * -EINVAL when ctrl credits are <= 0
1218 */
4034b81b 1219static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl)
9ca9050b 1220{
d49ed64a 1221 if (WARN_ON(!cl || !cl->me_cl))
90e0b5f1
TW
1222 return -EINVAL;
1223
1df629ef
AU
1224 if (mei_cl_is_fixed_address(cl))
1225 return 0;
1226
d49ed64a 1227 if (mei_cl_is_single_recv_buf(cl)) {
4034b81b 1228 if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0))
d49ed64a 1229 return -EINVAL;
4034b81b 1230 cl->me_cl->tx_flow_ctrl_creds--;
12d00665 1231 } else {
4034b81b 1232 if (WARN_ON(cl->tx_flow_ctrl_creds <= 0))
d49ed64a 1233 return -EINVAL;
4034b81b 1234 cl->tx_flow_ctrl_creds--;
9ca9050b 1235 }
d49ed64a 1236 return 0;
9ca9050b
TW
1237}
1238
51678ccb
TW
1239/**
1240 * mei_cl_notify_fop2req - convert fop to proper request
1241 *
1242 * @fop: client notification start response command
1243 *
1244 * Return: MEI_HBM_NOTIFICATION_START/STOP
1245 */
1246u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop)
1247{
1248 if (fop == MEI_FOP_NOTIFY_START)
1249 return MEI_HBM_NOTIFICATION_START;
1250 else
1251 return MEI_HBM_NOTIFICATION_STOP;
1252}
1253
1254/**
1255 * mei_cl_notify_req2fop - convert notification request top file operation type
1256 *
1257 * @req: hbm notification request type
1258 *
1259 * Return: MEI_FOP_NOTIFY_START/STOP
1260 */
1261enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)
1262{
1263 if (req == MEI_HBM_NOTIFICATION_START)
1264 return MEI_FOP_NOTIFY_START;
1265 else
1266 return MEI_FOP_NOTIFY_STOP;
1267}
1268
1269/**
1270 * mei_cl_irq_notify - send notification request in irq_thread context
1271 *
1272 * @cl: client
1273 * @cb: callback block.
1274 * @cmpl_list: complete list.
1275 *
1276 * Return: 0 on such and error otherwise.
1277 */
1278int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
1279 struct mei_cl_cb *cmpl_list)
1280{
1281 struct mei_device *dev = cl->dev;
1282 u32 msg_slots;
1283 int slots;
1284 int ret;
1285 bool request;
1286
1287 msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
1288 slots = mei_hbuf_empty_slots(dev);
1289
1290 if (slots < msg_slots)
1291 return -EMSGSIZE;
1292
1293 request = mei_cl_notify_fop2req(cb->fop_type);
1294 ret = mei_hbm_cl_notify_req(dev, cl, request);
1295 if (ret) {
1296 cl->status = ret;
1297 list_move_tail(&cb->list, &cmpl_list->list);
1298 return ret;
1299 }
1300
1301 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
1302 return 0;
1303}
1304
1305/**
1306 * mei_cl_notify_request - send notification stop/start request
1307 *
1308 * @cl: host client
3030dc05 1309 * @fp: associate request with file
51678ccb
TW
1310 * @request: 1 for start or 0 for stop
1311 *
1312 * Locking: called under "dev->device_lock" lock
1313 *
1314 * Return: 0 on such and error otherwise.
1315 */
f23e2cc4 1316int mei_cl_notify_request(struct mei_cl *cl,
3030dc05 1317 const struct file *fp, u8 request)
51678ccb
TW
1318{
1319 struct mei_device *dev;
1320 struct mei_cl_cb *cb;
1321 enum mei_cb_file_ops fop_type;
1322 int rets;
1323
1324 if (WARN_ON(!cl || !cl->dev))
1325 return -ENODEV;
1326
1327 dev = cl->dev;
1328
1329 if (!dev->hbm_f_ev_supported) {
1330 cl_dbg(dev, cl, "notifications not supported\n");
1331 return -EOPNOTSUPP;
1332 }
1333
7c47d2ca
AU
1334 if (!mei_cl_is_connected(cl))
1335 return -ENODEV;
1336
51678ccb
TW
1337 rets = pm_runtime_get(dev->dev);
1338 if (rets < 0 && rets != -EINPROGRESS) {
1339 pm_runtime_put_noidle(dev->dev);
1340 cl_err(dev, cl, "rpm: get failed %d\n", rets);
1341 return rets;
1342 }
1343
1344 fop_type = mei_cl_notify_req2fop(request);
3030dc05 1345 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, fop_type, fp);
51678ccb
TW
1346 if (!cb) {
1347 rets = -ENOMEM;
1348 goto out;
1349 }
1350
1351 if (mei_hbuf_acquire(dev)) {
1352 if (mei_hbm_cl_notify_req(dev, cl, request)) {
1353 rets = -ENODEV;
1354 goto out;
1355 }
3030dc05 1356 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
51678ccb
TW
1357 }
1358
1359 mutex_unlock(&dev->device_lock);
7ff4bdd4
AU
1360 wait_event_timeout(cl->wait,
1361 cl->notify_en == request || !mei_cl_is_connected(cl),
1362 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
51678ccb
TW
1363 mutex_lock(&dev->device_lock);
1364
4a8eaa96
AU
1365 if (cl->notify_en != request && !cl->status)
1366 cl->status = -EFAULT;
51678ccb
TW
1367
1368 rets = cl->status;
1369
1370out:
1371 cl_dbg(dev, cl, "rpm: autosuspend\n");
1372 pm_runtime_mark_last_busy(dev->dev);
1373 pm_runtime_put_autosuspend(dev->dev);
1374
1375 mei_io_cb_free(cb);
1376 return rets;
1377}
1378
237092bf
TW
1379/**
1380 * mei_cl_notify - raise notification
1381 *
1382 * @cl: host client
1383 *
1384 * Locking: called under "dev->device_lock" lock
1385 */
1386void mei_cl_notify(struct mei_cl *cl)
1387{
1388 struct mei_device *dev;
1389
1390 if (!cl || !cl->dev)
1391 return;
1392
1393 dev = cl->dev;
1394
1395 if (!cl->notify_en)
1396 return;
1397
1398 cl_dbg(dev, cl, "notify event");
1399 cl->notify_ev = true;
850f8940
TW
1400 if (!mei_cl_bus_notify_event(cl))
1401 wake_up_interruptible(&cl->ev_wait);
237092bf
TW
1402
1403 if (cl->ev_async)
1404 kill_fasync(&cl->ev_async, SIGIO, POLL_PRI);
bb2ef9c3 1405
237092bf
TW
1406}
1407
b38a362f
TW
1408/**
1409 * mei_cl_notify_get - get or wait for notification event
1410 *
1411 * @cl: host client
1412 * @block: this request is blocking
1413 * @notify_ev: true if notification event was received
1414 *
1415 * Locking: called under "dev->device_lock" lock
1416 *
1417 * Return: 0 on such and error otherwise.
1418 */
1419int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
1420{
1421 struct mei_device *dev;
1422 int rets;
1423
1424 *notify_ev = false;
1425
1426 if (WARN_ON(!cl || !cl->dev))
1427 return -ENODEV;
1428
1429 dev = cl->dev;
1430
6c0d6701
AU
1431 if (!dev->hbm_f_ev_supported) {
1432 cl_dbg(dev, cl, "notifications not supported\n");
1433 return -EOPNOTSUPP;
1434 }
1435
b38a362f
TW
1436 if (!mei_cl_is_connected(cl))
1437 return -ENODEV;
1438
1439 if (cl->notify_ev)
1440 goto out;
1441
1442 if (!block)
1443 return -EAGAIN;
1444
1445 mutex_unlock(&dev->device_lock);
1446 rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev);
1447 mutex_lock(&dev->device_lock);
1448
1449 if (rets < 0)
1450 return rets;
1451
1452out:
1453 *notify_ev = cl->notify_ev;
1454 cl->notify_ev = false;
1455 return 0;
1456}
1457
ab841160 1458/**
393b148f 1459 * mei_cl_read_start - the start read client message function.
ab841160 1460 *
90e0b5f1 1461 * @cl: host client
ce23139c 1462 * @length: number of bytes to read
bca67d68 1463 * @fp: pointer to file structure
ab841160 1464 *
a8605ea2 1465 * Return: 0 on success, <0 on failure.
ab841160 1466 */
f23e2cc4 1467int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
ab841160 1468{
90e0b5f1 1469 struct mei_device *dev;
ab841160 1470 struct mei_cl_cb *cb;
664df38b 1471 int rets;
ab841160 1472
90e0b5f1
TW
1473 if (WARN_ON(!cl || !cl->dev))
1474 return -ENODEV;
1475
1476 dev = cl->dev;
1477
b950ac1d 1478 if (!mei_cl_is_connected(cl))
ab841160
OW
1479 return -ENODEV;
1480
d49ed64a
AU
1481 if (!mei_me_cl_is_active(cl->me_cl)) {
1482 cl_err(dev, cl, "no such me client\n");
7ca96aa2 1483 return -ENOTTY;
664df38b 1484 }
1df629ef 1485
9d27e73c 1486 if (mei_cl_is_fixed_address(cl) || cl == &dev->iamthif_cl)
e51dfa5a
AU
1487 return 0;
1488
46978ada
AU
1489 /* HW currently supports only one pending read */
1490 if (cl->rx_flow_ctrl_creds)
1491 return -EBUSY;
1492
3030dc05 1493 cb = mei_cl_enqueue_ctrl_wr_cb(cl, length, MEI_FOP_READ, fp);
1df629ef
AU
1494 if (!cb)
1495 return -ENOMEM;
1496
2bf94cab 1497 rets = pm_runtime_get(dev->dev);
04bb139a 1498 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 1499 pm_runtime_put_noidle(dev->dev);
04bb139a 1500 cl_err(dev, cl, "rpm: get failed %d\n", rets);
1df629ef 1501 goto nortpm;
04bb139a
TW
1502 }
1503
46978ada 1504 rets = 0;
6aae48ff 1505 if (mei_hbuf_acquire(dev)) {
86113500
AU
1506 rets = mei_hbm_cl_flow_control_req(dev, cl);
1507 if (rets < 0)
04bb139a 1508 goto out;
04bb139a 1509
46978ada 1510 list_move_tail(&cb->list, &cl->rd_pending);
ab841160 1511 }
46978ada 1512 cl->rx_flow_ctrl_creds++;
accb884b 1513
04bb139a
TW
1514out:
1515 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
1516 pm_runtime_mark_last_busy(dev->dev);
1517 pm_runtime_put_autosuspend(dev->dev);
1df629ef 1518nortpm:
04bb139a
TW
1519 if (rets)
1520 mei_io_cb_free(cb);
1521
ab841160
OW
1522 return rets;
1523}
1524
21767546 1525/**
9d098192 1526 * mei_cl_irq_write - write a message to device
21767546
TW
1527 * from the interrupt thread context
1528 *
1529 * @cl: client
1530 * @cb: callback block.
21767546
TW
1531 * @cmpl_list: complete list.
1532 *
a8605ea2 1533 * Return: 0, OK; otherwise error.
21767546 1534 */
9d098192
TW
1535int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
1536 struct mei_cl_cb *cmpl_list)
21767546 1537{
136698e5
TW
1538 struct mei_device *dev;
1539 struct mei_msg_data *buf;
21767546 1540 struct mei_msg_hdr mei_hdr;
136698e5
TW
1541 size_t len;
1542 u32 msg_slots;
9d098192 1543 int slots;
2ebf8c94 1544 int rets;
b8b73035 1545 bool first_chunk;
21767546 1546
136698e5
TW
1547 if (WARN_ON(!cl || !cl->dev))
1548 return -ENODEV;
1549
1550 dev = cl->dev;
1551
5db7514d 1552 buf = &cb->buf;
136698e5 1553
b8b73035
AU
1554 first_chunk = cb->buf_idx == 0;
1555
4034b81b 1556 rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;
136698e5 1557 if (rets < 0)
e09ee853 1558 goto err;
136698e5
TW
1559
1560 if (rets == 0) {
04bb139a 1561 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
136698e5
TW
1562 return 0;
1563 }
1564
9d098192 1565 slots = mei_hbuf_empty_slots(dev);
136698e5
TW
1566 len = buf->size - cb->buf_idx;
1567 msg_slots = mei_data2slots(len);
1568
1df629ef 1569 mei_hdr.host_addr = mei_cl_host_addr(cl);
d49ed64a 1570 mei_hdr.me_addr = mei_cl_me_id(cl);
21767546 1571 mei_hdr.reserved = 0;
479327fc 1572 mei_hdr.internal = cb->internal;
21767546 1573
9d098192 1574 if (slots >= msg_slots) {
21767546
TW
1575 mei_hdr.length = len;
1576 mei_hdr.msg_complete = 1;
1577 /* Split the message only if we can write the whole host buffer */
9d098192
TW
1578 } else if (slots == dev->hbuf_depth) {
1579 msg_slots = slots;
1580 len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
21767546
TW
1581 mei_hdr.length = len;
1582 mei_hdr.msg_complete = 0;
1583 } else {
1584 /* wait for next time the host buffer is empty */
1585 return 0;
1586 }
1587
35bf7692 1588 cl_dbg(dev, cl, "buf: size = %zu idx = %zu\n",
5db7514d 1589 cb->buf.size, cb->buf_idx);
21767546 1590
136698e5 1591 rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
e09ee853
AU
1592 if (rets)
1593 goto err;
21767546
TW
1594
1595 cl->status = 0;
4dfaa9f7 1596 cl->writing_state = MEI_WRITING;
21767546 1597 cb->buf_idx += mei_hdr.length;
8660172e 1598 cb->completed = mei_hdr.msg_complete == 1;
4dfaa9f7 1599
b8b73035 1600 if (first_chunk) {
e09ee853
AU
1601 if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
1602 rets = -EIO;
1603 goto err;
1604 }
21767546
TW
1605 }
1606
b8b73035
AU
1607 if (mei_hdr.msg_complete)
1608 list_move_tail(&cb->list, &dev->write_waiting_list.list);
1609
21767546 1610 return 0;
e09ee853
AU
1611
1612err:
1613 cl->status = rets;
1614 list_move_tail(&cb->list, &cmpl_list->list);
1615 return rets;
21767546
TW
1616}
1617
4234a6de
TW
1618/**
1619 * mei_cl_write - submit a write cb to mei device
a8605ea2 1620 * assumes device_lock is locked
4234a6de
TW
1621 *
1622 * @cl: host client
a8605ea2 1623 * @cb: write callback with filled data
4234a6de 1624 *
a8605ea2 1625 * Return: number of bytes sent on success, <0 on failure.
4234a6de 1626 */
e0cb6b2f 1627int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
4234a6de
TW
1628{
1629 struct mei_device *dev;
1630 struct mei_msg_data *buf;
1631 struct mei_msg_hdr mei_hdr;
23253c31 1632 int size;
4234a6de 1633 int rets;
e0cb6b2f 1634 bool blocking;
4234a6de
TW
1635
1636 if (WARN_ON(!cl || !cl->dev))
1637 return -ENODEV;
1638
1639 if (WARN_ON(!cb))
1640 return -EINVAL;
1641
1642 dev = cl->dev;
1643
5db7514d 1644 buf = &cb->buf;
23253c31 1645 size = buf->size;
e0cb6b2f 1646 blocking = cb->blocking;
4234a6de 1647
23253c31 1648 cl_dbg(dev, cl, "size=%d\n", size);
4234a6de 1649
2bf94cab 1650 rets = pm_runtime_get(dev->dev);
04bb139a 1651 if (rets < 0 && rets != -EINPROGRESS) {
2bf94cab 1652 pm_runtime_put_noidle(dev->dev);
04bb139a 1653 cl_err(dev, cl, "rpm: get failed %d\n", rets);
6cbb097f 1654 goto free;
04bb139a 1655 }
4234a6de 1656
6aae48ff
TW
1657 cb->buf_idx = 0;
1658 cl->writing_state = MEI_IDLE;
1659
1df629ef 1660 mei_hdr.host_addr = mei_cl_host_addr(cl);
d49ed64a 1661 mei_hdr.me_addr = mei_cl_me_id(cl);
6aae48ff
TW
1662 mei_hdr.reserved = 0;
1663 mei_hdr.msg_complete = 0;
1664 mei_hdr.internal = cb->internal;
4234a6de 1665
4034b81b 1666 rets = mei_cl_tx_flow_ctrl_creds(cl);
4234a6de
TW
1667 if (rets < 0)
1668 goto err;
1669
6aae48ff
TW
1670 if (rets == 0) {
1671 cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
23253c31 1672 rets = size;
6aae48ff
TW
1673 goto out;
1674 }
1675 if (!mei_hbuf_acquire(dev)) {
1676 cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
23253c31 1677 rets = size;
4234a6de
TW
1678 goto out;
1679 }
4234a6de
TW
1680
1681 /* Check for a maximum length */
23253c31 1682 if (size > mei_hbuf_max_len(dev)) {
4234a6de
TW
1683 mei_hdr.length = mei_hbuf_max_len(dev);
1684 mei_hdr.msg_complete = 0;
1685 } else {
23253c31 1686 mei_hdr.length = size;
4234a6de
TW
1687 mei_hdr.msg_complete = 1;
1688 }
1689
2ebf8c94
TW
1690 rets = mei_write_message(dev, &mei_hdr, buf->data);
1691 if (rets)
4234a6de 1692 goto err;
4234a6de 1693
4034b81b 1694 rets = mei_cl_tx_flow_ctrl_creds_reduce(cl);
b8b73035
AU
1695 if (rets)
1696 goto err;
1697
4234a6de
TW
1698 cl->writing_state = MEI_WRITING;
1699 cb->buf_idx = mei_hdr.length;
8660172e 1700 cb->completed = mei_hdr.msg_complete == 1;
4234a6de 1701
4234a6de 1702out:
b8b73035 1703 if (mei_hdr.msg_complete)
4234a6de 1704 list_add_tail(&cb->list, &dev->write_waiting_list.list);
b8b73035 1705 else
4234a6de 1706 list_add_tail(&cb->list, &dev->write_list.list);
4234a6de 1707
23253c31 1708 cb = NULL;
4234a6de
TW
1709 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
1710
1711 mutex_unlock(&dev->device_lock);
7ca96aa2 1712 rets = wait_event_interruptible(cl->tx_wait,
0faf6a3b
AU
1713 cl->writing_state == MEI_WRITE_COMPLETE ||
1714 (!mei_cl_is_connected(cl)));
4234a6de 1715 mutex_lock(&dev->device_lock);
7ca96aa2
AU
1716 /* wait_event_interruptible returns -ERESTARTSYS */
1717 if (rets) {
1718 if (signal_pending(current))
1719 rets = -EINTR;
1720 goto err;
1721 }
0faf6a3b
AU
1722 if (cl->writing_state != MEI_WRITE_COMPLETE) {
1723 rets = -EFAULT;
1724 goto err;
1725 }
4234a6de 1726 }
7ca96aa2 1727
23253c31 1728 rets = size;
4234a6de 1729err:
04bb139a 1730 cl_dbg(dev, cl, "rpm: autosuspend\n");
2bf94cab
TW
1731 pm_runtime_mark_last_busy(dev->dev);
1732 pm_runtime_put_autosuspend(dev->dev);
6cbb097f
AU
1733free:
1734 mei_io_cb_free(cb);
04bb139a 1735
4234a6de
TW
1736 return rets;
1737}
1738
1739
db086fa9
TW
1740/**
1741 * mei_cl_complete - processes completed operation for a client
1742 *
1743 * @cl: private data of the file object.
1744 * @cb: callback block.
1745 */
1746void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
1747{
a1809d38
AU
1748 struct mei_device *dev = cl->dev;
1749
3c666182
TW
1750 switch (cb->fop_type) {
1751 case MEI_FOP_WRITE:
db086fa9 1752 mei_io_cb_free(cb);
db086fa9 1753 cl->writing_state = MEI_WRITE_COMPLETE;
a1809d38 1754 if (waitqueue_active(&cl->tx_wait)) {
db086fa9 1755 wake_up_interruptible(&cl->tx_wait);
a1809d38
AU
1756 } else {
1757 pm_runtime_mark_last_busy(dev->dev);
1758 pm_request_autosuspend(dev->dev);
1759 }
3c666182 1760 break;
db086fa9 1761
3c666182 1762 case MEI_FOP_READ:
a9bed610 1763 list_add_tail(&cb->list, &cl->rd_completed);
46978ada
AU
1764 if (!mei_cl_is_fixed_address(cl) &&
1765 !WARN_ON(!cl->rx_flow_ctrl_creds))
1766 cl->rx_flow_ctrl_creds--;
a1f9ae2b
TW
1767 if (!mei_cl_bus_rx_event(cl))
1768 wake_up_interruptible(&cl->rx_wait);
3c666182
TW
1769 break;
1770
1771 case MEI_FOP_CONNECT:
1772 case MEI_FOP_DISCONNECT:
51678ccb
TW
1773 case MEI_FOP_NOTIFY_STOP:
1774 case MEI_FOP_NOTIFY_START:
3c666182
TW
1775 if (waitqueue_active(&cl->wait))
1776 wake_up(&cl->wait);
db086fa9 1777
6a8d648c
AU
1778 break;
1779 case MEI_FOP_DISCONNECT_RSP:
1780 mei_io_cb_free(cb);
1781 mei_cl_set_disconnected(cl);
3c666182
TW
1782 break;
1783 default:
1784 BUG_ON(0);
db086fa9
TW
1785 }
1786}
1787
4234a6de 1788
074b4c01
TW
1789/**
1790 * mei_cl_all_disconnect - disconnect forcefully all connected clients
1791 *
a8605ea2 1792 * @dev: mei device
074b4c01 1793 */
074b4c01
TW
1794void mei_cl_all_disconnect(struct mei_device *dev)
1795{
31f88f57 1796 struct mei_cl *cl;
074b4c01 1797
3c666182
TW
1798 list_for_each_entry(cl, &dev->file_list, link)
1799 mei_cl_set_disconnected(cl);
074b4c01 1800}