3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
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.
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
17 #include <linux/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/delay.h>
22 #include <linux/mei.h>
26 #include "interface.h"
30 * mei_me_cl_by_uuid - locate index of me client
33 * returns me client index or -ENOENT if not found
35 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
39 for (i = 0; i < dev->me_clients_num; ++i)
40 if (uuid_le_cmp(*uuid,
41 dev->me_clients[i].props.protocol_name) == 0) {
51 * mei_me_cl_by_id return index to me_clients for client_id
53 * @dev: the device structure
54 * @client_id: me client id
56 * Locking: called under "dev->device_lock" lock
58 * returns index on success, -ENOENT on failure.
61 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
64 for (i = 0; i < dev->me_clients_num; i++)
65 if (dev->me_clients[i].client_id == client_id)
67 if (WARN_ON(dev->me_clients[i].client_id != client_id))
70 if (i == dev->me_clients_num)
78 * mei_io_list_flush - removes list entry belonging to cl.
80 * @list: An instance of our list structure
83 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
86 struct mei_cl_cb *next;
88 list_for_each_entry_safe(cb, next, &list->list, list) {
89 if (cb->cl && mei_cl_cmp_id(cl, cb->cl))
95 * mei_io_cb_free - free mei_cb_private related memory
97 * @cb: mei callback struct
99 void mei_io_cb_free(struct mei_cl_cb *cb)
104 kfree(cb->request_buffer.data);
105 kfree(cb->response_buffer.data);
110 * mei_io_cb_init - allocate and initialize io callback
113 * @file: pointer to file structure
115 * returns mei_cl_cb pointer or NULL;
117 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
119 struct mei_cl_cb *cb;
121 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
125 mei_io_list_init(cb);
127 cb->file_object = fp;
134 * mei_io_cb_alloc_req_buf - allocate request buffer
136 * @cb - io callback structure
137 * @size: size of the buffer
139 * returns 0 on success
140 * -EINVAL if cb is NULL
141 * -ENOMEM if allocation failed
143 int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
151 cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
152 if (!cb->request_buffer.data)
154 cb->request_buffer.size = length;
158 * mei_io_cb_alloc_req_buf - allocate respose buffer
160 * @cb - io callback structure
161 * @size: size of the buffer
163 * returns 0 on success
164 * -EINVAL if cb is NULL
165 * -ENOMEM if allocation failed
167 int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
175 cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
176 if (!cb->response_buffer.data)
178 cb->response_buffer.size = length;
185 * mei_cl_flush_queues - flushes queue lists belonging to cl.
187 * @dev: the device structure
190 int mei_cl_flush_queues(struct mei_cl *cl)
192 if (WARN_ON(!cl || !cl->dev))
195 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
196 mei_io_list_flush(&cl->dev->read_list, cl);
197 mei_io_list_flush(&cl->dev->write_list, cl);
198 mei_io_list_flush(&cl->dev->write_waiting_list, cl);
199 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
200 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
201 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
202 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
208 * mei_cl_init - initializes intialize cl.
210 * @cl: host client to be initialized
213 void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
215 memset(cl, 0, sizeof(struct mei_cl));
216 init_waitqueue_head(&cl->wait);
217 init_waitqueue_head(&cl->rx_wait);
218 init_waitqueue_head(&cl->tx_wait);
219 INIT_LIST_HEAD(&cl->link);
220 cl->reading_state = MEI_IDLE;
221 cl->writing_state = MEI_IDLE;
226 * mei_cl_allocate - allocates cl structure and sets it up.
229 * returns The allocated file or NULL on failure
231 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
235 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
239 mei_cl_init(cl, dev);
245 * mei_cl_find_read_cb - find this cl's callback in the read list
247 * @dev: device structure
248 * returns cb on success, NULL on error
250 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
252 struct mei_device *dev = cl->dev;
253 struct mei_cl_cb *cb = NULL;
254 struct mei_cl_cb *next = NULL;
256 list_for_each_entry_safe(cb, next, &dev->read_list.list, list)
257 if (mei_cl_cmp_id(cl, cb->cl))
264 * mei_me_cl_link - create link between host and me clinet and add
267 * @cl: link between me and host client assocated with opened file descriptor
268 * @uuid: uuid of ME client
269 * @client_id: id of the host client
271 * returns ME client index if ME client
272 * -EINVAL on incorrect values
273 * -ENONET if client not found
275 int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id)
277 struct mei_device *dev;
280 if (WARN_ON(!cl || !cl->dev || !uuid))
285 /* check for valid client id */
286 i = mei_me_cl_by_uuid(dev, uuid);
288 cl->me_client_id = dev->me_clients[i].client_id;
289 cl->state = MEI_FILE_CONNECTING;
290 cl->host_client_id = host_cl_id;
292 list_add_tail(&cl->link, &dev->file_list);
299 * mei_cl_unlink - remove me_cl from the list
301 * @dev: the device structure
302 * @host_client_id: host client id to be removed
304 int mei_cl_unlink(struct mei_cl *cl)
306 struct mei_device *dev;
307 struct mei_cl *pos, *next;
309 if (WARN_ON(!cl || !cl->dev))
314 list_for_each_entry_safe(pos, next, &dev->file_list, link) {
315 if (cl->host_client_id == pos->host_client_id) {
316 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
317 pos->host_client_id, pos->me_client_id);
318 list_del_init(&pos->link);
326 void mei_host_client_init(struct work_struct *work)
328 struct mei_device *dev = container_of(work,
329 struct mei_device, init_work);
330 struct mei_client_properties *client_props;
333 mutex_lock(&dev->device_lock);
335 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
336 dev->open_handle_count = 0;
339 * Reserving the first three client IDs
340 * 0: Reserved for MEI Bus Message communications
341 * 1: Reserved for Watchdog
342 * 2: Reserved for AMTHI
344 bitmap_set(dev->host_clients_map, 0, 3);
346 for (i = 0; i < dev->me_clients_num; i++) {
347 client_props = &dev->me_clients[i].props;
349 if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
350 mei_amthif_host_init(dev);
351 else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
352 mei_wd_host_init(dev);
355 dev->dev_state = MEI_DEV_ENABLED;
357 mutex_unlock(&dev->device_lock);
362 * mei_cl_disconnect - disconnect host clinet form the me one
366 * Locking: called under "dev->device_lock" lock
368 * returns 0 on success, <0 on failure.
370 int mei_cl_disconnect(struct mei_cl *cl)
372 struct mei_device *dev;
373 struct mei_cl_cb *cb;
376 if (WARN_ON(!cl || !cl->dev))
381 if (cl->state != MEI_FILE_DISCONNECTING)
384 cb = mei_io_cb_init(cl, NULL);
388 cb->fop_type = MEI_FOP_CLOSE;
389 if (dev->mei_host_buffer_is_empty) {
390 dev->mei_host_buffer_is_empty = false;
391 if (mei_hbm_cl_disconnect_req(dev, cl)) {
393 dev_err(&dev->pdev->dev, "failed to disconnect.\n");
396 mdelay(10); /* Wait for hardware disconnection ready */
397 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
399 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
400 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
403 mutex_unlock(&dev->device_lock);
405 err = wait_event_timeout(dev->wait_recvd_msg,
406 MEI_FILE_DISCONNECTED == cl->state,
407 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
409 mutex_lock(&dev->device_lock);
410 if (MEI_FILE_DISCONNECTED == cl->state) {
412 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
415 if (MEI_FILE_DISCONNECTED != cl->state)
416 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
419 dev_dbg(&dev->pdev->dev,
420 "wait failed disconnect err=%08x\n",
423 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
426 mei_io_list_flush(&dev->ctrl_rd_list, cl);
427 mei_io_list_flush(&dev->ctrl_wr_list, cl);
435 * mei_cl_is_other_connecting - checks if other
436 * client with the same me client id is connecting
438 * @cl: private data of the file object
440 * returns ture if other client is connected, 0 - otherwise.
442 bool mei_cl_is_other_connecting(struct mei_cl *cl)
444 struct mei_device *dev;
448 if (WARN_ON(!cl || !cl->dev))
453 list_for_each_entry_safe(pos, next, &dev->file_list, link) {
454 if ((pos->state == MEI_FILE_CONNECTING) &&
455 (pos != cl) && cl->me_client_id == pos->me_client_id)
464 * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
466 * @dev: the device structure
467 * @cl: private data of the file object
469 * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
470 * -ENOENT if mei_cl is not present
471 * -EINVAL if single_recv_buf == 0
473 int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
475 struct mei_device *dev;
478 if (WARN_ON(!cl || !cl->dev))
483 if (!dev->me_clients_num)
486 if (cl->mei_flow_ctrl_creds > 0)
489 for (i = 0; i < dev->me_clients_num; i++) {
490 struct mei_me_client *me_cl = &dev->me_clients[i];
491 if (me_cl->client_id == cl->me_client_id) {
492 if (me_cl->mei_flow_ctrl_creds) {
493 if (WARN_ON(me_cl->props.single_recv_buf == 0))
505 * mei_cl_flow_ctrl_reduce - reduces flow_control.
507 * @dev: the device structure
508 * @cl: private data of the file object
511 * -ENOENT when me client is not found
512 * -EINVAL when ctrl credits are <= 0
514 int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
516 struct mei_device *dev;
519 if (WARN_ON(!cl || !cl->dev))
524 if (!dev->me_clients_num)
527 for (i = 0; i < dev->me_clients_num; i++) {
528 struct mei_me_client *me_cl = &dev->me_clients[i];
529 if (me_cl->client_id == cl->me_client_id) {
530 if (me_cl->props.single_recv_buf != 0) {
531 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
533 dev->me_clients[i].mei_flow_ctrl_creds--;
535 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
537 cl->mei_flow_ctrl_creds--;
548 * mei_ioctl_connect_client - the connect to fw client IOCTL function
550 * @dev: the device structure
551 * @data: IOCTL connect data, input and output parameters
552 * @file: private data of the file object
554 * Locking: called under "dev->device_lock" lock
556 * returns 0 on success, <0 on failure.
558 int mei_ioctl_connect_client(struct file *file,
559 struct mei_connect_client_data *data)
561 struct mei_device *dev;
562 struct mei_cl_cb *cb;
563 struct mei_client *client;
565 long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
570 cl = file->private_data;
571 if (WARN_ON(!cl || !cl->dev))
576 dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
578 /* buffered ioctl cb */
579 cb = mei_io_cb_init(cl, file);
585 cb->fop_type = MEI_FOP_IOCTL;
587 if (dev->dev_state != MEI_DEV_ENABLED) {
591 if (cl->state != MEI_FILE_INITIALIZING &&
592 cl->state != MEI_FILE_DISCONNECTED) {
597 /* find ME client we're trying to connect to */
598 i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
599 if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
600 cl->me_client_id = dev->me_clients[i].client_id;
601 cl->state = MEI_FILE_CONNECTING;
604 dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
606 dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
607 dev->me_clients[i].props.protocol_version);
608 dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
609 dev->me_clients[i].props.max_msg_length);
611 /* if we're connecting to amthi client then we will use the
612 * existing connection
614 if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
615 dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
616 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
620 clear_bit(cl->host_client_id, dev->host_clients_map);
625 file->private_data = &dev->iamthif_cl;
627 client = &data->out_client_properties;
628 client->max_msg_length =
629 dev->me_clients[i].props.max_msg_length;
630 client->protocol_version =
631 dev->me_clients[i].props.protocol_version;
632 rets = dev->iamthif_cl.status;
637 if (cl->state != MEI_FILE_CONNECTING) {
643 /* prepare the output buffer */
644 client = &data->out_client_properties;
645 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
646 client->protocol_version = dev->me_clients[i].props.protocol_version;
647 dev_dbg(&dev->pdev->dev, "Can connect?\n");
648 if (dev->mei_host_buffer_is_empty &&
649 !mei_cl_is_other_connecting(cl)) {
650 dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
651 dev->mei_host_buffer_is_empty = false;
652 if (mei_hbm_cl_connect_req(dev, cl)) {
653 dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
657 dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
658 cl->timer_count = MEI_CONNECT_TIMEOUT;
659 list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
664 dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
665 dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
666 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
668 mutex_unlock(&dev->device_lock);
669 err = wait_event_timeout(dev->wait_recvd_msg,
670 (MEI_FILE_CONNECTED == cl->state ||
671 MEI_FILE_DISCONNECTED == cl->state), timeout);
673 mutex_lock(&dev->device_lock);
674 if (MEI_FILE_CONNECTED == cl->state) {
675 dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
679 dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
682 dev_dbg(&dev->pdev->dev,
683 "wait_event_interruptible_timeout failed on client"
684 " connect message fw response message.\n");
688 mei_io_list_flush(&dev->ctrl_rd_list, cl);
689 mei_io_list_flush(&dev->ctrl_wr_list, cl);
694 dev_dbg(&dev->pdev->dev, "free connect cb memory.");
700 * mei_cl_start_read - the start read client message function.
704 * returns 0 on success, <0 on failure.
706 int mei_cl_read_start(struct mei_cl *cl)
708 struct mei_device *dev;
709 struct mei_cl_cb *cb;
713 if (WARN_ON(!cl || !cl->dev))
718 if (cl->state != MEI_FILE_CONNECTED)
721 if (dev->dev_state != MEI_DEV_ENABLED)
724 if (cl->read_pending || cl->read_cb) {
725 dev_dbg(&dev->pdev->dev, "read is pending.\n");
728 i = mei_me_cl_by_id(dev, cl->me_client_id);
730 dev_err(&dev->pdev->dev, "no such me client %d\n",
735 cb = mei_io_cb_init(cl, NULL);
739 rets = mei_io_cb_alloc_resp_buf(cb,
740 dev->me_clients[i].props.max_msg_length);
744 cb->fop_type = MEI_FOP_READ;
746 if (dev->mei_host_buffer_is_empty) {
747 dev->mei_host_buffer_is_empty = false;
748 if (mei_hbm_cl_flow_control_req(dev, cl)) {
752 list_add_tail(&cb->list, &dev->read_list.list);
754 list_add_tail(&cb->list, &dev->ctrl_wr_list.list);