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
);
302 file_ext
->timer_count
= HECI_CONNECT_TIMEOUT
;
303 priv_cb
->file_private
= file_ext
;
304 list_add_tail(&priv_cb
->cb_list
,
305 &dev
->ctrl_rd_list
.heci_cb
.
311 priv_cb
->file_private
= file_ext
;
312 DBG("add connect cb to control write list.\n");
313 list_add_tail(&priv_cb
->cb_list
,
314 &dev
->ctrl_wr_list
.heci_cb
.cb_list
);
316 spin_unlock_bh(&dev
->device_lock
);
317 spin_unlock(&file_ext
->file_lock
);
318 err
= wait_event_timeout(dev
->wait_recvd_msg
,
319 (HECI_FILE_CONNECTED
== file_ext
->state
320 || HECI_FILE_DISCONNECTED
== file_ext
->state
),
323 if (HECI_FILE_CONNECTED
== file_ext
->state
) {
324 DBG("successfully connected to FW client.\n");
325 rets
= file_ext
->status
;
326 /* now copy the data to user space */
327 if (copy_to_user((void __user
*)k_msg
.data
,
328 res_msg
.data
, res_msg
.size
)) {
332 if (put_user(res_msg
.size
, &u_msg
->size
)) {
338 DBG("failed to connect to FW client.file_ext->state = %d.\n",
341 DBG("wait_event_interruptible_timeout failed on client"
342 " connect message fw response message.\n");
350 spin_lock_bh(&dev
->device_lock
);
351 heci_flush_list(&dev
->ctrl_rd_list
, file_ext
);
352 heci_flush_list(&dev
->ctrl_wr_list
, file_ext
);
353 spin_unlock_bh(&dev
->device_lock
);
356 DBG("free connect cb memory.");
364 * heci_ioctl_wd - the wd IOCTL function
366 * @dev: Device object for our driver
367 * @if_num: minor number
368 * @k_msg: data in kernel on the stack
369 * @file_ext: private data of the file object
371 * returns 0 on success, <0 on failure.
373 int heci_ioctl_wd(struct iamt_heci_device
*dev
, int if_num
,
374 struct heci_message_data k_msg
,
375 struct heci_file_private
*file_ext
)
378 struct heci_message_data req_msg
; /*in kernel on the stack */
380 if (if_num
!= HECI_MINOR_NUMBER
)
383 spin_lock(&file_ext
->file_lock
);
384 if (k_msg
.size
!= HECI_WATCHDOG_DATA_SIZE
) {
385 DBG("user buffer has invalid size.\n");
386 spin_unlock(&file_ext
->file_lock
);
389 spin_unlock(&file_ext
->file_lock
);
391 req_msg
.data
= kmalloc(HECI_WATCHDOG_DATA_SIZE
, GFP_KERNEL
);
393 DBG("failed allocation request buffer size = %d.\n",
394 HECI_WATCHDOG_DATA_SIZE
);
397 req_msg
.size
= HECI_WATCHDOG_DATA_SIZE
;
399 /* copy the message to kernel space - use a pointer already
400 * copied into kernel space
402 if (copy_from_user(req_msg
.data
,
403 (void __user
*)k_msg
.data
, req_msg
.size
)) {
407 spin_lock_bh(&dev
->device_lock
);
408 if (dev
->heci_state
!= HECI_ENABLED
) {
410 spin_unlock_bh(&dev
->device_lock
);
414 if (dev
->wd_file_ext
.state
!= HECI_FILE_CONNECTED
) {
416 spin_unlock_bh(&dev
->device_lock
);
419 if (!dev
->asf_mode
) {
421 spin_unlock_bh(&dev
->device_lock
);
425 memcpy(&dev
->wd_data
[HECI_WD_PARAMS_SIZE
], req_msg
.data
,
426 HECI_WATCHDOG_DATA_SIZE
);
428 dev
->wd_timeout
= (req_msg
.data
[1] << 8) + req_msg
.data
[0];
430 dev
->wd_due_counter
= 1; /* next timer */
431 if (dev
->wd_timeout
== 0) {
432 memcpy(dev
->wd_data
, heci_stop_wd_params
,
433 HECI_WD_PARAMS_SIZE
);
435 memcpy(dev
->wd_data
, heci_start_wd_params
,
436 HECI_WD_PARAMS_SIZE
);
437 mod_timer(&dev
->wd_timer
, jiffies
);
439 spin_unlock_bh(&dev
->device_lock
);
447 * heci_ioctl_bypass_wd - the bypass_wd IOCTL function
449 * @dev: Device object for our driver
450 * @if_num: minor number
451 * @k_msg: data in kernel on the stack
452 * @file_ext: private data of the file object
454 * returns 0 on success, <0 on failure.
456 int heci_ioctl_bypass_wd(struct iamt_heci_device
*dev
, int if_num
,
457 struct heci_message_data k_msg
,
458 struct heci_file_private
*file_ext
)
463 if (if_num
!= HECI_MINOR_NUMBER
)
466 spin_lock(&file_ext
->file_lock
);
467 if (k_msg
.size
< 1) {
468 DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n");
469 spin_unlock(&file_ext
->file_lock
);
472 spin_unlock(&file_ext
->file_lock
);
473 if (copy_from_user(&flag
, (void __user
*)k_msg
.data
, 1)) {
478 spin_lock_bh(&dev
->device_lock
);
479 flag
= flag
? (1) : (0);
480 dev
->wd_bypass
= flag
;
481 spin_unlock_bh(&dev
->device_lock
);
487 * find_pthi_read_list_entry - finds a PTHIlist entry for current file
489 * @dev: Device object for our driver
490 * @file: pointer to file object
492 * returns returned a list entry on success, NULL on failure.
494 struct heci_cb_private
*find_pthi_read_list_entry(
495 struct iamt_heci_device
*dev
,
498 struct heci_file_private
*file_ext_temp
;
499 struct heci_cb_private
*priv_cb_pos
= NULL
;
500 struct heci_cb_private
*priv_cb_next
= NULL
;
502 if ((dev
->pthi_read_complete_list
.status
== 0) &&
503 !list_empty(&dev
->pthi_read_complete_list
.heci_cb
.cb_list
)) {
504 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
505 &dev
->pthi_read_complete_list
.heci_cb
.cb_list
, cb_list
) {
506 file_ext_temp
= (struct heci_file_private
*)
507 priv_cb_pos
->file_private
;
508 if ((file_ext_temp
!= NULL
) &&
509 (file_ext_temp
== &dev
->iamthif_file_ext
) &&
510 (priv_cb_pos
->file_object
== file
))
518 * pthi_read - read data from pthi client
520 * @dev: Device object for our driver
521 * @if_num: minor number
522 * @file: pointer to file object
523 * @*ubuf: pointer to user data in user space
524 * @length: data length to read
525 * @offset: data read offset
528 * returned data length on success,
529 * zero if no data to read,
530 * negative on failure.
532 int pthi_read(struct iamt_heci_device
*dev
, int if_num
, struct file
*file
,
533 char __user
*ubuf
, size_t length
, loff_t
*offset
)
536 struct heci_cb_private
*priv_cb
= NULL
;
537 struct heci_file_private
*file_ext
= file
->private_data
;
539 unsigned long currtime
= get_seconds();
541 if ((if_num
!= HECI_MINOR_NUMBER
) || (!dev
))
544 if ((file_ext
== NULL
) || (file_ext
!= &dev
->iamthif_file_ext
))
547 spin_lock_bh(&dev
->device_lock
);
548 for (i
= 0; i
< dev
->num_heci_me_clients
; i
++) {
549 if (dev
->me_clients
[i
].client_id
==
550 dev
->iamthif_file_ext
.me_client_id
)
553 BUG_ON(dev
->me_clients
[i
].client_id
!= file_ext
->me_client_id
);
554 if ((i
== dev
->num_heci_me_clients
)
555 || (dev
->me_clients
[i
].client_id
!=
556 dev
->iamthif_file_ext
.me_client_id
)) {
557 DBG("PTHI client not found.\n");
558 spin_unlock_bh(&dev
->device_lock
);
561 priv_cb
= find_pthi_read_list_entry(dev
, file
);
563 spin_unlock_bh(&dev
->device_lock
);
564 return 0; /* No more data to read */
567 (currtime
- priv_cb
->read_time
> IAMTHIF_READ_TIMER
)) {
568 /* 15 sec for the message has expired */
569 list_del(&priv_cb
->cb_list
);
570 spin_unlock_bh(&dev
->device_lock
);
574 /* if the whole message will fit remove it from the list */
575 if ((priv_cb
->information
>= *offset
) &&
576 (length
>= (priv_cb
->information
- *offset
)))
577 list_del(&priv_cb
->cb_list
);
578 else if ((priv_cb
->information
> 0) &&
579 (priv_cb
->information
<= *offset
)) {
580 /* end of the message has been reached */
581 list_del(&priv_cb
->cb_list
);
583 spin_unlock_bh(&dev
->device_lock
);
586 /* else means that not full buffer will be read and do not
587 * remove message from deletion list
590 DBG("pthi priv_cb->response_buffer size - %d\n",
591 priv_cb
->response_buffer
.size
);
592 DBG("pthi priv_cb->information - %lu\n",
593 priv_cb
->information
);
594 spin_unlock_bh(&dev
->device_lock
);
596 /* length is being turncated to PAGE_SIZE, however,
597 * the information may be longer */
598 length
= length
< (priv_cb
->information
- *offset
) ?
599 length
: (priv_cb
->information
- *offset
);
601 if (copy_to_user(ubuf
,
602 priv_cb
->response_buffer
.data
+ *offset
,
607 if ((*offset
+ length
) < priv_cb
->information
) {
613 DBG("free pthi cb memory.\n");
615 heci_free_cb_private(priv_cb
);
621 * heci_start_read - the start read client message function.
623 * @dev: Device object for our driver
624 * @if_num: minor number
625 * @file_ext: private data of the file object
627 * returns 0 on success, <0 on failure.
629 int heci_start_read(struct iamt_heci_device
*dev
, int if_num
,
630 struct heci_file_private
*file_ext
)
634 struct heci_cb_private
*priv_cb
= NULL
;
636 if ((if_num
!= HECI_MINOR_NUMBER
) || (!dev
) || (!file_ext
)) {
637 DBG("received wrong function input param.\n");
640 if (file_ext
->state
!= HECI_FILE_CONNECTED
) {
644 spin_lock_bh(&dev
->device_lock
);
645 if (dev
->heci_state
!= HECI_ENABLED
) {
646 spin_unlock_bh(&dev
->device_lock
);
649 spin_unlock_bh(&dev
->device_lock
);
650 DBG("check if read is pending.\n");
651 spin_lock_bh(&file_ext
->read_io_lock
);
652 if ((file_ext
->read_pending
) || (file_ext
->read_cb
!= NULL
)) {
653 DBG("read is pending.\n");
654 spin_unlock_bh(&file_ext
->read_io_lock
);
657 spin_unlock_bh(&file_ext
->read_io_lock
);
659 priv_cb
= kzalloc(sizeof(struct heci_cb_private
), GFP_KERNEL
);
663 spin_lock_bh(&file_ext
->read_io_lock
);
664 DBG("allocation call back success\n"
665 "host client = %d, ME client = %d\n",
666 file_ext
->host_client_id
, file_ext
->me_client_id
);
667 spin_unlock_bh(&file_ext
->read_io_lock
);
669 spin_lock_bh(&dev
->device_lock
);
670 spin_lock_bh(&file_ext
->read_io_lock
);
671 for (i
= 0; i
< dev
->num_heci_me_clients
; i
++) {
672 if (dev
->me_clients
[i
].client_id
== file_ext
->me_client_id
)
677 BUG_ON(dev
->me_clients
[i
].client_id
!= file_ext
->me_client_id
);
678 spin_unlock_bh(&file_ext
->read_io_lock
);
679 if (i
== dev
->num_heci_me_clients
) {
684 priv_cb
->response_buffer
.size
= dev
->me_clients
[i
].props
.max_msg_length
;
685 spin_unlock_bh(&dev
->device_lock
);
686 priv_cb
->response_buffer
.data
=
687 kmalloc(priv_cb
->response_buffer
.size
, GFP_KERNEL
);
688 if (!priv_cb
->response_buffer
.data
) {
692 DBG("allocation call back data success.\n");
693 priv_cb
->major_file_operations
= HECI_READ
;
694 /* make sure information is zero before we start */
695 priv_cb
->information
= 0;
696 priv_cb
->file_private
= (void *) file_ext
;
697 spin_lock_bh(&dev
->device_lock
);
698 spin_lock_bh(&file_ext
->read_io_lock
);
699 file_ext
->read_cb
= priv_cb
;
700 if (dev
->host_buffer_is_empty
) {
701 dev
->host_buffer_is_empty
= 0;
702 if (!heci_send_flow_control(dev
, file_ext
)) {
704 spin_unlock_bh(&file_ext
->read_io_lock
);
707 list_add_tail(&priv_cb
->cb_list
,
708 &dev
->read_list
.heci_cb
.cb_list
);
711 list_add_tail(&priv_cb
->cb_list
,
712 &dev
->ctrl_wr_list
.heci_cb
.cb_list
);
714 spin_unlock_bh(&file_ext
->read_io_lock
);
715 spin_unlock_bh(&dev
->device_lock
);
718 spin_unlock_bh(&dev
->device_lock
);
720 heci_free_cb_private(priv_cb
);
725 * pthi_write - write iamthif data to pthi client
727 * @dev: Device object for our driver
728 * @priv_cb: heci call back struct
730 * returns 0 on success, <0 on failure.
732 int pthi_write(struct iamt_heci_device
*dev
,
733 struct heci_cb_private
*priv_cb
)
736 struct heci_msg_hdr heci_hdr
;
738 if ((!dev
) || (!priv_cb
))
741 DBG("write data to pthi client.\n");
743 dev
->iamthif_state
= HECI_IAMTHIF_WRITING
;
744 dev
->iamthif_current_cb
= priv_cb
;
745 dev
->iamthif_file_object
= priv_cb
->file_object
;
746 dev
->iamthif_canceled
= 0;
747 dev
->iamthif_ioctl
= 1;
748 dev
->iamthif_msg_buf_size
= priv_cb
->request_buffer
.size
;
749 memcpy(dev
->iamthif_msg_buf
, priv_cb
->request_buffer
.data
,
750 priv_cb
->request_buffer
.size
);
752 if (flow_ctrl_creds(dev
, &dev
->iamthif_file_ext
) &&
753 dev
->host_buffer_is_empty
) {
754 dev
->host_buffer_is_empty
= 0;
755 if (priv_cb
->request_buffer
.size
>
756 (((dev
->host_hw_state
& H_CBD
) >> 24) *
757 sizeof(__u32
)) - sizeof(struct heci_msg_hdr
)) {
759 (((dev
->host_hw_state
& H_CBD
) >> 24) *
760 sizeof(__u32
)) - sizeof(struct heci_msg_hdr
);
761 heci_hdr
.msg_complete
= 0;
763 heci_hdr
.length
= priv_cb
->request_buffer
.size
;
764 heci_hdr
.msg_complete
= 1;
767 heci_hdr
.host_addr
= dev
->iamthif_file_ext
.host_client_id
;
768 heci_hdr
.me_addr
= dev
->iamthif_file_ext
.me_client_id
;
769 heci_hdr
.reserved
= 0;
770 dev
->iamthif_msg_buf_index
+= heci_hdr
.length
;
771 if (!heci_write_message(dev
, &heci_hdr
,
772 (unsigned char *)(dev
->iamthif_msg_buf
),
776 if (heci_hdr
.msg_complete
) {
777 flow_ctrl_reduce(dev
, &dev
->iamthif_file_ext
);
778 dev
->iamthif_flow_control_pending
= 1;
779 dev
->iamthif_state
= HECI_IAMTHIF_FLOW_CONTROL
;
780 DBG("add pthi cb to write waiting list\n");
781 dev
->iamthif_current_cb
= priv_cb
;
782 dev
->iamthif_file_object
= priv_cb
->file_object
;
783 list_add_tail(&priv_cb
->cb_list
,
784 &dev
->write_waiting_list
.heci_cb
.cb_list
);
786 DBG("message does not complete, "
787 "so add pthi cb to write list.\n");
788 list_add_tail(&priv_cb
->cb_list
,
789 &dev
->write_list
.heci_cb
.cb_list
);
792 if (!(dev
->host_buffer_is_empty
))
793 DBG("host buffer is not empty");
795 DBG("No flow control credentials, "
796 "so add iamthif cb to write list.\n");
797 list_add_tail(&priv_cb
->cb_list
,
798 &dev
->write_list
.heci_cb
.cb_list
);
804 * iamthif_ioctl_send_msg - send cmd data to pthi client
806 * @dev: Device object for our driver
808 * returns 0 on success, <0 on failure.
810 void run_next_iamthif_cmd(struct iamt_heci_device
*dev
)
812 struct heci_file_private
*file_ext_tmp
;
813 struct heci_cb_private
*priv_cb_pos
= NULL
;
814 struct heci_cb_private
*priv_cb_next
= NULL
;
820 dev
->iamthif_msg_buf_size
= 0;
821 dev
->iamthif_msg_buf_index
= 0;
822 dev
->iamthif_canceled
= 0;
823 dev
->iamthif_ioctl
= 1;
824 dev
->iamthif_state
= HECI_IAMTHIF_IDLE
;
825 dev
->iamthif_timer
= 0;
826 dev
->iamthif_file_object
= NULL
;
828 if (dev
->pthi_cmd_list
.status
== 0 &&
829 !list_empty(&dev
->pthi_cmd_list
.heci_cb
.cb_list
)) {
830 DBG("complete pthi cmd_list cb.\n");
832 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
833 &dev
->pthi_cmd_list
.heci_cb
.cb_list
, cb_list
) {
834 list_del(&priv_cb_pos
->cb_list
);
835 file_ext_tmp
= (struct heci_file_private
*)
836 priv_cb_pos
->file_private
;
838 if ((file_ext_tmp
!= NULL
) &&
839 (file_ext_tmp
== &dev
->iamthif_file_ext
)) {
840 status
= pthi_write(dev
, priv_cb_pos
);
842 DBG("pthi write failed status = %d\n",
853 * heci_free_cb_private - free heci_cb_private related memory
855 * @priv_cb: heci callback struct
857 void heci_free_cb_private(struct heci_cb_private
*priv_cb
)
862 kfree(priv_cb
->request_buffer
.data
);
863 kfree(priv_cb
->response_buffer
.data
);