xref: /openbmc/linux/drivers/misc/mei/client.c (revision 781d0d89)
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2012, Intel Corporation.
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 
17 #include <linux/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/delay.h>
21 
22 #include <linux/mei.h>
23 
24 #include "mei_dev.h"
25 #include "hbm.h"
26 #include "client.h"
27 
28 /**
29  * mei_me_cl_by_uuid - locate index of me client
30  *
31  * @dev: mei device
32  * returns me client index or -ENOENT if not found
33  */
34 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
35 {
36 	int i, res = -ENOENT;
37 
38 	for (i = 0; i < dev->me_clients_num; ++i)
39 		if (uuid_le_cmp(*uuid,
40 				dev->me_clients[i].props.protocol_name) == 0) {
41 			res = i;
42 			break;
43 		}
44 
45 	return res;
46 }
47 
48 
49 /**
50  * mei_me_cl_by_id return index to me_clients for client_id
51  *
52  * @dev: the device structure
53  * @client_id: me client id
54  *
55  * Locking: called under "dev->device_lock" lock
56  *
57  * returns index on success, -ENOENT on failure.
58  */
59 
60 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
61 {
62 	int i;
63 	for (i = 0; i < dev->me_clients_num; i++)
64 		if (dev->me_clients[i].client_id == client_id)
65 			break;
66 	if (WARN_ON(dev->me_clients[i].client_id != client_id))
67 		return -ENOENT;
68 
69 	if (i == dev->me_clients_num)
70 		return -ENOENT;
71 
72 	return i;
73 }
74 
75 
76 /**
77  * mei_io_list_flush - removes list entry belonging to cl.
78  *
79  * @list:  An instance of our list structure
80  * @cl: host client
81  */
82 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
83 {
84 	struct mei_cl_cb *cb;
85 	struct mei_cl_cb *next;
86 
87 	list_for_each_entry_safe(cb, next, &list->list, list) {
88 		if (cb->cl && mei_cl_cmp_id(cl, cb->cl))
89 			list_del(&cb->list);
90 	}
91 }
92 
93 /**
94  * mei_io_cb_free - free mei_cb_private related memory
95  *
96  * @cb: mei callback struct
97  */
98 void mei_io_cb_free(struct mei_cl_cb *cb)
99 {
100 	if (cb == NULL)
101 		return;
102 
103 	kfree(cb->request_buffer.data);
104 	kfree(cb->response_buffer.data);
105 	kfree(cb);
106 }
107 
108 /**
109  * mei_io_cb_init - allocate and initialize io callback
110  *
111  * @cl - mei client
112  * @file: pointer to file structure
113  *
114  * returns mei_cl_cb pointer or NULL;
115  */
116 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
117 {
118 	struct mei_cl_cb *cb;
119 
120 	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
121 	if (!cb)
122 		return NULL;
123 
124 	mei_io_list_init(cb);
125 
126 	cb->file_object = fp;
127 	cb->cl = cl;
128 	cb->buf_idx = 0;
129 	return cb;
130 }
131 
132 /**
133  * mei_io_cb_alloc_req_buf - allocate request buffer
134  *
135  * @cb -  io callback structure
136  * @size: size of the buffer
137  *
138  * returns 0 on success
139  *         -EINVAL if cb is NULL
140  *         -ENOMEM if allocation failed
141  */
142 int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
143 {
144 	if (!cb)
145 		return -EINVAL;
146 
147 	if (length == 0)
148 		return 0;
149 
150 	cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
151 	if (!cb->request_buffer.data)
152 		return -ENOMEM;
153 	cb->request_buffer.size = length;
154 	return 0;
155 }
156 /**
157  * mei_io_cb_alloc_req_buf - allocate respose buffer
158  *
159  * @cb -  io callback structure
160  * @size: size of the buffer
161  *
162  * returns 0 on success
163  *         -EINVAL if cb is NULL
164  *         -ENOMEM if allocation failed
165  */
166 int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
167 {
168 	if (!cb)
169 		return -EINVAL;
170 
171 	if (length == 0)
172 		return 0;
173 
174 	cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
175 	if (!cb->response_buffer.data)
176 		return -ENOMEM;
177 	cb->response_buffer.size = length;
178 	return 0;
179 }
180 
181 
182 
183 /**
184  * mei_cl_flush_queues - flushes queue lists belonging to cl.
185  *
186  * @dev: the device structure
187  * @cl: host client
188  */
189 int mei_cl_flush_queues(struct mei_cl *cl)
190 {
191 	if (WARN_ON(!cl || !cl->dev))
192 		return -EINVAL;
193 
194 	dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
195 	mei_io_list_flush(&cl->dev->read_list, cl);
196 	mei_io_list_flush(&cl->dev->write_list, cl);
197 	mei_io_list_flush(&cl->dev->write_waiting_list, cl);
198 	mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
199 	mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
200 	mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
201 	mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
202 	return 0;
203 }
204 
205 
206 /**
207  * mei_cl_init - initializes intialize cl.
208  *
209  * @cl: host client to be initialized
210  * @dev: mei device
211  */
212 void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
213 {
214 	memset(cl, 0, sizeof(struct mei_cl));
215 	init_waitqueue_head(&cl->wait);
216 	init_waitqueue_head(&cl->rx_wait);
217 	init_waitqueue_head(&cl->tx_wait);
218 	INIT_LIST_HEAD(&cl->link);
219 	cl->reading_state = MEI_IDLE;
220 	cl->writing_state = MEI_IDLE;
221 	cl->dev = dev;
222 }
223 
224 /**
225  * mei_cl_allocate - allocates cl  structure and sets it up.
226  *
227  * @dev: mei device
228  * returns  The allocated file or NULL on failure
229  */
230 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
231 {
232 	struct mei_cl *cl;
233 
234 	cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
235 	if (!cl)
236 		return NULL;
237 
238 	mei_cl_init(cl, dev);
239 
240 	return cl;
241 }
242 
243 /**
244  * mei_cl_find_read_cb - find this cl's callback in the read list
245  *
246  * @dev: device structure
247  * returns cb on success, NULL on error
248  */
249 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
250 {
251 	struct mei_device *dev = cl->dev;
252 	struct mei_cl_cb *cb = NULL;
253 	struct mei_cl_cb *next = NULL;
254 
255 	list_for_each_entry_safe(cb, next, &dev->read_list.list, list)
256 		if (mei_cl_cmp_id(cl, cb->cl))
257 			return cb;
258 	return NULL;
259 }
260 
261 /** mei_cl_link: allocte host id in the host map
262  *
263  * @cl - host client
264  * @id - fixed host id or -1 for genereting one
265  * returns 0 on success
266  *	-EINVAL on incorrect values
267  *	-ENONET if client not found
268  */
269 int mei_cl_link(struct mei_cl *cl, int id)
270 {
271 	struct mei_device *dev;
272 
273 	if (WARN_ON(!cl || !cl->dev))
274 		return -EINVAL;
275 
276 	dev = cl->dev;
277 
278 	/* If Id is not asigned get one*/
279 	if (id == MEI_HOST_CLIENT_ID_ANY)
280 		id = find_first_zero_bit(dev->host_clients_map,
281 					MEI_CLIENTS_MAX);
282 
283 	if (id >= MEI_CLIENTS_MAX) {
284 		dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ;
285 		return -ENOENT;
286 	}
287 
288 	dev->open_handle_count++;
289 
290 	cl->host_client_id = id;
291 	list_add_tail(&cl->link, &dev->file_list);
292 
293 	set_bit(id, dev->host_clients_map);
294 
295 	cl->state = MEI_FILE_INITIALIZING;
296 
297 	dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
298 	return 0;
299 }
300 
301 /**
302  * mei_cl_unlink - remove me_cl from the list
303  *
304  * @dev: the device structure
305  */
306 int mei_cl_unlink(struct mei_cl *cl)
307 {
308 	struct mei_device *dev;
309 	struct mei_cl *pos, *next;
310 
311 	/* don't shout on error exit path */
312 	if (!cl)
313 		return 0;
314 
315 	if (WARN_ON(!cl->dev))
316 		return -EINVAL;
317 
318 	dev = cl->dev;
319 
320 	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
321 		if (cl->host_client_id == pos->host_client_id) {
322 			dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
323 				pos->host_client_id, pos->me_client_id);
324 			list_del_init(&pos->link);
325 			break;
326 		}
327 	}
328 	return 0;
329 }
330 
331 
332 void mei_host_client_init(struct work_struct *work)
333 {
334 	struct mei_device *dev = container_of(work,
335 					      struct mei_device, init_work);
336 	struct mei_client_properties *client_props;
337 	int i;
338 
339 	mutex_lock(&dev->device_lock);
340 
341 	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
342 	dev->open_handle_count = 0;
343 
344 	/*
345 	 * Reserving the first three client IDs
346 	 * 0: Reserved for MEI Bus Message communications
347 	 * 1: Reserved for Watchdog
348 	 * 2: Reserved for AMTHI
349 	 */
350 	bitmap_set(dev->host_clients_map, 0, 3);
351 
352 	for (i = 0; i < dev->me_clients_num; i++) {
353 		client_props = &dev->me_clients[i].props;
354 
355 		if (!uuid_le_cmp(client_props->protocol_name, mei_amthif_guid))
356 			mei_amthif_host_init(dev);
357 		else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
358 			mei_wd_host_init(dev);
359 	}
360 
361 	dev->dev_state = MEI_DEV_ENABLED;
362 
363 	mutex_unlock(&dev->device_lock);
364 }
365 
366 
367 /**
368  * mei_cl_disconnect - disconnect host clinet form the me one
369  *
370  * @cl: host client
371  *
372  * Locking: called under "dev->device_lock" lock
373  *
374  * returns 0 on success, <0 on failure.
375  */
376 int mei_cl_disconnect(struct mei_cl *cl)
377 {
378 	struct mei_device *dev;
379 	struct mei_cl_cb *cb;
380 	int rets, err;
381 
382 	if (WARN_ON(!cl || !cl->dev))
383 		return -ENODEV;
384 
385 	dev = cl->dev;
386 
387 	if (cl->state != MEI_FILE_DISCONNECTING)
388 		return 0;
389 
390 	cb = mei_io_cb_init(cl, NULL);
391 	if (!cb)
392 		return -ENOMEM;
393 
394 	cb->fop_type = MEI_FOP_CLOSE;
395 	if (dev->mei_host_buffer_is_empty) {
396 		dev->mei_host_buffer_is_empty = false;
397 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
398 			rets = -ENODEV;
399 			dev_err(&dev->pdev->dev, "failed to disconnect.\n");
400 			goto free;
401 		}
402 		mdelay(10); /* Wait for hardware disconnection ready */
403 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
404 	} else {
405 		dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
406 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
407 
408 	}
409 	mutex_unlock(&dev->device_lock);
410 
411 	err = wait_event_timeout(dev->wait_recvd_msg,
412 			MEI_FILE_DISCONNECTED == cl->state,
413 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
414 
415 	mutex_lock(&dev->device_lock);
416 	if (MEI_FILE_DISCONNECTED == cl->state) {
417 		rets = 0;
418 		dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
419 	} else {
420 		rets = -ENODEV;
421 		if (MEI_FILE_DISCONNECTED != cl->state)
422 			dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
423 
424 		if (err)
425 			dev_dbg(&dev->pdev->dev,
426 					"wait failed disconnect err=%08x\n",
427 					err);
428 
429 		dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
430 	}
431 
432 	mei_io_list_flush(&dev->ctrl_rd_list, cl);
433 	mei_io_list_flush(&dev->ctrl_wr_list, cl);
434 free:
435 	mei_io_cb_free(cb);
436 	return rets;
437 }
438 
439 
440 /**
441  * mei_cl_is_other_connecting - checks if other
442  *    client with the same me client id is connecting
443  *
444  * @cl: private data of the file object
445  *
446  * returns ture if other client is connected, 0 - otherwise.
447  */
448 bool mei_cl_is_other_connecting(struct mei_cl *cl)
449 {
450 	struct mei_device *dev;
451 	struct mei_cl *pos;
452 	struct mei_cl *next;
453 
454 	if (WARN_ON(!cl || !cl->dev))
455 		return false;
456 
457 	dev = cl->dev;
458 
459 	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
460 		if ((pos->state == MEI_FILE_CONNECTING) &&
461 		    (pos != cl) && cl->me_client_id == pos->me_client_id)
462 			return true;
463 
464 	}
465 
466 	return false;
467 }
468 
469 /**
470  * mei_cl_connect - connect host clinet to the me one
471  *
472  * @cl: host client
473  *
474  * Locking: called under "dev->device_lock" lock
475  *
476  * returns 0 on success, <0 on failure.
477  */
478 int mei_cl_connect(struct mei_cl *cl, struct file *file)
479 {
480 	struct mei_device *dev;
481 	struct mei_cl_cb *cb;
482 	long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
483 	int rets;
484 
485 	if (WARN_ON(!cl || !cl->dev))
486 		return -ENODEV;
487 
488 	dev = cl->dev;
489 
490 	cb = mei_io_cb_init(cl, file);
491 	if (!cb) {
492 		rets = -ENOMEM;
493 		goto out;
494 	}
495 
496 	cb->fop_type = MEI_FOP_IOCTL;
497 
498 	if (dev->mei_host_buffer_is_empty &&
499 	    !mei_cl_is_other_connecting(cl)) {
500 		dev->mei_host_buffer_is_empty = false;
501 
502 		if (mei_hbm_cl_connect_req(dev, cl)) {
503 			rets = -ENODEV;
504 			goto out;
505 		}
506 		cl->timer_count = MEI_CONNECT_TIMEOUT;
507 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
508 	} else {
509 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
510 	}
511 
512 	mutex_unlock(&dev->device_lock);
513 	rets = wait_event_timeout(dev->wait_recvd_msg,
514 				 (cl->state == MEI_FILE_CONNECTED ||
515 				  cl->state == MEI_FILE_DISCONNECTED),
516 				 timeout * HZ);
517 	mutex_lock(&dev->device_lock);
518 
519 	if (cl->state != MEI_FILE_CONNECTED) {
520 		rets = -EFAULT;
521 
522 		mei_io_list_flush(&dev->ctrl_rd_list, cl);
523 		mei_io_list_flush(&dev->ctrl_wr_list, cl);
524 		goto out;
525 	}
526 
527 	rets = cl->status;
528 
529 out:
530 	mei_io_cb_free(cb);
531 	return rets;
532 }
533 
534 /**
535  * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
536  *
537  * @dev: the device structure
538  * @cl: private data of the file object
539  *
540  * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
541  *	-ENOENT if mei_cl is not present
542  *	-EINVAL if single_recv_buf == 0
543  */
544 int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
545 {
546 	struct mei_device *dev;
547 	int i;
548 
549 	if (WARN_ON(!cl || !cl->dev))
550 		return -EINVAL;
551 
552 	dev = cl->dev;
553 
554 	if (!dev->me_clients_num)
555 		return 0;
556 
557 	if (cl->mei_flow_ctrl_creds > 0)
558 		return 1;
559 
560 	for (i = 0; i < dev->me_clients_num; i++) {
561 		struct mei_me_client  *me_cl = &dev->me_clients[i];
562 		if (me_cl->client_id == cl->me_client_id) {
563 			if (me_cl->mei_flow_ctrl_creds) {
564 				if (WARN_ON(me_cl->props.single_recv_buf == 0))
565 					return -EINVAL;
566 				return 1;
567 			} else {
568 				return 0;
569 			}
570 		}
571 	}
572 	return -ENOENT;
573 }
574 
575 /**
576  * mei_cl_flow_ctrl_reduce - reduces flow_control.
577  *
578  * @dev: the device structure
579  * @cl: private data of the file object
580  * @returns
581  *	0 on success
582  *	-ENOENT when me client is not found
583  *	-EINVAL when ctrl credits are <= 0
584  */
585 int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
586 {
587 	struct mei_device *dev;
588 	int i;
589 
590 	if (WARN_ON(!cl || !cl->dev))
591 		return -EINVAL;
592 
593 	dev = cl->dev;
594 
595 	if (!dev->me_clients_num)
596 		return -ENOENT;
597 
598 	for (i = 0; i < dev->me_clients_num; i++) {
599 		struct mei_me_client  *me_cl = &dev->me_clients[i];
600 		if (me_cl->client_id == cl->me_client_id) {
601 			if (me_cl->props.single_recv_buf != 0) {
602 				if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
603 					return -EINVAL;
604 				dev->me_clients[i].mei_flow_ctrl_creds--;
605 			} else {
606 				if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
607 					return -EINVAL;
608 				cl->mei_flow_ctrl_creds--;
609 			}
610 			return 0;
611 		}
612 	}
613 	return -ENOENT;
614 }
615 
616 /**
617  * mei_cl_start_read - the start read client message function.
618  *
619  * @cl: host client
620  *
621  * returns 0 on success, <0 on failure.
622  */
623 int mei_cl_read_start(struct mei_cl *cl)
624 {
625 	struct mei_device *dev;
626 	struct mei_cl_cb *cb;
627 	int rets;
628 	int i;
629 
630 	if (WARN_ON(!cl || !cl->dev))
631 		return -ENODEV;
632 
633 	dev = cl->dev;
634 
635 	if (cl->state != MEI_FILE_CONNECTED)
636 		return -ENODEV;
637 
638 	if (dev->dev_state != MEI_DEV_ENABLED)
639 		return -ENODEV;
640 
641 	if (cl->read_cb) {
642 		dev_dbg(&dev->pdev->dev, "read is pending.\n");
643 		return -EBUSY;
644 	}
645 	i = mei_me_cl_by_id(dev, cl->me_client_id);
646 	if (i < 0) {
647 		dev_err(&dev->pdev->dev, "no such me client %d\n",
648 			cl->me_client_id);
649 		return  -ENODEV;
650 	}
651 
652 	cb = mei_io_cb_init(cl, NULL);
653 	if (!cb)
654 		return -ENOMEM;
655 
656 	rets = mei_io_cb_alloc_resp_buf(cb,
657 			dev->me_clients[i].props.max_msg_length);
658 	if (rets)
659 		goto err;
660 
661 	cb->fop_type = MEI_FOP_READ;
662 	cl->read_cb = cb;
663 	if (dev->mei_host_buffer_is_empty) {
664 		dev->mei_host_buffer_is_empty = false;
665 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
666 			rets = -ENODEV;
667 			goto err;
668 		}
669 		list_add_tail(&cb->list, &dev->read_list.list);
670 	} else {
671 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
672 	}
673 	return rets;
674 err:
675 	mei_io_cb_free(cb);
676 	return rets;
677 }
678 
679