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);
95 /* clear H_IS bit in H_CSR */
96 heci_csr_clear_his(dev);
99 * Our device interrupted, schedule work the heci_bh_handler
100 * to handle the interrupt processing. This needs to be a
101 * workqueue item since the handler can sleep.
103 PREPARE_WORK(&dev->work, heci_bh_handler);
104 DBG("schedule work the heci_bh_handler.\n");
105 err = schedule_work(&dev->work);
107 printk(KERN_ERR "heci: schedule the heci_bh_handler"
108 " failed error=%x\n", err);
114 * _heci_cmpl - process completed operation.
116 * @file_ext: private data of the file object.
117 * @priv_cb_pos: callback block.
119 static void _heci_cmpl(struct heci_file_private *file_ext,
120 struct heci_cb_private *priv_cb_pos)
122 if (priv_cb_pos->major_file_operations == HECI_WRITE) {
123 heci_free_cb_private(priv_cb_pos);
124 DBG("completing write call back.\n");
125 file_ext->writing_state = HECI_WRITE_COMPLETE;
126 if ((&file_ext->tx_wait) &&
127 waitqueue_active(&file_ext->tx_wait))
128 wake_up_interruptible(&file_ext->tx_wait);
130 } else if (priv_cb_pos->major_file_operations == HECI_READ
131 && HECI_READING == file_ext->reading_state) {
132 DBG("completing read call back information= %lu\n",
133 priv_cb_pos->information);
134 file_ext->reading_state = HECI_READ_COMPLETE;
135 if ((&file_ext->rx_wait) &&
136 waitqueue_active(&file_ext->rx_wait))
137 wake_up_interruptible(&file_ext->rx_wait);
143 * _heci_cmpl_iamthif - process completed iamthif operation.
145 * @dev: Device object for our driver.
146 * @priv_cb_pos: callback block.
148 static void _heci_cmpl_iamthif(struct iamt_heci_device *dev,
149 struct heci_cb_private *priv_cb_pos)
151 if (dev->iamthif_canceled != 1) {
152 dev->iamthif_state = HECI_IAMTHIF_READ_COMPLETE;
153 dev->iamthif_stall_timer = 0;
154 memcpy(priv_cb_pos->response_buffer.data,
155 dev->iamthif_msg_buf,
156 dev->iamthif_msg_buf_index);
157 list_add_tail(&priv_cb_pos->cb_list,
158 &dev->pthi_read_complete_list.heci_cb.cb_list);
159 DBG("pthi read completed.\n");
161 run_next_iamthif_cmd(dev);
163 if (&dev->iamthif_file_ext.wait) {
164 DBG("completing pthi call back.\n");
165 wake_up_interruptible(&dev->iamthif_file_ext.wait);
169 * heci_bh_handler - function called after ISR to handle the interrupt
172 * @work: pointer to the work structure
174 * NOTE: This function is called by schedule work
176 static void heci_bh_handler(struct work_struct *work)
178 struct iamt_heci_device *dev =
179 container_of(work, struct iamt_heci_device, work);
180 struct io_heci_list complete_list;
183 struct heci_cb_private *cb_pos = NULL, *cb_next = NULL;
184 struct heci_file_private *file_ext;
185 int bus_message_received = 0;
186 struct task_struct *tsk;
188 DBG("function called after ISR to handle the interrupt processing.\n");
189 /* initialize our complete list */
190 spin_lock_bh(&dev->device_lock);
191 heci_initialize_list(&complete_list, dev);
192 dev->host_hw_state = read_heci_register(dev, H_CSR);
193 dev->me_hw_state = read_heci_register(dev, ME_CSR_HA);
195 /* check if ME wants a reset */
196 if (((dev->me_hw_state & ME_RDY_HRA) == 0)
197 && (dev->heci_state != HECI_RESETING)
198 && (dev->heci_state != HECI_INITIALIZING)) {
199 DBG("FW not ready.\n");
201 spin_unlock_bh(&dev->device_lock);
205 /* check if we need to start the dev */
206 if ((dev->host_hw_state & H_RDY) == 0) {
207 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
208 DBG("we need to start the dev.\n");
209 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
210 heci_set_csr_register(dev);
211 if (dev->heci_state == HECI_INITIALIZING) {
213 spin_unlock_bh(&dev->device_lock);
214 wake_up_interruptible(&dev->wait_recvd_msg);
218 spin_unlock_bh(&dev->device_lock);
219 tsk = kthread_run(heci_task_initialize_clients,
222 int rc = PTR_ERR(tsk);
223 printk(KERN_WARNING "heci: Unable to"
224 "start the heci thread: %d\n", rc);
229 DBG("enable interrupt FW not ready.\n");
230 heci_csr_enable_interrupts(dev);
231 spin_unlock_bh(&dev->device_lock);
235 /* check slots avalable for reading */
236 slots = count_full_read_slots(dev);
237 DBG("slots =%08x extra_write_index =%08x.\n",
238 slots, dev->extra_write_index);
239 while ((slots > 0) && (!dev->extra_write_index)) {
240 DBG("slots =%08x extra_write_index =%08x.\n", slots,
241 dev->extra_write_index);
242 DBG("call heci_bh_read_handler.\n");
243 rets = heci_bh_read_handler(&complete_list, dev, &slots);
247 rets = heci_bh_write_handler(&complete_list, dev, &slots);
249 DBG("end of bottom half function.\n");
250 dev->host_hw_state = read_heci_register(dev, H_CSR);
251 dev->host_buffer_is_empty = host_buffer_is_empty(dev);
253 if ((dev->host_hw_state & H_IS) == H_IS) {
254 /* acknowledge interrupt and disable interrupts */
255 heci_csr_disable_interrupts(dev);
257 /* clear H_IS bit in H_CSR */
258 heci_csr_clear_his(dev);
260 PREPARE_WORK(&dev->work, heci_bh_handler);
261 DBG("schedule work the heci_bh_handler.\n");
262 rets = schedule_work(&dev->work);
264 printk(KERN_ERR "heci: schedule the heci_bh_handler"
265 " failed error=%x\n", rets);
268 heci_csr_enable_interrupts(dev);
271 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
272 DBG("received waiting bus message\n");
273 bus_message_received = 1;
275 spin_unlock_bh(&dev->device_lock);
276 if (bus_message_received) {
277 DBG("wake up dev->wait_recvd_msg\n");
278 wake_up_interruptible(&dev->wait_recvd_msg);
279 bus_message_received = 0;
281 if ((complete_list.status != 0)
282 || list_empty(&complete_list.heci_cb.cb_list))
286 list_for_each_entry_safe(cb_pos, cb_next,
287 &complete_list.heci_cb.cb_list, cb_list) {
288 file_ext = (struct heci_file_private *)cb_pos->file_private;
289 list_del(&cb_pos->cb_list);
290 if (file_ext != NULL) {
291 if (file_ext != &dev->iamthif_file_ext) {
292 DBG("completing call back.\n");
293 _heci_cmpl(file_ext, cb_pos);
295 } else if (file_ext == &dev->iamthif_file_ext) {
296 _heci_cmpl_iamthif(dev, cb_pos);
304 * heci_bh_read_handler - bottom half read routine after ISR to
305 * handle the read processing.
307 * @cmpl_list: An instance of our list structure
308 * @dev: Device object for our driver
309 * @slots: slots to read.
311 * returns 0 on success, <0 on failure.
313 static int heci_bh_read_handler(struct io_heci_list *cmpl_list,
314 struct iamt_heci_device *dev,
317 struct heci_msg_hdr *heci_hdr;
319 struct heci_file_private *file_pos = NULL;
320 struct heci_file_private *file_next = NULL;
322 if (!dev->rd_msg_hdr) {
323 dev->rd_msg_hdr = read_heci_register(dev, ME_CB_RW);
324 DBG("slots=%08x.\n", *slots);
326 DBG("slots=%08x.\n", *slots);
328 heci_hdr = (struct heci_msg_hdr *) &dev->rd_msg_hdr;
329 DBG("heci_hdr->length =%d\n", heci_hdr->length);
331 if ((heci_hdr->reserved) || !(dev->rd_msg_hdr)) {
332 DBG("corrupted message header.\n");
333 ret = -ECORRUPTED_MESSAGE_HEADER;
337 if ((heci_hdr->host_addr) || (heci_hdr->me_addr)) {
338 list_for_each_entry_safe(file_pos, file_next,
339 &dev->file_list, link) {
340 DBG("list_for_each_entry_safe read host"
341 " client = %d, ME client = %d\n",
342 file_pos->host_client_id,
343 file_pos->me_client_id);
344 if ((file_pos->host_client_id == heci_hdr->host_addr)
345 && (file_pos->me_client_id == heci_hdr->me_addr))
349 if (&file_pos->link == &dev->file_list) {
350 DBG("corrupted message header\n");
351 ret = -ECORRUPTED_MESSAGE_HEADER;
355 if (((*slots) * sizeof(__u32)) < heci_hdr->length) {
356 DBG("we can't read the message slots=%08x.\n", *slots);
357 /* we can't read the message */
362 /* decide where to read the message too */
363 if (!heci_hdr->host_addr) {
364 DBG("call heci_bh_read_bus_message.\n");
365 heci_bh_read_bus_message(dev, heci_hdr);
366 DBG("end heci_bh_read_bus_message.\n");
367 } else if ((heci_hdr->host_addr == dev->iamthif_file_ext.host_client_id)
368 && (HECI_FILE_CONNECTED == dev->iamthif_file_ext.state)
369 && (dev->iamthif_state == HECI_IAMTHIF_READING)) {
370 DBG("call heci_bh_read_iamthif_message.\n");
371 DBG("heci_hdr->length =%d\n", heci_hdr->length);
372 ret = heci_bh_read_pthi_message(cmpl_list, dev, heci_hdr);
377 DBG("call heci_bh_read_client_message.\n");
378 ret = heci_bh_read_client_message(cmpl_list, dev, heci_hdr);
384 /* reset the number of slots and header */
385 *slots = count_full_read_slots(dev);
388 if (*slots == -ESLOTS_OVERFLOW) {
389 /* overflow - reset */
390 DBG("reseting due to slots overflow.\n");
391 /* set the event since message has been read */
401 * heci_bh_read_bus_message - bottom half read routine after ISR to
402 * handle the read bus message cmd processing.
404 * @dev: Device object for our driver
405 * @heci_hdr: header of bus message
407 static void heci_bh_read_bus_message(struct iamt_heci_device *dev,
408 struct heci_msg_hdr *heci_hdr)
410 struct heci_bus_message *heci_msg;
411 struct hbm_host_version_response *version_res;
412 struct hbm_client_connect_response *connect_res;
413 struct hbm_client_connect_response *disconnect_res;
414 struct hbm_flow_control *flow_control;
415 struct hbm_props_response *props_res;
416 struct hbm_host_enum_response *enum_res;
417 struct hbm_client_disconnect_request *disconnect_req;
418 struct hbm_host_stop_request *h_stop_req;
420 unsigned char *buffer;
422 /* read the message to our buffer */
423 buffer = (unsigned char *) dev->rd_msg_buf;
424 BUG_ON(heci_hdr->length >= sizeof(dev->rd_msg_buf));
425 heci_read_slots(dev, buffer, heci_hdr->length);
426 heci_msg = (struct heci_bus_message *) buffer;
428 switch (*(__u8 *) heci_msg) {
429 case HOST_START_RES_CMD:
430 version_res = (struct hbm_host_version_response *) heci_msg;
431 if (version_res->host_version_supported) {
432 dev->version.major_version = HBM_MAJOR_VERSION;
433 dev->version.minor_version = HBM_MINOR_VERSION;
435 dev->version = version_res->me_max_version;
438 DBG("host start response message received.\n");
441 case CLIENT_CONNECT_RES_CMD:
443 (struct hbm_client_connect_response *) heci_msg;
444 heci_client_connect_response(dev, connect_res);
445 DBG("client connect response message received.\n");
446 wake_up(&dev->wait_recvd_msg);
449 case CLIENT_DISCONNECT_RES_CMD:
451 (struct hbm_client_connect_response *) heci_msg;
452 heci_client_disconnect_response(dev, disconnect_res);
453 DBG("client disconnect response message received.\n");
454 wake_up(&dev->wait_recvd_msg);
457 case HECI_FLOW_CONTROL_CMD:
458 flow_control = (struct hbm_flow_control *) heci_msg;
459 heci_client_flow_control_response(dev, flow_control);
460 DBG("client flow control response message received.\n");
463 case HOST_CLIENT_PROPERTEIS_RES_CMD:
464 props_res = (struct hbm_props_response *) heci_msg;
465 if (props_res->status != 0) {
469 for (i = 0; i < dev->num_heci_me_clients; i++) {
470 if (dev->me_clients[i].client_id ==
471 props_res->address) {
472 dev->me_clients[i].props =
473 props_res->client_properties;
481 case HOST_ENUM_RES_CMD:
482 enum_res = (struct hbm_host_enum_response *) heci_msg;
483 memcpy(dev->heci_me_clients, enum_res->valid_addresses, 32);
487 case HOST_STOP_RES_CMD:
488 dev->heci_state = HECI_DISABLED;
489 DBG("reseting because of FW stop response.\n");
493 case CLIENT_DISCONNECT_REQ_CMD:
494 /* search for client */
496 (struct hbm_client_disconnect_request *) heci_msg;
497 heci_client_disconnect_request(dev, disconnect_req);
500 case ME_STOP_REQ_CMD:
501 /* prepare stop request */
502 heci_hdr = (struct heci_msg_hdr *) &dev->ext_msg_buf[0];
503 heci_hdr->host_addr = 0;
504 heci_hdr->me_addr = 0;
505 heci_hdr->length = sizeof(struct hbm_host_stop_request);
506 heci_hdr->msg_complete = 1;
507 heci_hdr->reserved = 0;
509 (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
510 memset(h_stop_req, 0, sizeof(struct hbm_host_stop_request));
511 h_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
512 h_stop_req->reason = DRIVER_STOP_REQUEST;
513 h_stop_req->reserved[0] = 0;
514 h_stop_req->reserved[1] = 0;
515 dev->extra_write_index = 2;
526 * heci_bh_read_pthi_message - bottom half read routine after ISR to
527 * handle the read pthi message data processing.
529 * @complete_list: An instance of our list structure
530 * @dev: Device object for our driver
531 * @heci_hdr: header of pthi message
533 * returns 0 on success, <0 on failure.
535 static int heci_bh_read_pthi_message(struct io_heci_list *complete_list,
536 struct iamt_heci_device *dev,
537 struct heci_msg_hdr *heci_hdr)
539 struct heci_file_private *file_ext;
540 struct heci_cb_private *priv_cb;
541 unsigned char *buffer;
543 BUG_ON(heci_hdr->me_addr != dev->iamthif_file_ext.me_client_id);
544 BUG_ON(dev->iamthif_state != HECI_IAMTHIF_READING);
546 buffer = (unsigned char *) (dev->iamthif_msg_buf +
547 dev->iamthif_msg_buf_index);
548 BUG_ON(sizeof(dev->iamthif_msg_buf) <
549 (dev->iamthif_msg_buf_index + heci_hdr->length));
551 heci_read_slots(dev, buffer, heci_hdr->length);
553 dev->iamthif_msg_buf_index += heci_hdr->length;
555 if (!(heci_hdr->msg_complete))
558 DBG("pthi_message_buffer_index=%d\n", heci_hdr->length);
559 DBG("completed pthi read.\n ");
560 if (!dev->iamthif_current_cb)
563 priv_cb = dev->iamthif_current_cb;
564 dev->iamthif_current_cb = NULL;
566 file_ext = (struct heci_file_private *)priv_cb->file_private;
570 dev->iamthif_stall_timer = 0;
571 priv_cb->information = dev->iamthif_msg_buf_index;
572 priv_cb->read_time = get_seconds();
573 if ((dev->iamthif_ioctl) && (file_ext == &dev->iamthif_file_ext)) {
574 /* found the iamthif cb */
575 DBG("complete the pthi read cb.\n ");
576 if (&dev->iamthif_file_ext) {
577 DBG("add the pthi read cb to complete.\n ");
578 list_add_tail(&priv_cb->cb_list,
579 &complete_list->heci_cb.cb_list);
586 * _heci_bh_state_ok - check if heci header matches file private data
588 * @file_ext: private data of the file object
589 * @heci_hdr: header of heci client message
591 * returns !=0 if matches, 0 if no match.
593 static int _heci_bh_state_ok(struct heci_file_private *file_ext,
594 struct heci_msg_hdr *heci_hdr)
596 return ((file_ext->host_client_id == heci_hdr->host_addr)
597 && (file_ext->me_client_id == heci_hdr->me_addr)
598 && (file_ext->state == HECI_FILE_CONNECTED)
599 && (HECI_READ_COMPLETE != file_ext->reading_state));
603 * heci_bh_read_client_message - bottom half read routine after ISR to
604 * handle the read heci client message data processing.
606 * @complete_list: An instance of our list structure
607 * @dev: Device object for our driver
608 * @heci_hdr: header of heci client message
610 * returns 0 on success, <0 on failure.
612 static int heci_bh_read_client_message(struct io_heci_list *complete_list,
613 struct iamt_heci_device *dev,
614 struct heci_msg_hdr *heci_hdr)
616 struct heci_file_private *file_ext;
617 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
618 unsigned char *buffer = NULL;
620 DBG("start client msg\n");
621 if (!((dev->read_list.status == 0) &&
622 !list_empty(&dev->read_list.heci_cb.cb_list)))
625 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
626 &dev->read_list.heci_cb.cb_list, cb_list) {
627 file_ext = (struct heci_file_private *)
628 priv_cb_pos->file_private;
629 if ((file_ext != NULL) &&
630 (_heci_bh_state_ok(file_ext, heci_hdr))) {
631 spin_lock_bh(&file_ext->read_io_lock);
632 file_ext->reading_state = HECI_READING;
633 buffer = (unsigned char *)
634 (priv_cb_pos->response_buffer.data +
635 priv_cb_pos->information);
636 BUG_ON(priv_cb_pos->response_buffer.size <
638 priv_cb_pos->information);
640 if (priv_cb_pos->response_buffer.size <
642 priv_cb_pos->information) {
643 DBG("message overflow.\n");
644 list_del(&priv_cb_pos->cb_list);
645 spin_unlock_bh(&file_ext->read_io_lock);
649 heci_read_slots(dev, buffer,
652 priv_cb_pos->information += heci_hdr->length;
653 if (heci_hdr->msg_complete) {
654 file_ext->status = 0;
655 list_del(&priv_cb_pos->cb_list);
656 spin_unlock_bh(&file_ext->read_io_lock);
657 DBG("completed read host client = %d,"
659 "data length = %lu\n",
660 file_ext->host_client_id,
661 file_ext->me_client_id,
662 priv_cb_pos->information);
664 *(priv_cb_pos->response_buffer.data +
665 priv_cb_pos->information) = '\0';
666 DBG("priv_cb_pos->res_buffer - %s\n",
667 priv_cb_pos->response_buffer.data);
668 list_add_tail(&priv_cb_pos->cb_list,
669 &complete_list->heci_cb.cb_list);
671 spin_unlock_bh(&file_ext->read_io_lock);
680 DBG("message read\n");
682 heci_read_slots(dev, (unsigned char *) dev->rd_msg_buf,
684 DBG("discarding message, header=%08x.\n",
685 *(__u32 *) dev->rd_msg_buf);
692 * _heci_bh_iamthif_read - prepare to read iamthif data.
694 * @dev: Device object for our driver.
695 * @slots: free slots.
697 * returns 0, OK; otherwise, error.
699 static int _heci_bh_iamthif_read(struct iamt_heci_device *dev, __s32 *slots)
702 if (((*slots) * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr)
703 + sizeof(struct hbm_flow_control))) {
704 *slots -= (sizeof(struct heci_msg_hdr) +
705 sizeof(struct hbm_flow_control) + 3) / 4;
706 if (!heci_send_flow_control(dev, &dev->iamthif_file_ext)) {
707 DBG("iamthif flow control failed\n");
709 DBG("iamthif flow control success\n");
710 dev->iamthif_state = HECI_IAMTHIF_READING;
711 dev->iamthif_flow_control_pending = 0;
712 dev->iamthif_msg_buf_index = 0;
713 dev->iamthif_msg_buf_size = 0;
714 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
715 dev->host_buffer_is_empty = host_buffer_is_empty(dev);
719 return -ECOMPLETE_MESSAGE;
724 * _heci_bh_close - process close related operation.
726 * @dev: Device object for our driver.
727 * @slots: free slots.
728 * @priv_cb_pos: callback block.
729 * @file_ext: private data of the file object.
730 * @cmpl_list: complete list.
732 * returns 0, OK; otherwise, error.
734 static int _heci_bh_close(struct iamt_heci_device *dev, __s32 *slots,
735 struct heci_cb_private *priv_cb_pos,
736 struct heci_file_private *file_ext,
737 struct io_heci_list *cmpl_list)
739 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
740 sizeof(struct hbm_client_disconnect_request))) {
741 *slots -= (sizeof(struct heci_msg_hdr) +
742 sizeof(struct hbm_client_disconnect_request) + 3) / 4;
744 if (!heci_disconnect(dev, file_ext)) {
745 file_ext->status = 0;
746 priv_cb_pos->information = 0;
747 list_move_tail(&priv_cb_pos->cb_list,
748 &cmpl_list->heci_cb.cb_list);
749 return -ECOMPLETE_MESSAGE;
751 file_ext->state = HECI_FILE_DISCONNECTING;
752 file_ext->status = 0;
753 priv_cb_pos->information = 0;
754 list_move_tail(&priv_cb_pos->cb_list,
755 &dev->ctrl_rd_list.heci_cb.cb_list);
756 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
759 /* return the cancel routine */
760 return -ECORRUPTED_MESSAGE_HEADER;
767 * _heci_hb_close - process read related operation.
769 * @dev: Device object for our driver.
770 * @slots: free slots.
771 * @priv_cb_pos: callback block.
772 * @file_ext: private data of the file object.
773 * @cmpl_list: complete list.
775 * returns 0, OK; otherwise, error.
777 static int _heci_bh_read(struct iamt_heci_device *dev, __s32 *slots,
778 struct heci_cb_private *priv_cb_pos,
779 struct heci_file_private *file_ext,
780 struct io_heci_list *cmpl_list)
782 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
783 sizeof(struct hbm_flow_control))) {
784 *slots -= (sizeof(struct heci_msg_hdr) +
785 sizeof(struct hbm_flow_control) + 3) / 4;
786 if (!heci_send_flow_control(dev, file_ext)) {
787 file_ext->status = -ENODEV;
788 priv_cb_pos->information = 0;
789 list_move_tail(&priv_cb_pos->cb_list,
790 &cmpl_list->heci_cb.cb_list);
793 list_move_tail(&priv_cb_pos->cb_list,
794 &dev->read_list.heci_cb.cb_list);
797 /* return the cancel routine */
798 list_del(&priv_cb_pos->cb_list);
799 return -ECORRUPTED_MESSAGE_HEADER;
807 * _heci_bh_ioctl - process ioctl related operation.
809 * @dev: Device object for our driver.
810 * @slots: free slots.
811 * @priv_cb_pos: callback block.
812 * @file_ext: private data of the file object.
813 * @cmpl_list: complete list.
815 * returns 0, OK; otherwise, error.
817 static int _heci_bh_ioctl(struct iamt_heci_device *dev, __s32 *slots,
818 struct heci_cb_private *priv_cb_pos,
819 struct heci_file_private *file_ext,
820 struct io_heci_list *cmpl_list)
822 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
823 sizeof(struct hbm_client_connect_request))) {
824 file_ext->state = HECI_FILE_CONNECTING;
825 *slots -= (sizeof(struct heci_msg_hdr) +
826 sizeof(struct hbm_client_connect_request) + 3) / 4;
827 if (!heci_connect(dev, file_ext)) {
828 file_ext->status = -ENODEV;
829 priv_cb_pos->information = 0;
830 list_del(&priv_cb_pos->cb_list);
833 list_move_tail(&priv_cb_pos->cb_list,
834 &dev->ctrl_rd_list.heci_cb.cb_list);
835 file_ext->timer_count = HECI_CONNECT_TIMEOUT;
838 /* return the cancel routine */
839 list_del(&priv_cb_pos->cb_list);
840 return -ECORRUPTED_MESSAGE_HEADER;
847 * _heci_bh_cmpl - process completed and no-iamthif operation.
849 * @dev: Device object for our driver.
850 * @slots: free slots.
851 * @priv_cb_pos: callback block.
852 * @file_ext: private data of the file object.
853 * @cmpl_list: complete list.
855 * returns 0, OK; otherwise, error.
857 static int _heci_bh_cmpl(struct iamt_heci_device *dev, __s32 *slots,
858 struct heci_cb_private *priv_cb_pos,
859 struct heci_file_private *file_ext,
860 struct io_heci_list *cmpl_list)
862 struct heci_msg_hdr *heci_hdr;
864 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
865 (priv_cb_pos->request_buffer.size -
866 priv_cb_pos->information))) {
867 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
868 heci_hdr->host_addr = file_ext->host_client_id;
869 heci_hdr->me_addr = file_ext->me_client_id;
870 heci_hdr->length = ((priv_cb_pos->request_buffer.size) -
871 (priv_cb_pos->information));
872 heci_hdr->msg_complete = 1;
873 heci_hdr->reserved = 0;
874 DBG("priv_cb_pos->request_buffer.size =%d"
875 "heci_hdr->msg_complete= %d\n",
876 priv_cb_pos->request_buffer.size,
877 heci_hdr->msg_complete);
878 DBG("priv_cb_pos->information =%lu\n",
879 priv_cb_pos->information);
880 DBG("heci_hdr->length =%d\n",
882 *slots -= (sizeof(struct heci_msg_hdr) +
883 heci_hdr->length + 3) / 4;
884 if (!heci_write_message(dev, heci_hdr,
886 (priv_cb_pos->request_buffer.data +
887 priv_cb_pos->information),
889 file_ext->status = -ENODEV;
890 list_move_tail(&priv_cb_pos->cb_list,
891 &cmpl_list->heci_cb.cb_list);
894 flow_ctrl_reduce(dev, file_ext);
895 file_ext->status = 0;
896 priv_cb_pos->information += heci_hdr->length;
897 list_move_tail(&priv_cb_pos->cb_list,
898 &dev->write_waiting_list.heci_cb.cb_list);
900 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
901 /* buffer is still empty */
902 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
903 heci_hdr->host_addr = file_ext->host_client_id;
904 heci_hdr->me_addr = file_ext->me_client_id;
906 (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr);
907 heci_hdr->msg_complete = 0;
908 heci_hdr->reserved = 0;
910 (*slots) -= (sizeof(struct heci_msg_hdr) +
911 heci_hdr->length + 3) / 4;
912 if (!heci_write_message(dev, heci_hdr,
914 (priv_cb_pos->request_buffer.data +
915 priv_cb_pos->information),
917 file_ext->status = -ENODEV;
918 list_move_tail(&priv_cb_pos->cb_list,
919 &cmpl_list->heci_cb.cb_list);
922 priv_cb_pos->information += heci_hdr->length;
923 DBG("priv_cb_pos->request_buffer.size =%d"
924 " heci_hdr->msg_complete= %d\n",
925 priv_cb_pos->request_buffer.size,
926 heci_hdr->msg_complete);
927 DBG("priv_cb_pos->information =%lu\n",
928 priv_cb_pos->information);
929 DBG("heci_hdr->length =%d\n", heci_hdr->length);
931 return -ECOMPLETE_MESSAGE;
933 return -ECORRUPTED_MESSAGE_HEADER;
940 * _heci_bh_cmpl_iamthif - process completed iamthif operation.
942 * @dev: Device object for our driver.
943 * @slots: free slots.
944 * @priv_cb_pos: callback block.
945 * @file_ext: private data of the file object.
946 * @cmpl_list: complete list.
948 * returns 0, OK; otherwise, error.
950 static int _heci_bh_cmpl_iamthif(struct iamt_heci_device *dev, __s32 *slots,
951 struct heci_cb_private *priv_cb_pos,
952 struct heci_file_private *file_ext,
953 struct io_heci_list *cmpl_list)
955 struct heci_msg_hdr *heci_hdr;
957 if ((*slots * sizeof(__u32)) >= (sizeof(struct heci_msg_hdr) +
958 dev->iamthif_msg_buf_size -
959 dev->iamthif_msg_buf_index)) {
960 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
961 heci_hdr->host_addr = file_ext->host_client_id;
962 heci_hdr->me_addr = file_ext->me_client_id;
963 heci_hdr->length = dev->iamthif_msg_buf_size -
964 dev->iamthif_msg_buf_index;
965 heci_hdr->msg_complete = 1;
966 heci_hdr->reserved = 0;
968 *slots -= (sizeof(struct heci_msg_hdr) +
969 heci_hdr->length + 3) / 4;
971 if (!heci_write_message(dev, heci_hdr,
972 (dev->iamthif_msg_buf +
973 dev->iamthif_msg_buf_index),
975 dev->iamthif_state = HECI_IAMTHIF_IDLE;
976 file_ext->status = -ENODEV;
977 list_del(&priv_cb_pos->cb_list);
980 flow_ctrl_reduce(dev, file_ext);
981 dev->iamthif_msg_buf_index += heci_hdr->length;
982 priv_cb_pos->information = dev->iamthif_msg_buf_index;
983 file_ext->status = 0;
984 dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
985 dev->iamthif_flow_control_pending = 1;
986 /* save iamthif cb sent to pthi client */
987 dev->iamthif_current_cb = priv_cb_pos;
988 list_move_tail(&priv_cb_pos->cb_list,
989 &dev->write_waiting_list.heci_cb.cb_list);
992 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
993 /* buffer is still empty */
994 heci_hdr = (struct heci_msg_hdr *) &dev->wr_msg_buf[0];
995 heci_hdr->host_addr = file_ext->host_client_id;
996 heci_hdr->me_addr = file_ext->me_client_id;
998 (*slots * sizeof(__u32)) - sizeof(struct heci_msg_hdr);
999 heci_hdr->msg_complete = 0;
1000 heci_hdr->reserved = 0;
1002 *slots -= (sizeof(struct heci_msg_hdr) +
1003 heci_hdr->length + 3) / 4;
1005 if (!heci_write_message(dev, heci_hdr,
1006 (dev->iamthif_msg_buf +
1007 dev->iamthif_msg_buf_index),
1008 heci_hdr->length)) {
1009 file_ext->status = -ENODEV;
1010 list_del(&priv_cb_pos->cb_list);
1012 dev->iamthif_msg_buf_index += heci_hdr->length;
1014 return -ECOMPLETE_MESSAGE;
1016 return -ECORRUPTED_MESSAGE_HEADER;
1023 * heci_bh_write_handler - bottom half write routine after
1024 * ISR to handle the write processing.
1026 * @cmpl_list: An instance of our list structure
1027 * @dev: Device object for our driver
1028 * @slots: slots to write.
1030 * returns 0 on success, <0 on failure.
1032 static int heci_bh_write_handler(struct io_heci_list *cmpl_list,
1033 struct iamt_heci_device *dev,
1037 struct heci_file_private *file_ext;
1038 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1039 struct io_heci_list *list;
1042 if (!host_buffer_is_empty(dev)) {
1043 DBG("host buffer is not empty.\n");
1046 dev->write_hang = -1;
1047 *slots = count_empty_write_slots(dev);
1048 /* complete all waiting for write CB */
1049 DBG("complete all waiting for write cb.\n");
1051 list = &dev->write_waiting_list;
1052 if ((list->status == 0)
1053 && !list_empty(&list->heci_cb.cb_list)) {
1054 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1055 &list->heci_cb.cb_list, cb_list) {
1056 file_ext = (struct heci_file_private *)
1057 priv_cb_pos->file_private;
1058 if (file_ext != NULL) {
1059 file_ext->status = 0;
1060 list_del(&priv_cb_pos->cb_list);
1061 if ((HECI_WRITING == file_ext->writing_state) &&
1062 (priv_cb_pos->major_file_operations ==
1064 (file_ext != &dev->iamthif_file_ext)) {
1065 DBG("HECI WRITE COMPLETE\n");
1066 file_ext->writing_state =
1067 HECI_WRITE_COMPLETE;
1068 list_add_tail(&priv_cb_pos->cb_list,
1069 &cmpl_list->heci_cb.cb_list);
1071 if (file_ext == &dev->iamthif_file_ext) {
1072 DBG("check iamthif flow control.\n");
1073 if (dev->iamthif_flow_control_pending) {
1074 ret = _heci_bh_iamthif_read(dev,
1085 if ((dev->stop) && (!dev->wd_pending)) {
1087 wake_up_interruptible(&dev->wait_stop_wd);
1091 if (dev->extra_write_index != 0) {
1092 DBG("extra_write_index =%d.\n", dev->extra_write_index);
1093 heci_write_message(dev,
1094 (struct heci_msg_hdr *) &dev->ext_msg_buf[0],
1095 (unsigned char *) &dev->ext_msg_buf[1],
1096 (dev->extra_write_index - 1) * sizeof(__u32));
1097 *slots -= dev->extra_write_index;
1098 dev->extra_write_index = 0;
1100 if (dev->heci_state == HECI_ENABLED) {
1101 if ((dev->wd_pending)
1102 && flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1103 if (!heci_send_wd(dev))
1104 DBG("wd send failed.\n");
1106 flow_ctrl_reduce(dev, &dev->wd_file_ext);
1108 dev->wd_pending = 0;
1110 if (dev->wd_timeout != 0) {
1111 *slots -= (sizeof(struct heci_msg_hdr) +
1112 HECI_START_WD_DATA_SIZE + 3) / 4;
1113 dev->wd_due_counter = 2;
1115 *slots -= (sizeof(struct heci_msg_hdr) +
1116 HECI_WD_PARAMS_SIZE + 3) / 4;
1117 dev->wd_due_counter = 0;
1125 /* complete control write list CB */
1126 if (dev->ctrl_wr_list.status == 0) {
1127 /* complete control write list CB */
1128 DBG("complete control write list cb.\n");
1129 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1130 &dev->ctrl_wr_list.heci_cb.cb_list, cb_list) {
1131 file_ext = (struct heci_file_private *)
1132 priv_cb_pos->file_private;
1133 if (file_ext == NULL) {
1134 list_del(&priv_cb_pos->cb_list);
1137 switch (priv_cb_pos->major_file_operations) {
1139 /* send disconnect message */
1140 ret = _heci_bh_close(dev, slots,
1142 file_ext, cmpl_list);
1148 /* send flow control message */
1149 ret = _heci_bh_read(dev, slots,
1151 file_ext, cmpl_list);
1157 /* connect message */
1158 if (!other_client_is_connecting(dev, file_ext))
1160 ret = _heci_bh_ioctl(dev, slots,
1162 file_ext, cmpl_list);
1174 /* complete write list CB */
1175 if ((dev->write_list.status == 0)
1176 && !list_empty(&dev->write_list.heci_cb.cb_list)) {
1177 DBG("complete write list cb.\n");
1178 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1179 &dev->write_list.heci_cb.cb_list, cb_list) {
1180 file_ext = (struct heci_file_private *)
1181 priv_cb_pos->file_private;
1183 if (file_ext != NULL) {
1184 if (file_ext != &dev->iamthif_file_ext) {
1185 if (!flow_ctrl_creds(dev, file_ext)) {
1186 DBG("No flow control"
1187 " credentials for client"
1188 " %d, not sending.\n",
1189 file_ext->host_client_id);
1192 ret = _heci_bh_cmpl(dev, slots,
1199 } else if (file_ext == &dev->iamthif_file_ext) {
1201 DBG("complete pthi write cb.\n");
1202 if (!flow_ctrl_creds(dev, file_ext)) {
1203 DBG("No flow control"
1204 " credentials for pthi"
1206 file_ext->host_client_id);
1209 ret = _heci_bh_cmpl_iamthif(dev, slots,
1226 * is_treat_specially_client - check if the message belong
1227 * to the file private data.
1229 * @file_ext: private data of the file object
1230 * @rs: connect response bus message
1231 * @dev: Device object for our driver
1233 * returns 0 on success, <0 on failure.
1235 static int is_treat_specially_client(struct heci_file_private *file_ext,
1236 struct hbm_client_connect_response *rs)
1240 if ((file_ext->host_client_id == rs->host_addr) &&
1241 (file_ext->me_client_id == rs->me_addr)) {
1242 if (rs->status == 0) {
1243 DBG("client connect status = 0x%08x.\n", rs->status);
1244 file_ext->state = HECI_FILE_CONNECTED;
1245 file_ext->status = 0;
1247 DBG("client connect status = 0x%08x.\n", rs->status);
1248 file_ext->state = HECI_FILE_DISCONNECTED;
1249 file_ext->status = -ENODEV;
1253 DBG("client state = %d.\n", file_ext->state);
1258 * heci_client_connect_response - connect response bh routine
1260 * @dev: Device object for our driver
1261 * @rs: connect response bus message
1263 static void heci_client_connect_response(struct iamt_heci_device *dev,
1264 struct hbm_client_connect_response *rs)
1267 struct heci_file_private *file_ext;
1268 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1270 /* if WD or iamthif client treat specially */
1272 if ((is_treat_specially_client(&(dev->wd_file_ext), rs)) ||
1273 (is_treat_specially_client(&(dev->iamthif_file_ext), rs)))
1276 if (dev->ctrl_rd_list.status == 0
1277 && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
1278 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1279 &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) {
1280 file_ext = (struct heci_file_private *)
1281 priv_cb_pos->file_private;
1282 if (file_ext == NULL) {
1283 list_del(&priv_cb_pos->cb_list);
1286 if (HECI_IOCTL == priv_cb_pos->major_file_operations) {
1287 if (is_treat_specially_client(file_ext, rs)) {
1288 list_del(&priv_cb_pos->cb_list);
1289 file_ext->status = 0;
1290 file_ext->timer_count = 0;
1299 * heci_client_disconnect_response - disconnect response bh routine
1301 * @dev: Device object for our driver
1302 * @rs: disconnect response bus message
1304 static void heci_client_disconnect_response(struct iamt_heci_device *dev,
1305 struct hbm_client_connect_response *rs)
1307 struct heci_file_private *file_ext;
1308 struct heci_cb_private *priv_cb_pos = NULL, *priv_cb_next = NULL;
1310 if (dev->ctrl_rd_list.status == 0
1311 && !list_empty(&dev->ctrl_rd_list.heci_cb.cb_list)) {
1312 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
1313 &dev->ctrl_rd_list.heci_cb.cb_list, cb_list) {
1314 file_ext = (struct heci_file_private *)
1315 priv_cb_pos->file_private;
1317 if (file_ext == NULL) {
1318 list_del(&priv_cb_pos->cb_list);
1322 DBG("list_for_each_entry_safe in ctrl_rd_list.\n");
1323 if ((file_ext->host_client_id == rs->host_addr) &&
1324 (file_ext->me_client_id == rs->me_addr)) {
1326 list_del(&priv_cb_pos->cb_list);
1327 if (rs->status == 0) {
1329 HECI_FILE_DISCONNECTED;
1332 file_ext->status = 0;
1333 file_ext->timer_count = 0;
1341 * same_flow_addr - tell they have same address.
1343 * @file: private data of the file object.
1344 * @flow: flow control.
1346 * returns !=0, same; 0,not.
1348 static int same_flow_addr(struct heci_file_private *file,
1349 struct hbm_flow_control *flow)
1351 return ((file->host_client_id == flow->host_addr)
1352 && (file->me_client_id == flow->me_addr));
1356 * add_single_flow_creds - add single buffer credentials.
1358 * @file: private data ot the file object.
1359 * @flow: flow control.
1361 static void add_single_flow_creds(struct iamt_heci_device *dev,
1362 struct hbm_flow_control *flow)
1364 struct heci_me_client *client;
1367 for (i = 0; i < dev->num_heci_me_clients; i++) {
1368 client = &dev->me_clients[i];
1369 if ((client != NULL) &&
1370 (flow->me_addr == client->client_id)) {
1371 if (client->props.single_recv_buf != 0) {
1372 client->flow_ctrl_creds++;
1373 DBG("recv flow ctrl msg ME %d (single).\n",
1375 DBG("flow control credentials=%d.\n",
1376 client->flow_ctrl_creds);
1378 BUG(); /* error in flow control */
1385 * heci_client_flow_control_response - flow control response bh routine
1387 * @dev: Device object for our driver
1388 * @flow_control: flow control response bus message
1390 static void heci_client_flow_control_response(struct iamt_heci_device *dev,
1391 struct hbm_flow_control *flow_control)
1393 struct heci_file_private *file_pos = NULL;
1394 struct heci_file_private *file_next = NULL;
1396 if (flow_control->host_addr == 0) {
1397 /* single receive buffer */
1398 add_single_flow_creds(dev, flow_control);
1400 /* normal connection */
1401 list_for_each_entry_safe(file_pos, file_next,
1402 &dev->file_list, link) {
1403 DBG("list_for_each_entry_safe in file_list\n");
1405 DBG("file_ext of host client %d ME client %d.\n",
1406 file_pos->host_client_id,
1407 file_pos->me_client_id);
1408 DBG("flow ctrl msg for host %d ME %d.\n",
1409 flow_control->host_addr,
1410 flow_control->me_addr);
1411 if (same_flow_addr(file_pos, flow_control)) {
1412 DBG("recv ctrl msg for host %d ME %d.\n",
1413 flow_control->host_addr,
1414 flow_control->me_addr);
1415 file_pos->flow_ctrl_creds++;
1416 DBG("flow control credentials=%d.\n",
1417 file_pos->flow_ctrl_creds);
1425 * same_disconn_addr - tell they have same address
1427 * @file: private data of the file object.
1428 * @disconn: disconnection request.
1430 * returns !=0, same; 0,not.
1432 static int same_disconn_addr(struct heci_file_private *file,
1433 struct hbm_client_disconnect_request *disconn)
1435 return ((file->host_client_id == disconn->host_addr)
1436 && (file->me_client_id == disconn->me_addr));
1440 * heci_client_disconnect_request - disconnect request bh routine
1442 * @dev: Device object for our driver.
1443 * @disconnect_req: disconnect request bus message.
1445 static void heci_client_disconnect_request(struct iamt_heci_device *dev,
1446 struct hbm_client_disconnect_request *disconnect_req)
1448 struct heci_msg_hdr *heci_hdr;
1449 struct hbm_client_connect_response *disconnect_res;
1450 struct heci_file_private *file_pos = NULL;
1451 struct heci_file_private *file_next = NULL;
1453 list_for_each_entry_safe(file_pos, file_next, &dev->file_list, link) {
1454 if (same_disconn_addr(file_pos, disconnect_req)) {
1455 DBG("disconnect request host client %d ME client %d.\n",
1456 disconnect_req->host_addr,
1457 disconnect_req->me_addr);
1458 file_pos->state = HECI_FILE_DISCONNECTED;
1459 file_pos->timer_count = 0;
1460 if (file_pos == &dev->wd_file_ext) {
1461 dev->wd_due_counter = 0;
1462 dev->wd_pending = 0;
1463 } else if (file_pos == &dev->iamthif_file_ext)
1464 dev->iamthif_timer = 0;
1466 /* prepare disconnect response */
1468 (struct heci_msg_hdr *) &dev->ext_msg_buf[0];
1469 heci_hdr->host_addr = 0;
1470 heci_hdr->me_addr = 0;
1472 sizeof(struct hbm_client_connect_response);
1473 heci_hdr->msg_complete = 1;
1474 heci_hdr->reserved = 0;
1477 (struct hbm_client_connect_response *)
1478 &dev->ext_msg_buf[1];
1479 disconnect_res->host_addr = file_pos->host_client_id;
1480 disconnect_res->me_addr = file_pos->me_client_id;
1481 *(__u8 *) (&disconnect_res->cmd) =
1482 CLIENT_DISCONNECT_RES_CMD;
1483 disconnect_res->status = 0;
1484 dev->extra_write_index = 2;
1491 * heci_timer - timer function.
1493 * @data: pointer to the device structure
1495 * NOTE: This function is called by timer interrupt work
1497 void heci_wd_timer(unsigned long data)
1499 struct iamt_heci_device *dev = (struct iamt_heci_device *) data;
1501 DBG("send watchdog.\n");
1502 spin_lock_bh(&dev->device_lock);
1503 if (dev->heci_state != HECI_ENABLED) {
1504 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1505 spin_unlock_bh(&dev->device_lock);
1508 if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
1509 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1510 spin_unlock_bh(&dev->device_lock);
1514 if ((dev->wd_due_counter != 0) && (dev->wd_bypass == 0)) {
1515 if (--dev->wd_due_counter == 0) {
1516 if (dev->host_buffer_is_empty &&
1517 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1518 dev->host_buffer_is_empty = 0;
1519 if (!heci_send_wd(dev)) {
1520 DBG("wd send failed.\n");
1522 flow_ctrl_reduce(dev,
1526 if (dev->wd_timeout != 0)
1527 dev->wd_due_counter = 2;
1529 dev->wd_due_counter = 0;
1532 dev->wd_pending = 1;
1536 if (dev->iamthif_stall_timer != 0) {
1537 if (--dev->iamthif_stall_timer == 0) {
1538 DBG("reseting because of hang to PTHI.\n");
1540 dev->iamthif_msg_buf_size = 0;
1541 dev->iamthif_msg_buf_index = 0;
1542 dev->iamthif_canceled = 0;
1543 dev->iamthif_ioctl = 1;
1544 dev->iamthif_state = HECI_IAMTHIF_IDLE;
1545 dev->iamthif_timer = 0;
1546 spin_unlock_bh(&dev->device_lock);
1548 if (dev->iamthif_current_cb)
1549 heci_free_cb_private(dev->iamthif_current_cb);
1551 spin_lock_bh(&dev->device_lock);
1552 dev->iamthif_file_object = NULL;
1553 dev->iamthif_current_cb = NULL;
1554 run_next_iamthif_cmd(dev);
1557 mod_timer(&dev->wd_timer, round_jiffies(jiffies + 2 * HZ));
1558 spin_unlock_bh(&dev->device_lock);