X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fi2c%2Fi2c-dev.c;h=58ccddd5c237dd5823140da8857691ed9780cc9f;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=a0a4aa15aa971051e05c2f89cb2c04ee2ee7a23e;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index a0a4aa15a..58ccddd5c 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -26,19 +26,15 @@ /* The I2C_RDWR ioctl code is written by Kolja Waschk */ -/* The devfs code is contributed by Philipp Matthias Hahn - */ - -#include #include #include #include #include #include -#include #include #include #include +#include #include static struct i2c_client i2cdev_client_template; @@ -46,16 +42,15 @@ static struct i2c_client i2cdev_client_template; struct i2c_dev { int minor; struct i2c_adapter *adap; - struct class_device class_dev; - struct completion released; /* FIXME, we need a class_device_unregister() */ + struct class_device *class_dev; }; #define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev) #define I2C_MINORS 256 static struct i2c_dev *i2c_dev_array[I2C_MINORS]; -static spinlock_t i2c_dev_array_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(i2c_dev_array_lock); -struct i2c_dev *i2c_dev_get_by_minor(unsigned index) +static struct i2c_dev *i2c_dev_get_by_minor(unsigned index) { struct i2c_dev *i2c_dev; @@ -65,7 +60,7 @@ struct i2c_dev *i2c_dev_get_by_minor(unsigned index) return i2c_dev; } -struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap) +static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap) { struct i2c_dev *i2c_dev = NULL; @@ -81,10 +76,9 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap) { struct i2c_dev *i2c_dev; - i2c_dev = kmalloc(sizeof(*i2c_dev), GFP_KERNEL); + i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) return ERR_PTR(-ENOMEM); - memset(i2c_dev, 0x00, sizeof(*i2c_dev)); spin_lock(&i2c_dev_array_lock); if (i2c_dev_array[adap->nr]) { @@ -108,16 +102,12 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) spin_unlock(&i2c_dev_array_lock); } -static ssize_t show_dev(struct class_device *class_dev, char *buf) -{ - struct i2c_dev *i2c_dev = to_i2c_dev(class_dev); - return print_dev_t(buf, MKDEV(I2C_MAJOR, i2c_dev->minor)); -} -static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); - static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) { - struct i2c_dev *i2c_dev = to_i2c_dev(class_dev); + struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt)); + + if (!i2c_dev) + return -ENODEV; return sprintf(buf, "%s\n", i2c_dev->adap->name); } static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); @@ -173,20 +163,20 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c return ret; } -int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int i2cdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { struct i2c_client *client = (struct i2c_client *)file->private_data; struct i2c_rdwr_ioctl_data rdwr_arg; struct i2c_smbus_ioctl_data data_arg; union i2c_smbus_data temp; struct i2c_msg *rdwr_pa; - u8 **data_ptrs; + u8 __user **data_ptrs; int i,datasize,res; unsigned long funcs; - dev_dbg(&client->adapter->dev, "i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", - iminor(inode),cmd, arg); + dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", + cmd, arg); switch ( cmd ) { case I2C_SLAVE: @@ -221,7 +211,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, sizeof(rdwr_arg))) return -EFAULT; - /* Put an arbritrary limit on the number of messages that can + /* Put an arbitrary limit on the number of messages that can * be sent at once */ if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) return -EINVAL; @@ -238,8 +228,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, return -EFAULT; } - data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *), - GFP_KERNEL); + data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); if (data_ptrs == NULL) { kfree(rdwr_pa); return -ENOMEM; @@ -252,7 +241,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, res = -EINVAL; break; } - data_ptrs[i] = rdwr_pa[i].buf; + data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); if(rdwr_pa[i].buf == NULL) { res = -ENOMEM; @@ -421,48 +410,34 @@ static struct file_operations i2cdev_fops = { .release = i2cdev_release, }; -static void release_i2c_dev(struct class_device *dev) -{ - struct i2c_dev *i2c_dev = to_i2c_dev(dev); - complete(&i2c_dev->released); -} - -static struct class i2c_dev_class = { - .name = "i2c-dev", - .release = &release_i2c_dev, -}; +static struct class *i2c_dev_class; static int i2cdev_attach_adapter(struct i2c_adapter *adap) { struct i2c_dev *i2c_dev; - int retval; + struct device *dev; i2c_dev = get_free_i2c_dev(adap); if (IS_ERR(i2c_dev)) return PTR_ERR(i2c_dev); - devfs_mk_cdev(MKDEV(I2C_MAJOR, i2c_dev->minor), - S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i2c_dev->minor); - dev_dbg(&adap->dev, "Registered as minor %d\n", i2c_dev->minor); + pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", + adap->name, i2c_dev->minor); /* register this i2c device with the driver core */ i2c_dev->adap = adap; - if (adap->dev.parent == &platform_bus) - i2c_dev->class_dev.dev = &adap->dev; - else - i2c_dev->class_dev.dev = adap->dev.parent; - i2c_dev->class_dev.class = &i2c_dev_class; - snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor); - retval = class_device_register(&i2c_dev->class_dev); - if (retval) + dev = &adap->dev; + i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, + MKDEV(I2C_MAJOR, i2c_dev->minor), + dev, "i2c-%d", i2c_dev->minor); + if (!i2c_dev->class_dev) goto error; - class_device_create_file(&i2c_dev->class_dev, &class_device_attr_dev); - class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name); + class_device_create_file(i2c_dev->class_dev, &class_device_attr_name); return 0; error: return_i2c_dev(i2c_dev); kfree(i2c_dev); - return retval; + return -ENODEV; } static int i2cdev_detach_adapter(struct i2c_adapter *adap) @@ -473,14 +448,11 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) if (!i2c_dev) return -ENODEV; - init_completion(&i2c_dev->released); - devfs_remove("i2c/%d", i2c_dev->minor); return_i2c_dev(i2c_dev); - class_device_unregister(&i2c_dev->class_dev); - wait_for_completion(&i2c_dev->released); + class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor)); kfree(i2c_dev); - dev_dbg(&adap->dev, "Adapter unregistered\n"); + pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); return 0; } @@ -489,26 +461,18 @@ static int i2cdev_detach_client(struct i2c_client *client) return 0; } -static int i2cdev_command(struct i2c_client *client, unsigned int cmd, - void *arg) -{ - return -1; -} - static struct i2c_driver i2cdev_driver = { - .owner = THIS_MODULE, - .name = "dev_driver", + .driver = { + .name = "dev_driver", + }, .id = I2C_DRIVERID_I2CDEV, - .flags = I2C_DF_NOTIFY, .attach_adapter = i2cdev_attach_adapter, .detach_adapter = i2cdev_detach_adapter, .detach_client = i2cdev_detach_client, - .command = i2cdev_command, }; static struct i2c_client i2cdev_client_template = { .name = "I2C /dev entry", - .id = 1, .addr = -1, .driver = &i2cdev_driver, }; @@ -519,27 +483,33 @@ static int __init i2c_dev_init(void) printk(KERN_INFO "i2c /dev entries driver\n"); - if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) { - printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n", - I2C_MAJOR); - return -EIO; - } - devfs_mk_dir("i2c"); - class_register(&i2c_dev_class); - if ((res = i2c_add_driver(&i2cdev_driver))) { - printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n"); - devfs_remove("i2c"); - unregister_chrdev(I2C_MAJOR,"i2c"); - return res; - } + res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops); + if (res) + goto out; + + i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); + if (IS_ERR(i2c_dev_class)) + goto out_unreg_chrdev; + + res = i2c_add_driver(&i2cdev_driver); + if (res) + goto out_unreg_class; + return 0; + +out_unreg_class: + class_destroy(i2c_dev_class); +out_unreg_chrdev: + unregister_chrdev(I2C_MAJOR, "i2c"); +out: + printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); + return res; } static void __exit i2c_dev_exit(void) { i2c_del_driver(&i2cdev_driver); - class_unregister(&i2c_dev_class); - devfs_remove("i2c"); + class_destroy(i2c_dev_class); unregister_chrdev(I2C_MAJOR,"i2c"); }