Staging: heci: fix checkpatch warnings
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / heci / heci_main.c
blob3db9a03886453f61b6a5222c36846b874dbf4b95
1 /*
2 * Part of Intel(R) Manageability Engine Interface Linux driver
4 * Copyright (c) 2003 - 2008 Intel Corp.
5 * All rights reserved.
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.
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.
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.
42 #include <linux/module.h>
43 #include <linux/moduleparam.h>
44 #include <linux/kernel.h>
45 #include <linux/slab.h>
46 #include <linux/fs.h>
47 #include <linux/errno.h>
48 #include <linux/types.h>
49 #include <linux/fcntl.h>
50 #include <linux/aio.h>
51 #include <linux/pci.h>
52 #include <linux/reboot.h>
53 #include <linux/poll.h>
54 #include <linux/init.h>
55 #include <linux/kdev_t.h>
56 #include <linux/ioctl.h>
57 #include <linux/cdev.h>
58 #include <linux/device.h>
59 #include <linux/unistd.h>
60 #include <linux/kthread.h>
62 #include "heci.h"
63 #include "heci_interface.h"
64 #include "heci_version.h"
67 #define HECI_READ_TIMEOUT 45
69 #define HECI_DRIVER_NAME "heci"
72 * heci driver strings
74 char heci_driver_name[] = HECI_DRIVER_NAME;
75 char heci_driver_string[] = "Intel(R) Management Engine Interface";
76 char heci_driver_version[] = HECI_DRIVER_VERSION;
77 char heci_copyright[] = "Copyright (c) 2003 - 2008 Intel Corporation.";
80 #ifdef HECI_DEBUG
81 int heci_debug = 1;
82 #else
83 int heci_debug;
84 #endif
85 MODULE_PARM_DESC(heci_debug, "Debug enabled or not");
86 module_param(heci_debug, int, 0644);
89 #define HECI_DEV_NAME "heci"
91 /* heci char device for registration */
92 static struct cdev heci_cdev;
94 /* major number for device */
95 static int heci_major;
96 /* The device pointer */
97 static struct pci_dev *heci_device;
99 struct class *heci_class;
102 /* heci_pci_tbl - PCI Device ID Table */
103 static struct pci_device_id heci_pci_tbl[] = {
104 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82946GZ)},
105 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G35)},
106 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82Q965)},
107 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G965)},
108 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GM965)},
109 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GME965)},
110 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q35)},
111 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82G33)},
112 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q33)},
113 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82X38)},
114 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_3200)},
115 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_6)},
116 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_7)},
117 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_8)},
118 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_9)},
119 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_10)},
120 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_1)},
121 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_2)},
122 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_3)},
123 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_4)},
124 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_1)},
125 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_2)},
126 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_3)},
127 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_4)},
128 /* required last entry */
129 {0, }
132 MODULE_DEVICE_TABLE(pci, heci_pci_tbl);
135 * Local Function Prototypes
137 static int __init heci_init_module(void);
138 static void __exit heci_exit_module(void);
139 static int __devinit heci_probe(struct pci_dev *pdev,
140 const struct pci_device_id *ent);
141 static void __devexit heci_remove(struct pci_dev *pdev);
142 static int heci_open(struct inode *inode, struct file *file);
143 static int heci_release(struct inode *inode, struct file *file);
144 static ssize_t heci_read(struct file *file, char __user *ubuf,
145 size_t length, loff_t *offset);
146 static int heci_ioctl(struct inode *inode, struct file *file,
147 unsigned int cmd, unsigned long data);
148 static ssize_t heci_write(struct file *file, const char __user *ubuf,
149 size_t length, loff_t *offset);
150 static unsigned int heci_poll(struct file *file, poll_table *wait);
151 static struct heci_cb_private *find_read_list_entry(
152 struct iamt_heci_device *dev,
153 struct heci_file_private *file_ext);
154 #ifdef CONFIG_PM
155 static int heci_suspend(struct pci_dev *pdev, pm_message_t state);
156 static int heci_resume(struct pci_dev *pdev);
157 static __u16 g_sus_wd_timeout;
158 #else
159 #define heci_suspend NULL
160 #define heci_resume NULL
161 #endif
163 * PCI driver structure
165 static struct pci_driver heci_driver = {
166 .name = heci_driver_name,
167 .id_table = heci_pci_tbl,
168 .probe = heci_probe,
169 .remove = __devexit_p(heci_remove),
170 .shutdown = __devexit_p(heci_remove),
171 .suspend = heci_suspend,
172 .resume = heci_resume
176 * file operations structure will be use heci char device.
178 static const struct file_operations heci_fops = {
179 .owner = THIS_MODULE,
180 .read = heci_read,
181 .ioctl = heci_ioctl,
182 .open = heci_open,
183 .release = heci_release,
184 .write = heci_write,
185 .poll = heci_poll,
189 * heci_registration_cdev - set up the cdev structure for heci device.
191 * @dev: char device struct
192 * @hminor: minor number for registration char device
193 * @fops: file operations structure
195 * returns 0 on success, <0 on failure.
197 static int heci_registration_cdev(struct cdev *dev, int hminor,
198 const struct file_operations *fops)
200 int ret, devno = MKDEV(heci_major, hminor);
202 cdev_init(dev, fops);
203 dev->owner = THIS_MODULE;
204 ret = cdev_add(dev, devno, 1);
205 /* Fail gracefully if need be */
206 if (ret) {
207 printk(KERN_ERR "heci: Error %d registering heci device %d\n",
208 ret, hminor);
210 return ret;
213 /* Display the version of heci driver. */
214 static ssize_t version_show(struct class *dev, char *buf)
216 return sprintf(buf, "%s %s.\n",
217 heci_driver_string, heci_driver_version);
220 static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
223 * heci_register_cdev - registers heci char device
225 * returns 0 on success, <0 on failure.
227 static int heci_register_cdev(void)
229 int ret;
230 dev_t dev;
232 /* registration of char devices */
233 ret = alloc_chrdev_region(&dev, HECI_MINORS_BASE, HECI_MINORS_COUNT,
234 HECI_DRIVER_NAME);
235 if (ret) {
236 printk(KERN_ERR "heci: Error allocating char device region.\n");
237 return ret;
240 heci_major = MAJOR(dev);
242 ret = heci_registration_cdev(&heci_cdev, HECI_MINOR_NUMBER,
243 &heci_fops);
244 if (ret)
245 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
246 HECI_MINORS_COUNT);
248 return ret;
252 * heci_unregister_cdev - unregisters heci char device
254 static void heci_unregister_cdev(void)
256 cdev_del(&heci_cdev);
257 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
258 HECI_MINORS_COUNT);
261 #ifndef HECI_DEVICE_CREATE
262 #define HECI_DEVICE_CREATE device_create
263 #endif
265 * heci_sysfs_device_create - adds device entry to sysfs
267 * returns 0 on success, <0 on failure.
269 static int heci_sysfs_device_create(void)
271 struct class *class;
272 void *tmphdev;
273 int err = 0;
275 class = class_create(THIS_MODULE, HECI_DRIVER_NAME);
276 if (IS_ERR(class)) {
277 err = PTR_ERR(class);
278 printk(KERN_ERR "heci: Error creating heci class.\n");
279 goto err_out;
282 err = class_create_file(class, &class_attr_version);
283 if (err) {
284 class_destroy(class);
285 printk(KERN_ERR "heci: Error creating heci class file.\n");
286 goto err_out;
289 tmphdev = HECI_DEVICE_CREATE(class, NULL, heci_cdev.dev, NULL,
290 HECI_DEV_NAME);
291 if (IS_ERR(tmphdev)) {
292 err = PTR_ERR(tmphdev);
293 class_remove_file(class, &class_attr_version);
294 class_destroy(class);
295 goto err_out;
298 heci_class = class;
299 err_out:
300 return err;
304 * heci_sysfs_device_remove - unregisters the device entry on sysfs
306 static void heci_sysfs_device_remove(void)
308 if ((heci_class == NULL) || (IS_ERR(heci_class)))
309 return;
311 device_destroy(heci_class, heci_cdev.dev);
312 class_remove_file(heci_class, &class_attr_version);
313 class_destroy(heci_class);
317 * heci_init_module - Driver Registration Routine
319 * heci_init_module is the first routine called when the driver is
320 * loaded. All it does is register with the PCI subsystem.
322 * returns 0 on success, <0 on failure.
324 static int __init heci_init_module(void)
326 int ret = 0;
328 printk(KERN_INFO "heci: %s - version %s\n", heci_driver_string,
329 heci_driver_version);
330 printk(KERN_INFO "heci: %s\n", heci_copyright);
332 /* init pci module */
333 ret = pci_register_driver(&heci_driver);
334 if (ret < 0) {
335 printk(KERN_ERR "heci: Error registering driver.\n");
336 goto end;
339 ret = heci_register_cdev();
340 if (ret)
341 goto unregister_pci;
343 ret = heci_sysfs_device_create();
344 if (ret)
345 goto unregister_cdev;
347 return ret;
349 unregister_cdev:
350 heci_unregister_cdev();
351 unregister_pci:
352 pci_unregister_driver(&heci_driver);
353 end:
354 return ret;
357 module_init(heci_init_module);
361 * heci_exit_module - Driver Exit Cleanup Routine
363 * heci_exit_module is called just before the driver is removed
364 * from memory.
366 static void __exit heci_exit_module(void)
368 pci_unregister_driver(&heci_driver);
369 heci_sysfs_device_remove();
370 heci_unregister_cdev();
373 module_exit(heci_exit_module);
377 * heci_probe - Device Initialization Routine
379 * @pdev: PCI device information struct
380 * @ent: entry in kcs_pci_tbl
382 * returns 0 on success, <0 on failure.
384 static int __devinit heci_probe(struct pci_dev *pdev,
385 const struct pci_device_id *ent)
387 struct iamt_heci_device *dev = NULL;
388 int i, err = 0;
390 if (heci_device) {
391 err = -EEXIST;
392 goto end;
394 /* enable pci dev */
395 err = pci_enable_device(pdev);
396 if (err) {
397 printk(KERN_ERR "heci: Failed to enable pci device.\n");
398 goto end;
400 /* set PCI host mastering */
401 pci_set_master(pdev);
402 /* pci request regions for heci driver */
403 err = pci_request_regions(pdev, heci_driver_name);
404 if (err) {
405 printk(KERN_ERR "heci: Failed to get pci regions.\n");
406 goto disable_device;
408 /* allocates and initializes the heci dev structure */
409 dev = init_heci_device(pdev);
410 if (!dev) {
411 err = -ENOMEM;
412 goto release_regions;
414 /* mapping IO device memory */
415 for (i = 0; i <= 5; i++) {
416 if (pci_resource_len(pdev, i) == 0)
417 continue;
418 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
419 printk(KERN_ERR "heci: heci has IO ports.\n");
420 goto free_device;
421 } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
422 if (dev->mem_base) {
423 printk(KERN_ERR
424 "heci: Too many mem addresses.\n");
425 goto free_device;
427 dev->mem_base = pci_resource_start(pdev, i);
428 dev->mem_length = pci_resource_len(pdev, i);
431 if (!dev->mem_base) {
432 printk(KERN_ERR "heci: No address to use.\n");
433 err = -ENODEV;
434 goto free_device;
436 dev->mem_addr = ioremap_nocache(dev->mem_base,
437 dev->mem_length);
438 if (!dev->mem_addr) {
439 printk(KERN_ERR "heci: Remap IO device memory failure.\n");
440 err = -ENOMEM;
441 goto free_device;
443 /* request and enable interrupt */
444 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
445 heci_driver_name, dev);
446 if (err) {
447 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
448 pdev->irq);
449 goto unmap_memory;
452 if (heci_hw_init(dev)) {
453 printk(KERN_ERR "heci: Init hw failure.\n");
454 err = -ENODEV;
455 goto release_irq;
457 init_timer(&dev->wd_timer);
459 heci_initialize_clients(dev);
460 if (dev->heci_state != HECI_ENABLED) {
461 err = -ENODEV;
462 goto release_hw;
465 spin_lock_bh(&dev->device_lock);
466 heci_device = pdev;
467 pci_set_drvdata(pdev, dev);
468 spin_unlock_bh(&dev->device_lock);
470 if (dev->wd_timeout)
471 mod_timer(&dev->wd_timer, jiffies);
473 #ifdef CONFIG_PM
474 g_sus_wd_timeout = 0;
475 #endif
476 printk(KERN_INFO "heci driver initialization successful.\n");
477 return 0;
479 release_hw:
480 /* disable interrupts */
481 dev->host_hw_state = read_heci_register(dev, H_CSR);
482 heci_csr_disable_interrupts(dev);
484 del_timer_sync(&dev->wd_timer);
486 flush_scheduled_work();
488 release_irq:
489 free_irq(pdev->irq, dev);
490 unmap_memory:
491 if (dev->mem_addr)
492 iounmap(dev->mem_addr);
493 free_device:
494 kfree(dev);
495 release_regions:
496 pci_release_regions(pdev);
497 disable_device:
498 pci_disable_device(pdev);
499 end:
500 printk(KERN_ERR "heci driver initialization failed.\n");
501 return err;
505 * heci_remove - Device Removal Routine
507 * @pdev: PCI device information struct
509 * heci_remove is called by the PCI subsystem to alert the driver
510 * that it should release a PCI device.
512 static void __devexit heci_remove(struct pci_dev *pdev)
514 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
516 if (heci_device != pdev)
517 return;
519 if (dev == NULL)
520 return;
522 spin_lock_bh(&dev->device_lock);
523 if (heci_device != pdev) {
524 spin_unlock_bh(&dev->device_lock);
525 return;
528 if (dev->reinit_tsk != NULL) {
529 kthread_stop(dev->reinit_tsk);
530 dev->reinit_tsk = NULL;
533 del_timer_sync(&dev->wd_timer);
534 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
535 && dev->wd_timeout) {
536 dev->wd_timeout = 0;
537 dev->wd_due_counter = 0;
538 memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE);
539 dev->stop = 1;
540 if (dev->host_buffer_is_empty &&
541 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
542 dev->host_buffer_is_empty = 0;
544 if (!heci_send_wd(dev))
545 DBG("send stop WD failed\n");
546 else
547 flow_ctrl_reduce(dev, &dev->wd_file_ext);
549 dev->wd_pending = 0;
550 } else {
551 dev->wd_pending = 1;
553 dev->wd_stoped = 0;
554 spin_unlock_bh(&dev->device_lock);
556 wait_event_interruptible_timeout(dev->wait_stop_wd,
557 (dev->wd_stoped), 10 * HZ);
558 spin_lock_bh(&dev->device_lock);
559 if (!dev->wd_stoped)
560 DBG("stop wd failed to complete.\n");
561 else
562 DBG("stop wd complete.\n");
566 heci_device = NULL;
567 spin_unlock_bh(&dev->device_lock);
569 if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
570 dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
571 heci_disconnect_host_client(dev,
572 &dev->iamthif_file_ext);
574 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
575 dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
576 heci_disconnect_host_client(dev,
577 &dev->wd_file_ext);
580 spin_lock_bh(&dev->device_lock);
582 /* remove entry if already in list */
583 DBG("list del iamthif and wd file list.\n");
584 heci_remove_client_from_file_list(dev, dev->wd_file_ext.
585 host_client_id);
586 heci_remove_client_from_file_list(dev,
587 dev->iamthif_file_ext.host_client_id);
589 dev->iamthif_current_cb = NULL;
590 dev->iamthif_file_ext.file = NULL;
591 dev->num_heci_me_clients = 0;
593 spin_unlock_bh(&dev->device_lock);
595 flush_scheduled_work();
597 /* disable interrupts */
598 heci_csr_disable_interrupts(dev);
600 free_irq(pdev->irq, dev);
601 pci_set_drvdata(pdev, NULL);
603 if (dev->mem_addr)
604 iounmap(dev->mem_addr);
606 kfree(dev);
608 pci_release_regions(pdev);
609 pci_disable_device(pdev);
613 * heci_clear_list - remove all callbacks associated with file
614 * from heci_cb_list
616 * @file: file information struct
617 * @heci_cb_list: callbacks list
619 * heci_clear_list is called to clear resources associated with file
620 * when application calls close function or Ctrl-C was pressed
622 * returns 1 if callback removed from the list, 0 otherwise
624 static int heci_clear_list(struct iamt_heci_device *dev,
625 struct file *file, struct list_head *heci_cb_list)
627 struct heci_cb_private *priv_cb_pos = NULL;
628 struct heci_cb_private *priv_cb_next = NULL;
629 struct file *file_temp;
630 int rets = 0;
632 /* list all list member */
633 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
634 heci_cb_list, cb_list) {
635 file_temp = (struct file *)priv_cb_pos->file_object;
636 /* check if list member associated with a file */
637 if (file_temp == file) {
638 /* remove member from the list */
639 list_del(&priv_cb_pos->cb_list);
640 /* check if cb equal to current iamthif cb */
641 if (dev->iamthif_current_cb == priv_cb_pos) {
642 dev->iamthif_current_cb = NULL;
643 /* send flow control to iamthif client */
644 heci_send_flow_control(dev,
645 &dev->iamthif_file_ext);
647 /* free all allocated buffers */
648 heci_free_cb_private(priv_cb_pos);
649 rets = 1;
652 return rets;
656 * heci_clear_lists - remove all callbacks associated with file
658 * @dev: device information struct
659 * @file: file information struct
661 * heci_clear_lists is called to clear resources associated with file
662 * when application calls close function or Ctrl-C was pressed
664 * returns 1 if callback removed from the list, 0 otherwise
666 static int heci_clear_lists(struct iamt_heci_device *dev, struct file *file)
668 int rets = 0;
670 /* remove callbacks associated with a file */
671 heci_clear_list(dev, file, &dev->pthi_cmd_list.heci_cb.cb_list);
672 if (heci_clear_list(dev, file,
673 &dev->pthi_read_complete_list.heci_cb.cb_list))
674 rets = 1;
676 heci_clear_list(dev, file, &dev->ctrl_rd_list.heci_cb.cb_list);
678 if (heci_clear_list(dev, file, &dev->ctrl_wr_list.heci_cb.cb_list))
679 rets = 1;
681 if (heci_clear_list(dev, file,
682 &dev->write_waiting_list.heci_cb.cb_list))
683 rets = 1;
685 if (heci_clear_list(dev, file, &dev->write_list.heci_cb.cb_list))
686 rets = 1;
688 /* check if iamthif_current_cb not NULL */
689 if (dev->iamthif_current_cb && (!rets)) {
690 /* check file and iamthif current cb association */
691 if (dev->iamthif_current_cb->file_object == file) {
692 /* remove cb */
693 heci_free_cb_private(dev->iamthif_current_cb);
694 dev->iamthif_current_cb = NULL;
695 rets = 1;
698 return rets;
702 * heci_open - the open function
704 * @inode: pointer to inode structure
705 * @file: pointer to file structure
707 * returns 0 on success, <0 on error
709 static int heci_open(struct inode *inode, struct file *file)
711 struct heci_file_private *file_ext;
712 int if_num = iminor(inode);
713 struct iamt_heci_device *dev;
715 if (!heci_device)
716 return -ENODEV;
718 dev = pci_get_drvdata(heci_device);
719 if ((if_num != HECI_MINOR_NUMBER) || (!dev))
720 return -ENODEV;
722 file_ext = heci_alloc_file_private(file);
723 if (file_ext == NULL)
724 return -ENOMEM;
726 spin_lock_bh(&dev->device_lock);
727 if (dev->heci_state != HECI_ENABLED) {
728 spin_unlock_bh(&dev->device_lock);
729 kfree(file_ext);
730 return -ENODEV;
732 if (dev->open_handle_count >= HECI_MAX_OPEN_HANDLE_COUNT) {
733 spin_unlock_bh(&dev->device_lock);
734 kfree(file_ext);
735 return -ENFILE;
737 dev->open_handle_count++;
738 list_add_tail(&file_ext->link, &dev->file_list);
739 while ((dev->heci_host_clients[dev->current_host_client_id / 8]
740 & (1 << (dev->current_host_client_id % 8))) != 0) {
742 dev->current_host_client_id++; /* allow overflow */
743 DBG("current_host_client_id = %d\n",
744 dev->current_host_client_id);
745 DBG("dev->open_handle_count = %lu\n",
746 dev->open_handle_count);
748 DBG("current_host_client_id = %d\n", dev->current_host_client_id);
749 file_ext->host_client_id = dev->current_host_client_id;
750 dev->heci_host_clients[file_ext->host_client_id / 8] |=
751 (1 << (file_ext->host_client_id % 8));
752 spin_unlock_bh(&dev->device_lock);
753 spin_lock(&file_ext->file_lock);
754 file_ext->state = HECI_FILE_INITIALIZING;
755 file_ext->sm_state = 0;
757 file->private_data = file_ext;
758 spin_unlock(&file_ext->file_lock);
760 return 0;
764 * heci_release - the release function
766 * @inode: pointer to inode structure
767 * @file: pointer to file structure
769 * returns 0 on success, <0 on error
771 static int heci_release(struct inode *inode, struct file *file)
773 int rets = 0;
774 int if_num = iminor(inode);
775 struct heci_file_private *file_ext = file->private_data;
776 struct heci_cb_private *priv_cb = NULL;
777 struct iamt_heci_device *dev;
779 if (!heci_device)
780 return -ENODEV;
782 dev = pci_get_drvdata(heci_device);
783 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
784 return -ENODEV;
786 if (file_ext != &dev->iamthif_file_ext) {
787 spin_lock(&file_ext->file_lock);
788 if (file_ext->state == HECI_FILE_CONNECTED) {
789 file_ext->state = HECI_FILE_DISCONNECTING;
790 spin_unlock(&file_ext->file_lock);
791 DBG("disconnecting client host client = %d, "
792 "ME client = %d\n",
793 file_ext->host_client_id,
794 file_ext->me_client_id);
795 rets = heci_disconnect_host_client(dev, file_ext);
796 spin_lock(&file_ext->file_lock);
798 spin_lock_bh(&dev->device_lock);
799 heci_flush_queues(dev, file_ext);
800 DBG("remove client host client = %d, ME client = %d\n",
801 file_ext->host_client_id,
802 file_ext->me_client_id);
804 if (dev->open_handle_count > 0) {
805 dev->heci_host_clients[file_ext->host_client_id / 8] &=
806 ~(1 << (file_ext->host_client_id % 8));
807 dev->open_handle_count--;
809 heci_remove_client_from_file_list(dev,
810 file_ext->host_client_id);
812 /* free read cb */
813 if (file_ext->read_cb != NULL) {
814 priv_cb = find_read_list_entry(dev, file_ext);
815 /* Remove entry from read list */
816 if (priv_cb != NULL)
817 list_del(&priv_cb->cb_list);
819 priv_cb = file_ext->read_cb;
820 file_ext->read_cb = NULL;
823 spin_unlock_bh(&dev->device_lock);
824 file->private_data = NULL;
825 spin_unlock(&file_ext->file_lock);
827 if (priv_cb != NULL)
828 heci_free_cb_private(priv_cb);
830 kfree(file_ext);
831 } else {
832 spin_lock_bh(&dev->device_lock);
834 if (dev->open_handle_count > 0)
835 dev->open_handle_count--;
837 if (dev->iamthif_file_object == file
838 && dev->iamthif_state != HECI_IAMTHIF_IDLE) {
839 DBG("pthi canceled iamthif state %d\n",
840 dev->iamthif_state);
841 dev->iamthif_canceled = 1;
842 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE) {
843 DBG("run next pthi iamthif cb\n");
844 run_next_iamthif_cmd(dev);
848 if (heci_clear_lists(dev, file))
849 dev->iamthif_state = HECI_IAMTHIF_IDLE;
851 spin_unlock_bh(&dev->device_lock);
853 return rets;
856 static struct heci_cb_private *find_read_list_entry(
857 struct iamt_heci_device *dev,
858 struct heci_file_private *file_ext)
860 struct heci_cb_private *priv_cb_pos = NULL;
861 struct heci_cb_private *priv_cb_next = NULL;
862 struct heci_file_private *file_ext_list_temp;
864 if (dev->read_list.status == 0
865 && !list_empty(&dev->read_list.heci_cb.cb_list)) {
866 DBG("remove read_list CB \n");
867 list_for_each_entry_safe(priv_cb_pos,
868 priv_cb_next,
869 &dev->read_list.heci_cb.cb_list, cb_list) {
871 file_ext_list_temp = (struct heci_file_private *)
872 priv_cb_pos->file_private;
874 if ((file_ext_list_temp != NULL) &&
875 heci_fe_same_id(file_ext, file_ext_list_temp))
876 return priv_cb_pos;
880 return NULL;
884 * heci_read - the read client message function.
886 * @file: pointer to file structure
887 * @ubuf: pointer to user buffer
888 * @length: buffer length
889 * @offset: data offset in buffer
891 * returns >=0 data length on success , <0 on error
893 static ssize_t heci_read(struct file *file, char __user *ubuf,
894 size_t length, loff_t *offset)
896 int i;
897 int rets = 0, err = 0;
898 int if_num = iminor(file->f_dentry->d_inode);
899 struct heci_file_private *file_ext = file->private_data;
900 struct heci_cb_private *priv_cb_pos = NULL;
901 struct heci_cb_private *priv_cb = NULL;
902 struct iamt_heci_device *dev;
904 if (!heci_device)
905 return -ENODEV;
907 dev = pci_get_drvdata(heci_device);
908 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
909 return -ENODEV;
911 spin_lock_bh(&dev->device_lock);
912 if (dev->heci_state != HECI_ENABLED) {
913 spin_unlock_bh(&dev->device_lock);
914 return -ENODEV;
916 spin_unlock_bh(&dev->device_lock);
918 spin_lock(&file_ext->file_lock);
919 if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
920 spin_unlock(&file_ext->file_lock);
921 /* Do not allow to read watchdog client */
922 for (i = 0; i < dev->num_heci_me_clients; i++) {
923 if (memcmp(&heci_wd_guid,
924 &dev->me_clients[i].props.protocol_name,
925 sizeof(struct guid)) == 0) {
926 if (file_ext->me_client_id ==
927 dev->me_clients[i].client_id)
928 return -EBADF;
931 } else {
932 file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
933 spin_unlock(&file_ext->file_lock);
936 if (file_ext == &dev->iamthif_file_ext) {
937 rets = pthi_read(dev, if_num, file, ubuf, length, offset);
938 goto out;
941 if (file_ext->read_cb && file_ext->read_cb->information > *offset) {
942 priv_cb = file_ext->read_cb;
943 goto copy_buffer;
944 } else if (file_ext->read_cb && file_ext->read_cb->information > 0 &&
945 file_ext->read_cb->information <= *offset) {
946 priv_cb = file_ext->read_cb;
947 rets = 0;
948 goto free;
949 } else if ((!file_ext->read_cb || file_ext->read_cb->information == 0)
950 && *offset > 0) {
951 /*Offset needs to be cleaned for contingous reads*/
952 *offset = 0;
953 rets = 0;
954 goto out;
957 spin_lock(&file_ext->read_io_lock);
958 err = heci_start_read(dev, if_num, file_ext);
959 if (err != 0 && err != -EBUSY) {
960 DBG("heci start read failure with status = %d\n", err);
961 spin_unlock(&file_ext->read_io_lock);
962 rets = err;
963 goto out;
965 if (HECI_READ_COMPLETE != file_ext->reading_state
966 && !waitqueue_active(&file_ext->rx_wait)) {
967 if (file->f_flags & O_NONBLOCK) {
968 rets = -EAGAIN;
969 spin_unlock(&file_ext->read_io_lock);
970 goto out;
972 spin_unlock(&file_ext->read_io_lock);
974 if (wait_event_interruptible(file_ext->rx_wait,
975 (HECI_READ_COMPLETE == file_ext->reading_state
976 || HECI_FILE_INITIALIZING == file_ext->state
977 || HECI_FILE_DISCONNECTED == file_ext->state
978 || HECI_FILE_DISCONNECTING == file_ext->state))) {
979 if (signal_pending(current)) {
980 rets = -EINTR;
981 goto out;
983 return -ERESTARTSYS;
986 if (HECI_FILE_INITIALIZING == file_ext->state ||
987 HECI_FILE_DISCONNECTED == file_ext->state ||
988 HECI_FILE_DISCONNECTING == file_ext->state) {
989 rets = -EBUSY;
990 goto out;
992 spin_lock(&file_ext->read_io_lock);
995 priv_cb = file_ext->read_cb;
997 if (!priv_cb) {
998 spin_unlock(&file_ext->read_io_lock);
999 return -ENODEV;
1001 if (file_ext->reading_state != HECI_READ_COMPLETE) {
1002 spin_unlock(&file_ext->read_io_lock);
1003 return 0;
1005 spin_unlock(&file_ext->read_io_lock);
1006 /* now copy the data to user space */
1007 copy_buffer:
1008 DBG("priv_cb->response_buffer size - %d\n",
1009 priv_cb->response_buffer.size);
1010 DBG("priv_cb->information - %lu\n",
1011 priv_cb->information);
1012 if (length == 0 || ubuf == NULL ||
1013 *offset > priv_cb->information) {
1014 rets = -EMSGSIZE;
1015 goto free;
1018 /* length is being turncated to PAGE_SIZE, however, */
1019 /* information size may be longer */
1020 length = (length < (priv_cb->information - *offset) ?
1021 length : (priv_cb->information - *offset));
1023 if (copy_to_user(ubuf,
1024 priv_cb->response_buffer.data + *offset,
1025 length)) {
1026 rets = -EFAULT;
1027 goto free;
1030 rets = length;
1031 *offset += length;
1032 if ((unsigned long)*offset < priv_cb->information)
1033 goto out;
1035 free:
1036 spin_lock_bh(&dev->device_lock);
1037 priv_cb_pos = find_read_list_entry(dev, file_ext);
1038 /* Remove entry from read list */
1039 if (priv_cb_pos != NULL)
1040 list_del(&priv_cb_pos->cb_list);
1041 spin_unlock_bh(&dev->device_lock);
1042 heci_free_cb_private(priv_cb);
1043 spin_lock(&file_ext->read_io_lock);
1044 file_ext->reading_state = HECI_IDLE;
1045 file_ext->read_cb = NULL;
1046 file_ext->read_pending = 0;
1047 spin_unlock(&file_ext->read_io_lock);
1048 out: DBG("end heci read rets= %d\n", rets);
1049 return rets;
1053 * heci_write - the write function.
1055 * @file: pointer to file structure
1056 * @ubuf: pointer to user buffer
1057 * @length: buffer length
1058 * @offset: data offset in buffer
1060 * returns >=0 data length on success , <0 on error
1062 static ssize_t heci_write(struct file *file, const char __user *ubuf,
1063 size_t length, loff_t *offset)
1065 int rets = 0;
1066 __u8 i;
1067 int if_num = iminor(file->f_dentry->d_inode);
1068 struct heci_file_private *file_ext = file->private_data;
1069 struct heci_cb_private *priv_write_cb = NULL;
1070 struct heci_msg_hdr heci_hdr;
1071 struct iamt_heci_device *dev;
1072 unsigned long currtime = get_seconds();
1074 if (!heci_device)
1075 return -ENODEV;
1077 dev = pci_get_drvdata(heci_device);
1079 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1080 return -ENODEV;
1082 spin_lock_bh(&dev->device_lock);
1084 if (dev->heci_state != HECI_ENABLED) {
1085 spin_unlock_bh(&dev->device_lock);
1086 return -ENODEV;
1088 if (file_ext == &dev->iamthif_file_ext) {
1089 priv_write_cb = find_pthi_read_list_entry(dev, file);
1090 if ((priv_write_cb != NULL) &&
1091 (((currtime - priv_write_cb->read_time) >
1092 IAMTHIF_READ_TIMER) ||
1093 (file_ext->reading_state == HECI_READ_COMPLETE))) {
1094 (*offset) = 0;
1095 list_del(&priv_write_cb->cb_list);
1096 heci_free_cb_private(priv_write_cb);
1097 priv_write_cb = NULL;
1101 /* free entry used in read */
1102 if (file_ext->reading_state == HECI_READ_COMPLETE) {
1103 *offset = 0;
1104 priv_write_cb = find_read_list_entry(dev, file_ext);
1105 if (priv_write_cb != NULL) {
1106 list_del(&priv_write_cb->cb_list);
1107 heci_free_cb_private(priv_write_cb);
1108 priv_write_cb = NULL;
1109 spin_lock(&file_ext->read_io_lock);
1110 file_ext->reading_state = HECI_IDLE;
1111 file_ext->read_cb = NULL;
1112 file_ext->read_pending = 0;
1113 spin_unlock(&file_ext->read_io_lock);
1115 } else if (file_ext->reading_state == HECI_IDLE &&
1116 file_ext->read_pending == 0)
1117 (*offset) = 0;
1119 spin_unlock_bh(&dev->device_lock);
1121 priv_write_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
1122 if (!priv_write_cb)
1123 return -ENOMEM;
1125 priv_write_cb->file_object = file;
1126 priv_write_cb->file_private = file_ext;
1127 priv_write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
1128 if (!priv_write_cb->request_buffer.data) {
1129 kfree(priv_write_cb);
1130 return -ENOMEM;
1132 DBG("length =%d\n", (int) length);
1134 if (copy_from_user(priv_write_cb->request_buffer.data,
1135 ubuf, length)) {
1136 rets = -EFAULT;
1137 goto fail;
1140 spin_lock(&file_ext->file_lock);
1141 file_ext->sm_state = 0;
1142 if ((length == 4) &&
1143 ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) ||
1144 (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0) ||
1145 (memcmp(heci_wd_state_independence_msg[2], ubuf, 4) == 0)))
1146 file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
1147 spin_unlock(&file_ext->file_lock);
1149 INIT_LIST_HEAD(&priv_write_cb->cb_list);
1150 if (file_ext == &dev->iamthif_file_ext) {
1151 priv_write_cb->response_buffer.data =
1152 kmalloc(IAMTHIF_MTU, GFP_KERNEL);
1153 if (!priv_write_cb->response_buffer.data) {
1154 rets = -ENOMEM;
1155 goto fail;
1157 spin_lock_bh(&dev->device_lock);
1158 if (dev->heci_state != HECI_ENABLED) {
1159 spin_unlock_bh(&dev->device_lock);
1160 rets = -ENODEV;
1161 goto fail;
1163 for (i = 0; i < dev->num_heci_me_clients; i++) {
1164 if (dev->me_clients[i].client_id ==
1165 dev->iamthif_file_ext.me_client_id)
1166 break;
1169 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1170 if ((i == dev->num_heci_me_clients) ||
1171 (dev->me_clients[i].client_id !=
1172 dev->iamthif_file_ext.me_client_id)) {
1174 spin_unlock_bh(&dev->device_lock);
1175 rets = -ENODEV;
1176 goto fail;
1177 } else if ((length > dev->me_clients[i].props.max_msg_length)
1178 || (length <= 0)) {
1179 spin_unlock_bh(&dev->device_lock);
1180 rets = -EMSGSIZE;
1181 goto fail;
1185 priv_write_cb->response_buffer.size = IAMTHIF_MTU;
1186 priv_write_cb->major_file_operations = HECI_IOCTL;
1187 priv_write_cb->information = 0;
1188 priv_write_cb->request_buffer.size = length;
1189 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
1190 spin_unlock_bh(&dev->device_lock);
1191 rets = -ENODEV;
1192 goto fail;
1195 if (!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)
1196 || dev->iamthif_state != HECI_IAMTHIF_IDLE) {
1197 DBG("pthi_state = %d\n", (int) dev->iamthif_state);
1198 DBG("add PTHI cb to pthi cmd waiting list\n");
1199 list_add_tail(&priv_write_cb->cb_list,
1200 &dev->pthi_cmd_list.heci_cb.cb_list);
1201 rets = length;
1202 } else {
1203 DBG("call pthi write\n");
1204 rets = pthi_write(dev, priv_write_cb);
1206 if (rets != 0) {
1207 DBG("pthi write failed with status = %d\n",
1208 rets);
1209 spin_unlock_bh(&dev->device_lock);
1210 goto fail;
1212 rets = length;
1214 spin_unlock_bh(&dev->device_lock);
1215 return rets;
1218 priv_write_cb->major_file_operations = HECI_WRITE;
1219 /* make sure information is zero before we start */
1221 priv_write_cb->information = 0;
1222 priv_write_cb->request_buffer.size = length;
1224 spin_lock(&file_ext->write_io_lock);
1225 DBG("host client = %d, ME client = %d\n",
1226 file_ext->host_client_id, file_ext->me_client_id);
1227 if (file_ext->state != HECI_FILE_CONNECTED) {
1228 rets = -ENODEV;
1229 DBG("host client = %d, is not connected to ME client = %d",
1230 file_ext->host_client_id,
1231 file_ext->me_client_id);
1233 goto unlock;
1235 for (i = 0; i < dev->num_heci_me_clients; i++) {
1236 if (dev->me_clients[i].client_id ==
1237 file_ext->me_client_id)
1238 break;
1240 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1241 if (i == dev->num_heci_me_clients) {
1242 rets = -ENODEV;
1243 goto unlock;
1245 if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
1246 rets = -EINVAL;
1247 goto unlock;
1249 priv_write_cb->file_private = file_ext;
1251 spin_lock_bh(&dev->device_lock);
1252 if (flow_ctrl_creds(dev, file_ext) &&
1253 dev->host_buffer_is_empty) {
1254 spin_unlock_bh(&dev->device_lock);
1255 dev->host_buffer_is_empty = 0;
1256 if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
1257 sizeof(__u32)) - sizeof(struct heci_msg_hdr))) {
1259 heci_hdr.length =
1260 (((dev->host_hw_state & H_CBD) >> 24) *
1261 sizeof(__u32)) -
1262 sizeof(struct heci_msg_hdr);
1263 heci_hdr.msg_complete = 0;
1264 } else {
1265 heci_hdr.length = length;
1266 heci_hdr.msg_complete = 1;
1268 heci_hdr.host_addr = file_ext->host_client_id;
1269 heci_hdr.me_addr = file_ext->me_client_id;
1270 heci_hdr.reserved = 0;
1271 DBG("call heci_write_message header=%08x.\n",
1272 *((__u32 *) &heci_hdr));
1273 spin_unlock(&file_ext->write_io_lock);
1274 /* protect heci low level write */
1275 spin_lock_bh(&dev->device_lock);
1276 if (!heci_write_message(dev, &heci_hdr,
1277 (unsigned char *) (priv_write_cb->request_buffer.data),
1278 heci_hdr.length)) {
1280 spin_unlock_bh(&dev->device_lock);
1281 heci_free_cb_private(priv_write_cb);
1282 rets = -ENODEV;
1283 priv_write_cb->information = 0;
1284 return rets;
1286 file_ext->writing_state = HECI_WRITING;
1287 priv_write_cb->information = heci_hdr.length;
1288 if (heci_hdr.msg_complete) {
1289 flow_ctrl_reduce(dev, file_ext);
1290 list_add_tail(&priv_write_cb->cb_list,
1291 &dev->write_waiting_list.heci_cb.cb_list);
1292 } else {
1293 list_add_tail(&priv_write_cb->cb_list,
1294 &dev->write_list.heci_cb.cb_list);
1296 spin_unlock_bh(&dev->device_lock);
1298 } else {
1300 spin_unlock_bh(&dev->device_lock);
1301 priv_write_cb->information = 0;
1302 file_ext->writing_state = HECI_WRITING;
1303 spin_unlock(&file_ext->write_io_lock);
1304 list_add_tail(&priv_write_cb->cb_list,
1305 &dev->write_list.heci_cb.cb_list);
1307 return length;
1309 unlock:
1310 spin_unlock(&file_ext->write_io_lock);
1311 fail:
1312 heci_free_cb_private(priv_write_cb);
1313 return rets;
1318 * heci_ioctl - the IOCTL function
1320 * @inode: pointer to inode structure
1321 * @file: pointer to file structure
1322 * @cmd: ioctl command
1323 * @data: pointer to heci message structure
1325 * returns 0 on success , <0 on error
1327 static int heci_ioctl(struct inode *inode, struct file *file,
1328 unsigned int cmd, unsigned long data)
1330 int rets = 0;
1331 int if_num = iminor(inode);
1332 struct heci_file_private *file_ext = file->private_data;
1333 /* in user space */
1334 struct heci_message_data *u_msg = (struct heci_message_data *) data;
1335 struct heci_message_data k_msg; /* all in kernel on the stack */
1336 struct iamt_heci_device *dev;
1338 if (!capable(CAP_SYS_ADMIN))
1339 return -EPERM;
1341 if (!heci_device)
1342 return -ENODEV;
1344 dev = pci_get_drvdata(heci_device);
1345 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1346 return -ENODEV;
1348 spin_lock_bh(&dev->device_lock);
1349 if (dev->heci_state != HECI_ENABLED) {
1350 spin_unlock_bh(&dev->device_lock);
1351 return -ENODEV;
1353 spin_unlock_bh(&dev->device_lock);
1355 /* first copy from user all data needed */
1356 if (copy_from_user(&k_msg, u_msg, sizeof(k_msg))) {
1357 DBG("first copy from user all data needed filled\n");
1358 return -EFAULT;
1360 DBG("user message size is %d\n", k_msg.size);
1362 switch (cmd) {
1363 case IOCTL_HECI_GET_VERSION:
1364 DBG(": IOCTL_HECI_GET_VERSION\n");
1365 rets = heci_ioctl_get_version(dev, if_num, u_msg, k_msg,
1366 file_ext);
1367 break;
1369 case IOCTL_HECI_CONNECT_CLIENT:
1370 DBG(": IOCTL_HECI_CONNECT_CLIENT.\n");
1371 rets = heci_ioctl_connect_client(dev, if_num, u_msg, k_msg,
1372 file);
1373 break;
1375 case IOCTL_HECI_WD:
1376 DBG(": IOCTL_HECI_WD.\n");
1377 rets = heci_ioctl_wd(dev, if_num, k_msg, file_ext);
1378 break;
1380 case IOCTL_HECI_BYPASS_WD:
1381 DBG(": IOCTL_HECI_BYPASS_WD.\n");
1382 rets = heci_ioctl_bypass_wd(dev, if_num, k_msg, file_ext);
1383 break;
1385 default:
1386 rets = -EINVAL;
1387 break;
1389 return rets;
1393 * heci_poll - the poll function
1395 * @file: pointer to file structure
1396 * @wait: pointer to poll_table structure
1398 * returns poll mask
1400 static unsigned int heci_poll(struct file *file, poll_table *wait)
1402 int if_num = iminor(file->f_dentry->d_inode);
1403 unsigned int mask = 0;
1404 struct heci_file_private *file_ext = file->private_data;
1405 struct iamt_heci_device *dev;
1407 if (!heci_device)
1408 return mask;
1410 dev = pci_get_drvdata(heci_device);
1412 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1413 return mask;
1415 spin_lock_bh(&dev->device_lock);
1416 if (dev->heci_state != HECI_ENABLED) {
1417 spin_unlock_bh(&dev->device_lock);
1418 return mask;
1420 spin_unlock_bh(&dev->device_lock);
1422 if (file_ext == &dev->iamthif_file_ext) {
1423 poll_wait(file, &dev->iamthif_file_ext.wait, wait);
1424 spin_lock(&dev->iamthif_file_ext.file_lock);
1425 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE
1426 && dev->iamthif_file_object == file) {
1427 mask |= (POLLIN | POLLRDNORM);
1428 spin_lock_bh(&dev->device_lock);
1429 DBG("run next pthi cb\n");
1430 run_next_iamthif_cmd(dev);
1431 spin_unlock_bh(&dev->device_lock);
1433 spin_unlock(&dev->iamthif_file_ext.file_lock);
1435 } else{
1436 poll_wait(file, &file_ext->tx_wait, wait);
1437 spin_lock(&file_ext->write_io_lock);
1438 if (HECI_WRITE_COMPLETE == file_ext->writing_state)
1439 mask |= (POLLIN | POLLRDNORM);
1441 spin_unlock(&file_ext->write_io_lock);
1444 return mask;
1447 #ifdef CONFIG_PM
1448 static int heci_suspend(struct pci_dev *pdev, pm_message_t state)
1450 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
1451 int err = 0;
1453 spin_lock_bh(&dev->device_lock);
1454 if (dev->reinit_tsk != NULL) {
1455 kthread_stop(dev->reinit_tsk);
1456 dev->reinit_tsk = NULL;
1458 spin_unlock_bh(&dev->device_lock);
1460 /* Stop watchdog if exists */
1461 del_timer_sync(&dev->wd_timer);
1462 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
1463 && dev->wd_timeout) {
1464 spin_lock_bh(&dev->device_lock);
1465 g_sus_wd_timeout = dev->wd_timeout;
1466 dev->wd_timeout = 0;
1467 dev->wd_due_counter = 0;
1468 memcpy(dev->wd_data, heci_stop_wd_params,
1469 HECI_WD_PARAMS_SIZE);
1470 dev->stop = 1;
1471 if (dev->host_buffer_is_empty &&
1472 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1473 dev->host_buffer_is_empty = 0;
1474 if (!heci_send_wd(dev))
1475 DBG("send stop WD failed\n");
1476 else
1477 flow_ctrl_reduce(dev, &dev->wd_file_ext);
1479 dev->wd_pending = 0;
1480 } else {
1481 dev->wd_pending = 1;
1483 spin_unlock_bh(&dev->device_lock);
1484 dev->wd_stoped = 0;
1486 err = wait_event_interruptible_timeout(dev->wait_stop_wd,
1487 (dev->wd_stoped),
1488 10 * HZ);
1489 if (!dev->wd_stoped)
1490 DBG("stop wd failed to complete.\n");
1491 else {
1492 DBG("stop wd complete %d.\n", err);
1493 err = 0;
1496 /* Set new heci state */
1497 spin_lock_bh(&dev->device_lock);
1498 if (dev->heci_state == HECI_ENABLED ||
1499 dev->heci_state == HECI_RECOVERING_FROM_RESET) {
1500 dev->heci_state = HECI_POWER_DOWN;
1501 heci_reset(dev, 0);
1503 spin_unlock_bh(&dev->device_lock);
1505 pci_save_state(pdev);
1507 pci_disable_device(pdev);
1508 free_irq(pdev->irq, dev);
1510 pci_set_power_state(pdev, PCI_D3hot);
1512 return err;
1515 static int heci_resume(struct pci_dev *pdev)
1517 struct iamt_heci_device *dev;
1518 int err = 0;
1520 pci_set_power_state(pdev, PCI_D0);
1521 pci_restore_state(pdev);
1523 dev = pci_get_drvdata(pdev);
1524 if (!dev)
1525 return -ENODEV;
1527 /* request and enable interrupt */
1528 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
1529 heci_driver_name, dev);
1530 if (err) {
1531 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
1532 pdev->irq);
1533 return err;
1536 spin_lock_bh(&dev->device_lock);
1537 dev->heci_state = HECI_POWER_UP;
1538 heci_reset(dev, 1);
1539 spin_unlock_bh(&dev->device_lock);
1541 /* Start watchdog if stopped in suspend */
1542 if (g_sus_wd_timeout != 0) {
1543 dev->wd_timeout = g_sus_wd_timeout;
1545 memcpy(dev->wd_data, heci_start_wd_params,
1546 HECI_WD_PARAMS_SIZE);
1547 memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
1548 &dev->wd_timeout, sizeof(__u16));
1549 dev->wd_due_counter = 1;
1551 if (dev->wd_timeout)
1552 mod_timer(&dev->wd_timer, jiffies);
1554 g_sus_wd_timeout = 0;
1556 return err;
1558 #endif
1560 MODULE_AUTHOR("Intel Corporation");
1561 MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
1562 MODULE_LICENSE("Dual BSD/GPL");
1563 MODULE_VERSION(HECI_DRIVER_VERSION);