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/kthread.h>
44 #include "heci_interface.h"
47 * interrupt function prototypes
49 static void heci_bh_handler(struct work_struct
*work
);
50 static int heci_bh_read_handler(struct io_heci_list
*complete_list
,
51 struct iamt_heci_device
*dev
,
53 static int heci_bh_write_handler(struct io_heci_list
*complete_list
,
54 struct iamt_heci_device
*dev
,
56 static void heci_bh_read_bus_message(struct iamt_heci_device
*dev
,
57 struct heci_msg_hdr
*heci_hdr
);
58 static int heci_bh_read_pthi_message(struct io_heci_list
*complete_list
,
59 struct iamt_heci_device
*dev
,
60 struct heci_msg_hdr
*heci_hdr
);
61 static int heci_bh_read_client_message(struct io_heci_list
*complete_list
,
62 struct iamt_heci_device
*dev
,
63 struct heci_msg_hdr
*heci_hdr
);
64 static void heci_client_connect_response(struct iamt_heci_device
*dev
,
65 struct hbm_client_connect_response
*connect_res
);
66 static void heci_client_disconnect_response(struct iamt_heci_device
*dev
,
67 struct hbm_client_connect_response
*disconnect_res
);
68 static void heci_client_flow_control_response(struct iamt_heci_device
*dev
,
69 struct hbm_flow_control
*flow_control
);
70 static void heci_client_disconnect_request(struct iamt_heci_device
*dev
,
71 struct hbm_client_disconnect_request
*disconnect_req
);
75 * heci_isr_interrupt - The ISR of the HECI device
77 * @irq: The irq number
78 * @dev_id: pointer to the device structure
82 irqreturn_t
heci_isr_interrupt(int irq
, void *dev_id
)
85 struct iamt_heci_device
*dev
= (struct iamt_heci_device
*) dev_id
;
87 dev
->host_hw_state
= read_heci_register(dev
, H_CSR
);
89 if ((dev
->host_hw_state
& H_IS
) != H_IS
)
92 /* disable interrupts */
93 heci_csr_disable_interrupts(dev
);
96 * Our device interrupted, schedule work the heci_bh_handler
97 * to handle the interrupt processing. This needs to be a
98 * workqueue item since the handler can sleep.
100 PREPARE_WORK(&dev
->work
, heci_bh_handler
);
101 DBG("schedule work the heci_bh_handler.\n");
102 err
= schedule_work(&dev
->work
);
104 printk(KERN_ERR
"heci: schedule the heci_bh_handler"
105 " failed error=%x\n", err
);
111 * _heci_cmpl - process completed operation.
113 * @file_ext: private data of the file object.
114 * @priv_cb_pos: callback block.
116 static void _heci_cmpl(struct heci_file_private
*file_ext
,
117 struct heci_cb_private
*priv_cb_pos
)
119 if (priv_cb_pos
->major_file_operations
== HECI_WRITE
) {
120 heci_free_cb_private(priv_cb_pos
);
121 DBG("completing write call back.\n");
122 file_ext
->writing_state
= HECI_WRITE_COMPLETE
;
123 if ((&file_ext
->tx_wait
) &&
124 waitqueue_active(&file_ext
->tx_wait
))
125 wake_up_interruptible(&file_ext
->tx_wait
);
127 } else if (priv_cb_pos
->major_file_operations
== HECI_READ
128 && HECI_READING
== file_ext
->reading_state
) {
129 DBG("completing read call back information= %lu\n",
130 priv_cb_pos
->information
);
131 file_ext
->reading_state
= HECI_READ_COMPLETE
;
132 if ((&file_ext
->rx_wait
) &&
133 waitqueue_active(&file_ext
->rx_wait
))
134 wake_up_interruptible(&file_ext
->rx_wait
);
140 * _heci_cmpl_iamthif - process completed iamthif operation.
142 * @dev: Device object for our driver.
143 * @priv_cb_pos: callback block.
145 static void _heci_cmpl_iamthif(struct iamt_heci_device
*dev
,
146 struct heci_cb_private
*priv_cb_pos
)
148 if (dev
->iamthif_canceled
!= 1) {
149 dev
->iamthif_state
= HECI_IAMTHIF_READ_COMPLETE
;
150 dev
->iamthif_stall_timer
= 0;
151 memcpy(priv_cb_pos
->response_buffer
.data
,
152 dev
->iamthif_msg_buf
,
153 dev
->iamthif_msg_buf_index
);
154 list_add_tail(&priv_cb_pos
->cb_list
,
155 &dev
->pthi_read_complete_list
.heci_cb
.cb_list
);
156 DBG("pthi read completed.\n");
158 run_next_iamthif_cmd(dev
);
160 if (&dev
->iamthif_file_ext
.wait
) {
161 DBG("completing pthi call back.\n");
162 wake_up_interruptible(&dev
->iamthif_file_ext
.wait
);
166 * heci_bh_handler - function called after ISR to handle the interrupt
169 * @work: pointer to the work structure
171 * NOTE: This function is called by schedule work
173 static void heci_bh_handler(struct work_struct
*work
)
175 struct iamt_heci_device
*dev
=
176 container_of(work
, struct iamt_heci_device
, work
);
177 struct io_heci_list complete_list
;
180 struct heci_cb_private
*cb_pos
= NULL
, *cb_next
= NULL
;
181 struct heci_file_private
*file_ext
;
182 int bus_message_received
= 0;
183 struct task_struct
*tsk
;
185 DBG("function called after ISR to handle the interrupt processing.\n");
186 /* initialize our complete list */
187 spin_lock_bh(&dev
->device_lock
);
188 heci_initialize_list(&complete_list
, dev
);
189 dev
->host_hw_state
= read_heci_register(dev
, H_CSR
);
190 dev
->me_hw_state
= read_heci_register(dev
, ME_CSR_HA
);
192 /* check if ME wants a reset */
193 if (((dev
->me_hw_state
& ME_RDY_HRA
) == 0)
194 && (dev
->heci_state
!= HECI_RESETING
)
195 && (dev
->heci_state
!= HECI_INITIALIZING
)) {
196 DBG("FW not ready.\n");
198 spin_unlock_bh(&dev
->device_lock
);
202 /* check if we need to start the dev */
203 if ((dev
->host_hw_state
& H_RDY
) == 0) {
204 if ((dev
->me_hw_state
& ME_RDY_HRA
) == ME_RDY_HRA
) {
205 DBG("we need to start the dev.\n");
206 dev
->host_hw_state
|= (H_IE
| H_IG
| H_RDY
);
207 heci_set_csr_register(dev
);
208 if (dev
->heci_state
== HECI_INITIALIZING
) {
210 spin_unlock_bh(&dev
->device_lock
);
211 wake_up_interruptible(&dev
->wait_recvd_msg
);
215 spin_unlock_bh(&dev
->device_lock
);
216 tsk
= kthread_run(heci_task_initialize_clients
,
219 int rc
= PTR_ERR(tsk
);
220 printk(KERN_WARNING
"heci: Unable to"
221 "start the heci thread: %d\n", rc
);
226 DBG("enable interrupt FW not ready.\n");
227 heci_csr_enable_interrupts(dev
);
228 spin_unlock_bh(&dev
->device_lock
);
232 /* check slots avalable for reading */
233 slots
= count_full_read_slots(dev
);
234 DBG("slots =%08x extra_write_index =%08x.\n",
235 slots
, dev
->extra_write_index
);
236 while ((slots
> 0) && (!dev
->extra_write_index
)) {
237 DBG("slots =%08x extra_write_index =%08x.\n", slots
,
238 dev
->extra_write_index
);
239 DBG("call heci_bh_read_handler.\n");
240 rets
= heci_bh_read_handler(&complete_list
, dev
, &slots
);
244 rets
= heci_bh_write_handler(&complete_list
, dev
, &slots
);
246 DBG("end of bottom half function.\n");
247 dev
->host_hw_state
= read_heci_register(dev
, H_CSR
);
248 dev
->host_buffer_is_empty
= host_buffer_is_empty(dev
);
250 if ((dev
->host_hw_state
& H_IS
) == H_IS
) {
251 /* acknowledge interrupt and disable interrupts */
252 heci_csr_disable_interrupts(dev
);
254 PREPARE_WORK(&dev
->work
, heci_bh_handler
);
255 DBG("schedule work the heci_bh_handler.\n");
256 rets
= schedule_work(&dev
->work
);
258 printk(KERN_ERR
"heci: schedule the heci_bh_handler"
259 " failed error=%x\n", rets
);
262 heci_csr_enable_interrupts(dev
);
265 if (dev
->recvd_msg
&& waitqueue_active(&dev
->wait_recvd_msg
)) {
266 DBG("received waiting bus message\n");
267 bus_message_received
= 1;
269 spin_unlock_bh(&dev
->device_lock
);
270 if (bus_message_received
) {
271 DBG("wake up dev->wait_recvd_msg\n");
272 wake_up_interruptible(&dev
->wait_recvd_msg
);
273 bus_message_received
= 0;
275 if ((complete_list
.status
!= 0)
276 || list_empty(&complete_list
.heci_cb
.cb_list
))
280 list_for_each_entry_safe(cb_pos
, cb_next
,
281 &complete_list
.heci_cb
.cb_list
, cb_list
) {
282 file_ext
= (struct heci_file_private
*)cb_pos
->file_private
;
283 list_del(&cb_pos
->cb_list
);
284 if (file_ext
!= NULL
) {
285 if (file_ext
!= &dev
->iamthif_file_ext
) {
286 DBG("completing call back.\n");
287 _heci_cmpl(file_ext
, cb_pos
);
289 } else if (file_ext
== &dev
->iamthif_file_ext
) {
290 _heci_cmpl_iamthif(dev
, cb_pos
);
298 * heci_bh_read_handler - bottom half read routine after ISR to
299 * handle the read processing.
301 * @cmpl_list: An instance of our list structure
302 * @dev: Device object for our driver
303 * @slots: slots to read.
305 * returns 0 on success, <0 on failure.
307 static int heci_bh_read_handler(struct io_heci_list
*cmpl_list
,
308 struct iamt_heci_device
*dev
,
311 struct heci_msg_hdr
*heci_hdr
;
313 struct heci_file_private
*file_pos
= NULL
;
314 struct heci_file_private
*file_next
= NULL
;
316 if (!dev
->rd_msg_hdr
) {
317 dev
->rd_msg_hdr
= read_heci_register(dev
, ME_CB_RW
);
318 DBG("slots=%08x.\n", *slots
);
320 DBG("slots=%08x.\n", *slots
);
322 heci_hdr
= (struct heci_msg_hdr
*) &dev
->rd_msg_hdr
;
323 DBG("heci_hdr->length =%d\n", heci_hdr
->length
);
325 if ((heci_hdr
->reserved
) || !(dev
->rd_msg_hdr
)) {
326 DBG("corrupted message header.\n");
327 ret
= -ECORRUPTED_MESSAGE_HEADER
;
331 if ((heci_hdr
->host_addr
) || (heci_hdr
->me_addr
)) {
332 list_for_each_entry_safe(file_pos
, file_next
,
333 &dev
->file_list
, link
) {
334 DBG("list_for_each_entry_safe read host"
335 " client = %d, ME client = %d\n",
336 file_pos
->host_client_id
,
337 file_pos
->me_client_id
);
338 if ((file_pos
->host_client_id
== heci_hdr
->host_addr
)
339 && (file_pos
->me_client_id
== heci_hdr
->me_addr
))
343 if (&file_pos
->link
== &dev
->file_list
) {
344 DBG("corrupted message header\n");
345 ret
= -ECORRUPTED_MESSAGE_HEADER
;
349 if (((*slots
) * sizeof(__u32
)) < heci_hdr
->length
) {
350 DBG("we can't read the message slots=%08x.\n", *slots
);
351 /* we can't read the message */
356 /* decide where to read the message too */
357 if (!heci_hdr
->host_addr
) {
358 DBG("call heci_bh_read_bus_message.\n");
359 heci_bh_read_bus_message(dev
, heci_hdr
);
360 DBG("end heci_bh_read_bus_message.\n");
361 } else if ((heci_hdr
->host_addr
== dev
->iamthif_file_ext
.host_client_id
)
362 && (HECI_FILE_CONNECTED
== dev
->iamthif_file_ext
.state
)
363 && (dev
->iamthif_state
== HECI_IAMTHIF_READING
)) {
364 DBG("call heci_bh_read_iamthif_message.\n");
365 DBG("heci_hdr->length =%d\n", heci_hdr
->length
);
366 ret
= heci_bh_read_pthi_message(cmpl_list
, dev
, heci_hdr
);
371 DBG("call heci_bh_read_client_message.\n");
372 ret
= heci_bh_read_client_message(cmpl_list
, dev
, heci_hdr
);
378 /* reset the number of slots and header */
379 *slots
= count_full_read_slots(dev
);
382 if (*slots
== -ESLOTS_OVERFLOW
) {
383 /* overflow - reset */
384 DBG("reseting due to slots overflow.\n");
385 /* set the event since message has been read */
395 * heci_bh_read_bus_message - bottom half read routine after ISR to
396 * handle the read bus message cmd processing.
398 * @dev: Device object for our driver
399 * @heci_hdr: header of bus message
401 static void heci_bh_read_bus_message(struct iamt_heci_device
*dev
,
402 struct heci_msg_hdr
*heci_hdr
)
404 struct heci_bus_message
*heci_msg
;
405 struct hbm_host_version_response
*version_res
;
406 struct hbm_client_connect_response
*connect_res
;
407 struct hbm_client_connect_response
*disconnect_res
;
408 struct hbm_flow_control
*flow_control
;
409 struct hbm_props_response
*props_res
;
410 struct hbm_host_enum_response
*enum_res
;
411 struct hbm_client_disconnect_request
*disconnect_req
;
412 struct hbm_host_stop_request
*h_stop_req
;
414 unsigned char *buffer
;
416 /* read the message to our buffer */
417 buffer
= (unsigned char *) dev
->rd_msg_buf
;
418 BUG_ON(heci_hdr
->length
>= sizeof(dev
->rd_msg_buf
));
419 heci_read_slots(dev
, buffer
, heci_hdr
->length
);
420 heci_msg
= (struct heci_bus_message
*) buffer
;
422 switch (*(__u8
*) heci_msg
) {
423 case HOST_START_RES_CMD
:
424 version_res
= (struct hbm_host_version_response
*) heci_msg
;
425 if (version_res
->host_version_supported
) {
426 dev
->version
.major_version
= HBM_MAJOR_VERSION
;
427 dev
->version
.minor_version
= HBM_MINOR_VERSION
;
429 dev
->version
= version_res
->me_max_version
;
432 DBG("host start response message received.\n");
435 case CLIENT_CONNECT_RES_CMD
:
437 (struct hbm_client_connect_response
*) heci_msg
;
438 heci_client_connect_response(dev
, connect_res
);
439 DBG("client connect response message received.\n");
440 wake_up(&dev
->wait_recvd_msg
);
443 case CLIENT_DISCONNECT_RES_CMD
:
445 (struct hbm_client_connect_response
*) heci_msg
;
446 heci_client_disconnect_response(dev
, disconnect_res
);
447 DBG("client disconnect response message received.\n");
448 wake_up(&dev
->wait_recvd_msg
);
451 case HECI_FLOW_CONTROL_CMD
:
452 flow_control
= (struct hbm_flow_control
*) heci_msg
;
453 heci_client_flow_control_response(dev
, flow_control
);
454 DBG("client flow control response message received.\n");
457 case HOST_CLIENT_PROPERTEIS_RES_CMD
:
458 props_res
= (struct hbm_props_response
*) heci_msg
;
459 if (props_res
->status
!= 0) {
463 for (i
= 0; i
< dev
->num_heci_me_clients
; i
++) {
464 if (dev
->me_clients
[i
].client_id
==
465 props_res
->address
) {
466 dev
->me_clients
[i
].props
=
467 props_res
->client_properties
;
475 case HOST_ENUM_RES_CMD
:
476 enum_res
= (struct hbm_host_enum_response
*) heci_msg
;
477 memcpy(dev
->heci_me_clients
, enum_res
->valid_addresses
, 32);
481 case HOST_STOP_RES_CMD
:
482 dev
->heci_state
= HECI_DISABLED
;
483 DBG("reseting because of FW stop response.\n");
487 case CLIENT_DISCONNECT_REQ_CMD
:
488 /* search for client */
490 (struct hbm_client_disconnect_request
*) heci_msg
;
491 heci_client_disconnect_request(dev
, disconnect_req
);
494 case ME_STOP_REQ_CMD
:
495 /* prepare stop request */
496 heci_hdr
= (struct heci_msg_hdr
*) &dev
->ext_msg_buf
[0];
497 heci_hdr
->host_addr
= 0;
498 heci_hdr
->me_addr
= 0;
499 heci_hdr
->length
= sizeof(struct hbm_host_stop_request
);
500 heci_hdr
->msg_complete
= 1;
501 heci_hdr
->reserved
= 0;
503 (struct hbm_host_stop_request
*) &dev
->ext_msg_buf
[1];
504 memset(h_stop_req
, 0, sizeof(struct hbm_host_stop_request
));
505 h_stop_req
->cmd
.cmd
= HOST_STOP_REQ_CMD
;
506 h_stop_req
->reason
= DRIVER_STOP_REQUEST
;
507 h_stop_req
->reserved
[0] = 0;
508 h_stop_req
->reserved
[1] = 0;
509 dev
->extra_write_index
= 2;
520 * heci_bh_read_pthi_message - bottom half read routine after ISR to
521 * handle the read pthi message data processing.
523 * @complete_list: An instance of our list structure
524 * @dev: Device object for our driver
525 * @heci_hdr: header of pthi message
527 * returns 0 on success, <0 on failure.
529 static int heci_bh_read_pthi_message(struct io_heci_list
*complete_list
,
530 struct iamt_heci_device
*dev
,
531 struct heci_msg_hdr
*heci_hdr
)
533 struct heci_file_private
*file_ext
;
534 struct heci_cb_private
*priv_cb
;
535 unsigned char *buffer
;
537 BUG_ON(heci_hdr
->me_addr
!= dev
->iamthif_file_ext
.me_client_id
);
538 BUG_ON(dev
->iamthif_state
!= HECI_IAMTHIF_READING
);
540 buffer
= (unsigned char *) (dev
->iamthif_msg_buf
+
541 dev
->iamthif_msg_buf_index
);
542 BUG_ON(sizeof(dev
->iamthif_msg_buf
) <
543 (dev
->iamthif_msg_buf_index
+ heci_hdr
->length
));
545 heci_read_slots(dev
, buffer
, heci_hdr
->length
);
547 dev
->iamthif_msg_buf_index
+= heci_hdr
->length
;
549 if (!(heci_hdr
->msg_complete
))
552 DBG("pthi_message_buffer_index=%d\n", heci_hdr
->length
);
553 DBG("completed pthi read.\n ");
554 if (!dev
->iamthif_current_cb
)
557 priv_cb
= dev
->iamthif_current_cb
;
558 dev
->iamthif_current_cb
= NULL
;
560 file_ext
= (struct heci_file_private
*)priv_cb
->file_private
;
564 dev
->iamthif_stall_timer
= 0;
565 priv_cb
->information
= dev
->iamthif_msg_buf_index
;
566 priv_cb
->read_time
= get_seconds();
567 if ((dev
->iamthif_ioctl
) && (file_ext
== &dev
->iamthif_file_ext
)) {
568 /* found the iamthif cb */
569 DBG("complete the pthi read cb.\n ");
570 if (&dev
->iamthif_file_ext
) {
571 DBG("add the pthi read cb to complete.\n ");
572 list_add_tail(&priv_cb
->cb_list
,
573 &complete_list
->heci_cb
.cb_list
);
580 * _heci_bh_state_ok - check if heci header matches file private data
582 * @file_ext: private data of the file object
583 * @heci_hdr: header of heci client message
585 * returns !=0 if matches, 0 if no match.
587 static int _heci_bh_state_ok(struct heci_file_private
*file_ext
,
588 struct heci_msg_hdr
*heci_hdr
)
590 return ((file_ext
->host_client_id
== heci_hdr
->host_addr
)
591 && (file_ext
->me_client_id
== heci_hdr
->me_addr
)
592 && (file_ext
->state
== HECI_FILE_CONNECTED
)
593 && (HECI_READ_COMPLETE
!= file_ext
->reading_state
));
597 * heci_bh_read_client_message - bottom half read routine after ISR to
598 * handle the read heci client message data processing.
600 * @complete_list: An instance of our list structure
601 * @dev: Device object for our driver
602 * @heci_hdr: header of heci client message
604 * returns 0 on success, <0 on failure.
606 static int heci_bh_read_client_message(struct io_heci_list
*complete_list
,
607 struct iamt_heci_device
*dev
,
608 struct heci_msg_hdr
*heci_hdr
)
610 struct heci_file_private
*file_ext
;
611 struct heci_cb_private
*priv_cb_pos
= NULL
, *priv_cb_next
= NULL
;
612 unsigned char *buffer
= NULL
;
614 DBG("start client msg\n");
615 if (!((dev
->read_list
.status
== 0) &&
616 !list_empty(&dev
->read_list
.heci_cb
.cb_list
)))
619 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
620 &dev
->read_list
.heci_cb
.cb_list
, cb_list
) {
621 file_ext
= (struct heci_file_private
*)
622 priv_cb_pos
->file_private
;
623 if ((file_ext
!= NULL
) &&
624 (_heci_bh_state_ok(file_ext
, heci_hdr
))) {
625 spin_lock(&file_ext
->read_io_lock
);
626 file_ext
->reading_state
= HECI_READING
;
627 buffer
= (unsigned char *)
628 (priv_cb_pos
->response_buffer
.data
+
629 priv_cb_pos
->information
);
630 BUG_ON(priv_cb_pos
->response_buffer
.size
<
632 priv_cb_pos
->information
);
634 if (priv_cb_pos
->response_buffer
.size
<
636 priv_cb_pos
->information
) {
637 DBG("message overflow.\n");
638 list_del(&priv_cb_pos
->cb_list
);
639 spin_unlock(&file_ext
->read_io_lock
);
643 heci_read_slots(dev
, buffer
,
646 priv_cb_pos
->information
+= heci_hdr
->length
;
647 if (heci_hdr
->msg_complete
) {
648 file_ext
->status
= 0;
649 list_del(&priv_cb_pos
->cb_list
);
650 spin_unlock(&file_ext
->read_io_lock
);
651 DBG("completed read host client = %d,"
653 "data length = %lu\n",
654 file_ext
->host_client_id
,
655 file_ext
->me_client_id
,
656 priv_cb_pos
->information
);
658 *(priv_cb_pos
->response_buffer
.data
+
659 priv_cb_pos
->information
) = '\0';
660 DBG("priv_cb_pos->res_buffer - %s\n",
661 priv_cb_pos
->response_buffer
.data
);
662 list_add_tail(&priv_cb_pos
->cb_list
,
663 &complete_list
->heci_cb
.cb_list
);
665 spin_unlock(&file_ext
->read_io_lock
);
674 DBG("message read\n");
676 heci_read_slots(dev
, (unsigned char *) dev
->rd_msg_buf
,
678 DBG("discarding message, header=%08x.\n",
679 *(__u32
*) dev
->rd_msg_buf
);
686 * _heci_bh_iamthif_read - prepare to read iamthif data.
688 * @dev: Device object for our driver.
689 * @slots: free slots.
691 * returns 0, OK; otherwise, error.
693 static int _heci_bh_iamthif_read(struct iamt_heci_device
*dev
, __s32
*slots
)
696 if (((*slots
) * sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
)
697 + sizeof(struct hbm_flow_control
))) {
698 *slots
-= (sizeof(struct heci_msg_hdr
) +
699 sizeof(struct hbm_flow_control
) + 3) / 4;
700 if (!heci_send_flow_control(dev
, &dev
->iamthif_file_ext
)) {
701 DBG("iamthif flow control failed\n");
703 DBG("iamthif flow control success\n");
704 dev
->iamthif_state
= HECI_IAMTHIF_READING
;
705 dev
->iamthif_flow_control_pending
= 0;
706 dev
->iamthif_msg_buf_index
= 0;
707 dev
->iamthif_msg_buf_size
= 0;
708 dev
->iamthif_stall_timer
= IAMTHIF_STALL_TIMER
;
709 dev
->host_buffer_is_empty
= host_buffer_is_empty(dev
);
713 return -ECOMPLETE_MESSAGE
;
718 * _heci_bh_close - process close related operation.
720 * @dev: Device object for our driver.
721 * @slots: free slots.
722 * @priv_cb_pos: callback block.
723 * @file_ext: private data of the file object.
724 * @cmpl_list: complete list.
726 * returns 0, OK; otherwise, error.
728 static int _heci_bh_close(struct iamt_heci_device
*dev
, __s32
*slots
,
729 struct heci_cb_private
*priv_cb_pos
,
730 struct heci_file_private
*file_ext
,
731 struct io_heci_list
*cmpl_list
)
733 if ((*slots
* sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
) +
734 sizeof(struct hbm_client_disconnect_request
))) {
735 *slots
-= (sizeof(struct heci_msg_hdr
) +
736 sizeof(struct hbm_client_disconnect_request
) + 3) / 4;
738 if (!heci_disconnect(dev
, file_ext
)) {
739 file_ext
->status
= 0;
740 priv_cb_pos
->information
= 0;
741 list_move_tail(&priv_cb_pos
->cb_list
,
742 &cmpl_list
->heci_cb
.cb_list
);
743 return -ECOMPLETE_MESSAGE
;
745 file_ext
->state
= HECI_FILE_DISCONNECTING
;
746 file_ext
->status
= 0;
747 priv_cb_pos
->information
= 0;
748 list_move_tail(&priv_cb_pos
->cb_list
,
749 &dev
->ctrl_rd_list
.heci_cb
.cb_list
);
750 file_ext
->timer_count
= HECI_CONNECT_TIMEOUT
;
753 /* return the cancel routine */
754 return -ECORRUPTED_MESSAGE_HEADER
;
761 * _heci_hb_close - process read related operation.
763 * @dev: Device object for our driver.
764 * @slots: free slots.
765 * @priv_cb_pos: callback block.
766 * @file_ext: private data of the file object.
767 * @cmpl_list: complete list.
769 * returns 0, OK; otherwise, error.
771 static int _heci_bh_read(struct iamt_heci_device
*dev
, __s32
*slots
,
772 struct heci_cb_private
*priv_cb_pos
,
773 struct heci_file_private
*file_ext
,
774 struct io_heci_list
*cmpl_list
)
776 if ((*slots
* sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
) +
777 sizeof(struct hbm_flow_control
))) {
778 *slots
-= (sizeof(struct heci_msg_hdr
) +
779 sizeof(struct hbm_flow_control
) + 3) / 4;
780 if (!heci_send_flow_control(dev
, file_ext
)) {
781 file_ext
->status
= -ENODEV
;
782 priv_cb_pos
->information
= 0;
783 list_move_tail(&priv_cb_pos
->cb_list
,
784 &cmpl_list
->heci_cb
.cb_list
);
787 list_move_tail(&priv_cb_pos
->cb_list
,
788 &dev
->read_list
.heci_cb
.cb_list
);
791 /* return the cancel routine */
792 list_del(&priv_cb_pos
->cb_list
);
793 return -ECORRUPTED_MESSAGE_HEADER
;
801 * _heci_bh_ioctl - process ioctl related operation.
803 * @dev: Device object for our driver.
804 * @slots: free slots.
805 * @priv_cb_pos: callback block.
806 * @file_ext: private data of the file object.
807 * @cmpl_list: complete list.
809 * returns 0, OK; otherwise, error.
811 static int _heci_bh_ioctl(struct iamt_heci_device
*dev
, __s32
*slots
,
812 struct heci_cb_private
*priv_cb_pos
,
813 struct heci_file_private
*file_ext
,
814 struct io_heci_list
*cmpl_list
)
816 if ((*slots
* sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
) +
817 sizeof(struct hbm_client_connect_request
))) {
818 file_ext
->state
= HECI_FILE_CONNECTING
;
819 *slots
-= (sizeof(struct heci_msg_hdr
) +
820 sizeof(struct hbm_client_connect_request
) + 3) / 4;
821 if (!heci_connect(dev
, file_ext
)) {
822 file_ext
->status
= -ENODEV
;
823 priv_cb_pos
->information
= 0;
824 list_del(&priv_cb_pos
->cb_list
);
827 list_move_tail(&priv_cb_pos
->cb_list
,
828 &dev
->ctrl_rd_list
.heci_cb
.cb_list
);
829 file_ext
->timer_count
= HECI_CONNECT_TIMEOUT
;
832 /* return the cancel routine */
833 list_del(&priv_cb_pos
->cb_list
);
834 return -ECORRUPTED_MESSAGE_HEADER
;
841 * _heci_bh_cmpl - process completed and no-iamthif operation.
843 * @dev: Device object for our driver.
844 * @slots: free slots.
845 * @priv_cb_pos: callback block.
846 * @file_ext: private data of the file object.
847 * @cmpl_list: complete list.
849 * returns 0, OK; otherwise, error.
851 static int _heci_bh_cmpl(struct iamt_heci_device
*dev
, __s32
*slots
,
852 struct heci_cb_private
*priv_cb_pos
,
853 struct heci_file_private
*file_ext
,
854 struct io_heci_list
*cmpl_list
)
856 struct heci_msg_hdr
*heci_hdr
;
858 if ((*slots
* sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
) +
859 (priv_cb_pos
->request_buffer
.size
-
860 priv_cb_pos
->information
))) {
861 heci_hdr
= (struct heci_msg_hdr
*) &dev
->wr_msg_buf
[0];
862 heci_hdr
->host_addr
= file_ext
->host_client_id
;
863 heci_hdr
->me_addr
= file_ext
->me_client_id
;
864 heci_hdr
->length
= ((priv_cb_pos
->request_buffer
.size
) -
865 (priv_cb_pos
->information
));
866 heci_hdr
->msg_complete
= 1;
867 heci_hdr
->reserved
= 0;
868 DBG("priv_cb_pos->request_buffer.size =%d"
869 "heci_hdr->msg_complete= %d\n",
870 priv_cb_pos
->request_buffer
.size
,
871 heci_hdr
->msg_complete
);
872 DBG("priv_cb_pos->information =%lu\n",
873 priv_cb_pos
->information
);
874 DBG("heci_hdr->length =%d\n",
876 *slots
-= (sizeof(struct heci_msg_hdr
) +
877 heci_hdr
->length
+ 3) / 4;
878 if (!heci_write_message(dev
, heci_hdr
,
880 (priv_cb_pos
->request_buffer
.data
+
881 priv_cb_pos
->information
),
883 file_ext
->status
= -ENODEV
;
884 list_move_tail(&priv_cb_pos
->cb_list
,
885 &cmpl_list
->heci_cb
.cb_list
);
888 flow_ctrl_reduce(dev
, file_ext
);
889 file_ext
->status
= 0;
890 priv_cb_pos
->information
+= heci_hdr
->length
;
891 list_move_tail(&priv_cb_pos
->cb_list
,
892 &dev
->write_waiting_list
.heci_cb
.cb_list
);
894 } else if (*slots
== ((dev
->host_hw_state
& H_CBD
) >> 24)) {
895 /* buffer is still empty */
896 heci_hdr
= (struct heci_msg_hdr
*) &dev
->wr_msg_buf
[0];
897 heci_hdr
->host_addr
= file_ext
->host_client_id
;
898 heci_hdr
->me_addr
= file_ext
->me_client_id
;
900 (*slots
* sizeof(__u32
)) - sizeof(struct heci_msg_hdr
);
901 heci_hdr
->msg_complete
= 0;
902 heci_hdr
->reserved
= 0;
904 (*slots
) -= (sizeof(struct heci_msg_hdr
) +
905 heci_hdr
->length
+ 3) / 4;
906 if (!heci_write_message(dev
, heci_hdr
,
908 (priv_cb_pos
->request_buffer
.data
+
909 priv_cb_pos
->information
),
911 file_ext
->status
= -ENODEV
;
912 list_move_tail(&priv_cb_pos
->cb_list
,
913 &cmpl_list
->heci_cb
.cb_list
);
916 priv_cb_pos
->information
+= heci_hdr
->length
;
917 DBG("priv_cb_pos->request_buffer.size =%d"
918 " heci_hdr->msg_complete= %d\n",
919 priv_cb_pos
->request_buffer
.size
,
920 heci_hdr
->msg_complete
);
921 DBG("priv_cb_pos->information =%lu\n",
922 priv_cb_pos
->information
);
923 DBG("heci_hdr->length =%d\n", heci_hdr
->length
);
925 return -ECOMPLETE_MESSAGE
;
927 return -ECORRUPTED_MESSAGE_HEADER
;
934 * _heci_bh_cmpl_iamthif - process completed iamthif operation.
936 * @dev: Device object for our driver.
937 * @slots: free slots.
938 * @priv_cb_pos: callback block.
939 * @file_ext: private data of the file object.
940 * @cmpl_list: complete list.
942 * returns 0, OK; otherwise, error.
944 static int _heci_bh_cmpl_iamthif(struct iamt_heci_device
*dev
, __s32
*slots
,
945 struct heci_cb_private
*priv_cb_pos
,
946 struct heci_file_private
*file_ext
,
947 struct io_heci_list
*cmpl_list
)
949 struct heci_msg_hdr
*heci_hdr
;
951 if ((*slots
* sizeof(__u32
)) >= (sizeof(struct heci_msg_hdr
) +
952 dev
->iamthif_msg_buf_size
-
953 dev
->iamthif_msg_buf_index
)) {
954 heci_hdr
= (struct heci_msg_hdr
*) &dev
->wr_msg_buf
[0];
955 heci_hdr
->host_addr
= file_ext
->host_client_id
;
956 heci_hdr
->me_addr
= file_ext
->me_client_id
;
957 heci_hdr
->length
= dev
->iamthif_msg_buf_size
-
958 dev
->iamthif_msg_buf_index
;
959 heci_hdr
->msg_complete
= 1;
960 heci_hdr
->reserved
= 0;
962 *slots
-= (sizeof(struct heci_msg_hdr
) +
963 heci_hdr
->length
+ 3) / 4;
965 if (!heci_write_message(dev
, heci_hdr
,
966 (dev
->iamthif_msg_buf
+
967 dev
->iamthif_msg_buf_index
),
969 dev
->iamthif_state
= HECI_IAMTHIF_IDLE
;
970 file_ext
->status
= -ENODEV
;
971 list_del(&priv_cb_pos
->cb_list
);
974 flow_ctrl_reduce(dev
, file_ext
);
975 dev
->iamthif_msg_buf_index
+= heci_hdr
->length
;
976 priv_cb_pos
->information
= dev
->iamthif_msg_buf_index
;
977 file_ext
->status
= 0;
978 dev
->iamthif_state
= HECI_IAMTHIF_FLOW_CONTROL
;
979 dev
->iamthif_flow_control_pending
= 1;
980 /* save iamthif cb sent to pthi client */
981 dev
->iamthif_current_cb
= priv_cb_pos
;
982 list_move_tail(&priv_cb_pos
->cb_list
,
983 &dev
->write_waiting_list
.heci_cb
.cb_list
);
986 } else if (*slots
== ((dev
->host_hw_state
& H_CBD
) >> 24)) {
987 /* buffer is still empty */
988 heci_hdr
= (struct heci_msg_hdr
*) &dev
->wr_msg_buf
[0];
989 heci_hdr
->host_addr
= file_ext
->host_client_id
;
990 heci_hdr
->me_addr
= file_ext
->me_client_id
;
992 (*slots
* sizeof(__u32
)) - sizeof(struct heci_msg_hdr
);
993 heci_hdr
->msg_complete
= 0;
994 heci_hdr
->reserved
= 0;
996 *slots
-= (sizeof(struct heci_msg_hdr
) +
997 heci_hdr
->length
+ 3) / 4;
999 if (!heci_write_message(dev
, heci_hdr
,
1000 (dev
->iamthif_msg_buf
+
1001 dev
->iamthif_msg_buf_index
),
1002 heci_hdr
->length
)) {
1003 file_ext
->status
= -ENODEV
;
1004 list_del(&priv_cb_pos
->cb_list
);
1006 dev
->iamthif_msg_buf_index
+= heci_hdr
->length
;
1008 return -ECOMPLETE_MESSAGE
;
1010 return -ECORRUPTED_MESSAGE_HEADER
;
1017 * heci_bh_write_handler - bottom half write routine after
1018 * ISR to handle the write processing.
1020 * @cmpl_list: An instance of our list structure
1021 * @dev: Device object for our driver
1022 * @slots: slots to write.
1024 * returns 0 on success, <0 on failure.
1026 static int heci_bh_write_handler(struct io_heci_list
*cmpl_list
,
1027 struct iamt_heci_device
*dev
,
1031 struct heci_file_private
*file_ext
;
1032 struct heci_cb_private
*priv_cb_pos
= NULL
, *priv_cb_next
= NULL
;
1033 struct io_heci_list
*list
;
1036 if (!host_buffer_is_empty(dev
)) {
1037 DBG("host buffer is not empty.\n");
1040 dev
->write_hang
= -1;
1041 *slots
= count_empty_write_slots(dev
);
1042 /* complete all waiting for write CB */
1043 DBG("complete all waiting for write cb.\n");
1045 list
= &dev
->write_waiting_list
;
1046 if ((list
->status
== 0)
1047 && !list_empty(&list
->heci_cb
.cb_list
)) {
1048 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
1049 &list
->heci_cb
.cb_list
, cb_list
) {
1050 file_ext
= (struct heci_file_private
*)
1051 priv_cb_pos
->file_private
;
1052 if (file_ext
!= NULL
) {
1053 file_ext
->status
= 0;
1054 list_del(&priv_cb_pos
->cb_list
);
1055 if ((HECI_WRITING
== file_ext
->writing_state
) &&
1056 (priv_cb_pos
->major_file_operations
==
1058 (file_ext
!= &dev
->iamthif_file_ext
)) {
1059 DBG("HECI WRITE COMPLETE\n");
1060 file_ext
->writing_state
=
1061 HECI_WRITE_COMPLETE
;
1062 list_add_tail(&priv_cb_pos
->cb_list
,
1063 &cmpl_list
->heci_cb
.cb_list
);
1065 if (file_ext
== &dev
->iamthif_file_ext
) {
1066 DBG("check iamthif flow control.\n");
1067 if (dev
->iamthif_flow_control_pending
) {
1068 ret
= _heci_bh_iamthif_read(dev
,
1079 if ((dev
->stop
) && (!dev
->wd_pending
)) {
1081 wake_up_interruptible(&dev
->wait_stop_wd
);
1085 if (dev
->extra_write_index
!= 0) {
1086 DBG("extra_write_index =%d.\n", dev
->extra_write_index
);
1087 heci_write_message(dev
,
1088 (struct heci_msg_hdr
*) &dev
->ext_msg_buf
[0],
1089 (unsigned char *) &dev
->ext_msg_buf
[1],
1090 (dev
->extra_write_index
- 1) * sizeof(__u32
));
1091 *slots
-= dev
->extra_write_index
;
1092 dev
->extra_write_index
= 0;
1094 if (dev
->heci_state
== HECI_ENABLED
) {
1095 if ((dev
->wd_pending
)
1096 && flow_ctrl_creds(dev
, &dev
->wd_file_ext
)) {
1097 if (!heci_send_wd(dev
))
1098 DBG("wd send failed.\n");
1100 flow_ctrl_reduce(dev
, &dev
->wd_file_ext
);
1102 dev
->wd_pending
= 0;
1104 if (dev
->wd_timeout
!= 0) {
1105 *slots
-= (sizeof(struct heci_msg_hdr
) +
1106 HECI_START_WD_DATA_SIZE
+ 3) / 4;
1107 dev
->wd_due_counter
= 2;
1109 *slots
-= (sizeof(struct heci_msg_hdr
) +
1110 HECI_WD_PARAMS_SIZE
+ 3) / 4;
1111 dev
->wd_due_counter
= 0;
1119 /* complete control write list CB */
1120 if (dev
->ctrl_wr_list
.status
== 0) {
1121 /* complete control write list CB */
1122 DBG("complete control write list cb.\n");
1123 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
1124 &dev
->ctrl_wr_list
.heci_cb
.cb_list
, cb_list
) {
1125 file_ext
= (struct heci_file_private
*)
1126 priv_cb_pos
->file_private
;
1127 if (file_ext
== NULL
) {
1128 list_del(&priv_cb_pos
->cb_list
);
1131 switch (priv_cb_pos
->major_file_operations
) {
1133 /* send disconnect message */
1134 ret
= _heci_bh_close(dev
, slots
,
1136 file_ext
, cmpl_list
);
1142 /* send flow control message */
1143 ret
= _heci_bh_read(dev
, slots
,
1145 file_ext
, cmpl_list
);
1151 /* connect message */
1152 if (!other_client_is_connecting(dev
, file_ext
))
1154 ret
= _heci_bh_ioctl(dev
, slots
,
1156 file_ext
, cmpl_list
);
1168 /* complete write list CB */
1169 if ((dev
->write_list
.status
== 0)
1170 && !list_empty(&dev
->write_list
.heci_cb
.cb_list
)) {
1171 DBG("complete write list cb.\n");
1172 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
1173 &dev
->write_list
.heci_cb
.cb_list
, cb_list
) {
1174 file_ext
= (struct heci_file_private
*)
1175 priv_cb_pos
->file_private
;
1177 if (file_ext
!= NULL
) {
1178 if (file_ext
!= &dev
->iamthif_file_ext
) {
1179 if (!flow_ctrl_creds(dev
, file_ext
)) {
1180 DBG("No flow control"
1181 " credentials for client"
1182 " %d, not sending.\n",
1183 file_ext
->host_client_id
);
1186 ret
= _heci_bh_cmpl(dev
, slots
,
1193 } else if (file_ext
== &dev
->iamthif_file_ext
) {
1195 DBG("complete pthi write cb.\n");
1196 if (!flow_ctrl_creds(dev
, file_ext
)) {
1197 DBG("No flow control"
1198 " credentials for pthi"
1200 file_ext
->host_client_id
);
1203 ret
= _heci_bh_cmpl_iamthif(dev
, slots
,
1220 * is_treat_specially_client - check if the message belong
1221 * to the file private data.
1223 * @file_ext: private data of the file object
1224 * @rs: connect response bus message
1225 * @dev: Device object for our driver
1227 * returns 0 on success, <0 on failure.
1229 static int is_treat_specially_client(struct heci_file_private
*file_ext
,
1230 struct hbm_client_connect_response
*rs
)
1234 if ((file_ext
->host_client_id
== rs
->host_addr
) &&
1235 (file_ext
->me_client_id
== rs
->me_addr
)) {
1236 if (rs
->status
== 0) {
1237 DBG("client connect status = 0x%08x.\n", rs
->status
);
1238 file_ext
->state
= HECI_FILE_CONNECTED
;
1239 file_ext
->status
= 0;
1241 DBG("client connect status = 0x%08x.\n", rs
->status
);
1242 file_ext
->state
= HECI_FILE_DISCONNECTED
;
1243 file_ext
->status
= -ENODEV
;
1247 DBG("client state = %d.\n", file_ext
->state
);
1252 * heci_client_connect_response - connect response bh routine
1254 * @dev: Device object for our driver
1255 * @rs: connect response bus message
1257 static void heci_client_connect_response(struct iamt_heci_device
*dev
,
1258 struct hbm_client_connect_response
*rs
)
1261 struct heci_file_private
*file_ext
;
1262 struct heci_cb_private
*priv_cb_pos
= NULL
, *priv_cb_next
= NULL
;
1264 /* if WD or iamthif client treat specially */
1266 if ((is_treat_specially_client(&(dev
->wd_file_ext
), rs
)) ||
1267 (is_treat_specially_client(&(dev
->iamthif_file_ext
), rs
)))
1270 if (dev
->ctrl_rd_list
.status
== 0
1271 && !list_empty(&dev
->ctrl_rd_list
.heci_cb
.cb_list
)) {
1272 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
1273 &dev
->ctrl_rd_list
.heci_cb
.cb_list
, cb_list
) {
1274 file_ext
= (struct heci_file_private
*)
1275 priv_cb_pos
->file_private
;
1276 if (file_ext
== NULL
) {
1277 list_del(&priv_cb_pos
->cb_list
);
1280 if (HECI_IOCTL
== priv_cb_pos
->major_file_operations
) {
1281 if (is_treat_specially_client(file_ext
, rs
)) {
1282 list_del(&priv_cb_pos
->cb_list
);
1283 file_ext
->status
= 0;
1284 file_ext
->timer_count
= 0;
1293 * heci_client_disconnect_response - disconnect response bh routine
1295 * @dev: Device object for our driver
1296 * @rs: disconnect response bus message
1298 static void heci_client_disconnect_response(struct iamt_heci_device
*dev
,
1299 struct hbm_client_connect_response
*rs
)
1301 struct heci_file_private
*file_ext
;
1302 struct heci_cb_private
*priv_cb_pos
= NULL
, *priv_cb_next
= NULL
;
1304 if (dev
->ctrl_rd_list
.status
== 0
1305 && !list_empty(&dev
->ctrl_rd_list
.heci_cb
.cb_list
)) {
1306 list_for_each_entry_safe(priv_cb_pos
, priv_cb_next
,
1307 &dev
->ctrl_rd_list
.heci_cb
.cb_list
, cb_list
) {
1308 file_ext
= (struct heci_file_private
*)
1309 priv_cb_pos
->file_private
;
1311 if (file_ext
== NULL
) {
1312 list_del(&priv_cb_pos
->cb_list
);
1316 DBG("list_for_each_entry_safe in ctrl_rd_list.\n");
1317 if ((file_ext
->host_client_id
== rs
->host_addr
) &&
1318 (file_ext
->me_client_id
== rs
->me_addr
)) {
1320 list_del(&priv_cb_pos
->cb_list
);
1321 if (rs
->status
== 0) {
1323 HECI_FILE_DISCONNECTED
;
1326 file_ext
->status
= 0;
1327 file_ext
->timer_count
= 0;
1335 * same_flow_addr - tell they have same address.
1337 * @file: private data of the file object.
1338 * @flow: flow control.
1340 * returns !=0, same; 0,not.
1342 static int same_flow_addr(struct heci_file_private
*file
,
1343 struct hbm_flow_control
*flow
)
1345 return ((file
->host_client_id
== flow
->host_addr
)
1346 && (file
->me_client_id
== flow
->me_addr
));
1350 * add_single_flow_creds - add single buffer credentials.
1352 * @file: private data ot the file object.
1353 * @flow: flow control.
1355 static void add_single_flow_creds(struct iamt_heci_device
*dev
,
1356 struct hbm_flow_control
*flow
)
1358 struct heci_me_client
*client
;
1361 for (i
= 0; i
< dev
->num_heci_me_clients
; i
++) {
1362 client
= &dev
->me_clients
[i
];
1363 if ((client
!= NULL
) &&
1364 (flow
->me_addr
== client
->client_id
)) {
1365 if (client
->props
.single_recv_buf
!= 0) {
1366 client
->flow_ctrl_creds
++;
1367 DBG("recv flow ctrl msg ME %d (single).\n",
1369 DBG("flow control credentials=%d.\n",
1370 client
->flow_ctrl_creds
);
1372 BUG(); /* error in flow control */
1379 * heci_client_flow_control_response - flow control response bh routine
1381 * @dev: Device object for our driver
1382 * @flow_control: flow control response bus message
1384 static void heci_client_flow_control_response(struct iamt_heci_device
*dev
,
1385 struct hbm_flow_control
*flow_control
)
1387 struct heci_file_private
*file_pos
= NULL
;
1388 struct heci_file_private
*file_next
= NULL
;
1390 if (flow_control
->host_addr
== 0) {
1391 /* single receive buffer */
1392 add_single_flow_creds(dev
, flow_control
);
1394 /* normal connection */
1395 list_for_each_entry_safe(file_pos
, file_next
,
1396 &dev
->file_list
, link
) {
1397 DBG("list_for_each_entry_safe in file_list\n");
1399 DBG("file_ext of host client %d ME client %d.\n",
1400 file_pos
->host_client_id
,
1401 file_pos
->me_client_id
);
1402 DBG("flow ctrl msg for host %d ME %d.\n",
1403 flow_control
->host_addr
,
1404 flow_control
->me_addr
);
1405 if (same_flow_addr(file_pos
, flow_control
)) {
1406 DBG("recv ctrl msg for host %d ME %d.\n",
1407 flow_control
->host_addr
,
1408 flow_control
->me_addr
);
1409 file_pos
->flow_ctrl_creds
++;
1410 DBG("flow control credentials=%d.\n",
1411 file_pos
->flow_ctrl_creds
);
1419 * same_disconn_addr - tell they have same address
1421 * @file: private data of the file object.
1422 * @disconn: disconnection request.
1424 * returns !=0, same; 0,not.
1426 static int same_disconn_addr(struct heci_file_private
*file
,
1427 struct hbm_client_disconnect_request
*disconn
)
1429 return ((file
->host_client_id
== disconn
->host_addr
)
1430 && (file
->me_client_id
== disconn
->me_addr
));
1434 * heci_client_disconnect_request - disconnect request bh routine
1436 * @dev: Device object for our driver.
1437 * @disconnect_req: disconnect request bus message.
1439 static void heci_client_disconnect_request(struct iamt_heci_device
*dev
,
1440 struct hbm_client_disconnect_request
*disconnect_req
)
1442 struct heci_msg_hdr
*heci_hdr
;
1443 struct hbm_client_connect_response
*disconnect_res
;
1444 struct heci_file_private
*file_pos
= NULL
;
1445 struct heci_file_private
*file_next
= NULL
;
1447 list_for_each_entry_safe(file_pos
, file_next
, &dev
->file_list
, link
) {
1448 if (same_disconn_addr(file_pos
, disconnect_req
)) {
1449 DBG("disconnect request host client %d ME client %d.\n",
1450 disconnect_req
->host_addr
,
1451 disconnect_req
->me_addr
);
1452 file_pos
->state
= HECI_FILE_DISCONNECTED
;
1453 file_pos
->timer_count
= 0;
1454 if (file_pos
== &dev
->wd_file_ext
) {
1455 dev
->wd_due_counter
= 0;
1456 dev
->wd_pending
= 0;
1457 } else if (file_pos
== &dev
->iamthif_file_ext
)
1458 dev
->iamthif_timer
= 0;
1460 /* prepare disconnect response */
1462 (struct heci_msg_hdr
*) &dev
->ext_msg_buf
[0];
1463 heci_hdr
->host_addr
= 0;
1464 heci_hdr
->me_addr
= 0;
1466 sizeof(struct hbm_client_connect_response
);
1467 heci_hdr
->msg_complete
= 1;
1468 heci_hdr
->reserved
= 0;
1471 (struct hbm_client_connect_response
*)
1472 &dev
->ext_msg_buf
[1];
1473 disconnect_res
->host_addr
= file_pos
->host_client_id
;
1474 disconnect_res
->me_addr
= file_pos
->me_client_id
;
1475 *(__u8
*) (&disconnect_res
->cmd
) =
1476 CLIENT_DISCONNECT_RES_CMD
;
1477 disconnect_res
->status
= 0;
1478 dev
->extra_write_index
= 2;
1485 * heci_timer - timer function.
1487 * @data: pointer to the device structure
1489 * NOTE: This function is called by timer interrupt work
1491 void heci_wd_timer(unsigned long data
)
1493 struct iamt_heci_device
*dev
= (struct iamt_heci_device
*) data
;
1495 DBG("send watchdog.\n");
1496 spin_lock_bh(&dev
->device_lock
);
1497 if (dev
->heci_state
!= HECI_ENABLED
) {
1498 mod_timer(&dev
->wd_timer
, round_jiffies(jiffies
+ 2 * HZ
));
1499 spin_unlock_bh(&dev
->device_lock
);
1502 if (dev
->wd_file_ext
.state
!= HECI_FILE_CONNECTED
) {
1503 mod_timer(&dev
->wd_timer
, round_jiffies(jiffies
+ 2 * HZ
));
1504 spin_unlock_bh(&dev
->device_lock
);
1508 if ((dev
->wd_due_counter
!= 0) && (dev
->wd_bypass
== 0)) {
1509 if (--dev
->wd_due_counter
== 0) {
1510 if (dev
->host_buffer_is_empty
&&
1511 flow_ctrl_creds(dev
, &dev
->wd_file_ext
)) {
1512 dev
->host_buffer_is_empty
= 0;
1513 if (!heci_send_wd(dev
)) {
1514 DBG("wd send failed.\n");
1516 flow_ctrl_reduce(dev
,
1520 if (dev
->wd_timeout
!= 0)
1521 dev
->wd_due_counter
= 2;
1523 dev
->wd_due_counter
= 0;
1526 dev
->wd_pending
= 1;
1530 if (dev
->iamthif_stall_timer
!= 0) {
1531 if (--dev
->iamthif_stall_timer
== 0) {
1532 DBG("reseting because of hang to PTHI.\n");
1534 dev
->iamthif_msg_buf_size
= 0;
1535 dev
->iamthif_msg_buf_index
= 0;
1536 dev
->iamthif_canceled
= 0;
1537 dev
->iamthif_ioctl
= 1;
1538 dev
->iamthif_state
= HECI_IAMTHIF_IDLE
;
1539 dev
->iamthif_timer
= 0;
1540 spin_unlock_bh(&dev
->device_lock
);
1542 if (dev
->iamthif_current_cb
)
1543 heci_free_cb_private(dev
->iamthif_current_cb
);
1545 spin_lock_bh(&dev
->device_lock
);
1546 dev
->iamthif_file_object
= NULL
;
1547 dev
->iamthif_current_cb
= NULL
;
1548 run_next_iamthif_cmd(dev
);
1551 mod_timer(&dev
->wd_timer
, round_jiffies(jiffies
+ 2 * HZ
));
1552 spin_unlock_bh(&dev
->device_lock
);