Staging: add heci driver
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / heci / heci_main.c
bloba24cd2b3774e102e25654bf24ee7b0f9ee888b88
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>
61 #include "kcompat.h"
63 #include "heci.h"
64 #include "heci_interface.h"
65 #include "heci_version.h"
68 #define HECI_READ_TIMEOUT 45
70 #define HECI_DRIVER_NAME "heci"
73 * heci driver strings
75 char heci_driver_name[] = HECI_DRIVER_NAME;
76 char heci_driver_string[] = "Intel(R) Management Engine Interface";
77 char heci_driver_version[] = HECI_DRIVER_VERSION;
78 char heci_copyright[] = "Copyright (c) 2003 - 2008 Intel Corporation.";
81 #ifdef HECI_DEBUG
82 int heci_debug = 1;
83 #else
84 int heci_debug;
85 #endif
86 MODULE_PARM_DESC(heci_debug, "Debug enabled or not");
87 module_param(heci_debug, int, 0644);
90 #define HECI_DEV_NAME "heci"
92 /* heci char device for registration */
93 static struct cdev heci_cdev;
95 /* major number for device */
96 static int heci_major;
97 /* The device pointer */
98 static struct pci_dev *heci_device;
100 struct class *heci_class;
103 /* heci_pci_tbl - PCI Device ID Table */
104 static struct pci_device_id heci_pci_tbl[] = {
105 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82946GZ)},
106 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G35)},
107 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82Q965)},
108 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82G965)},
109 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GM965)},
110 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_82GME965)},
111 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q35)},
112 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82G33)},
113 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82Q33)},
114 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_82X38)},
115 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_3200)},
116 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_6)},
117 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_7)},
118 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_8)},
119 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_9)},
120 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9_10)},
121 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_1)},
122 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_2)},
123 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_3)},
124 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH9M_4)},
125 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_1)},
126 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_2)},
127 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_3)},
128 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, HECI_DEV_ID_ICH10_4)},
129 /* required last entry */
130 {0, }
133 MODULE_DEVICE_TABLE(pci, heci_pci_tbl);
136 * Local Function Prototypes
138 static int __init heci_init_module(void);
139 static void __exit heci_exit_module(void);
140 static int __devinit heci_probe(struct pci_dev *pdev,
141 const struct pci_device_id *ent);
142 static void __devexit heci_remove(struct pci_dev *pdev);
143 static int heci_open(struct inode *inode, struct file *file);
144 static int heci_release(struct inode *inode, struct file *file);
145 static ssize_t heci_read(struct file *file, char __user *ubuf,
146 size_t length, loff_t *offset);
147 static int heci_ioctl(struct inode *inode, struct file *file,
148 unsigned int cmd, unsigned long data);
149 static ssize_t heci_write(struct file *file, const char __user *ubuf,
150 size_t length, loff_t *offset);
151 static unsigned int heci_poll(struct file *file, poll_table *wait);
152 static struct heci_cb_private *find_read_list_entry(
153 struct iamt_heci_device *dev,
154 struct heci_file_private *file_ext);
155 #ifdef CONFIG_PM
156 static int heci_suspend(struct pci_dev *pdev, pm_message_t state);
157 static int heci_resume(struct pci_dev *pdev);
158 static __u16 g_sus_wd_timeout;
159 #else
160 #define heci_suspend NULL
161 #define heci_resume NULL
162 #endif
164 * PCI driver structure
166 static struct pci_driver heci_driver = {
167 .name = heci_driver_name,
168 .id_table = heci_pci_tbl,
169 .probe = heci_probe,
170 .remove = __devexit_p(heci_remove),
171 .shutdown = __devexit_p(heci_remove),
172 .suspend = heci_suspend,
173 .resume = heci_resume
177 * file operations structure will be use heci char device.
179 static struct file_operations heci_fops = {
180 .owner = THIS_MODULE,
181 .read = heci_read,
182 .ioctl = heci_ioctl,
183 .open = heci_open,
184 .release = heci_release,
185 .write = heci_write,
186 .poll = heci_poll,
190 * heci_registration_cdev - set up the cdev structure for heci device.
192 * @dev: char device struct
193 * @hminor: minor number for registration char device
194 * @fops: file operations structure
196 * returns 0 on success, <0 on failure.
198 static int heci_registration_cdev(struct cdev *dev, int hminor,
199 struct file_operations *fops)
201 int ret, devno = MKDEV(heci_major, hminor);
203 cdev_init(dev, fops);
204 dev->owner = THIS_MODULE;
205 ret = cdev_add(dev, devno, 1);
206 /* Fail gracefully if need be */
207 if (ret) {
208 printk(KERN_ERR "heci: Error %d registering heci device %d\n",
209 ret, hminor);
211 return ret;
214 /* Display the version of heci driver. */
215 static ssize_t version_show(struct class *dev, char *buf)
217 return sprintf(buf, "%s %s.\n",
218 heci_driver_string, heci_driver_version);
221 static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
224 * heci_register_cdev - registers heci char device
226 * returns 0 on success, <0 on failure.
228 static int heci_register_cdev(void)
230 int ret;
231 dev_t dev;
233 /* registration of char devices */
234 ret = alloc_chrdev_region(&dev, HECI_MINORS_BASE, HECI_MINORS_COUNT,
235 HECI_DRIVER_NAME);
236 if (ret) {
237 printk(KERN_ERR "heci: Error allocating char device region.\n");
238 return ret;
241 heci_major = MAJOR(dev);
243 ret = heci_registration_cdev(&heci_cdev, HECI_MINOR_NUMBER,
244 &heci_fops);
245 if (ret)
246 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
247 HECI_MINORS_COUNT);
249 return ret;
253 * heci_unregister_cdev - unregisters heci char device
255 static void heci_unregister_cdev(void)
257 cdev_del(&heci_cdev);
258 unregister_chrdev_region(MKDEV(heci_major, HECI_MINORS_BASE),
259 HECI_MINORS_COUNT);
262 #ifndef HECI_DEVICE_CREATE
263 #define HECI_DEVICE_CREATE device_create
264 #endif
266 * heci_sysfs_device_create - adds device entry to sysfs
268 * returns 0 on success, <0 on failure.
270 static int heci_sysfs_device_create(void)
272 struct class *class;
273 void *tmphdev;
274 int err = 0;
276 class = class_create(THIS_MODULE, HECI_DRIVER_NAME);
277 if (IS_ERR(class)) {
278 err = PTR_ERR(class);
279 printk(KERN_ERR "heci: Error creating heci class.\n");
280 goto err_out;
283 err = class_create_file(class, &class_attr_version);
284 if (err) {
285 class_destroy(class);
286 printk(KERN_ERR "heci: Error creating heci class file.\n");
287 goto err_out;
290 tmphdev = HECI_DEVICE_CREATE(class, NULL, heci_cdev.dev, NULL,
291 HECI_DEV_NAME);
292 if (IS_ERR(tmphdev)) {
293 err = PTR_ERR(tmphdev);
294 class_remove_file(class, &class_attr_version);
295 class_destroy(class);
296 goto err_out;
299 heci_class = class;
300 err_out:
301 return err;
305 * heci_sysfs_device_remove - unregisters the device entry on sysfs
307 static void heci_sysfs_device_remove(void)
309 if ((heci_class == NULL) || (IS_ERR(heci_class)))
310 return;
312 device_destroy(heci_class, heci_cdev.dev);
313 class_remove_file(heci_class, &class_attr_version);
314 class_destroy(heci_class);
318 * heci_init_module - Driver Registration Routine
320 * heci_init_module is the first routine called when the driver is
321 * loaded. All it does is register with the PCI subsystem.
323 * returns 0 on success, <0 on failure.
325 static int __init heci_init_module(void)
327 int ret = 0;
329 printk(KERN_INFO "heci: %s - version %s\n", heci_driver_string,
330 heci_driver_version);
331 printk(KERN_INFO "heci: %s\n", heci_copyright);
333 /* init pci module */
334 ret = pci_register_driver(&heci_driver);
335 if (ret < 0) {
336 printk(KERN_ERR "heci: Error registering driver.\n");
337 goto end;
340 ret = heci_register_cdev();
341 if (ret)
342 goto unregister_pci;
344 ret = heci_sysfs_device_create();
345 if (ret)
346 goto unregister_cdev;
348 return ret;
350 unregister_cdev:
351 heci_unregister_cdev();
352 unregister_pci:
353 pci_unregister_driver(&heci_driver);
354 end:
355 return ret;
358 module_init(heci_init_module);
362 * heci_exit_module - Driver Exit Cleanup Routine
364 * heci_exit_module is called just before the driver is removed
365 * from memory.
367 static void __exit heci_exit_module(void)
369 pci_unregister_driver(&heci_driver);
370 heci_sysfs_device_remove();
371 heci_unregister_cdev();
374 module_exit(heci_exit_module);
378 * heci_probe - Device Initialization Routine
380 * @pdev: PCI device information struct
381 * @ent: entry in kcs_pci_tbl
383 * returns 0 on success, <0 on failure.
385 static int __devinit heci_probe(struct pci_dev *pdev,
386 const struct pci_device_id *ent)
388 struct iamt_heci_device *dev = NULL;
389 int i, err = 0;
391 if (heci_device) {
392 err = -EEXIST;
393 goto end;
395 /* enable pci dev */
396 err = pci_enable_device(pdev);
397 if (err) {
398 printk(KERN_ERR "heci: Failed to enable pci device.\n");
399 goto end;
401 /* set PCI host mastering */
402 pci_set_master(pdev);
403 /* pci request regions for heci driver */
404 err = pci_request_regions(pdev, heci_driver_name);
405 if (err) {
406 printk(KERN_ERR "heci: Failed to get pci regions.\n");
407 goto disable_device;
409 /* allocates and initializes the heci dev structure */
410 dev = init_heci_device(pdev);
411 if (!dev) {
412 err = -ENOMEM;
413 goto release_regions;
415 /* mapping IO device memory */
416 for (i = 0; i <= 5; i++) {
417 if (pci_resource_len(pdev, i) == 0)
418 continue;
419 if (pci_resource_flags(pdev, i) & IORESOURCE_IO) {
420 printk(KERN_ERR "heci: heci has IO ports.\n");
421 goto free_device;
422 } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {
423 if (dev->mem_base) {
424 printk(KERN_ERR
425 "heci: Too many mem addresses.\n");
426 goto free_device;
428 dev->mem_base = pci_resource_start(pdev, i);
429 dev->mem_length = pci_resource_len(pdev, i);
432 if (!dev->mem_base) {
433 printk(KERN_ERR "heci: No address to use.\n");
434 err = -ENODEV;
435 goto free_device;
437 dev->mem_addr = ioremap_nocache(dev->mem_base,
438 dev->mem_length);
439 if (!dev->mem_addr) {
440 printk(KERN_ERR "heci: Remap IO device memory failure.\n");
441 err = -ENOMEM;
442 goto free_device;
444 /* request and enable interrupt */
445 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
446 heci_driver_name, dev);
447 if (err) {
448 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
449 pdev->irq);
450 goto unmap_memory;
453 if (heci_hw_init(dev)) {
454 printk(KERN_ERR "heci: Init hw failure.\n");
455 err = -ENODEV;
456 goto release_irq;
458 init_timer(&dev->wd_timer);
460 heci_initialize_clients(dev);
461 if (dev->heci_state != HECI_ENABLED) {
462 err = -ENODEV;
463 goto release_hw;
466 spin_lock_bh(&dev->device_lock);
467 heci_device = pdev;
468 pci_set_drvdata(pdev, dev);
469 spin_unlock_bh(&dev->device_lock);
471 if (dev->wd_timeout)
472 mod_timer(&dev->wd_timer, jiffies);
474 #ifdef CONFIG_PM
475 g_sus_wd_timeout = 0;
476 #endif
477 printk(KERN_INFO "heci driver initialization successful.\n");
478 return 0;
480 release_hw:
481 /* disable interrupts */
482 dev->host_hw_state = read_heci_register(dev, H_CSR);
483 heci_csr_disable_interrupts(dev);
485 del_timer_sync(&dev->wd_timer);
487 flush_scheduled_work();
489 release_irq:
490 free_irq(pdev->irq, dev);
491 unmap_memory:
492 if (dev->mem_addr)
493 iounmap(dev->mem_addr);
494 free_device:
495 kfree(dev);
496 release_regions:
497 pci_release_regions(pdev);
498 disable_device:
499 pci_disable_device(pdev);
500 end:
501 printk(KERN_ERR "heci driver initialization failed.\n");
502 return err;
506 * heci_remove - Device Removal Routine
508 * @pdev: PCI device information struct
510 * heci_remove is called by the PCI subsystem to alert the driver
511 * that it should release a PCI device.
513 static void __devexit heci_remove(struct pci_dev *pdev)
515 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
517 if (heci_device != pdev)
518 return;
520 if (dev == NULL)
521 return;
523 spin_lock_bh(&dev->device_lock);
524 if (heci_device != pdev) {
525 spin_unlock_bh(&dev->device_lock);
526 return;
529 if (dev->reinit_tsk != NULL) {
530 kthread_stop(dev->reinit_tsk);
531 dev->reinit_tsk = NULL;
534 del_timer_sync(&dev->wd_timer);
535 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
536 && dev->wd_timeout) {
537 dev->wd_timeout = 0;
538 dev->wd_due_counter = 0;
539 memcpy(dev->wd_data, heci_stop_wd_params, HECI_WD_PARAMS_SIZE);
540 dev->stop = 1;
541 if (dev->host_buffer_is_empty &&
542 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
543 dev->host_buffer_is_empty = 0;
545 if (!heci_send_wd(dev))
546 DBG("send stop WD failed\n");
547 else
548 flow_ctrl_reduce(dev, &dev->wd_file_ext);
550 dev->wd_pending = 0;
551 } else {
552 dev->wd_pending = 1;
554 dev->wd_stoped = 0;
555 spin_unlock_bh(&dev->device_lock);
557 wait_event_interruptible_timeout(dev->wait_stop_wd,
558 (dev->wd_stoped), 10 * HZ);
559 spin_lock_bh(&dev->device_lock);
560 if (!dev->wd_stoped)
561 DBG("stop wd failed to complete.\n");
562 else
563 DBG("stop wd complete.\n");
567 heci_device = NULL;
568 spin_unlock_bh(&dev->device_lock);
570 if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
571 dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
572 heci_disconnect_host_client(dev,
573 &dev->iamthif_file_ext);
575 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
576 dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
577 heci_disconnect_host_client(dev,
578 &dev->wd_file_ext);
581 spin_lock_bh(&dev->device_lock);
583 /* remove entry if already in list */
584 DBG("list del iamthif and wd file list.\n");
585 heci_remove_client_from_file_list(dev, dev->wd_file_ext.
586 host_client_id);
587 heci_remove_client_from_file_list(dev,
588 dev->iamthif_file_ext.host_client_id);
590 dev->iamthif_current_cb = NULL;
591 dev->iamthif_file_ext.file = NULL;
592 dev->num_heci_me_clients = 0;
594 spin_unlock_bh(&dev->device_lock);
596 flush_scheduled_work();
598 /* disable interrupts */
599 heci_csr_disable_interrupts(dev);
601 free_irq(pdev->irq, dev);
602 pci_set_drvdata(pdev, NULL);
604 if (dev->mem_addr)
605 iounmap(dev->mem_addr);
607 kfree(dev);
609 pci_release_regions(pdev);
610 pci_disable_device(pdev);
614 * heci_clear_list - remove all callbacks associated with file
615 * from heci_cb_list
617 * @file: file information struct
618 * @heci_cb_list: callbacks list
620 * heci_clear_list is called to clear resources associated with file
621 * when application calls close function or Ctrl-C was pressed
623 * returns 1 if callback removed from the list, 0 otherwise
625 static int heci_clear_list(struct iamt_heci_device *dev,
626 struct file *file, struct list_head *heci_cb_list)
628 struct heci_cb_private *priv_cb_pos = NULL;
629 struct heci_cb_private*priv_cb_next = NULL;
630 struct file *file_temp;
631 int rets = 0;
633 /* list all list member */
634 list_for_each_entry_safe(priv_cb_pos, priv_cb_next,
635 heci_cb_list, cb_list) {
636 file_temp = (struct file *)priv_cb_pos->file_object;
637 /* check if list member associated with a file */
638 if (file_temp == file) {
639 /* remove member from the list */
640 list_del(&priv_cb_pos->cb_list);
641 /* check if cb equal to current iamthif cb */
642 if (dev->iamthif_current_cb == priv_cb_pos) {
643 dev->iamthif_current_cb = NULL;
644 /* send flow control to iamthif client */
645 heci_send_flow_control(dev,
646 &dev->iamthif_file_ext);
648 /* free all allocated buffers */
649 heci_free_cb_private(priv_cb_pos);
650 rets = 1;
653 return rets;
657 * heci_clear_lists - remove all callbacks associated with file
659 * @dev: device information struct
660 * @file: file information struct
662 * heci_clear_lists is called to clear resources associated with file
663 * when application calls close function or Ctrl-C was pressed
665 * returns 1 if callback removed from the list, 0 otherwise
667 static int heci_clear_lists(struct iamt_heci_device *dev, struct file *file)
669 int rets = 0;
671 /* remove callbacks associated with a file */
672 heci_clear_list(dev, file, &dev->pthi_cmd_list.heci_cb.cb_list);
673 if (heci_clear_list(dev, file,
674 &dev->pthi_read_complete_list.heci_cb.cb_list))
675 rets = 1;
677 heci_clear_list(dev, file, &dev->ctrl_rd_list.heci_cb.cb_list);
679 if (heci_clear_list(dev, file, &dev->ctrl_wr_list.heci_cb.cb_list))
680 rets = 1;
682 if (heci_clear_list(dev, file,
683 &dev->write_waiting_list.heci_cb.cb_list))
684 rets = 1;
686 if (heci_clear_list(dev, file, &dev->write_list.heci_cb.cb_list))
687 rets = 1;
689 /* check if iamthif_current_cb not NULL */
690 if (dev->iamthif_current_cb && (!rets)) {
691 /* check file and iamthif current cb association */
692 if (dev->iamthif_current_cb->file_object == file) {
693 /* remove cb */
694 heci_free_cb_private(dev->iamthif_current_cb);
695 dev->iamthif_current_cb = NULL;
696 rets = 1;
699 return rets;
703 * heci_open - the open function
705 * @inode: pointer to inode structure
706 * @file: pointer to file structure
708 * returns 0 on success, <0 on error
710 static int heci_open(struct inode *inode, struct file *file)
712 struct heci_file_private *file_ext;
713 int if_num = iminor(inode);
714 struct iamt_heci_device *dev;
716 if (!heci_device)
717 return -ENODEV;
719 dev = pci_get_drvdata(heci_device);
720 if ((if_num != HECI_MINOR_NUMBER) || (!dev))
721 return -ENODEV;
723 file_ext = heci_alloc_file_private(file);
724 if (file_ext == NULL)
725 return -ENOMEM;
727 spin_lock_bh(&dev->device_lock);
728 if (dev->heci_state != HECI_ENABLED) {
729 spin_unlock_bh(&dev->device_lock);
730 kfree(file_ext);
731 return -ENODEV;
733 if (dev->open_handle_count >= HECI_MAX_OPEN_HANDLE_COUNT) {
734 spin_unlock_bh(&dev->device_lock);
735 kfree(file_ext);
736 return -ENFILE;
738 dev->open_handle_count++;
739 list_add_tail(&file_ext->link, &dev->file_list);
740 while ((dev->heci_host_clients[dev->current_host_client_id / 8]
741 & (1 << (dev->current_host_client_id % 8))) != 0) {
743 dev->current_host_client_id++; /* allow overflow */
744 DBG("current_host_client_id = %d\n",
745 dev->current_host_client_id);
746 DBG("dev->open_handle_count = %lu\n",
747 dev->open_handle_count);
749 DBG("current_host_client_id = %d\n", dev->current_host_client_id);
750 file_ext->host_client_id = dev->current_host_client_id;
751 dev->heci_host_clients[file_ext->host_client_id / 8] |=
752 (1 << (file_ext->host_client_id % 8));
753 spin_unlock_bh(&dev->device_lock);
754 spin_lock(&file_ext->file_lock);
755 file_ext->state = HECI_FILE_INITIALIZING;
756 file_ext->sm_state = 0;
758 file->private_data = file_ext;
759 spin_unlock(&file_ext->file_lock);
761 return 0;
765 * heci_release - the release function
767 * @inode: pointer to inode structure
768 * @file: pointer to file structure
770 * returns 0 on success, <0 on error
772 static int heci_release(struct inode *inode, struct file *file)
774 int rets = 0;
775 int if_num = iminor(inode);
776 struct heci_file_private *file_ext = file->private_data;
777 struct heci_cb_private *priv_cb = NULL;
778 struct iamt_heci_device *dev;
780 if (!heci_device)
781 return -ENODEV;
783 dev = pci_get_drvdata(heci_device);
784 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
785 return -ENODEV;
787 if (file_ext != &dev->iamthif_file_ext) {
788 spin_lock(&file_ext->file_lock);
789 if (file_ext->state == HECI_FILE_CONNECTED) {
790 file_ext->state = HECI_FILE_DISCONNECTING;
791 spin_unlock(&file_ext->file_lock);
792 DBG("disconnecting client host client = %d, "
793 "ME client = %d\n",
794 file_ext->host_client_id,
795 file_ext->me_client_id);
796 rets = heci_disconnect_host_client(dev, file_ext);
797 spin_lock(&file_ext->file_lock);
799 spin_lock_bh(&dev->device_lock);
800 heci_flush_queues(dev, file_ext);
801 DBG("remove client host client = %d, ME client = %d\n",
802 file_ext->host_client_id,
803 file_ext->me_client_id);
805 if (dev->open_handle_count > 0) {
806 dev->heci_host_clients[file_ext->host_client_id / 8] &=
807 ~(1 << (file_ext->host_client_id % 8));
808 dev->open_handle_count--;
810 heci_remove_client_from_file_list(dev,
811 file_ext->host_client_id);
813 /* free read cb */
814 if (file_ext->read_cb != NULL) {
815 priv_cb = find_read_list_entry(dev, file_ext);
816 /* Remove entry from read list */
817 if (priv_cb != NULL)
818 list_del(&priv_cb->cb_list);
820 priv_cb = file_ext->read_cb;
821 file_ext->read_cb = NULL;
824 spin_unlock_bh(&dev->device_lock);
825 file->private_data = NULL;
826 spin_unlock(&file_ext->file_lock);
828 if (priv_cb != NULL)
829 heci_free_cb_private(priv_cb);
831 kfree(file_ext);
832 } else {
833 spin_lock_bh(&dev->device_lock);
835 if (dev->open_handle_count > 0)
836 dev->open_handle_count--;
838 if (dev->iamthif_file_object == file
839 && dev->iamthif_state != HECI_IAMTHIF_IDLE) {
840 DBG("pthi canceled iamthif state %d\n",
841 dev->iamthif_state);
842 dev->iamthif_canceled = 1;
843 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE) {
844 DBG("run next pthi iamthif cb\n");
845 run_next_iamthif_cmd(dev);
849 if (heci_clear_lists(dev, file))
850 dev->iamthif_state = HECI_IAMTHIF_IDLE;
852 spin_unlock_bh(&dev->device_lock);
854 return rets;
857 static struct heci_cb_private *find_read_list_entry(
858 struct iamt_heci_device *dev,
859 struct heci_file_private *file_ext)
861 struct heci_cb_private *priv_cb_pos = NULL;
862 struct heci_cb_private *priv_cb_next = NULL;
863 struct heci_file_private *file_ext_list_temp;
865 if (dev->read_list.status == 0
866 && !list_empty(&dev->read_list.heci_cb.cb_list)) {
867 DBG("remove read_list CB \n");
868 list_for_each_entry_safe(priv_cb_pos,
869 priv_cb_next,
870 &dev->read_list.heci_cb.cb_list, cb_list) {
872 file_ext_list_temp = (struct heci_file_private *)
873 priv_cb_pos->file_private;
875 if ((file_ext_list_temp != NULL) &&
876 heci_fe_same_id(file_ext, file_ext_list_temp))
877 return priv_cb_pos;
881 return NULL;
885 * heci_read - the read client message function.
887 * @file: pointer to file structure
888 * @ubuf: pointer to user buffer
889 * @length: buffer length
890 * @offset: data offset in buffer
892 * returns >=0 data length on success , <0 on error
894 static ssize_t heci_read(struct file *file, char __user *ubuf,
895 size_t length, loff_t *offset)
897 int i;
898 int rets = 0, err = 0;
899 int if_num = iminor(file->f_dentry->d_inode);
900 struct heci_file_private *file_ext = file->private_data;
901 struct heci_cb_private *priv_cb_pos = NULL;
902 struct heci_cb_private *priv_cb = NULL;
903 struct iamt_heci_device *dev;
905 if (!heci_device)
906 return -ENODEV;
908 dev = pci_get_drvdata(heci_device);
909 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
910 return -ENODEV;
912 spin_lock_bh(&dev->device_lock);
913 if (dev->heci_state != HECI_ENABLED) {
914 spin_unlock_bh(&dev->device_lock);
915 return -ENODEV;
917 spin_unlock_bh(&dev->device_lock);
919 spin_lock(&file_ext->file_lock);
920 if ((file_ext->sm_state & HECI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
921 spin_unlock(&file_ext->file_lock);
922 /* Do not allow to read watchdog client */
923 for (i = 0; i < dev->num_heci_me_clients; i++) {
924 if (memcmp(&heci_wd_guid,
925 &dev->me_clients[i].props.protocol_name,
926 sizeof(struct guid)) == 0) {
927 if (file_ext->me_client_id ==
928 dev->me_clients[i].client_id)
929 return -EBADF;
932 } else {
933 file_ext->sm_state &= ~HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
934 spin_unlock(&file_ext->file_lock);
937 if (file_ext == &dev->iamthif_file_ext) {
938 rets = pthi_read(dev, if_num, file, ubuf, length, offset);
939 goto out;
942 if (file_ext->read_cb && file_ext->read_cb->information > *offset) {
943 priv_cb = file_ext->read_cb;
944 goto copy_buffer;
945 } else if (file_ext->read_cb && file_ext->read_cb->information > 0 &&
946 file_ext->read_cb->information <= *offset) {
947 priv_cb = file_ext->read_cb;
948 rets = 0;
949 goto free;
950 } else if ((!file_ext->read_cb || file_ext->read_cb->information == 0)
951 && *offset > 0) {
952 /*Offset needs to be cleaned for contingous reads*/
953 *offset = 0;
954 rets = 0;
955 goto out;
958 spin_lock(&file_ext->read_io_lock);
959 err = heci_start_read(dev, if_num, file_ext);
960 if (err != 0 && err != -EBUSY) {
961 DBG("heci start read failure with status = %d\n", err);
962 spin_unlock(&file_ext->read_io_lock);
963 rets = err;
964 goto out;
966 if (HECI_READ_COMPLETE != file_ext->reading_state
967 && !waitqueue_active(&file_ext->rx_wait)) {
968 if (file->f_flags & O_NONBLOCK) {
969 rets = -EAGAIN;
970 spin_unlock(&file_ext->read_io_lock);
971 goto out;
973 spin_unlock(&file_ext->read_io_lock);
975 if (wait_event_interruptible(file_ext->rx_wait,
976 (HECI_READ_COMPLETE == file_ext->reading_state
977 || HECI_FILE_INITIALIZING == file_ext->state
978 || HECI_FILE_DISCONNECTED == file_ext->state
979 || HECI_FILE_DISCONNECTING == file_ext->state))) {
980 if (signal_pending(current)) {
981 rets = -EINTR;
982 goto out;
984 return -ERESTARTSYS;
987 if (HECI_FILE_INITIALIZING == file_ext->state ||
988 HECI_FILE_DISCONNECTED == file_ext->state ||
989 HECI_FILE_DISCONNECTING == file_ext->state) {
990 rets = -EBUSY;
991 goto out;
993 spin_lock(&file_ext->read_io_lock);
996 priv_cb = file_ext->read_cb;
998 if (!priv_cb) {
999 spin_unlock(&file_ext->read_io_lock);
1000 return -ENODEV;
1002 if (file_ext->reading_state != HECI_READ_COMPLETE) {
1003 spin_unlock(&file_ext->read_io_lock);
1004 return 0;
1006 spin_unlock(&file_ext->read_io_lock);
1007 /* now copy the data to user space */
1008 copy_buffer:
1009 DBG("priv_cb->response_buffer size - %d\n",
1010 priv_cb->response_buffer.size);
1011 DBG("priv_cb->information - %lu\n",
1012 priv_cb->information);
1013 if (length == 0 || ubuf == NULL ||
1014 *offset > priv_cb->information) {
1015 rets = -EMSGSIZE;
1016 goto free;
1019 /* length is being turncated to PAGE_SIZE, however, */
1020 /* information size may be longer */
1021 length = (length < (priv_cb->information - *offset) ?
1022 length : (priv_cb->information - *offset));
1024 if (copy_to_user(ubuf,
1025 priv_cb->response_buffer.data + *offset,
1026 length)) {
1027 rets = -EFAULT;
1028 goto free;
1031 rets = length;
1032 *offset += length;
1033 if ((unsigned long)*offset < priv_cb->information)
1034 goto out;
1036 free:
1037 spin_lock_bh(&dev->device_lock);
1038 priv_cb_pos = find_read_list_entry(dev, file_ext);
1039 /* Remove entry from read list */
1040 if (priv_cb_pos != NULL)
1041 list_del(&priv_cb_pos->cb_list);
1042 spin_unlock_bh(&dev->device_lock);
1043 heci_free_cb_private(priv_cb);
1044 spin_lock(&file_ext->read_io_lock);
1045 file_ext->reading_state = HECI_IDLE;
1046 file_ext->read_cb = NULL;
1047 file_ext->read_pending = 0;
1048 spin_unlock(&file_ext->read_io_lock);
1049 out: DBG("end heci read rets= %d\n", rets);
1050 return rets;
1054 * heci_write - the write function.
1056 * @file: pointer to file structure
1057 * @ubuf: pointer to user buffer
1058 * @length: buffer length
1059 * @offset: data offset in buffer
1061 * returns >=0 data length on success , <0 on error
1063 static ssize_t heci_write(struct file *file, const char __user *ubuf,
1064 size_t length, loff_t *offset)
1066 int rets = 0;
1067 __u8 i;
1068 int if_num = iminor(file->f_dentry->d_inode);
1069 struct heci_file_private *file_ext = file->private_data;
1070 struct heci_cb_private *priv_write_cb = NULL;
1071 struct heci_msg_hdr heci_hdr;
1072 struct iamt_heci_device *dev;
1073 unsigned long currtime = get_seconds();
1075 if (!heci_device)
1076 return -ENODEV;
1078 dev = pci_get_drvdata(heci_device);
1080 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1081 return -ENODEV;
1083 spin_lock_bh(&dev->device_lock);
1085 if (dev->heci_state != HECI_ENABLED) {
1086 spin_unlock_bh(&dev->device_lock);
1087 return -ENODEV;
1089 if (file_ext == &dev->iamthif_file_ext) {
1090 priv_write_cb = find_pthi_read_list_entry(dev, file);
1091 if ((priv_write_cb != NULL) &&
1092 (((currtime - priv_write_cb->read_time) >
1093 IAMTHIF_READ_TIMER) ||
1094 (file_ext->reading_state == HECI_READ_COMPLETE))) {
1095 (*offset) = 0;
1096 list_del(&priv_write_cb->cb_list);
1097 heci_free_cb_private(priv_write_cb);
1098 priv_write_cb = NULL;
1102 /* free entry used in read */
1103 if (file_ext->reading_state == HECI_READ_COMPLETE) {
1104 *offset = 0;
1105 priv_write_cb = find_read_list_entry(dev, file_ext);
1106 if (priv_write_cb != NULL) {
1107 list_del(&priv_write_cb->cb_list);
1108 heci_free_cb_private(priv_write_cb);
1109 priv_write_cb = NULL;
1110 spin_lock(&file_ext->read_io_lock);
1111 file_ext->reading_state = HECI_IDLE;
1112 file_ext->read_cb = NULL;
1113 file_ext->read_pending = 0;
1114 spin_unlock(&file_ext->read_io_lock);
1116 } else if (file_ext->reading_state == HECI_IDLE &&
1117 file_ext->read_pending == 0)
1118 (*offset) = 0;
1120 spin_unlock_bh(&dev->device_lock);
1122 priv_write_cb = kzalloc(sizeof(struct heci_cb_private), GFP_KERNEL);
1123 if (!priv_write_cb)
1124 return -ENOMEM;
1126 priv_write_cb->file_object = file;
1127 priv_write_cb->file_private = file_ext;
1128 priv_write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
1129 if (!priv_write_cb->request_buffer.data) {
1130 kfree(priv_write_cb);
1131 return -ENOMEM;
1133 DBG("length =%d\n", (int) length);
1135 if (copy_from_user(priv_write_cb->request_buffer.data,
1136 ubuf, length)) {
1137 rets = -EFAULT;
1138 goto fail;
1141 spin_lock(&file_ext->file_lock);
1142 file_ext->sm_state = 0;
1143 if ((length == 4) &&
1144 ((memcmp(heci_wd_state_independence_msg[0], ubuf, 4) == 0) ||
1145 (memcmp(heci_wd_state_independence_msg[1], ubuf, 4) == 0) ||
1146 (memcmp(heci_wd_state_independence_msg[2], ubuf, 4) == 0)))
1147 file_ext->sm_state |= HECI_WD_STATE_INDEPENDENCE_MSG_SENT;
1148 spin_unlock(&file_ext->file_lock);
1150 INIT_LIST_HEAD(&priv_write_cb->cb_list);
1151 if (file_ext == &dev->iamthif_file_ext) {
1152 priv_write_cb->response_buffer.data =
1153 kmalloc(IAMTHIF_MTU, GFP_KERNEL);
1154 if (!priv_write_cb->response_buffer.data) {
1155 rets = -ENOMEM;
1156 goto fail;
1158 spin_lock_bh(&dev->device_lock);
1159 if (dev->heci_state != HECI_ENABLED) {
1160 spin_unlock_bh(&dev->device_lock);
1161 rets = -ENODEV;
1162 goto fail;
1164 for (i = 0; i < dev->num_heci_me_clients; i++) {
1165 if (dev->me_clients[i].client_id ==
1166 dev->iamthif_file_ext.me_client_id)
1167 break;
1170 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1171 if ((i == dev->num_heci_me_clients) ||
1172 (dev->me_clients[i].client_id !=
1173 dev->iamthif_file_ext.me_client_id)) {
1175 spin_unlock_bh(&dev->device_lock);
1176 rets = -ENODEV;
1177 goto fail;
1178 } else if ((length > dev->me_clients[i].props.max_msg_length)
1179 || (length <= 0)) {
1180 spin_unlock_bh(&dev->device_lock);
1181 rets = -EMSGSIZE;
1182 goto fail;
1186 priv_write_cb->response_buffer.size = IAMTHIF_MTU;
1187 priv_write_cb->major_file_operations = HECI_IOCTL;
1188 priv_write_cb->information = 0;
1189 priv_write_cb->request_buffer.size = length;
1190 if (dev->iamthif_file_ext.state != HECI_FILE_CONNECTED) {
1191 spin_unlock_bh(&dev->device_lock);
1192 rets = -ENODEV;
1193 goto fail;
1196 if (!list_empty(&dev->pthi_cmd_list.heci_cb.cb_list)
1197 || dev->iamthif_state != HECI_IAMTHIF_IDLE) {
1198 DBG("pthi_state = %d\n", (int) dev->iamthif_state);
1199 DBG("add PTHI cb to pthi cmd waiting list\n");
1200 list_add_tail(&priv_write_cb->cb_list,
1201 &dev->pthi_cmd_list.heci_cb.cb_list);
1202 rets = length;
1203 } else {
1204 DBG("call pthi write\n");
1205 rets = pthi_write(dev, priv_write_cb);
1207 if (rets != 0) {
1208 DBG("pthi write failed with status = %d\n",
1209 rets);
1210 spin_unlock_bh(&dev->device_lock);
1211 goto fail;
1213 rets = length;
1215 spin_unlock_bh(&dev->device_lock);
1216 return rets;
1219 priv_write_cb->major_file_operations = HECI_WRITE;
1220 /* make sure information is zero before we start */
1222 priv_write_cb->information = 0;
1223 priv_write_cb->request_buffer.size = length;
1225 spin_lock(&file_ext->write_io_lock);
1226 DBG("host client = %d, ME client = %d\n",
1227 file_ext->host_client_id, file_ext->me_client_id);
1228 if (file_ext->state != HECI_FILE_CONNECTED) {
1229 rets = -ENODEV;
1230 DBG("host client = %d, is not connected to ME client = %d",
1231 file_ext->host_client_id,
1232 file_ext->me_client_id);
1234 goto unlock;
1236 for (i = 0; i < dev->num_heci_me_clients; i++) {
1237 if (dev->me_clients[i].client_id ==
1238 file_ext->me_client_id)
1239 break;
1241 BUG_ON(dev->me_clients[i].client_id != file_ext->me_client_id);
1242 if (i == dev->num_heci_me_clients) {
1243 rets = -ENODEV;
1244 goto unlock;
1246 if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
1247 rets = -EINVAL;
1248 goto unlock;
1250 priv_write_cb->file_private = file_ext;
1252 spin_lock_bh(&dev->device_lock);
1253 if (flow_ctrl_creds(dev, file_ext) &&
1254 dev->host_buffer_is_empty) {
1255 spin_unlock_bh(&dev->device_lock);
1256 dev->host_buffer_is_empty = 0;
1257 if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
1258 sizeof(__u32)) - sizeof(struct heci_msg_hdr))) {
1260 heci_hdr.length =
1261 (((dev->host_hw_state & H_CBD) >> 24) *
1262 sizeof(__u32)) -
1263 sizeof(struct heci_msg_hdr);
1264 heci_hdr.msg_complete = 0;
1265 } else {
1266 heci_hdr.length = length;
1267 heci_hdr.msg_complete = 1;
1269 heci_hdr.host_addr = file_ext->host_client_id;
1270 heci_hdr.me_addr = file_ext->me_client_id;
1271 heci_hdr.reserved = 0;
1272 DBG("call heci_write_message header=%08x.\n",
1273 *((__u32 *) &heci_hdr));
1274 spin_unlock(&file_ext->write_io_lock);
1275 /* protect heci low level write */
1276 spin_lock_bh(&dev->device_lock);
1277 if (!heci_write_message(dev, &heci_hdr,
1278 (unsigned char *) (priv_write_cb->request_buffer.data),
1279 heci_hdr.length)) {
1281 spin_unlock_bh(&dev->device_lock);
1282 heci_free_cb_private(priv_write_cb);
1283 rets = -ENODEV;
1284 priv_write_cb->information = 0;
1285 return rets;
1287 file_ext->writing_state = HECI_WRITING;
1288 priv_write_cb->information = heci_hdr.length;
1289 if (heci_hdr.msg_complete) {
1290 flow_ctrl_reduce(dev, file_ext);
1291 list_add_tail(&priv_write_cb->cb_list,
1292 &dev->write_waiting_list.heci_cb.cb_list);
1293 } else {
1294 list_add_tail(&priv_write_cb->cb_list,
1295 &dev->write_list.heci_cb.cb_list);
1297 spin_unlock_bh(&dev->device_lock);
1299 } else {
1301 spin_unlock_bh(&dev->device_lock);
1302 priv_write_cb->information = 0;
1303 file_ext->writing_state = HECI_WRITING;
1304 spin_unlock(&file_ext->write_io_lock);
1305 list_add_tail(&priv_write_cb->cb_list,
1306 &dev->write_list.heci_cb.cb_list);
1308 return length;
1310 unlock:
1311 spin_unlock(&file_ext->write_io_lock);
1312 fail:
1313 heci_free_cb_private(priv_write_cb);
1314 return rets;
1319 * heci_ioctl - the IOCTL function
1321 * @inode: pointer to inode structure
1322 * @file: pointer to file structure
1323 * @cmd: ioctl command
1324 * @data: pointer to heci message structure
1326 * returns 0 on success , <0 on error
1328 static int heci_ioctl(struct inode *inode, struct file *file,
1329 unsigned int cmd, unsigned long data)
1331 int rets = 0;
1332 int if_num = iminor(inode);
1333 struct heci_file_private *file_ext = file->private_data;
1334 /* in user space */
1335 struct heci_message_data *u_msg = (struct heci_message_data *) data;
1336 struct heci_message_data k_msg; /* all in kernel on the stack */
1337 struct iamt_heci_device *dev;
1339 if (!capable(CAP_SYS_ADMIN))
1340 return -EPERM;
1342 if (!heci_device)
1343 return -ENODEV;
1345 dev = pci_get_drvdata(heci_device);
1346 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1347 return -ENODEV;
1349 spin_lock_bh(&dev->device_lock);
1350 if (dev->heci_state != HECI_ENABLED) {
1351 spin_unlock_bh(&dev->device_lock);
1352 return -ENODEV;
1354 spin_unlock_bh(&dev->device_lock);
1356 /* first copy from user all data needed */
1357 if (copy_from_user(&k_msg, u_msg, sizeof(k_msg))) {
1358 DBG("first copy from user all data needed filled\n");
1359 return -EFAULT;
1361 DBG("user message size is %d\n", k_msg.size);
1363 switch (cmd) {
1364 case IOCTL_HECI_GET_VERSION:
1365 DBG(": IOCTL_HECI_GET_VERSION\n");
1366 rets = heci_ioctl_get_version(dev, if_num, u_msg, k_msg,
1367 file_ext);
1368 break;
1370 case IOCTL_HECI_CONNECT_CLIENT:
1371 DBG(": IOCTL_HECI_CONNECT_CLIENT.\n");
1372 rets = heci_ioctl_connect_client(dev, if_num, u_msg, k_msg,
1373 file);
1374 break;
1376 case IOCTL_HECI_WD:
1377 DBG(": IOCTL_HECI_WD.\n");
1378 rets = heci_ioctl_wd(dev, if_num, k_msg, file_ext);
1379 break;
1381 case IOCTL_HECI_BYPASS_WD:
1382 DBG(": IOCTL_HECI_BYPASS_WD.\n");
1383 rets = heci_ioctl_bypass_wd(dev, if_num, k_msg, file_ext);
1384 break;
1386 default:
1387 rets = -EINVAL;
1388 break;
1390 return rets;
1394 * heci_poll - the poll function
1396 * @file: pointer to file structure
1397 * @wait: pointer to poll_table structure
1399 * returns poll mask
1401 static unsigned int heci_poll(struct file *file, poll_table *wait)
1403 int if_num = iminor(file->f_dentry->d_inode);
1404 unsigned int mask = 0;
1405 struct heci_file_private *file_ext = file->private_data;
1406 struct iamt_heci_device *dev;
1408 if (!heci_device)
1409 return mask;
1411 dev = pci_get_drvdata(heci_device);
1413 if ((if_num != HECI_MINOR_NUMBER) || (!dev) || (!file_ext))
1414 return mask;
1416 spin_lock_bh(&dev->device_lock);
1417 if (dev->heci_state != HECI_ENABLED) {
1418 spin_unlock_bh(&dev->device_lock);
1419 return mask;
1421 spin_unlock_bh(&dev->device_lock);
1423 if (file_ext == &dev->iamthif_file_ext) {
1424 poll_wait(file, &dev->iamthif_file_ext.wait, wait);
1425 spin_lock(&dev->iamthif_file_ext.file_lock);
1426 if (dev->iamthif_state == HECI_IAMTHIF_READ_COMPLETE
1427 && dev->iamthif_file_object == file) {
1428 mask |= (POLLIN | POLLRDNORM);
1429 spin_lock_bh(&dev->device_lock);
1430 DBG("run next pthi cb\n");
1431 run_next_iamthif_cmd(dev);
1432 spin_unlock_bh(&dev->device_lock);
1434 spin_unlock(&dev->iamthif_file_ext.file_lock);
1436 } else{
1437 poll_wait(file, &file_ext->tx_wait, wait);
1438 spin_lock(&file_ext->write_io_lock);
1439 if (HECI_WRITE_COMPLETE == file_ext->writing_state)
1440 mask |= (POLLIN | POLLRDNORM);
1442 spin_unlock(&file_ext->write_io_lock);
1445 return mask;
1448 #ifdef CONFIG_PM
1449 static int heci_suspend(struct pci_dev *pdev, pm_message_t state)
1451 struct iamt_heci_device *dev = pci_get_drvdata(pdev);
1452 int err = 0;
1454 spin_lock_bh(&dev->device_lock);
1455 if (dev->reinit_tsk != NULL) {
1456 kthread_stop(dev->reinit_tsk);
1457 dev->reinit_tsk = NULL;
1459 spin_unlock_bh(&dev->device_lock);
1461 /* Stop watchdog if exists */
1462 del_timer_sync(&dev->wd_timer);
1463 if (dev->wd_file_ext.state == HECI_FILE_CONNECTED
1464 && dev->wd_timeout) {
1465 spin_lock_bh(&dev->device_lock);
1466 g_sus_wd_timeout = dev->wd_timeout;
1467 dev->wd_timeout = 0;
1468 dev->wd_due_counter = 0;
1469 memcpy(dev->wd_data, heci_stop_wd_params,
1470 HECI_WD_PARAMS_SIZE);
1471 dev->stop = 1;
1472 if (dev->host_buffer_is_empty &&
1473 flow_ctrl_creds(dev, &dev->wd_file_ext)) {
1474 dev->host_buffer_is_empty = 0;
1475 if (!heci_send_wd(dev))
1476 DBG("send stop WD failed\n");
1477 else
1478 flow_ctrl_reduce(dev, &dev->wd_file_ext);
1480 dev->wd_pending = 0;
1481 } else {
1482 dev->wd_pending = 1;
1484 spin_unlock_bh(&dev->device_lock);
1485 dev->wd_stoped = 0;
1487 err = wait_event_interruptible_timeout(dev->wait_stop_wd,
1488 (dev->wd_stoped),
1489 10 * HZ);
1490 if (!dev->wd_stoped)
1491 DBG("stop wd failed to complete.\n");
1492 else {
1493 DBG("stop wd complete %d.\n", err);
1494 err = 0;
1497 /* Set new heci state */
1498 spin_lock_bh(&dev->device_lock);
1499 if (dev->heci_state == HECI_ENABLED ||
1500 dev->heci_state == HECI_RECOVERING_FROM_RESET) {
1501 dev->heci_state = HECI_POWER_DOWN;
1502 heci_reset(dev, 0);
1504 spin_unlock_bh(&dev->device_lock);
1506 pci_save_state(pdev);
1508 pci_disable_device(pdev);
1509 free_irq(pdev->irq, dev);
1511 pci_set_power_state(pdev, PCI_D3hot);
1513 return err;
1516 static int heci_resume(struct pci_dev *pdev)
1518 struct iamt_heci_device *dev;
1519 int err = 0;
1521 pci_set_power_state(pdev, PCI_D0);
1522 pci_restore_state(pdev);
1524 dev = pci_get_drvdata(pdev);
1525 if (!dev)
1526 return -ENODEV;
1528 /* request and enable interrupt */
1529 err = request_irq(pdev->irq, heci_isr_interrupt, IRQF_SHARED,
1530 heci_driver_name, dev);
1531 if (err) {
1532 printk(KERN_ERR "heci: Request_irq failure. irq = %d \n",
1533 pdev->irq);
1534 return err;
1537 spin_lock_bh(&dev->device_lock);
1538 dev->heci_state = HECI_POWER_UP;
1539 heci_reset(dev, 1);
1540 spin_unlock_bh(&dev->device_lock);
1542 /* Start watchdog if stopped in suspend */
1543 if (g_sus_wd_timeout != 0) {
1544 dev->wd_timeout = g_sus_wd_timeout;
1546 memcpy(dev->wd_data, heci_start_wd_params,
1547 HECI_WD_PARAMS_SIZE);
1548 memcpy(dev->wd_data + HECI_WD_PARAMS_SIZE,
1549 &dev->wd_timeout, sizeof(__u16));
1550 dev->wd_due_counter = 1;
1552 if (dev->wd_timeout)
1553 mod_timer(&dev->wd_timer, jiffies);
1555 g_sus_wd_timeout = 0;
1557 return err;
1559 #endif
1561 MODULE_AUTHOR("Intel Corporation");
1562 MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
1563 MODULE_LICENSE("Dual BSD/GPL");
1564 MODULE_VERSION(HECI_DRIVER_VERSION);