summaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2014-06-23 08:10:35 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-09 17:19:34 -0400
commitf3d8e8788b4efbd13b6e888e85af51385d87d306 (patch)
treead51362c02ae6292c4da2bb7ff88a0d02b225a36 /drivers/misc
parent7276883f1f98cd0a92fdc049f69bdc0912f7fc16 (diff)
mei: move from misc to char device
We need to support more then one mei interface hence the simple misc devices is not longer an option In order not break the user space a device with pci function 0 need to be linked to /dev/mei Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/main.c148
-rw-r--r--drivers/misc/mei/mei_dev.h9
-rw-r--r--drivers/misc/mei/pci-me.c3
-rw-r--r--drivers/misc/mei/pci-txe.c2
4 files changed, 131 insertions, 31 deletions
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 66f0a1a06451..401a3d526cd0 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -32,7 +32,6 @@
32#include <linux/compat.h> 32#include <linux/compat.h>
33#include <linux/jiffies.h> 33#include <linux/jiffies.h>
34#include <linux/interrupt.h> 34#include <linux/interrupt.h>
35#include <linux/miscdevice.h>
36 35
37#include <linux/mei.h> 36#include <linux/mei.h>
38 37
@@ -49,19 +48,12 @@
49 */ 48 */
50static int mei_open(struct inode *inode, struct file *file) 49static int mei_open(struct inode *inode, struct file *file)
51{ 50{
52 struct miscdevice *misc = file->private_data;
53 struct pci_dev *pdev;
54 struct mei_cl *cl;
55 struct mei_device *dev; 51 struct mei_device *dev;
52 struct mei_cl *cl;
56 53
57 int err; 54 int err;
58 55
59 if (!misc->parent) 56 dev = container_of(inode->i_cdev, struct mei_device, cdev);
60 return -ENODEV;
61
62 pdev = container_of(misc->parent, struct pci_dev, dev);
63
64 dev = pci_get_drvdata(pdev);
65 if (!dev) 57 if (!dev)
66 return -ENODEV; 58 return -ENODEV;
67 59
@@ -667,46 +659,148 @@ static const struct file_operations mei_fops = {
667 .llseek = no_llseek 659 .llseek = no_llseek
668}; 660};
669 661
670/* 662static struct class *mei_class;
671 * Misc Device Struct 663static dev_t mei_devt;
664#define MEI_MAX_DEVS MINORMASK
665static DEFINE_MUTEX(mei_minor_lock);
666static DEFINE_IDR(mei_idr);
667
668/**
669 * mei_minor_get - obtain next free device minor number
670 *
671 * @dev: device pointer
672 *
673 * returns allocated minor, or -ENOSPC if no free minor left
672 */ 674 */
673static struct miscdevice mei_misc_device = { 675static int mei_minor_get(struct mei_device *dev)
674 .name = "mei", 676{
675 .fops = &mei_fops, 677 int ret;
676 .minor = MISC_DYNAMIC_MINOR, 678
677}; 679 mutex_lock(&mei_minor_lock);
680 ret = idr_alloc(&mei_idr, dev, 0, MEI_MAX_DEVS, GFP_KERNEL);
681 if (ret >= 0)
682 dev->minor = ret;
683 else if (ret == -ENOSPC)
684 dev_err(&dev->pdev->dev, "too many mei devices\n");
678 685
686 mutex_unlock(&mei_minor_lock);
687 return ret;
688}
679 689
680int mei_register(struct mei_device *dev) 690/**
691 * mei_minor_free - mark device minor number as free
692 *
693 * @dev: device pointer
694 */
695static void mei_minor_free(struct mei_device *dev)
681{ 696{
682 int ret; 697 mutex_lock(&mei_minor_lock);
683 mei_misc_device.parent = &dev->pdev->dev; 698 idr_remove(&mei_idr, dev->minor);
684 ret = misc_register(&mei_misc_device); 699 mutex_unlock(&mei_minor_lock);
685 if (ret) 700}
701
702int mei_register(struct mei_device *dev, struct device *parent)
703{
704 struct device *clsdev; /* class device */
705 int ret, devno;
706
707 ret = mei_minor_get(dev);
708 if (ret < 0)
686 return ret; 709 return ret;
687 710
688 if (mei_dbgfs_register(dev, mei_misc_device.name)) 711 /* Fill in the data structures */
689 dev_err(&dev->pdev->dev, "cannot register debugfs\n"); 712 devno = MKDEV(MAJOR(mei_devt), dev->minor);
713 cdev_init(&dev->cdev, &mei_fops);
714 dev->cdev.owner = mei_fops.owner;
715
716 /* Add the device */
717 ret = cdev_add(&dev->cdev, devno, 1);
718 if (ret) {
719 dev_err(parent, "unable to add device %d:%d\n",
720 MAJOR(mei_devt), dev->minor);
721 goto err_dev_add;
722 }
723
724 clsdev = device_create(mei_class, parent, devno,
725 NULL, "mei%d", dev->minor);
726
727 if (IS_ERR(clsdev)) {
728 dev_err(parent, "unable to create device %d:%d\n",
729 MAJOR(mei_devt), dev->minor);
730 ret = PTR_ERR(clsdev);
731 goto err_dev_create;
732 }
733
734 ret = mei_dbgfs_register(dev, dev_name(clsdev));
735 if (ret) {
736 dev_err(clsdev, "cannot register debugfs ret = %d\n", ret);
737 goto err_dev_dbgfs;
738 }
690 739
691 return 0; 740 return 0;
741
742err_dev_dbgfs:
743 device_destroy(mei_class, devno);
744err_dev_create:
745 cdev_del(&dev->cdev);
746err_dev_add:
747 mei_minor_free(dev);
748 return ret;
692} 749}
693EXPORT_SYMBOL_GPL(mei_register); 750EXPORT_SYMBOL_GPL(mei_register);
694 751
695void mei_deregister(struct mei_device *dev) 752void mei_deregister(struct mei_device *dev)
696{ 753{
754 int devno;
755
756 devno = dev->cdev.dev;
757 cdev_del(&dev->cdev);
758
697 mei_dbgfs_deregister(dev); 759 mei_dbgfs_deregister(dev);
698 misc_deregister(&mei_misc_device); 760
699 mei_misc_device.parent = NULL; 761 device_destroy(mei_class, devno);
762
763 mei_minor_free(dev);
700} 764}
701EXPORT_SYMBOL_GPL(mei_deregister); 765EXPORT_SYMBOL_GPL(mei_deregister);
702 766
703static int __init mei_init(void) 767static int __init mei_init(void)
704{ 768{
705 return mei_cl_bus_init(); 769 int ret;
770
771 mei_class = class_create(THIS_MODULE, "mei");
772 if (IS_ERR(mei_class)) {
773 pr_err("couldn't create class\n");
774 ret = PTR_ERR(mei_class);
775 goto err;
776 }
777
778 ret = alloc_chrdev_region(&mei_devt, 0, MEI_MAX_DEVS, "mei");
779 if (ret < 0) {
780 pr_err("unable to allocate char dev region\n");
781 goto err_class;
782 }
783
784 ret = mei_cl_bus_init();
785 if (ret < 0) {
786 pr_err("unable to initialize bus\n");
787 goto err_chrdev;
788 }
789
790 return 0;
791
792err_chrdev:
793 unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
794err_class:
795 class_destroy(mei_class);
796err:
797 return ret;
706} 798}
707 799
708static void __exit mei_exit(void) 800static void __exit mei_exit(void)
709{ 801{
802 unregister_chrdev_region(mei_devt, MEI_MAX_DEVS);
803 class_destroy(mei_class);
710 mei_cl_bus_exit(); 804 mei_cl_bus_exit();
711} 805}
712 806
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 5c7e990e2f22..2afa3d69107d 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -400,6 +400,10 @@ struct mei_cfg {
400/** 400/**
401 * struct mei_device - MEI private device struct 401 * struct mei_device - MEI private device struct
402 402
403 * @pdev - pointer to pci device struct
404 * @cdev - character device
405 * @minor - minor number allocated for device
406 *
403 * @reset_count - limits the number of consecutive resets 407 * @reset_count - limits the number of consecutive resets
404 * @hbm_state - state of host bus message protocol 408 * @hbm_state - state of host bus message protocol
405 * @pg_event - power gating event 409 * @pg_event - power gating event
@@ -412,6 +416,9 @@ struct mei_cfg {
412 */ 416 */
413struct mei_device { 417struct mei_device {
414 struct pci_dev *pdev; /* pointer to pci device struct */ 418 struct pci_dev *pdev; /* pointer to pci device struct */
419 struct cdev cdev;
420 int minor;
421
415 /* 422 /*
416 * lists of queues 423 * lists of queues
417 */ 424 */
@@ -741,7 +748,7 @@ static inline int mei_dbgfs_register(struct mei_device *dev, const char *name)
741static inline void mei_dbgfs_deregister(struct mei_device *dev) {} 748static inline void mei_dbgfs_deregister(struct mei_device *dev) {}
742#endif /* CONFIG_DEBUG_FS */ 749#endif /* CONFIG_DEBUG_FS */
743 750
744int mei_register(struct mei_device *dev); 751int mei_register(struct mei_device *dev, struct device *parent);
745void mei_deregister(struct mei_device *dev); 752void mei_deregister(struct mei_device *dev);
746 753
747#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" 754#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d"
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1b46c64a649f..887ace14efa6 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -31,7 +31,6 @@
31#include <linux/compat.h> 31#include <linux/compat.h>
32#include <linux/jiffies.h> 32#include <linux/jiffies.h>
33#include <linux/interrupt.h> 33#include <linux/interrupt.h>
34#include <linux/miscdevice.h>
35 34
36#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
37 36
@@ -207,7 +206,7 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
207 pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT); 206 pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_ME_RPM_TIMEOUT);
208 pm_runtime_use_autosuspend(&pdev->dev); 207 pm_runtime_use_autosuspend(&pdev->dev);
209 208
210 err = mei_register(dev); 209 err = mei_register(dev, &pdev->dev);
211 if (err) 210 if (err)
212 goto release_irq; 211 goto release_irq;
213 212
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index 2343c6236df9..d7480fe8994d 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -149,7 +149,7 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
149 pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); 149 pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT);
150 pm_runtime_use_autosuspend(&pdev->dev); 150 pm_runtime_use_autosuspend(&pdev->dev);
151 151
152 err = mei_register(dev); 152 err = mei_register(dev, &pdev->dev);
153 if (err) 153 if (err)
154 goto release_irq; 154 goto release_irq;
155 155