X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fi2c%2Fi2c-dev.c;h=7e13d2df9af384f0b048faa36c427171dab30fa0;hb=d706834d995939c96b4952bf042918879b4db18b;hp=206e8052f90fdf3bd90788b857284f6139d37298;hpb=f3b3aadbbd66d8a020550b01b37d9b1ea559f2c3;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 206e805..7e13d2d 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -1,5 +1,5 @@ /* - i2c-dev.c - i2c-bus driver, char device interface + i2c-dev.c - i2c-bus driver, char device interface Copyright (C) 1995-97 Simon G. Vogl Copyright (C) 1998-99 Frodo Looijaard @@ -30,19 +30,29 @@ #include #include #include -#include #include #include #include #include +#include +#include #include -static struct i2c_client i2cdev_client_template; +static struct i2c_driver i2cdev_driver; +/* + * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a + * slave (i2c_client) with which messages will be exchanged. It's coupled + * with a character special file which is accessed by user mode drivers. + * + * The list of i2c_dev structures is parallel to the i2c_adapter lists + * maintained by the driver model, and is updated using notifications + * delivered to the i2cdev_driver. + */ struct i2c_dev { struct list_head list; struct i2c_adapter *adap; - struct class_device *class_dev; + struct device *dev; }; #define I2C_MINORS 256 @@ -90,17 +100,38 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) spin_lock(&i2c_dev_list_lock); list_del(&i2c_dev->list); spin_unlock(&i2c_dev_list_lock); + kfree(i2c_dev); } -static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) +static ssize_t show_adapter_name(struct device *dev, + struct device_attribute *attr, char *buf) { - struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt)); + struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(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); +static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); + +/* ------------------------------------------------------------------------- */ + +/* + * After opening an instance of this character special file, a file + * descriptor starts out associated only with an i2c_adapter (and bus). + * + * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg + * traffic to any devices on the bus used by that adapter. That's because + * the i2c_msg vectors embed all the addressing information they need, and + * are submitted directly to an i2c_adapter. However, SMBus-only adapters + * don't support that interface. + * + * To use read()/write() system calls on that file descriptor, or to use + * SMBus interfaces (and work with SMBus-only hosts!), you must first issue + * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous + * (never registered) i2c_client so it holds the addressing information + * needed by those system calls and by this SMBus interface. + */ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, loff_t *offset) @@ -117,8 +148,8 @@ static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, if (tmp==NULL) return -ENOMEM; - pr_debug("i2c-dev: i2c-%d reading %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_recv(client,tmp,count); if (ret >= 0) @@ -145,24 +176,201 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c return -EFAULT; } - pr_debug("i2c-dev: i2c-%d writing %zd bytes.\n", - iminor(file->f_dentry->d_inode), count); + pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", + iminor(file->f_path.dentry->d_inode), count); ret = i2c_master_send(client,tmp,count); kfree(tmp); return ret; } -static int i2cdev_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int i2cdev_check(struct device *dev, void *addrp) +{ + struct i2c_client *client = i2c_verify_client(dev); + + if (!client || client->addr != *(unsigned int *)addrp) + return 0; + + return dev->driver ? -EBUSY : 0; +} + +/* This address checking function differs from the one in i2c-core + in that it considers an address with a registered device, but no + driver bound to it, as NOT busy. */ +static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) +{ + return device_for_each_child(&adapter->dev, &addr, i2cdev_check); +} + +static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, + 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 __user **data_ptrs; - int i,datasize,res; + int i, res; + + if (copy_from_user(&rdwr_arg, + (struct i2c_rdwr_ioctl_data __user *)arg, + sizeof(rdwr_arg))) + return -EFAULT; + + /* 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; + + rdwr_pa = (struct i2c_msg *) + kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), + GFP_KERNEL); + if (!rdwr_pa) + return -ENOMEM; + + if (copy_from_user(rdwr_pa, rdwr_arg.msgs, + rdwr_arg.nmsgs * sizeof(struct i2c_msg))) { + kfree(rdwr_pa); + return -EFAULT; + } + + data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); + if (data_ptrs == NULL) { + kfree(rdwr_pa); + return -ENOMEM; + } + + res = 0; + for (i = 0; i < rdwr_arg.nmsgs; i++) { + /* Limit the size of the message to a sane amount; + * and don't let length change either. */ + if ((rdwr_pa[i].len > 8192) || + (rdwr_pa[i].flags & I2C_M_RECV_LEN)) { + res = -EINVAL; + break; + } + 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; + break; + } + if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], + rdwr_pa[i].len)) { + ++i; /* Needs to be kfreed too */ + res = -EFAULT; + break; + } + } + if (res < 0) { + int j; + for (j = 0; j < i; ++j) + kfree(rdwr_pa[j].buf); + kfree(data_ptrs); + kfree(rdwr_pa); + return res; + } + + res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); + while (i-- > 0) { + if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { + if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, + rdwr_pa[i].len)) + res = -EFAULT; + } + kfree(rdwr_pa[i].buf); + } + kfree(data_ptrs); + kfree(rdwr_pa); + return res; +} + +static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, + unsigned long arg) +{ + struct i2c_smbus_ioctl_data data_arg; + union i2c_smbus_data temp; + int datasize, res; + + if (copy_from_user(&data_arg, + (struct i2c_smbus_ioctl_data __user *) arg, + sizeof(struct i2c_smbus_ioctl_data))) + return -EFAULT; + if ((data_arg.size != I2C_SMBUS_BYTE) && + (data_arg.size != I2C_SMBUS_QUICK) && + (data_arg.size != I2C_SMBUS_BYTE_DATA) && + (data_arg.size != I2C_SMBUS_WORD_DATA) && + (data_arg.size != I2C_SMBUS_PROC_CALL) && + (data_arg.size != I2C_SMBUS_BLOCK_DATA) && + (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && + (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && + (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { + dev_dbg(&client->adapter->dev, + "size out of range (%x) in ioctl I2C_SMBUS.\n", + data_arg.size); + return -EINVAL; + } + /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, + so the check is valid if size==I2C_SMBUS_QUICK too. */ + if ((data_arg.read_write != I2C_SMBUS_READ) && + (data_arg.read_write != I2C_SMBUS_WRITE)) { + dev_dbg(&client->adapter->dev, + "read_write out of range (%x) in ioctl I2C_SMBUS.\n", + data_arg.read_write); + return -EINVAL; + } + + /* Note that command values are always valid! */ + + if ((data_arg.size == I2C_SMBUS_QUICK) || + ((data_arg.size == I2C_SMBUS_BYTE) && + (data_arg.read_write == I2C_SMBUS_WRITE))) + /* These are special: we do not use data */ + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags, data_arg.read_write, + data_arg.command, data_arg.size, NULL); + + if (data_arg.data == NULL) { + dev_dbg(&client->adapter->dev, + "data is NULL pointer in ioctl I2C_SMBUS.\n"); + return -EINVAL; + } + + if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || + (data_arg.size == I2C_SMBUS_BYTE)) + datasize = sizeof(data_arg.data->byte); + else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || + (data_arg.size == I2C_SMBUS_PROC_CALL)) + datasize = sizeof(data_arg.data->word); + else /* size == smbus block, i2c block, or block proc. call */ + datasize = sizeof(data_arg.data->block); + + if ((data_arg.size == I2C_SMBUS_PROC_CALL) || + (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || + (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || + (data_arg.read_write == I2C_SMBUS_WRITE)) { + if (copy_from_user(&temp, data_arg.data, datasize)) + return -EFAULT; + } + if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { + /* Convert old I2C block commands to the new + convention. This preserves binary compatibility. */ + data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; + if (data_arg.read_write == I2C_SMBUS_READ) + temp.block[0] = I2C_SMBUS_BLOCK_MAX; + } + res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + data_arg.read_write, data_arg.command, data_arg.size, &temp); + if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || + (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || + (data_arg.read_write == I2C_SMBUS_READ))) { + if (copy_to_user(data_arg.data, &temp, datasize)) + return -EFAULT; + } + return res; +} + +static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct i2c_client *client = (struct i2c_client *)file->private_data; unsigned long funcs; dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", @@ -171,11 +379,22 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, switch ( cmd ) { case I2C_SLAVE: case I2C_SLAVE_FORCE: - if ((arg > 0x3ff) || + /* NOTE: devices set up to work with "new style" drivers + * can't use I2C_SLAVE, even when the device node is not + * bound to a driver. Only I2C_SLAVE_FORCE will work. + * + * Setting the PEC flag here won't affect kernel drivers, + * which will be using the i2c_client node registered with + * the driver model core. Likewise, when that client has + * the PEC flag already set, the i2c-dev driver won't see + * (or use) this setting. + */ + if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) return -EINVAL; - if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg)) + if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) return -EBUSY; + /* REVISIT: address could become busy later */ client->addr = arg; return 0; case I2C_TENBIT: @@ -192,160 +411,30 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file, return 0; case I2C_FUNCS: funcs = i2c_get_functionality(client->adapter); - return (copy_to_user((unsigned long __user *)arg, &funcs, - sizeof(unsigned long)))?-EFAULT:0; + return put_user(funcs, (unsigned long __user *)arg); case I2C_RDWR: - if (copy_from_user(&rdwr_arg, - (struct i2c_rdwr_ioctl_data __user *)arg, - sizeof(rdwr_arg))) - return -EFAULT; - - /* 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; - - rdwr_pa = (struct i2c_msg *) - kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), - GFP_KERNEL); - - if (rdwr_pa == NULL) return -ENOMEM; - - if (copy_from_user(rdwr_pa, rdwr_arg.msgs, - rdwr_arg.nmsgs * sizeof(struct i2c_msg))) { - kfree(rdwr_pa); - return -EFAULT; - } - - data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); - if (data_ptrs == NULL) { - kfree(rdwr_pa); - return -ENOMEM; - } - - res = 0; - for( i=0; i 8192) { - res = -EINVAL; - break; - } - 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; - break; - } - if(copy_from_user(rdwr_pa[i].buf, - data_ptrs[i], - rdwr_pa[i].len)) { - ++i; /* Needs to be kfreed too */ - res = -EFAULT; - break; - } - } - if (res < 0) { - int j; - for (j = 0; j < i; ++j) - kfree(rdwr_pa[j].buf); - kfree(data_ptrs); - kfree(rdwr_pa); - return res; - } - - res = i2c_transfer(client->adapter, - rdwr_pa, - rdwr_arg.nmsgs); - while(i-- > 0) { - if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD)) { - if(copy_to_user( - data_ptrs[i], - rdwr_pa[i].buf, - rdwr_pa[i].len)) { - res = -EFAULT; - } - } - kfree(rdwr_pa[i].buf); - } - kfree(data_ptrs); - kfree(rdwr_pa); - return res; + return i2cdev_ioctl_rdrw(client, arg); case I2C_SMBUS: - if (copy_from_user(&data_arg, - (struct i2c_smbus_ioctl_data __user *) arg, - sizeof(struct i2c_smbus_ioctl_data))) - return -EFAULT; - if ((data_arg.size != I2C_SMBUS_BYTE) && - (data_arg.size != I2C_SMBUS_QUICK) && - (data_arg.size != I2C_SMBUS_BYTE_DATA) && - (data_arg.size != I2C_SMBUS_WORD_DATA) && - (data_arg.size != I2C_SMBUS_PROC_CALL) && - (data_arg.size != I2C_SMBUS_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { - dev_dbg(&client->adapter->dev, - "size out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.size); - return -EINVAL; - } - /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, - so the check is valid if size==I2C_SMBUS_QUICK too. */ - if ((data_arg.read_write != I2C_SMBUS_READ) && - (data_arg.read_write != I2C_SMBUS_WRITE)) { - dev_dbg(&client->adapter->dev, - "read_write out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.read_write); - return -EINVAL; - } - - /* Note that command values are always valid! */ - - if ((data_arg.size == I2C_SMBUS_QUICK) || - ((data_arg.size == I2C_SMBUS_BYTE) && - (data_arg.read_write == I2C_SMBUS_WRITE))) - /* These are special: we do not use data */ - return i2c_smbus_xfer(client->adapter, client->addr, - client->flags, - data_arg.read_write, - data_arg.command, - data_arg.size, NULL); - - if (data_arg.data == NULL) { - dev_dbg(&client->adapter->dev, - "data is NULL pointer in ioctl I2C_SMBUS.\n"); - return -EINVAL; - } - - if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || - (data_arg.size == I2C_SMBUS_BYTE)) - datasize = sizeof(data_arg.data->byte); - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || - (data_arg.size == I2C_SMBUS_PROC_CALL)) - datasize = sizeof(data_arg.data->word); - else /* size == smbus block, i2c block, or block proc. call */ - datasize = sizeof(data_arg.data->block); - - if ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_WRITE)) { - if (copy_from_user(&temp, data_arg.data, datasize)) - return -EFAULT; - } - res = i2c_smbus_xfer(client->adapter,client->addr,client->flags, - data_arg.read_write, - data_arg.command,data_arg.size,&temp); - if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_READ))) { - if (copy_to_user(data_arg.data, &temp, datasize)) - return -EFAULT; - } - return res; - + return i2cdev_ioctl_smbus(client, arg); + + case I2C_RETRIES: + client->adapter->retries = arg; + break; + case I2C_TIMEOUT: + /* For historical reasons, user-space sets the timeout + * value in units of 10 ms. + */ + client->adapter->timeout = msecs_to_jiffies(arg * 10); + break; default: - return i2c_control(client,cmd,arg); + /* NOTE: returning a fault code here could cause trouble + * in buggy userspace code. Some old kernel bugs returned + * zero in this case, and userspace code might accidentally + * have depended on that bug. + */ + return -ENOTTY; } return 0; } @@ -356,27 +445,43 @@ static int i2cdev_open(struct inode *inode, struct file *file) struct i2c_client *client; struct i2c_adapter *adap; struct i2c_dev *i2c_dev; + int ret = 0; + lock_kernel(); i2c_dev = i2c_dev_get_by_minor(minor); - if (!i2c_dev) - return -ENODEV; + if (!i2c_dev) { + ret = -ENODEV; + goto out; + } adap = i2c_get_adapter(i2c_dev->adap->nr); - if (!adap) - return -ENODEV; + if (!adap) { + ret = -ENODEV; + goto out; + } - client = kmalloc(sizeof(*client), GFP_KERNEL); + /* This creates an anonymous i2c_client, which may later be + * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE. + * + * This client is ** NEVER REGISTERED ** with the driver model + * or I2C core code!! It just holds private copies of addressing + * information and maybe a PEC flag. + */ + client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client) { i2c_put_adapter(adap); - return -ENOMEM; + ret = -ENOMEM; + goto out; } - memcpy(client, &i2cdev_client_template, sizeof(*client)); + snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); + client->driver = &i2cdev_driver; - /* registered with adapter, passed as client to user */ client->adapter = adap; file->private_data = client; - return 0; +out: + unlock_kernel(); + return ret; } static int i2cdev_release(struct inode *inode, struct file *file) @@ -390,42 +495,55 @@ static int i2cdev_release(struct inode *inode, struct file *file) return 0; } -static struct file_operations i2cdev_fops = { +static const struct file_operations i2cdev_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .read = i2cdev_read, .write = i2cdev_write, - .ioctl = i2cdev_ioctl, + .unlocked_ioctl = i2cdev_ioctl, .open = i2cdev_open, .release = i2cdev_release, }; +/* ------------------------------------------------------------------------- */ + +/* + * The legacy "i2cdev_driver" is used primarily to get notifications when + * I2C adapters are added or removed, so that each one gets an i2c_dev + * and is thus made available to userspace driver code. + */ + static struct class *i2c_dev_class; static int i2cdev_attach_adapter(struct i2c_adapter *adap) { struct i2c_dev *i2c_dev; + int res; i2c_dev = get_free_i2c_dev(adap); if (IS_ERR(i2c_dev)) return PTR_ERR(i2c_dev); - pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", - adap->name, adap->nr); - /* register this i2c device with the driver core */ - i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, - MKDEV(I2C_MAJOR, adap->nr), - &adap->dev, "i2c-%d", - adap->nr); - if (!i2c_dev->class_dev) + i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, + MKDEV(I2C_MAJOR, adap->nr), NULL, + "i2c-%d", adap->nr); + if (IS_ERR(i2c_dev->dev)) { + res = PTR_ERR(i2c_dev->dev); goto error; - class_device_create_file(i2c_dev->class_dev, &class_device_attr_name); + } + res = device_create_file(i2c_dev->dev, &dev_attr_name); + if (res) + goto error_destroy; + + pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", + adap->name, adap->nr); return 0; +error_destroy: + device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); error: return_i2c_dev(i2c_dev); - kfree(i2c_dev); - return -ENODEV; + return res; } static int i2cdev_detach_adapter(struct i2c_adapter *adap) @@ -433,37 +551,30 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) struct i2c_dev *i2c_dev; i2c_dev = i2c_dev_get_by_minor(adap->nr); - if (!i2c_dev) - return -ENODEV; + if (!i2c_dev) /* attach_adapter must have failed */ + return 0; + device_remove_file(i2c_dev->dev, &dev_attr_name); return_i2c_dev(i2c_dev); - class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); - kfree(i2c_dev); + device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); return 0; } -static int i2cdev_detach_client(struct i2c_client *client) -{ - return 0; -} - static struct i2c_driver i2cdev_driver = { .driver = { .name = "dev_driver", }, - .id = I2C_DRIVERID_I2CDEV, .attach_adapter = i2cdev_attach_adapter, .detach_adapter = i2cdev_detach_adapter, - .detach_client = i2cdev_detach_client, }; -static struct i2c_client i2cdev_client_template = { - .name = "I2C /dev entry", - .addr = -1, - .driver = &i2cdev_driver, -}; +/* ------------------------------------------------------------------------- */ + +/* + * module load/unload record keeping + */ static int __init i2c_dev_init(void) { @@ -476,8 +587,10 @@ static int __init i2c_dev_init(void) goto out; i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); - if (IS_ERR(i2c_dev_class)) + if (IS_ERR(i2c_dev_class)) { + res = PTR_ERR(i2c_dev_class); goto out_unreg_chrdev; + } res = i2c_add_driver(&i2cdev_driver); if (res)