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>
61
#include "heci_data_structures.h"
63
#include "heci_interface.h"
64
#include "heci_version.h"
68
* heci_ioctl_get_version - the get driver version IOCTL function
70
* @dev: Device object for our driver
71
* @if_num: minor number
72
* @*u_msg: pointer to user data struct in user space
73
* @k_msg: data in kernel on the stack
74
* @file_ext: private data of the file object
76
* returns 0 on success, <0 on failure.
78
int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
79
struct heci_message_data __user *u_msg,
80
struct heci_message_data k_msg,
81
struct heci_file_private *file_ext)
84
struct heci_driver_version *version;
85
struct heci_message_data res_msg;
87
if ((if_num != HECI_MINOR_NUMBER) || (!dev)
91
if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) {
92
DBG("user buffer less than heci_driver_version.\n");
96
res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL);
98
DBG("failed allocation response buffer size = %d.\n",
99
(int) sizeof(struct heci_driver_version));
103
version = (struct heci_driver_version *) res_msg.data;
104
version->major = MAJOR_VERSION;
105
version->minor = MINOR_VERSION;
106
version->hotfix = QUICK_FIX_NUMBER;
107
version->build = VER_BUILD;
108
res_msg.size = sizeof(struct heci_driver_version);
109
if (k_msg.size < sizeof(struct heci_driver_version))
112
rets = file_ext->status;
113
/* now copy the data to user space */
114
if (copy_to_user((void __user *)k_msg.data, res_msg.data, res_msg.size)) {
118
if (put_user(res_msg.size, &u_msg->size)) {
128
* heci_ioctl_connect_client - the connect to fw client IOCTL function
130
* @dev: Device object for our driver
131
* @if_num: minor number
132
* @*u_msg: pointer to user data struct in user space
133
* @k_msg: data in kernel on the stack
134
* @file_ext: private data of the file object
136
* returns 0 on success, <0 on failure.
138
int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
139
struct heci_message_data __user *u_msg,
140
struct heci_message_data k_msg,
144
struct heci_message_data req_msg, res_msg;
145
struct heci_cb_private *priv_cb = NULL;
146
struct heci_client *client;
147
struct heci_file_private *file_ext;
148
struct heci_file_private *file_pos = NULL;
149
struct heci_file_private *file_next = NULL;
150
long timeout = 15; /*15 second */
154
if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file))
157
file_ext = file->private_data;
161
if (k_msg.size != sizeof(struct guid)) {
162
DBG("user buffer size is not equal to size of struct "
170
req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL);
171
res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL);
174
DBG("failed allocation response buffer size = %d.\n",
175
(int) sizeof(struct heci_client));
180
DBG("failed allocation request buffer size = %d.\n",
181
(int) sizeof(struct guid));
185
req_msg.size = sizeof(struct guid);
186
res_msg.size = sizeof(struct heci_client);
188
/* copy the message to kernel space -
189
* use a pointer already copied into kernel space
191
if (copy_from_user(req_msg.data, (void __user *)k_msg.data, k_msg.size)) {
195
/* buffered ioctl cb */
196
priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
201
INIT_LIST_HEAD(&priv_cb->cb_list);
202
priv_cb->response_buffer.data = res_msg.data;
203
priv_cb->response_buffer.size = res_msg.size;
204
priv_cb->request_buffer.data = req_msg.data;
205
priv_cb->request_buffer.size = req_msg.size;
206
priv_cb->major_file_operations = HECI_IOCTL;
207
spin_lock_bh(&dev->device_lock);
208
if (dev->heci_state != HECI_ENABLED) {
210
spin_unlock_bh(&dev->device_lock);
213
if ((file_ext->state != HECI_FILE_INITIALIZING) &&
214
(file_ext->state != HECI_FILE_DISCONNECTED)) {
216
spin_unlock_bh(&dev->device_lock);
220
/* find ME client we're trying to connect to */
221
for (i = 0; i < dev->num_heci_me_clients; i++) {
222
if (memcmp((struct guid *)req_msg.data,
223
&dev->me_clients[i].props.protocol_name,
224
sizeof(struct guid)) == 0) {
225
if (dev->me_clients[i].props.fixed_address == 0) {
226
file_ext->me_client_id =
227
dev->me_clients[i].client_id;
228
file_ext->state = HECI_FILE_CONNECTING;
233
/* if we're connecting to PTHI client so we will use the exist
236
if (memcmp((struct guid *)req_msg.data, &heci_pthi_guid,
237
sizeof(struct guid)) == 0) {
238
if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
240
spin_unlock_bh(&dev->device_lock);
243
dev->heci_host_clients[file_ext->host_client_id / 8] &=
244
~(1 << (file_ext->host_client_id % 8));
245
list_for_each_entry_safe(file_pos,
246
file_next, &dev->file_list, link) {
247
if (heci_fe_same_id(file_ext, file_pos)) {
248
DBG("remove file private data node host"
249
" client = %d, ME client = %d.\n",
250
file_pos->host_client_id,
251
file_pos->me_client_id);
252
list_del(&file_pos->link);
256
DBG("free file private data memory.\n");
259
file->private_data = &dev->iamthif_file_ext;
260
client = (struct heci_client *) res_msg.data;
261
client->max_msg_length =
262
dev->me_clients[i].props.max_msg_length;
263
client->protocol_version =
264
dev->me_clients[i].props.protocol_version;
265
rets = dev->iamthif_file_ext.status;
266
spin_unlock_bh(&dev->device_lock);
268
/* now copy the data to user space */
269
if (copy_to_user((void __user *)k_msg.data,
270
res_msg.data, res_msg.size)) {
274
if (put_user(res_msg.size, &u_msg->size)) {
280
spin_unlock_bh(&dev->device_lock);
282
spin_lock(&file_ext->file_lock);
283
spin_lock_bh(&dev->device_lock);
284
if (file_ext->state != HECI_FILE_CONNECTING) {
286
spin_unlock_bh(&dev->device_lock);
287
spin_unlock(&file_ext->file_lock);
290
/* prepare the output buffer */
291
client = (struct heci_client *) res_msg.data;
292
client->max_msg_length = dev->me_clients[i].props.max_msg_length;
293
client->protocol_version = dev->me_clients[i].props.protocol_version;
294
if (dev->host_buffer_is_empty
295
&& !other_client_is_connecting(dev, file_ext)) {
296
dev->host_buffer_is_empty = 0;
297
if (!heci_connect(dev, file_ext)) {
299
spin_unlock_bh(&dev->device_lock);
300
spin_unlock(&file_ext->file_lock);
303
file_ext->timer_count = HECI_CONNECT_TIMEOUT;
304
priv_cb->file_private = file_ext;
305
list_add_tail(&priv_cb->cb_list,
306
&dev->ctrl_rd_list.heci_cb.
312
priv_cb->file_private = file_ext;
313
DBG("add connect cb to control write list.\n");
314
list_add_tail(&priv_cb->cb_list,
315
&dev->ctrl_wr_list.heci_cb.cb_list);
317
spin_unlock_bh(&dev->device_lock);
318
spin_unlock(&file_ext->file_lock);
319
err = wait_event_timeout(dev->wait_recvd_msg,
320
(HECI_FILE_CONNECTED == file_ext->state
321
|| HECI_FILE_DISCONNECTED == file_ext->state),
324
spin_lock_bh(&dev->device_lock);
325
if (HECI_FILE_CONNECTED == file_ext->state) {
326
spin_unlock_bh(&dev->device_lock);
327
DBG("successfully connected to FW client.\n");
328
rets = file_ext->status;
329
/* now copy the data to user space */
330
if (copy_to_user((void __user *)k_msg.data,
331
res_msg.data, res_msg.size)) {
335
if (put_user(res_msg.size, &u_msg->size)) {
341
DBG("failed to connect to FW client.file_ext->state = %d.\n",
343
spin_unlock_bh(&dev->device_lock);
345
DBG("wait_event_interruptible_timeout failed on client"
346
" connect message fw response message.\n");
354
spin_lock_bh(&dev->device_lock);
355
heci_flush_list(&dev->ctrl_rd_list, file_ext);
356
heci_flush_list(&dev->ctrl_wr_list, file_ext);
357
spin_unlock_bh(&dev->device_lock);
360
DBG("free connect cb memory.");
368
* heci_ioctl_wd - the wd IOCTL function
370
* @dev: Device object for our driver
371
* @if_num: minor number
372
* @k_msg: data in kernel on the stack
373
* @file_ext: private data of the file object
375
* returns 0 on success, <0 on failure.
377
int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
378
struct heci_message_data k_msg,
379
struct heci_file_private *file_ext)
382
struct heci_message_data req_msg; /*in kernel on the stack */
384
if (if_num != HECI_MINOR_NUMBER)
387
spin_lock(&file_ext->file_lock);
388
if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) {
389
DBG("user buffer has invalid size.\n");
390
spin_unlock(&file_ext->file_lock);
393
spin_unlock(&file_ext->file_lock);
395
req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL);
397
DBG("failed allocation request buffer size = %d.\n",
398
HECI_WATCHDOG_DATA_SIZE);
401
req_msg.size = HECI_WATCHDOG_DATA_SIZE;
403
/* copy the message to kernel space - use a pointer already
404
* copied into kernel space
406
if (copy_from_user(req_msg.data,
407
(void __user *)k_msg.data, req_msg.size)) {
411
spin_lock_bh(&dev->device_lock);
412
if (dev->heci_state != HECI_ENABLED) {
414
spin_unlock_bh(&dev->device_lock);
418
if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
420
spin_unlock_bh(&dev->device_lock);
423
if (!dev->asf_mode) {
425
spin_unlock_bh(&dev->device_lock);
429
memcpy(&dev->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data,
430
HECI_WATCHDOG_DATA_SIZE);
432
dev->wd_timeout = (req_msg.data[1] << 8) + req_msg.data[0];
434
dev->wd_due_counter = 1; /* next timer */
435
if (dev->wd_timeout == 0) {
436
memcpy(dev->wd_data, heci_stop_wd_params,
437
HECI_WD_PARAMS_SIZE);
439
memcpy(dev->wd_data, heci_start_wd_params,
440
HECI_WD_PARAMS_SIZE);
441
mod_timer(&dev->wd_timer, jiffies);
443
spin_unlock_bh(&dev->device_lock);
451
* heci_ioctl_bypass_wd - the bypass_wd IOCTL function
453
* @dev: Device object for our driver
454
* @if_num: minor number
455
* @k_msg: data in kernel on the stack
456
* @file_ext: private data of the file object
458
* returns 0 on success, <0 on failure.
460
int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
461
struct heci_message_data k_msg,
462
struct heci_file_private *file_ext)
467
if (if_num != HECI_MINOR_NUMBER)
470
spin_lock(&file_ext->file_lock);
471
if (k_msg.size < 1) {
472
DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n");
473
spin_unlock(&file_ext->file_lock);
476
spin_unlock(&file_ext->file_lock);
477
if (copy_from_user(&flag, (void __user *)k_msg.data, 1)) {
482
spin_lock_bh(&dev->device_lock);
483
flag = flag ? (1) : (0);
484
dev->wd_bypass = flag;
485
spin_unlock_bh(&dev->device_lock);
491
* find_pthi_read_list_entry - finds a PTHIlist entry for current file
493
* @dev: Device object for our driver
494
* @file: pointer to file object
496
* returns returned a list entry on success, NULL on failure.
498
struct heci_cb_private *find_pthi_read_list_entry(
499
struct iamt_heci_device *dev,
502
struct heci_file_private *file_ext_temp;
503
struct heci_cb_private *priv_cb_pos = NULL;
504
struct heci_cb_private *priv_cb_next = NULL;
506
if ((dev->pthi_read_complete_list.status == 0) &&
507
!list_empty(&dev->pthi_read_complete_list.heci_cb.cb_list)) {
508
list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
509
&dev->pthi_read_complete_list.heci_cb.cb_list, cb_list) {
510
file_ext_temp = (struct heci_file_private *)
511
priv_cb_pos->file_private;
512
if ((file_ext_temp != NULL) &&
513
(file_ext_temp == &dev->iamthif_file_ext) &&
514
(priv_cb_pos->file_object == file))
522
* pthi_read - read data from pthi client
524
* @dev: Device object for our driver
525
* @if_num: minor number
526
* @file: pointer to file object
527
* @*ubuf: pointer to user data in user space
528
* @length: data length to read
529
* @offset: data read offset
532
* returned data length on success,
533
* zero if no data to read,
534
* negative on failure.
536
int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file,
537
char __user *ubuf, size_t length, loff_t *offset)
540
struct heci_cb_private *priv_cb = NULL;
541
struct heci_file_private *file_ext = file->private_data;
543
unsigned long currtime = get_seconds();
545
if ((if_num != HECI_MINOR_NUMBER) || (!dev))
548
if ((file_ext == NULL) || (file_ext != &dev->iamthif_file_ext))
551
spin_lock_bh(&dev->device_lock);
552
for (i = 0; i < dev->num_heci_me_clients; i++) {
553
if (dev->me_clients[i].client_id ==
554
dev->iamthif_file_ext.me_client_id)
557
BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
558
if ((i == dev->num_heci_me_clients)
559
|| (dev->me_clients[i].client_id !=
560
dev->iamthif_file_ext.me_client_id)) {
561
DBG("PTHI client not found.\n");
562
spin_unlock_bh(&dev->device_lock);
565
priv_cb = find_pthi_read_list_entry(dev, file);
567
spin_unlock_bh(&dev->device_lock);
568
return 0; /* No more data to read */
571
(currtime - priv_cb->read_time > IAMTHIF_READ_TIMER)) {
572
/* 15 sec for the message has expired */
573
list_del(&priv_cb->cb_list);
574
spin_unlock_bh(&dev->device_lock);
578
/* if the whole message will fit remove it from the list */
579
if ((priv_cb->information >= *offset) &&
580
(length >= (priv_cb->information - *offset)))
581
list_del(&priv_cb->cb_list);
582
else if ((priv_cb->information > 0) &&
583
(priv_cb->information <= *offset)) {
584
/* end of the message has been reached */
585
list_del(&priv_cb->cb_list);
587
spin_unlock_bh(&dev->device_lock);
590
/* else means that not full buffer will be read and do not
591
* remove message from deletion list
594
DBG("pthi priv_cb->response_buffer size - %d\n",
595
priv_cb->response_buffer.size);
596
DBG("pthi priv_cb->information - %lu\n",
597
priv_cb->information);
598
spin_unlock_bh(&dev->device_lock);
600
/* length is being turncated to PAGE_SIZE, however,
601
* the information may be longer */
602
length = length < (priv_cb->information - *offset) ?
603
length : (priv_cb->information - *offset);
605
if (copy_to_user(ubuf,
606
priv_cb->response_buffer.data + *offset,
611
if ((*offset + length) < priv_cb->information) {
617
DBG("free pthi cb memory.\n");
619
heci_free_cb_private(priv_cb);
625
* heci_start_read - the start read client message function.
627
* @dev: Device object for our driver
628
* @if_num: minor number
629
* @file_ext: private data of the file object
631
* returns 0 on success, <0 on failure.
633
int heci_start_read(struct iamt_heci_device *dev, int if_num,
634
struct heci_file_private *file_ext)
638
struct heci_cb_private *priv_cb = NULL;
640
if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) {
641
DBG("received wrong function input param.\n");
645
spin_lock_bh(&dev->device_lock);
646
if (file_ext->state != HECI_FILE_CONNECTED) {
647
spin_unlock_bh(&dev->device_lock);
651
if (dev->heci_state != HECI_ENABLED) {
652
spin_unlock_bh(&dev->device_lock);
655
spin_unlock_bh(&dev->device_lock);
656
DBG("check if read is pending.\n");
657
spin_lock_bh(&file_ext->read_io_lock);
658
if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) {
659
DBG("read is pending.\n");
660
spin_unlock_bh(&file_ext->read_io_lock);
663
spin_unlock_bh(&file_ext->read_io_lock);
665
priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
669
spin_lock_bh(&file_ext->read_io_lock);
670
DBG("allocation call back success\n"
671
"host client = %d, ME client = %d\n",
672
file_ext->host_client_id, file_ext->me_client_id);
673
spin_unlock_bh(&file_ext->read_io_lock);
675
spin_lock_bh(&dev->device_lock);
676
spin_lock_bh(&file_ext->read_io_lock);
677
for (i = 0; i < dev->num_heci_me_clients; i++) {
678
if (dev->me_clients[i].client_id == file_ext->me_client_id)
683
BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
684
spin_unlock_bh(&file_ext->read_io_lock);
685
if (i == dev->num_heci_me_clients) {
690
priv_cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
691
spin_unlock_bh(&dev->device_lock);
692
priv_cb->response_buffer.data =
693
kmalloc(priv_cb->response_buffer.size, GFP_KERNEL);
694
if (!priv_cb->response_buffer.data) {
698
DBG("allocation call back data success.\n");
699
priv_cb->major_file_operations = HECI_READ;
700
/* make sure information is zero before we start */
701
priv_cb->information = 0;
702
priv_cb->file_private = (void *) file_ext;
703
spin_lock_bh(&dev->device_lock);
704
spin_lock_bh(&file_ext->read_io_lock);
705
file_ext->read_cb = priv_cb;
706
if (dev->host_buffer_is_empty) {
707
dev->host_buffer_is_empty = 0;
708
if (!heci_send_flow_control(dev, file_ext)) {
710
spin_unlock_bh(&file_ext->read_io_lock);
713
list_add_tail(&priv_cb->cb_list,
714
&dev->read_list.heci_cb.cb_list);
717
list_add_tail(&priv_cb->cb_list,
718
&dev->ctrl_wr_list.heci_cb.cb_list);
720
spin_unlock_bh(&file_ext->read_io_lock);
721
spin_unlock_bh(&dev->device_lock);
724
spin_unlock_bh(&dev->device_lock);
726
heci_free_cb_private(priv_cb);
731
* pthi_write - write iamthif data to pthi client
733
* @dev: Device object for our driver
734
* @priv_cb: heci call back struct
736
* returns 0 on success, <0 on failure.
738
int pthi_write(struct iamt_heci_device *dev,
739
struct heci_cb_private *priv_cb)
742
struct heci_msg_hdr heci_hdr;
744
if ((!dev) || (!priv_cb))
747
DBG("write data to pthi client.\n");
749
dev->iamthif_state = HECI_IAMTHIF_WRITING;
750
dev->iamthif_current_cb = priv_cb;
751
dev->iamthif_file_object = priv_cb->file_object;
752
dev->iamthif_canceled = 0;
753
dev->iamthif_ioctl = 1;
754
dev->iamthif_msg_buf_size = priv_cb->request_buffer.size;
755
memcpy(dev->iamthif_msg_buf, priv_cb->request_buffer.data,
756
priv_cb->request_buffer.size);
758
if (flow_ctrl_creds(dev, &dev->iamthif_file_ext) &&
759
dev->host_buffer_is_empty) {
760
dev->host_buffer_is_empty = 0;
761
if (priv_cb->request_buffer.size >
762
(((dev->host_hw_state & H_CBD) >> 24) *
763
sizeof(__u32)) - sizeof(struct heci_msg_hdr)) {
765
(((dev->host_hw_state & H_CBD) >> 24) *
766
sizeof(__u32)) - sizeof(struct heci_msg_hdr);
767
heci_hdr.msg_complete = 0;
769
heci_hdr.length = priv_cb->request_buffer.size;
770
heci_hdr.msg_complete = 1;
773
heci_hdr.host_addr = dev->iamthif_file_ext.host_client_id;
774
heci_hdr.me_addr = dev->iamthif_file_ext.me_client_id;
775
heci_hdr.reserved = 0;
776
dev->iamthif_msg_buf_index += heci_hdr.length;
777
if (!heci_write_message(dev, &heci_hdr,
778
(unsigned char *)(dev->iamthif_msg_buf),
782
if (heci_hdr.msg_complete) {
783
flow_ctrl_reduce(dev, &dev->iamthif_file_ext);
784
dev->iamthif_flow_control_pending = 1;
785
dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
786
DBG("add pthi cb to write waiting list\n");
787
dev->iamthif_current_cb = priv_cb;
788
dev->iamthif_file_object = priv_cb->file_object;
789
list_add_tail(&priv_cb->cb_list,
790
&dev->write_waiting_list.heci_cb.cb_list);
792
DBG("message does not complete, "
793
"so add pthi cb to write list.\n");
794
list_add_tail(&priv_cb->cb_list,
795
&dev->write_list.heci_cb.cb_list);
798
if (!(dev->host_buffer_is_empty))
799
DBG("host buffer is not empty");
801
DBG("No flow control credentials, "
802
"so add iamthif cb to write list.\n");
803
list_add_tail(&priv_cb->cb_list,
804
&dev->write_list.heci_cb.cb_list);
810
* iamthif_ioctl_send_msg - send cmd data to pthi client
812
* @dev: Device object for our driver
814
* returns 0 on success, <0 on failure.
816
void run_next_iamthif_cmd(struct iamt_heci_device *dev)
818
struct heci_file_private *file_ext_tmp;
819
struct heci_cb_private *priv_cb_pos = NULL;
820
struct heci_cb_private *priv_cb_next = NULL;
826
dev->iamthif_msg_buf_size = 0;
827
dev->iamthif_msg_buf_index = 0;
828
dev->iamthif_canceled = 0;
829
dev->iamthif_ioctl = 1;
830
dev->iamthif_state = HECI_IAMTHIF_IDLE;
831
dev->iamthif_timer = 0;
832
dev->iamthif_file_object = NULL;
834
if (dev->pthi_cmd_list.status == 0 &&
835
!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)) {
836
DBG("complete pthi cmd_list cb.\n");
838
list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
839
&dev->pthi_cmd_list.heci_cb.cb_list, cb_list) {
840
list_del(&priv_cb_pos->cb_list);
841
file_ext_tmp = (struct heci_file_private *)
842
priv_cb_pos->file_private;
844
if ((file_ext_tmp != NULL) &&
845
(file_ext_tmp == &dev->iamthif_file_ext)) {
846
status = pthi_write(dev, priv_cb_pos);
848
DBG("pthi write failed status = %d\n",
859
* heci_free_cb_private - free heci_cb_private related memory
861
* @priv_cb: heci callback struct
863
void heci_free_cb_private(struct heci_cb_private *priv_cb)
868
kfree(priv_cb->request_buffer.data);
869
kfree(priv_cb->response_buffer.data);