[char-misc-next 1/3] mei: move from misc to char device

From: Tomas Winkler
Date: Tue May 13 2014 - 04:24:35 EST


From: Alexander Usyskin <alexander.usyskin@xxxxxxxxx>

We need to support more then one mei interface
hence the simple misc devices is not longer an option.
We use char device now with to not break application
space we preserve /dev/mei for the first interface.

Signed-off-by: Alexander Usyskin <alexander.usyskin@xxxxxxxxx>
Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx>
---
drivers/misc/mei/main.c | 98 +++++++++++++++++++++++++++++++++-------------
drivers/misc/mei/mei_dev.h | 7 ++++
drivers/misc/mei/pci-me.c | 1 -
3 files changed, 78 insertions(+), 28 deletions(-)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 66f0a1a..c58e059 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -32,7 +32,6 @@
#include <linux/compat.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
-#include <linux/miscdevice.h>

#include <linux/mei.h>

@@ -49,19 +48,12 @@
*/
static int mei_open(struct inode *inode, struct file *file)
{
- struct miscdevice *misc = file->private_data;
- struct pci_dev *pdev;
struct mei_cl *cl;
struct mei_device *dev;

int err;

- if (!misc->parent)
- return -ENODEV;
-
- pdev = container_of(misc->parent, struct pci_dev, dev);
-
- dev = pci_get_drvdata(pdev);
+ dev = container_of(inode->i_cdev, struct mei_device, cdev);
if (!dev)
return -ENODEV;

@@ -667,26 +659,48 @@ static const struct file_operations mei_fops = {
.llseek = no_llseek
};

-/*
- * Misc Device Struct
- */
-static struct miscdevice mei_misc_device = {
- .name = "mei",
- .fops = &mei_fops,
- .minor = MISC_DYNAMIC_MINOR,
-};
-
+static struct class *mei_class;
+static dev_t mei_devt;
+#define MAX_MEI_DEVS 5 /* Maximum number of mei devices */

int mei_register(struct mei_device *dev)
{
- int ret;
- mei_misc_device.parent = &dev->pdev->dev;
- ret = misc_register(&mei_misc_device);
- if (ret)
+
+ int ret, devno;
+ int id = 0; /* FIXME: retrieve interface version*/
+
+ /* Fill in the data structures */
+ devno = MKDEV(MAJOR(mei_devt), id);
+ cdev_init(&dev->cdev, &mei_fops);
+ dev->cdev.owner = mei_fops.owner;
+
+ /* Add the device */
+ ret = cdev_add(&dev->cdev, devno, 1);
+ if (ret) {
+ dev_err(&dev->pdev->dev, "mei%d unable to add device %d:%d\n",
+ id, MAJOR(mei_devt), id);
+ return ret;
+ }
+
+ /* Preserve /dev/mei for the first interface */
+ if (id)
+ dev->dev = device_create(mei_class, NULL, devno,
+ NULL, "mei%d", id);
+ else
+ dev->dev = device_create(mei_class, NULL, devno,
+ NULL, "mei");
+
+ if (IS_ERR(dev->dev)) {
+ dev_err(&dev->pdev->dev, "mei%d unable to create device %d:%d\n",
+ id, MAJOR(mei_devt), id);
+ cdev_del(&dev->cdev);
+ ret = PTR_ERR(dev->dev);
return ret;
+ }

- if (mei_dbgfs_register(dev, mei_misc_device.name))
- dev_err(&dev->pdev->dev, "cannot register debugfs\n");
+ ret = mei_dbgfs_register(dev, dev->dev->kobj.name);
+ if (ret)
+ dev_err(dev->dev, "cannot register debugfs ret = %d\n", ret);

return 0;
}
@@ -694,19 +708,49 @@ EXPORT_SYMBOL_GPL(mei_register);

void mei_deregister(struct mei_device *dev)
{
+ int devno;
+
+ devno = dev->cdev.dev;
+ cdev_del(&dev->cdev);
+
mei_dbgfs_deregister(dev);
- misc_deregister(&mei_misc_device);
- mei_misc_device.parent = NULL;
+
+ device_destroy(mei_class, devno);
}
EXPORT_SYMBOL_GPL(mei_deregister);

static int __init mei_init(void)
{
- return mei_cl_bus_init();
+ int ret;
+
+ mei_class = class_create(THIS_MODULE, "mei");
+ if (IS_ERR(mei_class)) {
+ pr_err("couldn't create class\n");
+ return PTR_ERR(mei_class);
+ }
+
+ ret = alloc_chrdev_region(&mei_devt, 0, MAX_MEI_DEVS, "mei");
+ if (ret < 0) {
+ pr_err("unable to allocate char dev region\n");
+ goto err;
+ }
+
+ ret = mei_cl_bus_init();
+ if (ret < 0) {
+ pr_err("unable to initialize bus\n");
+ goto err;
+ }
+
+ return 0;
+err:
+ class_destroy(mei_class);
+ return ret;
}

static void __exit mei_exit(void)
{
+ unregister_chrdev_region(mei_devt, MAX_MEI_DEVS);
+ class_destroy(mei_class);
mei_cl_bus_exit();
}

diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 5c7e990..a418565 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -400,6 +400,10 @@ struct mei_cfg {
/**
* struct mei_device - MEI private device struct

+ * @pdev - pointer to pci device struct
+ * @cdev - character device
+ * @dev - pointer to device object
+ *
* @reset_count - limits the number of consecutive resets
* @hbm_state - state of host bus message protocol
* @pg_event - power gating event
@@ -412,6 +416,9 @@ struct mei_cfg {
*/
struct mei_device {
struct pci_dev *pdev; /* pointer to pci device struct */
+ struct cdev cdev;
+ struct device *dev;
+
/*
* lists of queues
*/
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 1b46c64..cf4f654 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -31,7 +31,6 @@
#include <linux/compat.h>
#include <linux/jiffies.h>
#include <linux/interrupt.h>
-#include <linux/miscdevice.h>

#include <linux/pm_runtime.h>

--
1.9.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/