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