2 * Part of Intel(R) Manageability Engine Interface Linux driver
4 * Copyright (c) 2003 - 2008 Intel Corp.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
14 * substantially similar to the "NO WARRANTY" disclaimer below
15 * ("Disclaimer") and any redistribution must be conditioned upon
16 * including a substantially similar Disclaimer requirement for further
17 * binary redistribution.
18 * 3. Neither the names of the above-listed copyright holders nor the names
19 * of any contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * Alternatively, this software may be distributed under the terms of the
23 * GNU General Public License ("GPL") version 2 as published by the Free
24 * Software Foundation.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
36 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGES.
41 #include <linux/module.h>
42 #include <linux/moduleparam.h>
43 #include <linux/kernel.h>
44 #include <linux/slab.h>
46 #include <linux/errno.h>
47 #include <linux/types.h>
48 #include <linux/fcntl.h>
49 #include <linux/aio.h>
50 #include <linux/pci.h>
51 #include <linux/reboot.h>
52 #include <linux/poll.h>
53 #include <linux/init.h>
54 #include <linux/kdev_t.h>
55 #include <linux/ioctl.h>
56 #include <linux/cdev.h>
57 #include <linux/list.h>
58 #include <linux/unistd.h>
59 #include <linux/delay.h>
62 #include "heci_data_structures.h"
64 #include "heci_interface.h"
65 #include "heci_version.h"
69 * heci_ioctl_get_version - the get driver version IOCTL function
71 * @dev: Device object for our driver
72 * @if_num: minor number
73 * @*u_msg: pointer to user data struct in user space
74 * @k_msg: data in kernel on the stack
75 * @file_ext: private data of the file object
77 * returns 0 on success, <0 on failure.
79 int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
80 struct heci_message_data *u_msg,
81 struct heci_message_data k_msg,
82 struct heci_file_private *file_ext)
85 struct heci_driver_version *version;
86 struct heci_message_data res_msg;
88 if ((if_num != HECI_MINOR_NUMBER) || (!dev)
92 if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) {
93 DBG("user buffer less than heci_driver_version.\n");
97 res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL);
99 DBG("failed allocation response buffer size = %d.\n",
100 (int) sizeof(struct heci_driver_version));
104 version = (struct heci_driver_version *) res_msg.data;
105 version->major = MAJOR_VERSION;
106 version->minor = MINOR_VERSION;
107 version->hotfix = QUICK_FIX_NUMBER;
108 version->build = VER_BUILD;
109 res_msg.size = sizeof(struct heci_driver_version);
110 if (k_msg.size < sizeof(struct heci_driver_version))
113 rets = file_ext->status;
114 /* now copy the data to user space */
115 if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
119 if (put_user(res_msg.size, &u_msg->size)) {
129 * heci_ioctl_connect_client - the connect to fw client IOCTL function
131 * @dev: Device object for our driver
132 * @if_num: minor number
133 * @*u_msg: pointer to user data struct in user space
134 * @k_msg: data in kernel on the stack
135 * @file_ext: private data of the file object
137 * returns 0 on success, <0 on failure.
139 int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
140 struct heci_message_data *u_msg,
141 struct heci_message_data k_msg,
145 struct heci_message_data req_msg, res_msg;
146 struct heci_cb_private *priv_cb = NULL;
147 struct heci_client *client;
148 struct heci_file_private *file_ext;
149 struct heci_file_private *file_pos = NULL;
150 struct heci_file_private *file_next = NULL;
151 long timeout = 15; /*15 second */
155 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file))
158 file_ext = file->private_data;
162 if (k_msg.size != sizeof(struct guid)) {
163 DBG("user buffer size is not equal to size of struct "
171 req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL);
172 res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL);
175 DBG("failed allocation response buffer size = %d.\n",
176 (int) sizeof(struct heci_client));
181 DBG("failed allocation request buffer size = %d.\n",
182 (int) sizeof(struct guid));
186 req_msg.size = sizeof(struct guid);
187 res_msg.size = sizeof(struct heci_client);
189 /* copy the message to kernel space -
190 * use a pointer already copied into kernel space
192 if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) {
196 /* buffered ioctl cb */
197 priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
202 INIT_LIST_HEAD(&priv_cb->cb_list);
203 priv_cb->response_buffer.data = res_msg.data;
204 priv_cb->response_buffer.size = res_msg.size;
205 priv_cb->request_buffer.data = req_msg.data;
206 priv_cb->request_buffer.size = req_msg.size;
207 priv_cb->major_file_operations = HECI_IOCTL;
208 spin_lock_bh(&dev->device_lock);
209 if (dev->heci_state != HECI_ENABLED) {
211 spin_unlock_bh(&dev->device_lock);
214 if ((file_ext->state != HECI_FILE_INITIALIZING) &&
215 (file_ext->state != HECI_FILE_DISCONNECTED)) {
217 spin_unlock_bh(&dev->device_lock);
221 /* find ME client we're trying to connect to */
222 for (i = 0; i < dev->num_heci_me_clients; i++) {
223 if (memcmp((struct guid *)req_msg.data,
224 &dev->me_clients[i].props.protocol_name,
225 sizeof(struct guid)) == 0) {
226 if (dev->me_clients[i].props.fixed_address == 0) {
227 file_ext->me_client_id =
228 dev->me_clients[i].client_id;
229 file_ext->state = HECI_FILE_CONNECTING;
234 /* if we're connecting to PTHI client so we will use the exist
237 if (memcmp((struct guid *)req_msg.data, &heci_pthi_guid,
238 sizeof(struct guid)) == 0) {
239 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
241 spin_unlock_bh(&dev->device_lock);
244 dev->heci_host_clients[file_ext->host_client_id / 8] &=
245 ~(1 << (file_ext->host_client_id % 8));
246 list_for_each_entry_safe(file_pos,
247 file_next, &dev->file_list, link) {
248 if (heci_fe_same_id(file_ext, file_pos)) {
249 DBG("remove file private data node host"
250 " client = %d, ME client = %d.\n",
251 file_pos->host_client_id,
252 file_pos->me_client_id);
253 list_del(&file_pos->link);
257 DBG("free file private data memory.\n");
260 file->private_data = &dev->iamthif_file_ext;
261 client = (struct heci_client *) res_msg.data;
262 client->max_msg_length =
263 dev->me_clients[i].props.max_msg_length;
264 client->protocol_version =
265 dev->me_clients[i].props.protocol_version;
266 rets = dev->iamthif_file_ext.status;
267 spin_unlock_bh(&dev->device_lock);
269 /* now copy the data to user space */
270 if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
274 if (put_user(res_msg.size, &u_msg->size)) {
280 spin_lock(&file_ext->file_lock);
281 if (file_ext->state != HECI_FILE_CONNECTING) {
283 spin_unlock(&file_ext->file_lock);
284 spin_unlock_bh(&dev->device_lock);
287 spin_unlock(&file_ext->file_lock);
288 /* prepare the output buffer */
289 client = (struct heci_client *) res_msg.data;
290 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
291 client->protocol_version = dev->me_clients[i].props.protocol_version;
292 if (dev->host_buffer_is_empty
293 && !other_client_is_connecting(dev, file_ext)) {
294 dev->host_buffer_is_empty = 0;
295 if (!heci_connect(dev, file_ext)) {
297 spin_unlock_bh(&dev->device_lock);
300 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
301 priv_cb->file_private = file_ext;
302 list_add_tail(&priv_cb->cb_list,
303 &dev->ctrl_rd_list.heci_cb.
309 priv_cb->file_private = file_ext;
310 DBG("add connect cb to control write list.\n");
311 list_add_tail(&priv_cb->cb_list,
312 &dev->ctrl_wr_list.heci_cb.cb_list);
314 spin_unlock_bh(&dev->device_lock);
315 err = wait_event_timeout(dev->wait_recvd_msg,
316 (HECI_FILE_CONNECTED == file_ext->state
317 || HECI_FILE_DISCONNECTED == file_ext->state),
320 if (HECI_FILE_CONNECTED == file_ext->state) {
321 DBG("successfully connected to FW client.\n");
322 rets = file_ext->status;
323 /* now copy the data to user space */
324 if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
328 if (put_user(res_msg.size, &u_msg->size)) {
334 DBG("failed to connect to FW client.file_ext->state = %d.\n",
337 DBG("wait_event_interruptible_timeout failed on client"
338 " connect message fw response message.\n");
346 spin_lock_bh(&dev->device_lock);
347 heci_flush_list(&dev->ctrl_rd_list, file_ext);
348 heci_flush_list(&dev->ctrl_wr_list, file_ext);
349 spin_unlock_bh(&dev->device_lock);
352 DBG("free connect cb memory.");
360 * heci_ioctl_wd - the wd IOCTL function
362 * @dev: Device object for our driver
363 * @if_num: minor number
364 * @k_msg: data in kernel on the stack
365 * @file_ext: private data of the file object
367 * returns 0 on success, <0 on failure.
369 int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
370 struct heci_message_data k_msg,
371 struct heci_file_private *file_ext)
374 struct heci_message_data req_msg; /*in kernel on the stack */
376 if (if_num != HECI_MINOR_NUMBER)
379 spin_lock(&file_ext->file_lock);
380 if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) {
381 DBG("user buffer has invalid size.\n");
382 spin_unlock(&file_ext->file_lock);
385 spin_unlock(&file_ext->file_lock);
387 req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL);
389 DBG("failed allocation request buffer size = %d.\n",
390 HECI_WATCHDOG_DATA_SIZE);
393 req_msg.size = HECI_WATCHDOG_DATA_SIZE;
395 /* copy the message to kernel space - use a pointer already
396 * copied into kernel space
398 if (copy_from_user(req_msg.data, k_msg.data, req_msg.size)) {
402 spin_lock_bh(&dev->device_lock);
403 if (dev->heci_state != HECI_ENABLED) {
405 spin_unlock_bh(&dev->device_lock);
409 if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
411 spin_unlock_bh(&dev->device_lock);
414 if (!dev->asf_mode) {
416 spin_unlock_bh(&dev->device_lock);
420 memcpy(&dev->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data,
421 HECI_WATCHDOG_DATA_SIZE);
423 dev->wd_timeout = (req_msg.data[1] << 8) + req_msg.data[0];
425 dev->wd_due_counter = 1; /* next timer */
426 if (dev->wd_timeout == 0) {
427 memcpy(dev->wd_data, heci_stop_wd_params,
428 HECI_WD_PARAMS_SIZE);
430 memcpy(dev->wd_data, heci_start_wd_params,
431 HECI_WD_PARAMS_SIZE);
432 mod_timer(&dev->wd_timer, jiffies);
434 spin_unlock_bh(&dev->device_lock);
442 * heci_ioctl_bypass_wd - the bypass_wd IOCTL function
444 * @dev: Device object for our driver
445 * @if_num: minor number
446 * @k_msg: data in kernel on the stack
447 * @file_ext: private data of the file object
449 * returns 0 on success, <0 on failure.
451 int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
452 struct heci_message_data k_msg,
453 struct heci_file_private *file_ext)
458 if (if_num != HECI_MINOR_NUMBER)
461 spin_lock(&file_ext->file_lock);
462 if (k_msg.size < 1) {
463 DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n");
464 spin_unlock(&file_ext->file_lock);
467 spin_unlock(&file_ext->file_lock);
468 if (copy_from_user(&flag, k_msg.data, 1)) {
473 spin_lock_bh(&dev->device_lock);
474 flag = flag ? (1) : (0);
475 dev->wd_bypass = flag;
476 spin_unlock_bh(&dev->device_lock);
482 * find_pthi_read_list_entry - finds a PTHIlist entry for current file
484 * @dev: Device object for our driver
485 * @file: pointer to file object
487 * returns returned a list entry on success, NULL on failure.
489 struct heci_cb_private *find_pthi_read_list_entry(
490 struct iamt_heci_device *dev,
493 struct heci_file_private *file_ext_temp;
494 struct heci_cb_private *priv_cb_pos = NULL;
495 struct heci_cb_private *priv_cb_next = NULL;
497 if ((dev->pthi_read_complete_list.status == 0) &&
498 !list_empty(&dev->pthi_read_complete_list.heci_cb.cb_list)) {
499 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
500 &dev->pthi_read_complete_list.heci_cb.cb_list, cb_list) {
501 file_ext_temp = (struct heci_file_private *)
502 priv_cb_pos->file_private;
503 if ((file_ext_temp != NULL) &&
504 (file_ext_temp == &dev->iamthif_file_ext) &&
505 (priv_cb_pos->file_object == file))
513 * pthi_read - read data from pthi client
515 * @dev: Device object for our driver
516 * @if_num: minor number
517 * @file: pointer to file object
518 * @*ubuf: pointer to user data in user space
519 * @length: data length to read
520 * @offset: data read offset
523 * returned data length on success,
524 * zero if no data to read,
525 * negative on failure.
527 int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file,
528 char *ubuf, size_t length, loff_t *offset)
531 struct heci_cb_private *priv_cb = NULL;
532 struct heci_file_private *file_ext = file->private_data;
534 unsigned long currtime = get_seconds();
536 if ((if_num != HECI_MINOR_NUMBER) || (!dev))
539 if ((file_ext == NULL) || (file_ext != &dev->iamthif_file_ext))
542 spin_lock_bh(&dev->device_lock);
543 for (i = 0; i < dev->num_heci_me_clients; i++) {
544 if (dev->me_clients[i].client_id ==
545 dev->iamthif_file_ext.me_client_id)
548 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
549 if ((i == dev->num_heci_me_clients)
550 || (dev->me_clients[i].client_id !=
551 dev->iamthif_file_ext.me_client_id)) {
552 DBG("PTHI client not found.\n");
553 spin_unlock_bh(&dev->device_lock);
556 priv_cb = find_pthi_read_list_entry(dev, file);
558 spin_unlock_bh(&dev->device_lock);
559 return 0; /* No more data to read */
562 (currtime - priv_cb->read_time > IAMTHIF_READ_TIMER)) {
563 /* 15 sec for the message has expired */
564 list_del(&priv_cb->cb_list);
565 spin_unlock_bh(&dev->device_lock);
569 /* if the whole message will fit remove it from the list */
570 if ((priv_cb->information >= *offset) &&
571 (length >= (priv_cb->information - *offset)))
572 list_del(&priv_cb->cb_list);
573 else if ((priv_cb->information > 0) &&
574 (priv_cb->information <= *offset)) {
575 /* end of the message has been reached */
576 list_del(&priv_cb->cb_list);
578 spin_unlock_bh(&dev->device_lock);
581 /* else means that not full buffer will be read and do not
582 * remove message from deletion list
585 DBG("pthi priv_cb->response_buffer size - %d\n",
586 priv_cb->response_buffer.size);
587 DBG("pthi priv_cb->information - %lu\n",
588 priv_cb->information);
589 spin_unlock_bh(&dev->device_lock);
591 /* length is being turncated to PAGE_SIZE, however,
592 * the information may be longer */
593 length = length < (priv_cb->information - *offset) ?
594 length : (priv_cb->information - *offset);
596 if (copy_to_user(ubuf,
597 priv_cb->response_buffer.data + *offset,
602 if ((*offset + length) < priv_cb->information) {
608 DBG("free pthi cb memory.\n");
610 heci_free_cb_private(priv_cb);
616 * heci_start_read - the start read client message function.
618 * @dev: Device object for our driver
619 * @if_num: minor number
620 * @file_ext: private data of the file object
622 * returns 0 on success, <0 on failure.
624 int heci_start_read(struct iamt_heci_device *dev, int if_num,
625 struct heci_file_private *file_ext)
629 struct heci_cb_private *priv_cb = NULL;
631 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) {
632 DBG("received wrong function input param.\n");
635 if (file_ext->state != HECI_FILE_CONNECTED)
638 spin_lock_bh(&dev->device_lock);
639 if (dev->heci_state != HECI_ENABLED) {
640 spin_unlock_bh(&dev->device_lock);
643 spin_unlock_bh(&dev->device_lock);
644 DBG("check if read is pending.\n");
645 if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) {
646 DBG("read is pending.\n");
649 priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
653 DBG("allocation call back success\n"
654 "host client = %d, ME client = %d\n",
655 file_ext->host_client_id, file_ext->me_client_id);
656 spin_lock_bh(&dev->device_lock);
657 for (i = 0; i < dev->num_heci_me_clients; i++) {
658 if (dev->me_clients[i].client_id == file_ext->me_client_id)
663 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
664 if (i == dev->num_heci_me_clients) {
669 priv_cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
670 spin_unlock_bh(&dev->device_lock);
671 priv_cb->response_buffer.data =
672 kmalloc(priv_cb->response_buffer.size, GFP_KERNEL);
673 if (!priv_cb->response_buffer.data) {
677 DBG("allocation call back data success.\n");
678 priv_cb->major_file_operations = HECI_READ;
679 /* make sure information is zero before we start */
680 priv_cb->information = 0;
681 priv_cb->file_private = (void *) file_ext;
682 file_ext->read_cb = priv_cb;
683 spin_lock_bh(&dev->device_lock);
684 if (dev->host_buffer_is_empty) {
685 dev->host_buffer_is_empty = 0;
686 if (!heci_send_flow_control(dev, file_ext)) {
690 list_add_tail(&priv_cb->cb_list,
691 &dev->read_list.heci_cb.cb_list);
694 list_add_tail(&priv_cb->cb_list,
695 &dev->ctrl_wr_list.heci_cb.cb_list);
697 spin_unlock_bh(&dev->device_lock);
700 spin_unlock_bh(&dev->device_lock);
702 heci_free_cb_private(priv_cb);
707 * pthi_write - write iamthif data to pthi client
709 * @dev: Device object for our driver
710 * @priv_cb: heci call back struct
712 * returns 0 on success, <0 on failure.
714 int pthi_write(struct iamt_heci_device *dev,
715 struct heci_cb_private *priv_cb)
718 struct heci_msg_hdr heci_hdr;
720 if ((!dev) || (!priv_cb))
723 DBG("write data to pthi client.\n");
725 dev->iamthif_state = HECI_IAMTHIF_WRITING;
726 dev->iamthif_current_cb = priv_cb;
727 dev->iamthif_file_object = priv_cb->file_object;
728 dev->iamthif_canceled = 0;
729 dev->iamthif_ioctl = 1;
730 dev->iamthif_msg_buf_size = priv_cb->request_buffer.size;
731 memcpy(dev->iamthif_msg_buf, priv_cb->request_buffer.data,
732 priv_cb->request_buffer.size);
734 if (flow_ctrl_creds(dev, &dev->iamthif_file_ext) &&
735 dev->host_buffer_is_empty) {
736 dev->host_buffer_is_empty = 0;
737 if (priv_cb->request_buffer.size >
738 (((dev->host_hw_state & H_CBD) >> 24) *
739 sizeof(__u32)) - sizeof(struct heci_msg_hdr)) {
741 (((dev->host_hw_state & H_CBD) >> 24) *
742 sizeof(__u32)) - sizeof(struct heci_msg_hdr);
743 heci_hdr.msg_complete = 0;
745 heci_hdr.length = priv_cb->request_buffer.size;
746 heci_hdr.msg_complete = 1;
749 heci_hdr.host_addr = dev->iamthif_file_ext.host_client_id;
750 heci_hdr.me_addr = dev->iamthif_file_ext.me_client_id;
751 heci_hdr.reserved = 0;
752 dev->iamthif_msg_buf_index += heci_hdr.length;
753 if (!heci_write_message(dev, &heci_hdr,
754 (unsigned char *)(dev->iamthif_msg_buf),
758 if (heci_hdr.msg_complete) {
759 flow_ctrl_reduce(dev, &dev->iamthif_file_ext);
760 dev->iamthif_flow_control_pending = 1;
761 dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
762 DBG("add pthi cb to write waiting list\n");
763 dev->iamthif_current_cb = priv_cb;
764 dev->iamthif_file_object = priv_cb->file_object;
765 list_add_tail(&priv_cb->cb_list,
766 &dev->write_waiting_list.heci_cb.cb_list);
768 DBG("message does not complete, "
769 "so add pthi cb to write list.\n");
770 list_add_tail(&priv_cb->cb_list,
771 &dev->write_list.heci_cb.cb_list);
774 if (!(dev->host_buffer_is_empty))
775 DBG("host buffer is not empty");
777 DBG("No flow control credentials, "
778 "so add iamthif cb to write list.\n");
779 list_add_tail(&priv_cb->cb_list,
780 &dev->write_list.heci_cb.cb_list);
786 * iamthif_ioctl_send_msg - send cmd data to pthi client
788 * @dev: Device object for our driver
790 * returns 0 on success, <0 on failure.
792 void run_next_iamthif_cmd(struct iamt_heci_device *dev)
794 struct heci_file_private *file_ext_tmp;
795 struct heci_cb_private *priv_cb_pos = NULL;
796 struct heci_cb_private *priv_cb_next = NULL;
802 dev->iamthif_msg_buf_size = 0;
803 dev->iamthif_msg_buf_index = 0;
804 dev->iamthif_canceled = 0;
805 dev->iamthif_ioctl = 1;
806 dev->iamthif_state = HECI_IAMTHIF_IDLE;
807 dev->iamthif_timer = 0;
808 dev->iamthif_file_object = NULL;
810 if (dev->pthi_cmd_list.status == 0 &&
811 !list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)) {
812 DBG("complete pthi cmd_list cb.\n");
814 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
815 &dev->pthi_cmd_list.heci_cb.cb_list, cb_list) {
816 list_del(&priv_cb_pos->cb_list);
817 file_ext_tmp = (struct heci_file_private *)
818 priv_cb_pos->file_private;
820 if ((file_ext_tmp != NULL) &&
821 (file_ext_tmp == &dev->iamthif_file_ext)) {
822 status = pthi_write(dev, priv_cb_pos);
824 DBG("pthi write failed status = %d\n",
835 * heci_free_cb_private - free heci_cb_private related memory
837 * @priv_cb: heci callback struct
839 void heci_free_cb_private(struct heci_cb_private *priv_cb)
844 kfree(priv_cb->request_buffer.data);
845 kfree(priv_cb->response_buffer.data);