Staging: add heci driver
[pandora-kernel.git] / drivers / staging / heci / io_heci.c
1 /*
2  * Part of Intel(R) Manageability Engine Interface Linux driver
3  *
4  * Copyright (c) 2003 - 2008 Intel Corp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
21  *
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.
25  *
26  * NO WARRANTY
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.
38  *
39  */
40
41 #include <linux/module.h>
42 #include <linux/moduleparam.h>
43 #include <linux/kernel.h>
44 #include <linux/slab.h>
45 #include <linux/fs.h>
46 #include <linux/errno.h>
47 #include <linux/types.h>
48 #include <linux/fcntl.h>
49 #include <linux/aio.h>
50 #include <linux/pci.h>
51 #include <linux/reboot.h>
52 #include <linux/poll.h>
53 #include <linux/init.h>
54 #include <linux/kdev_t.h>
55 #include <linux/ioctl.h>
56 #include <linux/cdev.h>
57 #include <linux/list.h>
58 #include <linux/unistd.h>
59 #include <linux/delay.h>
60 #include "kcompat.h"
61
62 #include "heci_data_structures.h"
63 #include "heci.h"
64 #include "heci_interface.h"
65 #include "heci_version.h"
66
67
68 /**
69  * heci_ioctl_get_version - the get driver version IOCTL function
70  *
71  * @dev: Device object for our driver
72  * @if_num:  minor number
73  * @*u_msg: pointer to user data struct in user space
74  * @k_msg: data in kernel on the stack
75  * @file_ext: private data of the file object
76  *
77  * returns 0 on success, <0 on failure.
78  */
79 int heci_ioctl_get_version(struct iamt_heci_device *dev, int if_num,
80                            struct heci_message_data *u_msg,
81                            struct heci_message_data k_msg,
82                            struct heci_file_private *file_ext)
83 {
84         int rets = 0;
85         struct heci_driver_version *version;
86         struct heci_message_data res_msg;
87
88         if ((if_num != HECI_MINOR_NUMBER) || (!dev)
89             || (!file_ext))
90                 return -ENODEV;
91
92         if (k_msg.size < (sizeof(struct heci_driver_version) - 2)) {
93                 DBG("user buffer less than heci_driver_version.\n");
94                 return -EMSGSIZE;
95         }
96
97         res_msg.data = kmalloc(sizeof(struct heci_driver_version), GFP_KERNEL);
98         if (!res_msg.data) {
99                 DBG("failed allocation response buffer size = %d.\n",
100                     (int) sizeof(struct heci_driver_version));
101                 return -ENOMEM;
102         }
103
104         version = (struct heci_driver_version *) res_msg.data;
105         version->major = MAJOR_VERSION;
106         version->minor = MINOR_VERSION;
107         version->hotfix = QUICK_FIX_NUMBER;
108         version->build = VER_BUILD;
109         res_msg.size = sizeof(struct heci_driver_version);
110         if (k_msg.size < sizeof(struct heci_driver_version))
111                 res_msg.size -= 2;
112
113         rets = file_ext->status;
114         /* now copy the data to user space */
115         if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
116                 rets = -EFAULT;
117                 goto end;
118         }
119         if (put_user(res_msg.size, &u_msg->size)) {
120                 rets = -EFAULT;
121                 goto end;
122         }
123 end:
124         kfree(res_msg.data);
125         return rets;
126 }
127
128 /**
129  * heci_ioctl_connect_client - the connect to fw client IOCTL function
130  *
131  * @dev: Device object for our driver
132  * @if_num:  minor number
133  * @*u_msg: pointer to user data struct in user space
134  * @k_msg: data in kernel on the stack
135  * @file_ext: private data of the file object
136  *
137  * returns 0 on success, <0 on failure.
138  */
139 int heci_ioctl_connect_client(struct iamt_heci_device *dev, int if_num,
140                               struct heci_message_data *u_msg,
141                               struct heci_message_data k_msg,
142                               struct file *file)
143 {
144         int rets = 0;
145         struct heci_message_data req_msg, res_msg;
146         struct heci_cb_private *priv_cb = NULL;
147         struct heci_client *client;
148         struct heci_file_private *file_ext;
149         struct heci_file_private *file_pos = NULL;
150         struct heci_file_private *file_next = NULL;
151         long timeout = 15;      /*15 second */
152         __u8 i;
153         int err = 0;
154
155         if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file))
156                 return -ENODEV;
157
158         file_ext = file->private_data;
159         if (!file_ext)
160                 return -ENODEV;
161
162         if (k_msg.size != sizeof(struct guid)) {
163                 DBG("user buffer size is not equal to size of struct "
164                                 "guid(16).\n");
165                 return -EMSGSIZE;
166         }
167
168         if (!k_msg.data)
169                 return -EIO;
170
171         req_msg.data = kmalloc(sizeof(struct guid), GFP_KERNEL);
172         res_msg.data = kmalloc(sizeof(struct heci_client), GFP_KERNEL);
173
174         if (!res_msg.data) {
175                 DBG("failed allocation response buffer size = %d.\n",
176                     (int) sizeof(struct heci_client));
177                 kfree(req_msg.data);
178                 return -ENOMEM;
179         }
180         if (!req_msg.data) {
181                 DBG("failed allocation request buffer size = %d.\n",
182                     (int) sizeof(struct guid));
183                 kfree(res_msg.data);
184                 return -ENOMEM;
185         }
186         req_msg.size = sizeof(struct guid);
187         res_msg.size = sizeof(struct heci_client);
188
189         /* copy the message to kernel space -
190          * use a pointer already copied into kernel space
191          */
192         if (copy_from_user(req_msg.data, k_msg.data, k_msg.size)) {
193                 rets = -EFAULT;
194                 goto end;
195         }
196         /* buffered ioctl cb */
197         priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
198         if (!priv_cb) {
199                 rets = -ENOMEM;
200                 goto end;
201         }
202         INIT_LIST_HEAD(&priv_cb->cb_list);
203         priv_cb->response_buffer.data = res_msg.data;
204         priv_cb->response_buffer.size = res_msg.size;
205         priv_cb->request_buffer.data = req_msg.data;
206         priv_cb->request_buffer.size = req_msg.size;
207         priv_cb->major_file_operations = HECI_IOCTL;
208         spin_lock_bh(&dev->device_lock);
209         if (dev->heci_state != HECI_ENABLED) {
210                 rets = -ENODEV;
211                 spin_unlock_bh(&dev->device_lock);
212                 goto end;
213         }
214         if ((file_ext->state != HECI_FILE_INITIALIZING) &&
215             (file_ext->state != HECI_FILE_DISCONNECTED)) {
216                 rets = -EBUSY;
217                 spin_unlock_bh(&dev->device_lock);
218                 goto end;
219         }
220
221         /* find ME client we're trying to connect to */
222         for (i = 0; i < dev->num_heci_me_clients; i++) {
223                 if (memcmp((struct guid *)req_msg.data,
224                             &dev->me_clients[i].props.protocol_name,
225                             sizeof(struct guid)) == 0) {
226                         if (dev->me_clients[i].props.fixed_address == 0) {
227                                 file_ext->me_client_id =
228                                     dev->me_clients[i].client_id;
229                                 file_ext->state = HECI_FILE_CONNECTING;
230                         }
231                         break;
232                 }
233         }
234         /* if we're connecting to PTHI client so we will use the exist
235          * connection
236          */
237         if (memcmp((struct guid *)req_msg.data, &heci_pthi_guid,
238                                 sizeof(struct guid)) == 0) {
239                 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
240                         rets = -ENODEV;
241                         spin_unlock_bh(&dev->device_lock);
242                         goto end;
243                 }
244                 dev->heci_host_clients[file_ext->host_client_id / 8] &=
245                         ~(1 << (file_ext->host_client_id % 8));
246                 list_for_each_entry_safe(file_pos,
247                     file_next, &dev->file_list, link) {
248                         if (heci_fe_same_id(file_ext, file_pos)) {
249                                 DBG("remove file private data node host"
250                                     " client = %d, ME client = %d.\n",
251                                     file_pos->host_client_id,
252                                     file_pos->me_client_id);
253                                 list_del(&file_pos->link);
254                         }
255
256                 }
257                 DBG("free file private data memory.\n");
258                 kfree(file_ext);
259                 file_ext = NULL;
260                 file->private_data = &dev->iamthif_file_ext;
261                 client = (struct heci_client *) res_msg.data;
262                 client->max_msg_length =
263                         dev->me_clients[i].props.max_msg_length;
264                 client->protocol_version =
265                         dev->me_clients[i].props.protocol_version;
266                 rets = dev->iamthif_file_ext.status;
267                 spin_unlock_bh(&dev->device_lock);
268
269                 /* now copy the data to user space */
270                 if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
271                         rets = -EFAULT;
272                         goto end;
273                 }
274                 if (put_user(res_msg.size, &u_msg->size)) {
275                         rets = -EFAULT;
276                         goto end;
277                 }
278                 goto end;
279         }
280         spin_lock(&file_ext->file_lock);
281         if (file_ext->state != HECI_FILE_CONNECTING) {
282                 rets = -ENODEV;
283                 spin_unlock(&file_ext->file_lock);
284                 spin_unlock_bh(&dev->device_lock);
285                 goto end;
286         }
287         spin_unlock(&file_ext->file_lock);
288         /* prepare the output buffer */
289         client = (struct heci_client *) res_msg.data;
290         client->max_msg_length = dev->me_clients[i].props.max_msg_length;
291         client->protocol_version = dev->me_clients[i].props.protocol_version;
292         if (dev->host_buffer_is_empty
293             && !other_client_is_connecting(dev, file_ext)) {
294                 dev->host_buffer_is_empty = 0;
295                 if (!heci_connect(dev, file_ext)) {
296                         rets = -ENODEV;
297                         spin_unlock_bh(&dev->device_lock);
298                         goto end;
299                 } else {
300                         file_ext->timer_count = HECI_CONNECT_TIMEOUT;
301                         priv_cb->file_private = file_ext;
302                         list_add_tail(&priv_cb->cb_list,
303                                       &dev->ctrl_rd_list.heci_cb.
304                                       cb_list);
305                 }
306
307
308         } else {
309                 priv_cb->file_private = file_ext;
310                 DBG("add connect cb to control write list.\n");
311                 list_add_tail(&priv_cb->cb_list,
312                               &dev->ctrl_wr_list.heci_cb.cb_list);
313         }
314         spin_unlock_bh(&dev->device_lock);
315         err = wait_event_timeout(dev->wait_recvd_msg,
316                         (HECI_FILE_CONNECTED == file_ext->state
317                          || HECI_FILE_DISCONNECTED == file_ext->state),
318                         timeout * HZ);
319
320         if (HECI_FILE_CONNECTED == file_ext->state) {
321                 DBG("successfully connected to FW client.\n");
322                 rets = file_ext->status;
323                 /* now copy the data to user space */
324                 if (copy_to_user(k_msg.data, res_msg.data, res_msg.size)) {
325                         rets = -EFAULT;
326                         goto end;
327                 }
328                 if (put_user(res_msg.size, &u_msg->size)) {
329                         rets = -EFAULT;
330                         goto end;
331                 }
332                 goto end;
333         } else {
334                 DBG("failed to connect to FW client.file_ext->state = %d.\n",
335                     file_ext->state);
336                 if (!err) {
337                         DBG("wait_event_interruptible_timeout failed on client"
338                             " connect message fw response message.\n");
339                 }
340                 rets = -EFAULT;
341                 goto remove_list;
342         }
343
344 remove_list:
345         if (priv_cb) {
346                 spin_lock_bh(&dev->device_lock);
347                 heci_flush_list(&dev->ctrl_rd_list, file_ext);
348                 heci_flush_list(&dev->ctrl_wr_list, file_ext);
349                 spin_unlock_bh(&dev->device_lock);
350         }
351 end:
352         DBG("free connect cb memory.");
353         kfree(req_msg.data);
354         kfree(res_msg.data);
355         kfree(priv_cb);
356         return rets;
357 }
358
359 /**
360  * heci_ioctl_wd  - the wd IOCTL function
361  *
362  * @dev: Device object for our driver
363  * @if_num:  minor number
364  * @k_msg: data in kernel on the stack
365  * @file_ext: private data of the file object
366  *
367  * returns 0 on success, <0 on failure.
368  */
369 int heci_ioctl_wd(struct iamt_heci_device *dev, int if_num,
370                   struct heci_message_data k_msg,
371                   struct heci_file_private *file_ext)
372 {
373         int rets = 0;
374         struct heci_message_data req_msg;       /*in kernel on the stack */
375
376         if (if_num != HECI_MINOR_NUMBER)
377                 return -ENODEV;
378
379         spin_lock(&file_ext->file_lock);
380         if (k_msg.size != HECI_WATCHDOG_DATA_SIZE) {
381                 DBG("user buffer has invalid size.\n");
382                 spin_unlock(&file_ext->file_lock);
383                 return -EMSGSIZE;
384         }
385         spin_unlock(&file_ext->file_lock);
386
387         req_msg.data = kmalloc(HECI_WATCHDOG_DATA_SIZE, GFP_KERNEL);
388         if (!req_msg.data) {
389                 DBG("failed allocation request buffer size = %d.\n",
390                     HECI_WATCHDOG_DATA_SIZE);
391                 return -ENOMEM;
392         }
393         req_msg.size = HECI_WATCHDOG_DATA_SIZE;
394
395         /* copy the message to kernel space - use a pointer already
396          * copied into kernel space
397          */
398         if (copy_from_user(req_msg.data, k_msg.data, req_msg.size)) {
399                 rets = -EFAULT;
400                 goto end;
401         }
402         spin_lock_bh(&dev->device_lock);
403         if (dev->heci_state != HECI_ENABLED) {
404                 rets = -ENODEV;
405                 spin_unlock_bh(&dev->device_lock);
406                 goto end;
407         }
408
409         if (dev->wd_file_ext.state != HECI_FILE_CONNECTED) {
410                 rets = -ENODEV;
411                 spin_unlock_bh(&dev->device_lock);
412                 goto end;
413         }
414         if (!dev->asf_mode) {
415                 rets = -EIO;
416                 spin_unlock_bh(&dev->device_lock);
417                 goto end;
418         }
419
420         memcpy(&dev->wd_data[HECI_WD_PARAMS_SIZE], req_msg.data,
421                HECI_WATCHDOG_DATA_SIZE);
422
423         dev->wd_timeout = (req_msg.data[1] << 8) + req_msg.data[0];
424         dev->wd_pending = 0;
425         dev->wd_due_counter = 1;        /* next timer */
426         if (dev->wd_timeout == 0) {
427                 memcpy(dev->wd_data, heci_stop_wd_params,
428                        HECI_WD_PARAMS_SIZE);
429         } else {
430                 memcpy(dev->wd_data, heci_start_wd_params,
431                        HECI_WD_PARAMS_SIZE);
432                 mod_timer(&dev->wd_timer, jiffies);
433         }
434         spin_unlock_bh(&dev->device_lock);
435 end:
436         kfree(req_msg.data);
437         return rets;
438 }
439
440
441 /**
442  * heci_ioctl_bypass_wd  - the bypass_wd IOCTL function
443  *
444  * @dev: Device object for our driver
445  * @if_num:  minor number
446  * @k_msg: data in kernel on the stack
447  * @file_ext: private data of the file object
448  *
449  * returns 0 on success, <0 on failure.
450  */
451 int heci_ioctl_bypass_wd(struct iamt_heci_device *dev, int if_num,
452                   struct heci_message_data k_msg,
453                   struct heci_file_private *file_ext)
454 {
455         __u8 flag = 0;
456         int rets = 0;
457
458         if (if_num != HECI_MINOR_NUMBER)
459                 return -ENODEV;
460
461         spin_lock(&file_ext->file_lock);
462         if (k_msg.size < 1) {
463                 DBG("user buffer less than HECI_WATCHDOG_DATA_SIZE.\n");
464                 spin_unlock(&file_ext->file_lock);
465                 return -EMSGSIZE;
466         }
467         spin_unlock(&file_ext->file_lock);
468         if (copy_from_user(&flag, k_msg.data, 1)) {
469                 rets = -EFAULT;
470                 goto end;
471         }
472
473         spin_lock_bh(&dev->device_lock);
474         flag = flag ? (1) : (0);
475         dev->wd_bypass = flag;
476         spin_unlock_bh(&dev->device_lock);
477 end:
478         return rets;
479 }
480
481 /**
482  * find_pthi_read_list_entry - finds a PTHIlist entry for current file
483  *
484  * @dev: Device object for our driver
485  * @file: pointer to file object
486  *
487  * returns   returned a list entry on success, NULL on failure.
488  */
489 struct heci_cb_private *find_pthi_read_list_entry(
490                 struct iamt_heci_device *dev,
491                 struct file *file)
492 {
493         struct heci_file_private *file_ext_temp;
494         struct heci_cb_private *priv_cb_pos = NULL;
495         struct heci_cb_private *priv_cb_next = NULL;
496
497         if ((dev->pthi_read_complete_list.status == 0) &&
498             !list_empty(&dev->pthi_read_complete_list.heci_cb.cb_list)) {
499                 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
500                     &dev->pthi_read_complete_list.heci_cb.cb_list, cb_list) {
501                         file_ext_temp = (struct heci_file_private *)
502                                         priv_cb_pos->file_private;
503                         if ((file_ext_temp != NULL) &&
504                             (file_ext_temp == &dev->iamthif_file_ext) &&
505                             (priv_cb_pos->file_object == file))
506                                 return priv_cb_pos;
507                 }
508         }
509         return NULL;
510 }
511
512 /**
513  * pthi_read - read data from pthi client
514  *
515  * @dev: Device object for our driver
516  * @if_num:  minor number
517  * @file: pointer to file object
518  * @*ubuf: pointer to user data in user space
519  * @length: data length to read
520  * @offset: data read offset
521  *
522  * returns
523  *  returned data length on success,
524  *  zero if no data to read,
525  *  negative on failure.
526  */
527 int pthi_read(struct iamt_heci_device *dev, int if_num, struct file *file,
528               char *ubuf, size_t length, loff_t *offset)
529 {
530         int rets = 0;
531         struct heci_cb_private *priv_cb = NULL;
532         struct heci_file_private *file_ext = file->private_data;
533         __u8 i;
534         unsigned long currtime = get_seconds();
535
536         if ((if_num != HECI_MINOR_NUMBER) || (!dev))
537                 return -ENODEV;
538
539         if ((file_ext == NULL) || (file_ext != &dev->iamthif_file_ext))
540                 return -ENODEV;
541
542         spin_lock_bh(&dev->device_lock);
543         for (i = 0; i < dev->num_heci_me_clients; i++) {
544                 if (dev->me_clients[i].client_id ==
545                     dev->iamthif_file_ext.me_client_id)
546                         break;
547         }
548         BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
549         if ((i == dev->num_heci_me_clients)
550             || (dev->me_clients[i].client_id !=
551                 dev->iamthif_file_ext.me_client_id)) {
552                 DBG("PTHI client not found.\n");
553                 spin_unlock_bh(&dev->device_lock);
554                 return -ENODEV;
555         }
556         priv_cb = find_pthi_read_list_entry(dev, file);
557         if (!priv_cb) {
558                 spin_unlock_bh(&dev->device_lock);
559                 return 0; /* No more data to read */
560         } else {
561                 if (priv_cb &&
562                     (currtime - priv_cb->read_time > IAMTHIF_READ_TIMER)) {
563                         /* 15 sec for the message has expired */
564                         list_del(&priv_cb->cb_list);
565                         spin_unlock_bh(&dev->device_lock);
566                         rets = -ETIMEDOUT;
567                         goto free;
568                 }
569                 /* if the whole message will fit remove it from the list */
570                 if ((priv_cb->information >= *offset)  &&
571                     (length >= (priv_cb->information - *offset)))
572                         list_del(&priv_cb->cb_list);
573                 else if ((priv_cb->information > 0) &&
574                     (priv_cb->information <= *offset)) {
575                         /* end of the message has been reached */
576                         list_del(&priv_cb->cb_list);
577                         rets = 0;
578                         spin_unlock_bh(&dev->device_lock);
579                         goto free;
580                 }
581                 /* else means that not full buffer will be read and do not
582                  * remove message from deletion list
583                  */
584         }
585         DBG("pthi priv_cb->response_buffer size - %d\n",
586             priv_cb->response_buffer.size);
587         DBG("pthi priv_cb->information - %lu\n",
588             priv_cb->information);
589         spin_unlock_bh(&dev->device_lock);
590
591         /* length is being turncated to PAGE_SIZE, however,
592          * the information may be longer */
593         length = length < (priv_cb->information - *offset) ?
594                         length : (priv_cb->information - *offset);
595
596         if (copy_to_user(ubuf,
597                          priv_cb->response_buffer.data + *offset,
598                          length))
599                 rets = -EFAULT;
600         else {
601                 rets = length;
602                 if ((*offset + length) < priv_cb->information) {
603                         *offset += length;
604                         goto out;
605                 }
606         }
607 free:
608         DBG("free pthi cb memory.\n");
609         *offset = 0;
610         heci_free_cb_private(priv_cb);
611 out:
612         return rets;
613 }
614
615 /**
616  * heci_start_read  - the start read client message function.
617  *
618  * @dev: Device object for our driver
619  * @if_num:  minor number
620  * @file_ext: private data of the file object
621  *
622  * returns 0 on success, <0 on failure.
623  */
624 int heci_start_read(struct iamt_heci_device *dev, int if_num,
625                     struct heci_file_private *file_ext)
626 {
627         int rets = 0;
628         __u8 i;
629         struct heci_cb_private *priv_cb = NULL;
630
631         if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext)) {
632                 DBG("received wrong function input param.\n");
633                 return -ENODEV;
634         }
635         if (file_ext->state != HECI_FILE_CONNECTED)
636                 return -ENODEV;
637
638         spin_lock_bh(&dev->device_lock);
639         if (dev->heci_state != HECI_ENABLED) {
640                 spin_unlock_bh(&dev->device_lock);
641                 return -ENODEV;
642         }
643         spin_unlock_bh(&dev->device_lock);
644         DBG("check if read is pending.\n");
645         if ((file_ext->read_pending) || (file_ext->read_cb != NULL)) {
646                 DBG("read is pending.\n");
647                 return -EBUSY;
648         }
649         priv_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
650         if (!priv_cb)
651                 return -ENOMEM;
652
653         DBG("allocation call back success\n"
654             "host client = %d, ME client = %d\n",
655             file_ext->host_client_id, file_ext->me_client_id);
656         spin_lock_bh(&dev->device_lock);
657         for (i = 0; i < dev->num_heci_me_clients; i++) {
658                 if (dev->me_clients[i].client_id == file_ext->me_client_id)
659                         break;
660
661         }
662
663         BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
664         if (i == dev->num_heci_me_clients) {
665                 rets = -ENODEV;
666                 goto unlock;
667         }
668
669         priv_cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
670         spin_unlock_bh(&dev->device_lock);
671         priv_cb->response_buffer.data =
672             kmalloc(priv_cb->response_buffer.size, GFP_KERNEL);
673         if (!priv_cb->response_buffer.data) {
674                 rets = -ENOMEM;
675                 goto fail;
676         }
677         DBG("allocation call back data success.\n");
678         priv_cb->major_file_operations = HECI_READ;
679         /* make sure information is zero before we start */
680         priv_cb->information = 0;
681         priv_cb->file_private = (void *) file_ext;
682         file_ext->read_cb = priv_cb;
683         spin_lock_bh(&dev->device_lock);
684         if (dev->host_buffer_is_empty) {
685                 dev->host_buffer_is_empty = 0;
686                 if (!heci_send_flow_control(dev, file_ext)) {
687                         rets = -ENODEV;
688                         goto unlock;
689                 } else {
690                         list_add_tail(&priv_cb->cb_list,
691                                       &dev->read_list.heci_cb.cb_list);
692                 }
693         } else {
694                 list_add_tail(&priv_cb->cb_list,
695                               &dev->ctrl_wr_list.heci_cb.cb_list);
696         }
697         spin_unlock_bh(&dev->device_lock);
698         return rets;
699 unlock:
700         spin_unlock_bh(&dev->device_lock);
701 fail:
702         heci_free_cb_private(priv_cb);
703         return rets;
704 }
705
706 /**
707  * pthi_write - write iamthif data to pthi client
708  *
709  * @dev: Device object for our driver
710  * @priv_cb: heci call back struct
711  *
712  * returns 0 on success, <0 on failure.
713  */
714 int pthi_write(struct iamt_heci_device *dev,
715                struct heci_cb_private *priv_cb)
716 {
717         int rets = 0;
718         struct heci_msg_hdr heci_hdr;
719
720         if ((!dev) || (!priv_cb))
721                 return -ENODEV;
722
723         DBG("write data to pthi client.\n");
724
725         dev->iamthif_state = HECI_IAMTHIF_WRITING;
726         dev->iamthif_current_cb = priv_cb;
727         dev->iamthif_file_object = priv_cb->file_object;
728         dev->iamthif_canceled = 0;
729         dev->iamthif_ioctl = 1;
730         dev->iamthif_msg_buf_size = priv_cb->request_buffer.size;
731         memcpy(dev->iamthif_msg_buf, priv_cb->request_buffer.data,
732             priv_cb->request_buffer.size);
733
734         if (flow_ctrl_creds(dev, &dev->iamthif_file_ext) &&
735             dev->host_buffer_is_empty) {
736                 dev->host_buffer_is_empty = 0;
737                 if (priv_cb->request_buffer.size >
738                     (((dev->host_hw_state & H_CBD) >> 24) *
739                     sizeof(__u32)) - sizeof(struct heci_msg_hdr)) {
740                         heci_hdr.length =
741                             (((dev->host_hw_state & H_CBD) >> 24) *
742                             sizeof(__u32)) - sizeof(struct heci_msg_hdr);
743                         heci_hdr.msg_complete = 0;
744                 } else {
745                         heci_hdr.length = priv_cb->request_buffer.size;
746                         heci_hdr.msg_complete = 1;
747                 }
748
749                 heci_hdr.host_addr = dev->iamthif_file_ext.host_client_id;
750                 heci_hdr.me_addr = dev->iamthif_file_ext.me_client_id;
751                 heci_hdr.reserved = 0;
752                 dev->iamthif_msg_buf_index += heci_hdr.length;
753                 if (!heci_write_message(dev, &heci_hdr,
754                                         (unsigned char *)(dev->iamthif_msg_buf),
755                                         heci_hdr.length))
756                         return -ENODEV;
757
758                 if (heci_hdr.msg_complete) {
759                         flow_ctrl_reduce(dev, &dev->iamthif_file_ext);
760                         dev->iamthif_flow_control_pending = 1;
761                         dev->iamthif_state = HECI_IAMTHIF_FLOW_CONTROL;
762                         DBG("add pthi cb to write waiting list\n");
763                         dev->iamthif_current_cb = priv_cb;
764                         dev->iamthif_file_object = priv_cb->file_object;
765                         list_add_tail(&priv_cb->cb_list,
766                                       &dev->write_waiting_list.heci_cb.cb_list);
767                 } else {
768                         DBG("message does not complete, "
769                                         "so add pthi cb to write list.\n");
770                         list_add_tail(&priv_cb->cb_list,
771                                       &dev->write_list.heci_cb.cb_list);
772                 }
773         } else {
774                 if (!(dev->host_buffer_is_empty))
775                         DBG("host buffer is not empty");
776
777                 DBG("No flow control credentials, "
778                                 "so add iamthif cb to write list.\n");
779                 list_add_tail(&priv_cb->cb_list,
780                               &dev->write_list.heci_cb.cb_list);
781         }
782         return rets;
783 }
784
785 /**
786  * iamthif_ioctl_send_msg - send cmd data to pthi client
787  *
788  * @dev: Device object for our driver
789  *
790  * returns 0 on success, <0 on failure.
791  */
792 void run_next_iamthif_cmd(struct iamt_heci_device *dev)
793 {
794         struct heci_file_private *file_ext_tmp;
795         struct heci_cb_private *priv_cb_pos = NULL;
796         struct heci_cb_private *priv_cb_next = NULL;
797         int status = 0;
798
799         if (!dev)
800                 return;
801
802         dev->iamthif_msg_buf_size = 0;
803         dev->iamthif_msg_buf_index = 0;
804         dev->iamthif_canceled = 0;
805         dev->iamthif_ioctl = 1;
806         dev->iamthif_state = HECI_IAMTHIF_IDLE;
807         dev->iamthif_timer = 0;
808         dev->iamthif_file_object = NULL;
809
810         if (dev->pthi_cmd_list.status == 0 &&
811             !list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)) {
812                 DBG("complete pthi cmd_list cb.\n");
813
814                 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
815                     &dev->pthi_cmd_list.heci_cb.cb_list, cb_list) {
816                         list_del(&priv_cb_pos->cb_list);
817                         file_ext_tmp = (struct heci_file_private *)
818                                         priv_cb_pos->file_private;
819
820                         if ((file_ext_tmp != NULL) &&
821                             (file_ext_tmp == &dev->iamthif_file_ext)) {
822                                 status = pthi_write(dev, priv_cb_pos);
823                                 if (status != 0) {
824                                         DBG("pthi write failed status = %d\n",
825                                                         status);
826                                         return;
827                                 }
828                                 break;
829                         }
830                 }
831         }
832 }
833
834 /**
835  * heci_free_cb_private - free heci_cb_private related memory
836  *
837  * @priv_cb: heci callback struct
838  */
839 void heci_free_cb_private(struct heci_cb_private *priv_cb)
840 {
841         if (priv_cb == NULL)
842                 return;
843
844         kfree(priv_cb->request_buffer.data);
845         kfree(priv_cb->response_buffer.data);
846         kfree(priv_cb);
847 }
848