aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-dev.c
diff options
context:
space:
mode:
authorErico Nunes <erico.nunes@datacom.ind.br>2016-05-03 14:45:43 -0400
committerWolfram Sang <wsa@the-dreams.de>2016-05-26 15:18:57 -0400
commitd6760b14d4a1243f918d983bba1e35c5a5cd5a6d (patch)
tree6d1cb31df8926bc31abc5f0154fb74f2718c5fef /drivers/i2c/i2c-dev.c
parente3879e4f3179121b1b59fd0033379d0ee700dead (diff)
i2c: dev: switch from register_chrdev to cdev API
i2c-dev had never moved away from the older register_chrdev interface to implement its char device registration. The register_chrdev API has the limitation of enabling only up to 256 i2c-dev busses to exist. Large platforms with lots of i2c devices (i.e. pluggable transceivers) with dedicated busses may have to exceed that limit. In particular, there are also platforms making use of the i2c bus multiplexing API, which instantiates a virtual bus for each possible multiplexed selection. This patch removes the register_chrdev usage and replaces it with the less old cdev API, which takes away the 256 i2c-dev bus limitation. It should not have any other impact for i2c bus drivers or user space. This patch has been tested on qemu x86 and qemu powerpc platforms with the aid of a module which adds and removes 5000 virtual i2c busses, as well as validated on an existing powerpc hardware platform which makes use of the i2c bus multiplexing API. i2c-dev busses with device minor numbers larger than 256 have also been validated to work with the existing i2c-tools. Signed-off-by: Erico Nunes <erico.nunes@datacom.ind.br> [wsa: kept includes sorted] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c/i2c-dev.c')
-rw-r--r--drivers/i2c/i2c-dev.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 0b1108d3c2f3..2562a45ff152 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -22,6 +22,7 @@
22 22
23/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */ 23/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */
24 24
25#include <linux/cdev.h>
25#include <linux/device.h> 26#include <linux/device.h>
26#include <linux/fs.h> 27#include <linux/fs.h>
27#include <linux/i2c-dev.h> 28#include <linux/i2c-dev.h>
@@ -47,9 +48,10 @@ struct i2c_dev {
47 struct list_head list; 48 struct list_head list;
48 struct i2c_adapter *adap; 49 struct i2c_adapter *adap;
49 struct device *dev; 50 struct device *dev;
51 struct cdev cdev;
50}; 52};
51 53
52#define I2C_MINORS 256 54#define I2C_MINORS MINORMASK
53static LIST_HEAD(i2c_dev_list); 55static LIST_HEAD(i2c_dev_list);
54static DEFINE_SPINLOCK(i2c_dev_list_lock); 56static DEFINE_SPINLOCK(i2c_dev_list_lock);
55 57
@@ -552,6 +554,12 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
552 if (IS_ERR(i2c_dev)) 554 if (IS_ERR(i2c_dev))
553 return PTR_ERR(i2c_dev); 555 return PTR_ERR(i2c_dev);
554 556
557 cdev_init(&i2c_dev->cdev, &i2cdev_fops);
558 i2c_dev->cdev.owner = THIS_MODULE;
559 res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
560 if (res)
561 goto error_cdev;
562
555 /* register this i2c device with the driver core */ 563 /* register this i2c device with the driver core */
556 i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, 564 i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
557 MKDEV(I2C_MAJOR, adap->nr), NULL, 565 MKDEV(I2C_MAJOR, adap->nr), NULL,
@@ -565,6 +573,8 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy)
565 adap->name, adap->nr); 573 adap->name, adap->nr);
566 return 0; 574 return 0;
567error: 575error:
576 cdev_del(&i2c_dev->cdev);
577error_cdev:
568 return_i2c_dev(i2c_dev); 578 return_i2c_dev(i2c_dev);
569 return res; 579 return res;
570} 580}
@@ -584,6 +594,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
584 594
585 return_i2c_dev(i2c_dev); 595 return_i2c_dev(i2c_dev);
586 device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); 596 device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
597 cdev_del(&i2c_dev->cdev);
587 598
588 pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); 599 pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
589 return 0; 600 return 0;
@@ -620,7 +631,7 @@ static int __init i2c_dev_init(void)
620 631
621 printk(KERN_INFO "i2c /dev entries driver\n"); 632 printk(KERN_INFO "i2c /dev entries driver\n");
622 633
623 res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops); 634 res = register_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS, "i2c");
624 if (res) 635 if (res)
625 goto out; 636 goto out;
626 637
@@ -644,7 +655,7 @@ static int __init i2c_dev_init(void)
644out_unreg_class: 655out_unreg_class:
645 class_destroy(i2c_dev_class); 656 class_destroy(i2c_dev_class);
646out_unreg_chrdev: 657out_unreg_chrdev:
647 unregister_chrdev(I2C_MAJOR, "i2c"); 658 unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
648out: 659out:
649 printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); 660 printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__);
650 return res; 661 return res;
@@ -655,7 +666,7 @@ static void __exit i2c_dev_exit(void)
655 bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier); 666 bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
656 i2c_for_each_dev(NULL, i2cdev_detach_adapter); 667 i2c_for_each_dev(NULL, i2cdev_detach_adapter);
657 class_destroy(i2c_dev_class); 668 class_destroy(i2c_dev_class);
658 unregister_chrdev(I2C_MAJOR, "i2c"); 669 unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
659} 670}
660 671
661MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " 672MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "