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);