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