aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/i2c-dev.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6e90dec02567..206e8052f90f 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -32,6 +32,7 @@
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/smp_lock.h> 33#include <linux/smp_lock.h>
34#include <linux/init.h> 34#include <linux/init.h>
35#include <linux/list.h>
35#include <linux/i2c.h> 36#include <linux/i2c.h>
36#include <linux/i2c-dev.h> 37#include <linux/i2c-dev.h>
37#include <asm/uaccess.h> 38#include <asm/uaccess.h>
@@ -39,21 +40,27 @@
39static struct i2c_client i2cdev_client_template; 40static struct i2c_client i2cdev_client_template;
40 41
41struct i2c_dev { 42struct i2c_dev {
43 struct list_head list;
42 struct i2c_adapter *adap; 44 struct i2c_adapter *adap;
43 struct class_device *class_dev; 45 struct class_device *class_dev;
44}; 46};
45 47
46#define I2C_MINORS 256 48#define I2C_MINORS 256
47static struct i2c_dev *i2c_dev_array[I2C_MINORS]; 49static LIST_HEAD(i2c_dev_list);
48static DEFINE_SPINLOCK(i2c_dev_array_lock); 50static DEFINE_SPINLOCK(i2c_dev_list_lock);
49 51
50static struct i2c_dev *i2c_dev_get_by_minor(unsigned index) 52static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
51{ 53{
52 struct i2c_dev *i2c_dev; 54 struct i2c_dev *i2c_dev;
53 55
54 spin_lock(&i2c_dev_array_lock); 56 spin_lock(&i2c_dev_list_lock);
55 i2c_dev = i2c_dev_array[index]; 57 list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
56 spin_unlock(&i2c_dev_array_lock); 58 if (i2c_dev->adap->nr == index)
59 goto found;
60 }
61 i2c_dev = NULL;
62found:
63 spin_unlock(&i2c_dev_list_lock);
57 return i2c_dev; 64 return i2c_dev;
58} 65}
59 66
@@ -61,30 +68,28 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
61{ 68{
62 struct i2c_dev *i2c_dev; 69 struct i2c_dev *i2c_dev;
63 70
71 if (adap->nr >= I2C_MINORS) {
72 printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
73 adap->nr);
74 return ERR_PTR(-ENODEV);
75 }
76
64 i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL); 77 i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
65 if (!i2c_dev) 78 if (!i2c_dev)
66 return ERR_PTR(-ENOMEM); 79 return ERR_PTR(-ENOMEM);
67
68 spin_lock(&i2c_dev_array_lock);
69 if (i2c_dev_array[adap->nr]) {
70 spin_unlock(&i2c_dev_array_lock);
71 dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
72 goto error;
73 }
74 i2c_dev->adap = adap; 80 i2c_dev->adap = adap;
75 i2c_dev_array[adap->nr] = i2c_dev; 81
76 spin_unlock(&i2c_dev_array_lock); 82 spin_lock(&i2c_dev_list_lock);
83 list_add_tail(&i2c_dev->list, &i2c_dev_list);
84 spin_unlock(&i2c_dev_list_lock);
77 return i2c_dev; 85 return i2c_dev;
78error:
79 kfree(i2c_dev);
80 return ERR_PTR(-ENODEV);
81} 86}
82 87
83static void return_i2c_dev(struct i2c_dev *i2c_dev) 88static void return_i2c_dev(struct i2c_dev *i2c_dev)
84{ 89{
85 spin_lock(&i2c_dev_array_lock); 90 spin_lock(&i2c_dev_list_lock);
86 i2c_dev_array[i2c_dev->adap->nr] = NULL; 91 list_del(&i2c_dev->list);
87 spin_unlock(&i2c_dev_array_lock); 92 spin_unlock(&i2c_dev_list_lock);
88} 93}
89 94
90static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) 95static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)