staging: mei: expose misc interface instead of char device
authorOren Weil <oren.jer.weil@intel.com>
Sun, 13 Nov 2011 07:41:14 +0000 (09:41 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 27 Nov 2011 00:05:13 +0000 (16:05 -0800)
Misc device provides everything MEI needs for registration,
it doesn't required separate driver class.

Signed-off-by: Oren Weil <oren.jer.weil@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/mei/main.c
drivers/staging/mei/mei_dev.h

index eb05c36f45d4181f0fb7c4df36165a9a9dd87e8f..410b5d46b1508bc5ac499cb81356316b61162ae8 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/compat.h>
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
+#include <linux/miscdevice.h>
 
 #include "mei_dev.h"
 #include "mei.h"
@@ -51,18 +52,10 @@ static char mei_driver_name[] = MEI_DRIVER_NAME;
 static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
 static const char mei_driver_version[] = MEI_DRIVER_VERSION;
 
-/* mei char device for registration */
-static struct cdev mei_cdev;
-
-/* major number for device */
-static int mei_major;
 /* The device pointer */
 /* Currently this driver works as long as there is only a single AMT device. */
 struct pci_dev *mei_device;
 
-static struct class *mei_class;
-
-
 /* mei_pci_tbl - PCI Device ID Table */
 static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
@@ -105,173 +98,6 @@ MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
 
 static DEFINE_MUTEX(mei_mutex);
 
-/**
- * mei_probe - Device Initialization Routine
- *
- * @pdev: PCI device structure
- * @ent: entry in kcs_pci_tbl
- *
- * returns 0 on success, <0 on failure.
- */
-static int __devinit mei_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
-{
-       struct mei_device *dev;
-       int err;
-
-       mutex_lock(&mei_mutex);
-       if (mei_device) {
-               err = -EEXIST;
-               goto end;
-       }
-       /* enable pci dev */
-       err = pci_enable_device(pdev);
-       if (err) {
-               printk(KERN_ERR "mei: Failed to enable pci device.\n");
-               goto end;
-       }
-       /* set PCI host mastering  */
-       pci_set_master(pdev);
-       /* pci request regions for mei driver */
-       err = pci_request_regions(pdev, mei_driver_name);
-       if (err) {
-               printk(KERN_ERR "mei: Failed to get pci regions.\n");
-               goto disable_device;
-       }
-       /* allocates and initializes the mei dev structure */
-       dev = mei_device_init(pdev);
-       if (!dev) {
-               err = -ENOMEM;
-               goto release_regions;
-       }
-       /* mapping  IO device memory */
-       dev->mem_addr = pci_iomap(pdev, 0, 0);
-       if (!dev->mem_addr) {
-               printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
-               err = -ENOMEM;
-               goto free_device;
-       }
-       pci_enable_msi(pdev);
-
-        /* request and enable interrupt */
-       if (pci_dev_msi_enabled(pdev))
-               err = request_threaded_irq(pdev->irq,
-                       NULL,
-                       mei_interrupt_thread_handler,
-                       0, mei_driver_name, dev);
-       else
-               err = request_threaded_irq(pdev->irq,
-                       mei_interrupt_quick_handler,
-                       mei_interrupt_thread_handler,
-                       IRQF_SHARED, mei_driver_name, dev);
-
-       if (err) {
-               printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
-                      pdev->irq);
-               goto unmap_memory;
-       }
-       INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
-       if (mei_hw_init(dev)) {
-               printk(KERN_ERR "mei: Init hw failure.\n");
-               err = -ENODEV;
-               goto release_irq;
-       }
-       mei_device = pdev;
-       pci_set_drvdata(pdev, dev);
-       schedule_delayed_work(&dev->timer_work, HZ);
-
-       mutex_unlock(&mei_mutex);
-
-       pr_debug("mei: Driver initialization successful.\n");
-
-       return 0;
-
-release_irq:
-       /* disable interrupts */
-       dev->host_hw_state = mei_hcsr_read(dev);
-       mei_disable_interrupts(dev);
-       flush_scheduled_work();
-       free_irq(pdev->irq, dev);
-       pci_disable_msi(pdev);
-unmap_memory:
-       pci_iounmap(pdev, dev->mem_addr);
-free_device:
-       kfree(dev);
-release_regions:
-       pci_release_regions(pdev);
-disable_device:
-       pci_disable_device(pdev);
-end:
-       mutex_unlock(&mei_mutex);
-       printk(KERN_ERR "mei: Driver initialization failed.\n");
-       return err;
-}
-
-/**
- * mei_remove - Device Removal Routine
- *
- * @pdev: PCI device structure
- *
- * mei_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
- */
-static void __devexit mei_remove(struct pci_dev *pdev)
-{
-       struct mei_device *dev;
-
-       if (mei_device != pdev)
-               return;
-
-       dev = pci_get_drvdata(pdev);
-       if (!dev)
-               return;
-
-       mutex_lock(&dev->device_lock);
-
-       mei_wd_stop(dev, false);
-
-       mei_device = NULL;
-
-       if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
-               dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
-               mei_disconnect_host_client(dev, &dev->iamthif_cl);
-       }
-       if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
-               dev->wd_cl.state = MEI_FILE_DISCONNECTING;
-               mei_disconnect_host_client(dev, &dev->wd_cl);
-       }
-
-       /* Unregistering watchdog device */
-       if (dev->wd_interface_reg)
-               watchdog_unregister_device(&amt_wd_dev);
-
-       /* remove entry if already in list */
-       dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
-       mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
-       mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
-
-       dev->iamthif_current_cb = NULL;
-       dev->me_clients_num = 0;
-
-       mutex_unlock(&dev->device_lock);
-
-       flush_scheduled_work();
-
-       /* disable interrupts */
-       mei_disable_interrupts(dev);
-
-       free_irq(pdev->irq, dev);
-       pci_disable_msi(pdev);
-       pci_set_drvdata(pdev, NULL);
-
-       if (dev->mem_addr)
-               pci_iounmap(pdev, dev->mem_addr);
-
-       kfree(dev);
-
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-}
 
 /**
  * mei_clear_list - removes all callbacks associated with file
@@ -402,7 +228,7 @@ static struct mei_cl_cb *find_read_list_entry(
 static int mei_open(struct inode *inode, struct file *file)
 {
        struct mei_cl *cl;
-       int if_num = iminor(inode), err;
+       int err;
        struct mei_device *dev;
 
        err = -ENODEV;
@@ -410,7 +236,7 @@ static int mei_open(struct inode *inode, struct file *file)
                goto out;
 
        dev = pci_get_drvdata(mei_device);
-       if (if_num != MEI_MINOR_NUMBER || !dev)
+       if (!dev)
                goto out;
 
        mutex_lock(&dev->device_lock);
@@ -446,7 +272,7 @@ static int mei_open(struct inode *inode, struct file *file)
        file->private_data = cl;
        mutex_unlock(&dev->device_lock);
 
-       return 0;
+       return nonseekable_open(inode, file);
 
 out_unlock:
        mutex_unlock(&dev->device_lock);
@@ -1090,6 +916,207 @@ out:
        return mask;
 }
 
+/*
+ * file operations structure will be used for mei char device.
+ */
+static const struct file_operations mei_fops = {
+       .owner = THIS_MODULE,
+       .read = mei_read,
+       .unlocked_ioctl = mei_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = mei_compat_ioctl,
+#endif
+       .open = mei_open,
+       .release = mei_release,
+       .write = mei_write,
+       .poll = mei_poll,
+       .llseek = no_llseek
+};
+
+
+/*
+ * Misc Device Struct
+ */
+static struct miscdevice  mei_misc_device = {
+               .name = MEI_DRIVER_NAME,
+               .fops = &mei_fops,
+               .minor = MISC_DYNAMIC_MINOR,
+};
+
+/**
+ * mei_probe - Device Initialization Routine
+ *
+ * @pdev: PCI device structure
+ * @ent: entry in kcs_pci_tbl
+ *
+ * returns 0 on success, <0 on failure.
+ */
+static int __devinit mei_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
+{
+       struct mei_device *dev;
+       int err;
+
+       mutex_lock(&mei_mutex);
+       if (mei_device) {
+               err = -EEXIST;
+               goto end;
+       }
+       /* enable pci dev */
+       err = pci_enable_device(pdev);
+       if (err) {
+               printk(KERN_ERR "mei: Failed to enable pci device.\n");
+               goto end;
+       }
+       /* set PCI host mastering  */
+       pci_set_master(pdev);
+       /* pci request regions for mei driver */
+       err = pci_request_regions(pdev, mei_driver_name);
+       if (err) {
+               printk(KERN_ERR "mei: Failed to get pci regions.\n");
+               goto disable_device;
+       }
+       /* allocates and initializes the mei dev structure */
+       dev = mei_device_init(pdev);
+       if (!dev) {
+               err = -ENOMEM;
+               goto release_regions;
+       }
+       /* mapping  IO device memory */
+       dev->mem_addr = pci_iomap(pdev, 0, 0);
+       if (!dev->mem_addr) {
+               printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
+               err = -ENOMEM;
+               goto free_device;
+       }
+       pci_enable_msi(pdev);
+
+        /* request and enable interrupt */
+       if (pci_dev_msi_enabled(pdev))
+               err = request_threaded_irq(pdev->irq,
+                       NULL,
+                       mei_interrupt_thread_handler,
+                       0, mei_driver_name, dev);
+       else
+               err = request_threaded_irq(pdev->irq,
+                       mei_interrupt_quick_handler,
+                       mei_interrupt_thread_handler,
+                       IRQF_SHARED, mei_driver_name, dev);
+
+       if (err) {
+               printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
+                      pdev->irq);
+               goto unmap_memory;
+       }
+       INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
+       if (mei_hw_init(dev)) {
+               printk(KERN_ERR "mei: Init hw failure.\n");
+               err = -ENODEV;
+               goto release_irq;
+       }
+
+       err = misc_register(&mei_misc_device);
+       if (err)
+               goto release_irq;
+
+       mei_device = pdev;
+       pci_set_drvdata(pdev, dev);
+
+
+       schedule_delayed_work(&dev->timer_work, HZ);
+
+       mutex_unlock(&mei_mutex);
+
+       pr_debug("mei: Driver initialization successful.\n");
+
+       return 0;
+
+release_irq:
+       /* disable interrupts */
+       dev->host_hw_state = mei_hcsr_read(dev);
+       mei_disable_interrupts(dev);
+       flush_scheduled_work();
+       free_irq(pdev->irq, dev);
+       pci_disable_msi(pdev);
+unmap_memory:
+       pci_iounmap(pdev, dev->mem_addr);
+free_device:
+       kfree(dev);
+release_regions:
+       pci_release_regions(pdev);
+disable_device:
+       pci_disable_device(pdev);
+end:
+       mutex_unlock(&mei_mutex);
+       printk(KERN_ERR "mei: Driver initialization failed.\n");
+       return err;
+}
+
+/**
+ * mei_remove - Device Removal Routine
+ *
+ * @pdev: PCI device structure
+ *
+ * mei_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ */
+static void __devexit mei_remove(struct pci_dev *pdev)
+{
+       struct mei_device *dev;
+
+       if (mei_device != pdev)
+               return;
+
+       dev = pci_get_drvdata(pdev);
+       if (!dev)
+               return;
+
+       mutex_lock(&dev->device_lock);
+
+       mei_wd_stop(dev, false);
+
+       mei_device = NULL;
+
+       if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
+               dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
+               mei_disconnect_host_client(dev, &dev->iamthif_cl);
+       }
+       if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
+               dev->wd_cl.state = MEI_FILE_DISCONNECTING;
+               mei_disconnect_host_client(dev, &dev->wd_cl);
+       }
+
+       /* Unregistering watchdog device */
+       if (dev->wd_interface_reg)
+               watchdog_unregister_device(&amt_wd_dev);
+
+       /* remove entry if already in list */
+       dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
+       mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
+       mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
+
+       dev->iamthif_current_cb = NULL;
+       dev->me_clients_num = 0;
+
+       mutex_unlock(&dev->device_lock);
+
+       flush_scheduled_work();
+
+       /* disable interrupts */
+       mei_disable_interrupts(dev);
+
+       free_irq(pdev->irq, dev);
+       pci_disable_msi(pdev);
+       pci_set_drvdata(pdev, NULL);
+
+       if (dev->mem_addr)
+               pci_iounmap(pdev, dev->mem_addr);
+
+       kfree(dev);
+
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+}
 #ifdef CONFIG_PM
 static int mei_pci_suspend(struct device *device)
 {
@@ -1173,131 +1200,6 @@ static struct pci_driver mei_driver = {
        .driver.pm = MEI_PM_OPS,
 };
 
-/*
- * file operations structure will be used for mei char device.
- */
-static const struct file_operations mei_fops = {
-       .owner = THIS_MODULE,
-       .read = mei_read,
-       .unlocked_ioctl = mei_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = mei_compat_ioctl,
-#endif
-       .open = mei_open,
-       .release = mei_release,
-       .write = mei_write,
-       .poll = mei_poll,
-};
-
-/**
- * mei_registration_cdev - sets up the cdev structure for mei device.
- *
- * @dev: char device struct
- * @hminor: minor number for registration char device
- * @fops: file operations structure
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_registration_cdev(struct cdev *dev, int hminor,
-                                 const struct file_operations *fops)
-{
-       int ret, devno = MKDEV(mei_major, hminor);
-
-       cdev_init(dev, fops);
-       dev->owner = THIS_MODULE;
-       ret = cdev_add(dev, devno, 1);
-       /* Fail gracefully if need be */
-       if (ret)
-               printk(KERN_ERR "mei: Error %d registering mei device %d\n",
-                      ret, hminor);
-       return ret;
-}
-
-/**
- * mei_register_cdev - registers mei char device
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_register_cdev(void)
-{
-       int ret;
-       dev_t dev;
-
-       /* registration of char devices */
-       ret = alloc_chrdev_region(&dev, MEI_MINORS_BASE, MEI_MINORS_COUNT,
-                                 MEI_DRIVER_NAME);
-       if (ret) {
-               printk(KERN_ERR "mei: Error allocating char device region.\n");
-               return ret;
-       }
-
-       mei_major = MAJOR(dev);
-
-       ret = mei_registration_cdev(&mei_cdev, MEI_MINOR_NUMBER,
-                                    &mei_fops);
-       if (ret)
-               unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE),
-                                        MEI_MINORS_COUNT);
-
-       return ret;
-}
-
-/**
- * mei_unregister_cdev - unregisters mei char device
- */
-static void mei_unregister_cdev(void)
-{
-       cdev_del(&mei_cdev);
-       unregister_chrdev_region(MKDEV(mei_major, MEI_MINORS_BASE),
-                                MEI_MINORS_COUNT);
-}
-
-/**
- * mei_sysfs_device_create - adds device entry to sysfs
- *
- * returns 0 on success, <0 on failure.
- */
-static int mei_sysfs_device_create(void)
-{
-       struct class *class;
-       void *tmphdev;
-       int err;
-
-       class = class_create(THIS_MODULE, MEI_DRIVER_NAME);
-       if (IS_ERR(class)) {
-               err = PTR_ERR(class);
-               printk(KERN_ERR "mei: Error creating mei class.\n");
-               goto err_out;
-       }
-
-       tmphdev = device_create(class, NULL, mei_cdev.dev, NULL,
-                                       MEI_DEV_NAME);
-       if (IS_ERR(tmphdev)) {
-               err = PTR_ERR(tmphdev);
-               goto err_destroy;
-       }
-
-       mei_class = class;
-       return 0;
-
-err_destroy:
-       class_destroy(class);
-err_out:
-       return err;
-}
-
-/**
- * mei_sysfs_device_remove - unregisters the device entry on sysfs
- */
-static void mei_sysfs_device_remove(void)
-{
-       if (IS_ERR_OR_NULL(mei_class))
-               return;
-
-       device_destroy(mei_class, mei_cdev.dev);
-       class_destroy(mei_class);
-}
-
 /**
  * mei_init_module - Driver Registration Routine
  *
@@ -1314,26 +1216,9 @@ static int __init mei_init_module(void)
                mei_driver_string, mei_driver_version);
        /* init pci module */
        ret = pci_register_driver(&mei_driver);
-       if (ret < 0) {
+       if (ret < 0)
                printk(KERN_ERR "mei: Error registering driver.\n");
-               goto end;
-       }
 
-       ret = mei_register_cdev();
-       if (ret)
-               goto unregister_pci;
-
-       ret = mei_sysfs_device_create();
-       if (ret)
-               goto unregister_cdev;
-
-       return ret;
-
-unregister_cdev:
-       mei_unregister_cdev();
-unregister_pci:
-       pci_unregister_driver(&mei_driver);
-end:
        return ret;
 }
 
@@ -1347,8 +1232,7 @@ module_init(mei_init_module);
  */
 static void __exit mei_exit_module(void)
 {
-       mei_sysfs_device_remove();
-       mei_unregister_cdev();
+       misc_deregister(&mei_misc_device);
        pci_unregister_driver(&mei_driver);
 
        pr_debug("mei: Driver unloaded successfully.\n");
index af4b1af9eeac93e833e3a41585e2654d215e3b94..13c2ba022974b6caf87df5f5551929138e13f58e 100644 (file)
 #include "mei.h"
 #include "hw.h"
 
-/*
- * MEI Char Driver Minors
- */
-#define MEI_MINORS_BASE        1
-#define MEI_MINORS_COUNT       1
-#define MEI_MINOR_NUMBER       1
-
 /*
  * watch dog definition
  */