ChangeSet 1.1082, 2003/05/06 17:16:15-07:00, kraxel at bytesex.org [PATCH] i2c #1/3: listify i2c core This is the first of tree patches for i2c. Trying to get the i2c cleanups finshed before 2.6.x, so we (hopefully) don't have a ever-changing i2c subsystem in 2.7.x again (which is very annonying for driver maintainance). Changes: * listify i2c-core, i.e. make it use <linux/list.h> instead of statically-sized arrays, removed lots of ugly code :) * added i2c_(get|put)_adapter, changed i2c-dev.c to use these functions instead maintaining is own adapter list. * killed the I2C_DF_DUMMY flag which had the strange semantics to make the i2c subsystem call driver->attach_adapter on detaches. Added a detach_adapter() callback instead. * some other minor cleanups along the way ... drivers/i2c/i2c-core.c | 325 +++++++++++++++++------------------------- drivers/i2c/i2c-dev.c | 62 +++----- drivers/media/video/dpc7146.c | 13 - drivers/media/video/mxb.c | 33 ++-- drivers/media/video/tvmixer.c | 17 +- include/linux/i2c.h | 28 ++- 6 files changed, 213 insertions(+), 265 deletions(-) diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Tue May 6 17:24:42 2003 +++ b/drivers/i2c/i2c-core.c Tue May 6 17:24:42 2003 @@ -38,8 +38,8 @@ #define DEB(x) if (i2c_debug>=1) x; #define DEB2(x) if (i2c_debug>=2) x; -static struct i2c_adapter *adapters[I2C_ADAP_MAX]; -static struct i2c_driver *drivers[I2C_DRIVER_MAX]; +static LIST_HEAD(adapters); +static LIST_HEAD(drivers); static DECLARE_MUTEX(core_lists); /**** debug level */ @@ -75,23 +75,17 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + static int nr = 0; + struct list_head *item; + struct i2c_driver *driver; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (NULL == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, - "register_adapter - enlarge I2C_ADAP_MAX.\n"); - res = -ENOMEM; - goto out_unlock; - } - adapters[i] = adap; - - init_MUTEX(&adap->bus); - init_MUTEX(&adap->list); + adap->nr = nr++; + init_MUTEX(&adap->bus_lock); + init_MUTEX(&adap->clist_lock); + list_add_tail(&adap->list,&adapters); + INIT_LIST_HEAD(&adap->clients); /* Add the adapter to the driver core. * If the parent pointer is not set up, @@ -99,77 +93,65 @@ */ if (adap->dev.parent == NULL) adap->dev.parent = &legacy_bus; - sprintf(adap->dev.bus_id, "i2c-%d", i); + sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); adap->dev.driver = &i2c_generic_driver; device_register(&adap->dev); /* inform drivers of new adapters */ - for (j=0;j<I2C_DRIVER_MAX;j++) - if (drivers[j]!=NULL && - (drivers[j]->flags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->flags & I2C_DF_NOTIFY) /* We ignore the return code; if it fails, too bad */ - drivers[j]->attach_adapter(adap); + driver->attach_adapter(adap); + } up(&core_lists); - - DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i)); - out_unlock: - up(&core_lists); - return res;; + DEB(dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr)); + return 0; } int i2c_del_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + struct list_head *item; + struct i2c_driver *driver; + struct i2c_client *client; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, "unregister_adapter adap not found.\n"); - res = -ENODEV; - goto out_unlock; - } - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - for (j = 0; j < I2C_DRIVER_MAX; j++) - if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) - if ((res = drivers[j]->attach_adapter(adap))) { + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->detach_adapter) + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "can't detach adapter" - "while detaching driver %s: driver not " - "detached!", drivers[j]->name); + "while detaching driver %s: driver not " + "detached!", driver->name); goto out_unlock; } + } /* detach any active clients. This must be done first, because * it can fail; in which case we give upp. */ - for (j=0;j<I2C_CLIENT_MAX;j++) { - struct i2c_client *client = adap->clients[j]; - if (client!=NULL) { - /* detaching devices is unconditional of the set notify - * flag, as _all_ clients that reside on the adapter - * must be deleted, as this would cause invalid states. - */ - if ((res=client->driver->detach_client(client))) { - dev_err(&adap->dev, "adapter not " - "unregistered, because client at " - "address %02x can't be detached. ", - client->addr); - goto out_unlock; - } + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + + /* detaching devices is unconditional of the set notify + * flag, as _all_ clients that reside on the adapter + * must be deleted, as this would cause invalid states. + */ + if ((res=client->driver->detach_client(client))) { + dev_err(&adap->dev, "adapter not " + "unregistered, because client at " + "address %02x can't be detached. ", + client->addr); + goto out_unlock; } } /* clean up the sysfs representation */ device_unregister(&adap->dev); - - adapters[i] = NULL; + list_del(&adap->list); DEB(dev_dbg(&adap->dev, "adapter unregistered\n")); @@ -187,24 +169,11 @@ int i2c_add_driver(struct i2c_driver *driver) { - int res = 0, i; + struct list_head *item; + struct i2c_adapter *adapter; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (NULL == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: register_driver(%s) " - "- enlarge I2C_DRIVER_MAX.\n", - driver->name); - res = -ENOMEM; - goto out_unlock; - } - - drivers[i] = driver; - - DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); /* add the driver to the list of i2c drivers in the driver core */ driver->driver.name = driver->name; @@ -216,13 +185,14 @@ if (res) goto out_unlock; - /* now look for instances of driver on our adapters - */ - if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { - for (i=0;i<I2C_ADAP_MAX;i++) { - if (adapters[i]!=NULL) - /* Ignore errors */ - driver->attach_adapter(adapters[i]); + list_add_tail(&driver->list,&drivers); + DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); + + /* now look for instances of driver on our adapters */ + if (driver->flags & I2C_DF_NOTIFY) { + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + driver->attach_adapter(adapter); } } @@ -233,44 +203,29 @@ int i2c_del_driver(struct i2c_driver *driver) { - int res = 0, i, j, k; + struct list_head *item1; + struct list_head *item2; + struct i2c_client *client; + struct i2c_adapter *adap; + + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (driver == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_driver: " - "[%s] not found\n", - driver->name); - res = -ENODEV; - goto out_unlock; - } - - driver_unregister(&driver->driver); /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n")); - /* removing clients does not depend on the notify flag, else * invalid operation might (will!) result, when using stale client * pointers. */ - for (k=0;k<I2C_ADAP_MAX;k++) { - struct i2c_adapter *adap = adapters[k]; - if (adap == NULL) /* skip empty entries. */ - continue; + list_for_each(item1,&adapters) { + adap = list_entry(item1, struct i2c_adapter, list); DEB2(dev_dbg(&adap->dev, "examining adapter\n")); - if (driver->flags & I2C_DF_DUMMY) { - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - if ((res = driver->attach_adapter(adap))) { + if (driver->detach_adapter) { + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "while unregistering " "dummy driver %s, adapter could " "not be detached properly; driver " @@ -278,31 +233,31 @@ goto out_unlock; } } else { - for (j=0;j<I2C_CLIENT_MAX;j++) { - struct i2c_client *client = adap->clients[j]; - if (client != NULL && - client->driver == driver) { - DEB2(printk(KERN_DEBUG "i2c-core.o: " - "detaching client %s:\n", - client->dev.name)); - if ((res = driver->detach_client(client))) { - dev_err(&adap->dev, "while " - "unregistering driver " - "`%s', the client at " - "address %02x of " - "adapter could not " - "be detached; driver " - "not unloaded!", - driver->name, - client->addr); - goto out_unlock; - } + list_for_each(item2,&adap->clients) { + client = list_entry(item2, struct i2c_client, list); + if (client->driver != driver) + continue; + DEB2(printk(KERN_DEBUG "i2c-core.o: " + "detaching client %s:\n", + client->dev.name)); + if ((res = driver->detach_client(client))) { + dev_err(&adap->dev, "while " + "unregistering driver " + "`%s', the client at " + "address %02x of " + "adapter could not " + "be detached; driver " + "not unloaded!", + driver->name, + client->addr); + goto out_unlock; } } } } - drivers[i] = NULL; - + + driver_unregister(&driver->driver); + list_del(&driver->list); DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name)); out_unlock: @@ -310,14 +265,16 @@ return 0; } -static int __i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - int i; + struct list_head *item; + struct i2c_client *client; - for (i = 0; i < I2C_CLIENT_MAX ; i++) - if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) + list_for_each(item,&adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) return -EBUSY; - + } return 0; } @@ -325,9 +282,9 @@ { int rval; - down(&adapter->list); + down(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->list); + up(&adapter->clist_lock); return rval; } @@ -335,28 +292,14 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int i; - - down(&adapter->list); - if (__i2c_check_addr(client->adapter, client->addr)) - goto out_unlock_list; - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (!adapter->clients[i]) - goto free_slot; + down(&adapter->clist_lock); + if (__i2c_check_addr(client->adapter, client->addr)) { + up(&adapter->clist_lock); + return -EBUSY; } - - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->dev.name); - - out_unlock_list: - up(&adapter->list); - return -EBUSY; - - free_slot: - adapter->clients[i] = client; - up(&adapter->list); + list_add_tail(&client->list,&adapter->clients); + up(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -388,7 +331,7 @@ int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int res = 0, i; + int res = 0; if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0)) return -EBUSY; @@ -403,22 +346,11 @@ } } - down(&adapter->list); - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (client == adapter->clients[i]) { - adapter->clients[i] = NULL; - goto out_unlock; - } - } - - printk(KERN_WARNING - " i2c-core.o: unregister_client [%s] not found\n", - client->dev.name); - res = -ENODEV; - - out_unlock: + down(&adapter->clist_lock); + list_del(&client->list); device_unregister(&client->dev); - up(&adapter->list); + up(&adapter->clist_lock); + out: return res; } @@ -516,9 +448,9 @@ if (adap->algo->master_xfer) { DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus); + up(&adap->bus_lock); return ret; } else { @@ -542,9 +474,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. @@ -572,9 +504,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n", ret, count, client->addr)); @@ -743,11 +675,30 @@ */ int i2c_adapter_id(struct i2c_adapter *adap) { - int i; - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - return i; - return -1; + return adap->nr; +} + +struct i2c_adapter* i2c_get_adapter(int id) +{ + struct list_head *item; + struct i2c_adapter *adapter; + + down(&core_lists); + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + if (id == adapter->nr && + try_module_get(adapter->owner)) { + up(&core_lists); + return adapter; + } + } + up(&core_lists); + return NULL; +} + +void i2c_put_adapter(struct i2c_adapter *adap) +{ + module_put(adap->owner); } /* The SMBus parts */ @@ -1189,10 +1140,10 @@ } if (adapter->algo->smbus_xfer) { - down(&adapter->bus); + down(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus); + up(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); @@ -1239,6 +1190,8 @@ EXPORT_SYMBOL(i2c_control); EXPORT_SYMBOL(i2c_transfer); EXPORT_SYMBOL(i2c_adapter_id); +EXPORT_SYMBOL(i2c_get_adapter); +EXPORT_SYMBOL(i2c_put_adapter); EXPORT_SYMBOL(i2c_probe); EXPORT_SYMBOL(i2c_smbus_xfer); diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Tue May 6 17:24:42 2003 +++ b/drivers/i2c/i2c-dev.c Tue May 6 17:24:42 2003 @@ -58,6 +58,7 @@ static int i2cdev_release (struct inode *inode, struct file *file); static int i2cdev_attach_adapter(struct i2c_adapter *adap); +static int i2cdev_detach_adapter(struct i2c_adapter *adap); static int i2cdev_detach_client(struct i2c_client *client); static int i2cdev_command(struct i2c_client *client, unsigned int cmd, void *arg); @@ -72,15 +73,13 @@ .release = i2cdev_release, }; -#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX -static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX]; - static struct i2c_driver i2cdev_driver = { .owner = THIS_MODULE, .name = "dev driver", .id = I2C_DRIVERID_I2CDEV, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = i2cdev_attach_adapter, + .detach_adapter = i2cdev_detach_adapter, .detach_client = i2cdev_detach_client, .command = i2cdev_command, }; @@ -340,35 +339,31 @@ { unsigned int minor = minor(inode->i_rdev); struct i2c_client *client; + struct i2c_adapter *adap; - if ((minor >= I2CDEV_ADAPS_MAX) || !(i2cdev_adaps[minor])) + adap = i2c_get_adapter(minor); + if (NULL == adap) return -ENODEV; client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) + if (!client) { + i2c_put_adapter(adap); return -ENOMEM; + } memcpy(client, &i2cdev_client_template, sizeof(*client)); /* registered with adapter, passed as client to user */ - client->adapter = i2cdev_adaps[minor]; + client->adapter = adap; file->private_data = client; - /* use adapter module, i2c-dev handled with fops */ - if (!try_module_get(client->adapter->owner)) - goto out_kfree; - return 0; - -out_kfree: - kfree(client); - return -ENODEV; } static int i2cdev_release(struct inode *inode, struct file *file) { struct i2c_client *client = file->private_data; - module_put(client->adapter->owner); + i2c_put_adapter(client->adapter); kfree(client); file->private_data = NULL; @@ -377,33 +372,28 @@ int i2cdev_attach_adapter(struct i2c_adapter *adap) { - int i; char name[12]; + int i; - if ((i = i2c_adapter_id(adap)) < 0) { - dev_dbg(&adap->dev, "Unknown adapter ?!?\n"); - return -ENODEV; - } - if (i >= I2CDEV_ADAPS_MAX) { - dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i); - return -ENODEV; - } - + i = i2c_adapter_id(adap); sprintf (name, "i2c/%d", i); - if (! i2cdev_adaps[i]) { - i2cdev_adaps[i] = adap; - devfs_register (NULL, name, + + devfs_register (NULL, name, DEVFS_FL_DEFAULT, I2C_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, &i2cdev_fops, NULL); - dev_dbg(&adap->dev, "Registered as minor %d\n", i); - } else { - /* This is actually a detach_adapter call! */ - devfs_remove("i2c/%d", i); - i2cdev_adaps[i] = NULL; - dev_dbg(&adap->dev, "Adapter unregistered\n"); - } + dev_dbg(&adap->dev, "Registered as minor %d\n", i); + return 0; +} + +int i2cdev_detach_adapter(struct i2c_adapter *adap) +{ + int i; + + i = i2c_adapter_id(adap); + devfs_remove("i2c/%d", i); + dev_dbg(&adap->dev, "Adapter unregistered\n"); return 0; } diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c --- a/drivers/media/video/dpc7146.c Tue May 6 17:24:42 2003 +++ b/drivers/media/video/dpc7146.c Tue May 6 17:24:42 2003 @@ -96,7 +96,8 @@ static int dpc_probe(struct saa7146_dev* dev) { struct dpc* dpc = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL); if( NULL == dpc ) { @@ -117,12 +118,10 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == dpc->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_SAA7111A == dpc->i2c_adapter.clients[i]->addr ) - dpc->saa7111a = dpc->i2c_adapter.clients[i]; + list_for_each(item,&dpc->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_SAA7111A == client->addr ) + dpc->saa7111a = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c --- a/drivers/media/video/mxb.c Tue May 6 17:24:42 2003 +++ b/drivers/media/video/mxb.c Tue May 6 17:24:42 2003 @@ -208,7 +208,8 @@ static int mxb_probe(struct saa7146_dev* dev) { struct mxb* mxb = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; request_module("tuner"); request_module("tea6420"); @@ -235,22 +236,20 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == mxb->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_1 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_2 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6415c = mxb->i2c_adapter.clients[i]; - if( I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tda9840 = mxb->i2c_adapter.clients[i]; - if( I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr ) - mxb->saa7111a = mxb->i2c_adapter.clients[i]; - if( 0x60 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tuner = mxb->i2c_adapter.clients[i]; + list_for_each(item,&mxb->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_TEA6420_1 == client->addr ) + mxb->tea6420_1 = client; + if( I2C_TEA6420_2 == client->addr ) + mxb->tea6420_2 = client; + if( I2C_TEA6415C_2 == client->addr ) + mxb->tea6415c = client; + if( I2C_TDA9840 == client->addr ) + mxb->tda9840 = client; + if( I2C_SAA7111A == client->addr ) + mxb->saa7111a = client; + if( 0x60 == client->addr ) + mxb->tuner = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c --- a/drivers/media/video/tvmixer.c Tue May 6 17:24:42 2003 +++ b/drivers/media/video/tvmixer.c Tue May 6 17:24:42 2003 @@ -217,8 +217,9 @@ .owner = THIS_MODULE, .name = "tv card mixer driver", .id = I2C_DRIVERID_TVMIXER, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, .detach_client = tvmixer_clients, }; @@ -234,14 +235,15 @@ static int tvmixer_adapters(struct i2c_adapter *adap) { - int i; + struct list_head *item; + struct i2c_client *client; if (debug) printk("tvmixer: adapter %s\n",adap->dev.name); - for (i=0; i<I2C_CLIENT_MAX; i++) { - if (!adap->clients[i]) - continue; - tvmixer_clients(adap->clients[i]); + + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + tvmixer_clients(client); } return 0; } @@ -264,7 +266,8 @@ client->adapter->dev.name); return -1; } - printk("tvmixer: debug: %s\n",client->dev.name); + if (debug) + printk("tvmixer: debug: %s\n",client->dev.name); /* unregister ?? */ for (i = 0; i < DEV_MAX; i++) { diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h --- a/include/linux/i2c.h Tue May 6 17:24:42 2003 +++ b/include/linux/i2c.h Tue May 6 17:24:42 2003 @@ -39,12 +39,6 @@ /* --- General options ------------------------------------------------ */ -#define I2C_ALGO_MAX 4 /* control memory consumption */ -#define I2C_ADAP_MAX 16 -#define I2C_DRIVER_MAX 16 -#define I2C_CLIENT_MAX 32 -#define I2C_DUMMY_MAX 4 - struct i2c_msg; struct i2c_algorithm; struct i2c_adapter; @@ -131,6 +125,7 @@ * i2c_attach_client. */ int (*attach_adapter)(struct i2c_adapter *); + int (*detach_adapter)(struct i2c_adapter *); /* tells the driver that a client is about to be deleted & gives it * the chance to remove its private data. Also, if the client struct @@ -145,6 +140,7 @@ int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); struct device_driver driver; + struct list_head list; }; #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) @@ -169,6 +165,7 @@ int usage_count; /* How many accesses currently */ /* to the client */ struct device dev; /* the device structure */ + struct list_head list; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) @@ -236,12 +233,10 @@ int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct semaphore bus; - struct semaphore list; + struct semaphore bus_lock; + struct semaphore clist_lock; unsigned int flags;/* flags specifying div. data */ - struct i2c_client *clients[I2C_CLIENT_MAX]; - int timeout; int retries; struct device dev; /* the adapter device */ @@ -250,6 +245,10 @@ /* No need to set this when you initialize the adapter */ int inode; #endif /* def CONFIG_PROC_FS */ + + int nr; + struct list_head clients; + struct list_head list; }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) @@ -265,7 +264,11 @@ /*flags for the driver struct: */ #define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */ -#define I2C_DF_DUMMY 0x02 /* do not connect any clients */ +#if 0 +/* this flag is gone -- there is a (optional) driver->detach_adapter + * callback now which can be used instead */ +# define I2C_DF_DUMMY 0x02 +#endif /*flags for the client struct: */ #define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */ @@ -352,7 +355,8 @@ * or -1 if the adapter was not registered. */ extern int i2c_adapter_id(struct i2c_adapter *adap); - +extern struct i2c_adapter* i2c_get_adapter(int id); +extern void i2c_put_adapter(struct i2c_adapter *adap); /* Return the functionality mask */