2003-05-06 19:45:08

by Gerd Knorr

[permalink] [raw]
Subject: [patch] i2c #1/3: listify i2c core

Hi,

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 ...

Please apply,

Gerd

diff -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/drivers/i2c/i2c-core.c linux-i2c-1-2.5.69/drivers/i2c/i2c-core.c
--- linux-vanilla-2.5.69/drivers/i2c/i2c-core.c 2003-05-06 14:01:54.000000000 +0200
+++ linux-i2c-1-2.5.69/drivers/i2c/i2c-core.c 2003-05-06 13:42:07.000000000 +0200
@@ -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 -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/drivers/i2c/i2c-dev.c linux-i2c-1-2.5.69/drivers/i2c/i2c-dev.c
--- linux-vanilla-2.5.69/drivers/i2c/i2c-dev.c 2003-05-06 14:03:11.000000000 +0200
+++ linux-i2c-1-2.5.69/drivers/i2c/i2c-dev.c 2003-05-06 13:46:19.000000000 +0200
@@ -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 -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/drivers/media/video/dpc7146.c linux-i2c-1-2.5.69/drivers/media/video/dpc7146.c
--- linux-vanilla-2.5.69/drivers/media/video/dpc7146.c 2003-05-06 14:02:27.000000000 +0200
+++ linux-i2c-1-2.5.69/drivers/media/video/dpc7146.c 2003-05-06 13:55:30.000000000 +0200
@@ -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 -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/drivers/media/video/mxb.c linux-i2c-1-2.5.69/drivers/media/video/mxb.c
--- linux-vanilla-2.5.69/drivers/media/video/mxb.c 2003-05-06 14:01:35.000000000 +0200
+++ linux-i2c-1-2.5.69/drivers/media/video/mxb.c 2003-05-06 13:53:36.000000000 +0200
@@ -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 -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/drivers/media/video/tvmixer.c linux-i2c-1-2.5.69/drivers/media/video/tvmixer.c
--- linux-vanilla-2.5.69/drivers/media/video/tvmixer.c 2003-05-06 14:03:31.000000000 +0200
+++ linux-i2c-1-2.5.69/drivers/media/video/tvmixer.c 2003-05-06 13:49:59.000000000 +0200
@@ -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 -urN -X /home/kraxel/.kdontdiff linux-vanilla-2.5.69/include/linux/i2c.h linux-i2c-1-2.5.69/include/linux/i2c.h
--- linux-vanilla-2.5.69/include/linux/i2c.h 2003-05-06 14:01:56.000000000 +0200
+++ linux-i2c-1-2.5.69/include/linux/i2c.h 2003-05-06 13:41:07.000000000 +0200
@@ -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 */


2003-05-06 19:43:32

by Gerd Knorr

[permalink] [raw]
Subject: [patch] i2c #3/3: add class field to i2c_adapter

Hi,

This is the last of three patches for i2c. It introduces a new field
to i2c_adapter which classifies the kind of hardware a i2c adapter
belongs to (analog tv card / dvb card / smbus / gfx card ...). i2c chip
drivers can use this infomation to decide whenever they want to look for
hardware on that adapter or not. It doesn't make sense to probe for a
tv tuner on a smbus for example ...

Gerd

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-ali15x3.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-ali15x3.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-ali15x3.c 2003-05-06 10:22:40.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-ali15x3.c 2003-05-06 16:26:13.000000000 +0200
@@ -475,6 +475,7 @@
static struct i2c_adapter ali15x3_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.dev = {
.name = "unset",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-amd756.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-amd756.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-amd756.c 2003-05-06 10:23:29.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-amd756.c 2003-05-06 16:26:20.000000000 +0200
@@ -313,6 +313,7 @@
static struct i2c_adapter amd756_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.dev = {
.name = "unset",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-amd8111.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-amd8111.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-amd8111.c 2003-05-06 10:23:28.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-amd8111.c 2003-05-06 16:26:28.000000000 +0200
@@ -360,6 +360,7 @@
snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE,
"SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
+ smbus->adapter.class = I2C_ADAP_CLASS_SMBUS;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-i801.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-i801.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-i801.c 2003-05-06 10:22:39.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-i801.c 2003-05-06 16:16:02.000000000 +0200
@@ -547,6 +547,7 @@
static struct i2c_adapter i801_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.dev = {
.name = "unset",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-isa.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-isa.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-isa.c 2003-05-06 10:22:56.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-isa.c 2003-05-06 16:16:32.000000000 +0200
@@ -40,6 +40,7 @@
static struct i2c_adapter isa_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_ISA | I2C_HW_ISA,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &isa_algorithm,
.dev = {
.name = "ISA main adapter",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-piix4.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-piix4.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-piix4.c 2003-05-06 10:22:23.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-piix4.c 2003-05-06 16:17:10.000000000 +0200
@@ -395,6 +395,7 @@
static struct i2c_adapter piix4_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.dev = {
.name = "unset",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-viapro.c linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-viapro.c
--- linux-i2c-2-2.5.69/drivers/i2c/busses/i2c-viapro.c 2003-05-06 10:23:11.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/busses/i2c-viapro.c 2003-05-06 16:17:50.000000000 +0200
@@ -295,6 +295,7 @@
static struct i2c_adapter vt596_adapter = {
.owner = THIS_MODULE,
.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2,
+ .class = I2C_ADAP_CLASS_SMBUS,
.algo = &smbus_algorithm,
.dev = {
.name = "unset",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/chips/adm1021.c linux-i2c-3-2.5.69/drivers/i2c/chips/adm1021.c
--- linux-i2c-2-2.5.69/drivers/i2c/chips/adm1021.c 2003-05-06 13:34:18.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/chips/adm1021.c 2003-05-06 16:19:02.000000000 +0200
@@ -203,6 +203,8 @@

static int adm1021_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+ return 0;
return i2c_detect(adapter, &addr_data, adm1021_detect);
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/chips/it87.c linux-i2c-3-2.5.69/drivers/i2c/chips/it87.c
--- linux-i2c-2-2.5.69/drivers/i2c/chips/it87.c 2003-05-06 13:34:27.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/chips/it87.c 2003-05-06 16:19:19.000000000 +0200
@@ -525,6 +525,8 @@
* when a new adapter is inserted (and it87_driver is still present) */
static int it87_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+ return 0;
return i2c_detect(adapter, &addr_data, it87_detect);
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/chips/lm75.c linux-i2c-3-2.5.69/drivers/i2c/chips/lm75.c
--- linux-i2c-2-2.5.69/drivers/i2c/chips/lm75.c 2003-05-06 13:34:42.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/chips/lm75.c 2003-05-06 16:19:29.000000000 +0200
@@ -121,6 +121,8 @@

static int lm75_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+ return 0;
return i2c_detect(adapter, &addr_data, lm75_detect);
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/chips/via686a.c linux-i2c-3-2.5.69/drivers/i2c/chips/via686a.c
--- linux-i2c-2-2.5.69/drivers/i2c/chips/via686a.c 2003-05-06 13:34:50.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/chips/via686a.c 2003-05-06 16:19:37.000000000 +0200
@@ -661,6 +661,8 @@
/* This is called when the module is loaded */
static int via686a_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+ return 0;
return i2c_detect(adapter, &addr_data, via686a_detect);
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/i2c/chips/w83781d.c linux-i2c-3-2.5.69/drivers/i2c/chips/w83781d.c
--- linux-i2c-2-2.5.69/drivers/i2c/chips/w83781d.c 2003-05-06 13:35:02.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/i2c/chips/w83781d.c 2003-05-06 16:19:48.000000000 +0200
@@ -1026,6 +1026,8 @@
static int
w83781d_attach_adapter(struct i2c_adapter *adapter)
{
+ if (!(adapter->class & I2C_ADAP_CLASS_SMBUS))
+ return 0;
return i2c_detect(adapter, &addr_data, w83781d_detect);
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/bt832.c linux-i2c-3-2.5.69/drivers/media/video/bt832.c
--- linux-i2c-2-2.5.69/drivers/media/video/bt832.c 2003-05-06 10:23:11.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/bt832.c 2003-05-06 17:21:42.000000000 +0200
@@ -198,25 +198,9 @@

static int bt832_probe(struct i2c_adapter *adap)
{
- int rc;
-
- printk("bt832_probe\n");
-
- switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
- printk("bt832: probing %s i2c adapter [id=0x%x]\n",
- adap->name,adap->id);
- rc = i2c_probe(adap, &addr_data, bt832_attach);
- break;
- default:
- printk("bt832: ignoring %s i2c adapter [id=0x%x]\n",
- adap->name,adap->id);
- rc = 0;
- /* nothing */
- }
- return rc;
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, bt832_attach);
+ return 0;
}

static int bt832_detach(struct i2c_client *client)
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/bttv-if.c linux-i2c-3-2.5.69/drivers/media/video/bttv-if.c
--- linux-i2c-2-2.5.69/drivers/media/video/bttv-if.c 2003-05-06 16:57:13.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/bttv-if.c 2003-05-06 17:54:00.000000000 +0200
@@ -233,6 +233,7 @@
.owner = THIS_MODULE,
I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
.client_register = attach_inform,
};

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/msp3400.c linux-i2c-3-2.5.69/drivers/media/video/msp3400.c
--- linux-i2c-2-2.5.69/drivers/media/video/msp3400.c 2003-05-06 13:33:40.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/msp3400.c 2003-05-06 17:21:50.000000000 +0200
@@ -1372,7 +1372,7 @@

static int msp_probe(struct i2c_adapter *adap)
{
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, msp_attach);
return 0;
}
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/saa5249.c linux-i2c-3-2.5.69/drivers/media/video/saa5249.c
--- linux-i2c-2-2.5.69/drivers/media/video/saa5249.c 2003-05-06 10:23:11.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/saa5249.c 2003-05-06 17:21:57.000000000 +0200
@@ -224,12 +224,8 @@

static int saa5249_probe(struct i2c_adapter *adap)
{
- /* Only attach these chips to the BT848 bus for now */
-
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
- {
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, saa5249_attach);
- }
return 0;
}

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c linux-i2c-3-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-i2c-2-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c 2003-05-06 16:51:55.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c 2003-05-06 17:54:33.000000000 +0200
@@ -336,6 +336,7 @@
.owner = THIS_MODULE,
I2C_DEVNAME("saa7134"),
.id = I2C_ALGO_SAA7134,
+ .class = I2C_ADAP_CLASS_TV_ANALOG,
.algo = &saa7134_algo,
.client_register = attach_inform,
};
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tda7432.c linux-i2c-3-2.5.69/drivers/media/video/tda7432.c
--- linux-i2c-2-2.5.69/drivers/media/video/tda7432.c 2003-05-06 13:33:24.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tda7432.c 2003-05-06 17:22:02.000000000 +0200
@@ -340,7 +340,7 @@

static int tda7432_probe(struct i2c_adapter *adap)
{
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda7432_attach);
return 0;
}
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tda9875.c linux-i2c-3-2.5.69/drivers/media/video/tda9875.c
--- linux-i2c-2-2.5.69/drivers/media/video/tda9875.c 2003-05-06 13:33:14.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tda9875.c 2003-05-06 17:22:08.000000000 +0200
@@ -273,7 +273,7 @@

static int tda9875_probe(struct i2c_adapter *adap)
{
- if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tda9875_attach);
return 0;
}
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tda9887.c linux-i2c-3-2.5.69/drivers/media/video/tda9887.c
--- linux-i2c-2-2.5.69/drivers/media/video/tda9887.c 2003-05-06 10:21:50.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tda9887.c 2003-05-06 17:22:15.000000000 +0200
@@ -368,23 +368,9 @@

static int tda9887_probe(struct i2c_adapter *adap)
{
- int rc;
-
- switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
- printk("tda9887: probing %s i2c adapter [id=0x%x]\n",
- adap->dev.name,adap->id);
- rc = i2c_probe(adap, &addr_data, tda9887_attach);
- break;
- default:
- printk("tda9887: ignoring %s i2c adapter [id=0x%x]\n",
- adap->dev.name,adap->id);
- rc = 0;
- /* nothing */
- }
- return rc;
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, tda9887_attach);
+ return 0;
}

static int tda9887_detach(struct i2c_client *client)
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tuner.c linux-i2c-3-2.5.69/drivers/media/video/tuner.c
--- linux-i2c-2-2.5.69/drivers/media/video/tuner.c 2003-05-06 13:31:03.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tuner.c 2003-05-06 17:22:22.000000000 +0200
@@ -817,29 +817,15 @@

static int tuner_probe(struct i2c_adapter *adap)
{
- int rc;
-
if (0 != addr) {
normal_i2c_range[0] = addr;
normal_i2c_range[1] = addr;
}
this_adap = 0;
- switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- case I2C_ALGO_SAA7134:
- case I2C_ALGO_SAA7146:
- printk("tuner: probing %s i2c adapter [id=0x%x]\n",
- adap->dev.name,adap->id);
- rc = i2c_probe(adap, &addr_data, tuner_attach);
- break;
- default:
- printk("tuner: ignoring %s i2c adapter [id=0x%x]\n",
- adap->dev.name,adap->id);
- rc = 0;
- /* nothing */
- }
- return rc;
+
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
+ return i2c_probe(adap, &addr_data, tuner_attach);
+ return 0;
}

static int tuner_detach(struct i2c_client *client)
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tvaudio.c linux-i2c-3-2.5.69/drivers/media/video/tvaudio.c
--- linux-i2c-2-2.5.69/drivers/media/video/tvaudio.c 2003-05-06 13:33:33.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tvaudio.c 2003-05-06 17:22:29.000000000 +0200
@@ -1408,14 +1408,9 @@

static int chip_probe(struct i2c_adapter *adap)
{
- switch (adap->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
+ if (adap->class & I2C_ADAP_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, chip_attach);
- default:
- /* ignore this i2c bus */
- return 0;
- }
+ return 0;
}

static int chip_detach(struct i2c_client *client)
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/drivers/media/video/tvmixer.c linux-i2c-3-2.5.69/drivers/media/video/tvmixer.c
--- linux-i2c-2-2.5.69/drivers/media/video/tvmixer.c 2003-05-06 13:49:59.000000000 +0200
+++ linux-i2c-3-2.5.69/drivers/media/video/tvmixer.c 2003-05-06 17:28:37.000000000 +0200
@@ -254,12 +254,7 @@
int i,minor;

/* TV card ??? */
- switch (client->adapter->id) {
- case I2C_ALGO_BIT | I2C_HW_B_BT848:
- case I2C_ALGO_BIT | I2C_HW_B_RIVA:
- /* ok, have a look ... */
- break;
- default:
+ if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG)) {
/* ignore that one */
if (debug)
printk("tvmixer: %s is not a tv card\n",
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-2-2.5.69/include/linux/i2c.h linux-i2c-3-2.5.69/include/linux/i2c.h
--- linux-i2c-2-2.5.69/include/linux/i2c.h 2003-05-06 14:03:04.000000000 +0200
+++ linux-i2c-3-2.5.69/include/linux/i2c.h 2003-05-06 16:07:50.000000000 +0200
@@ -225,6 +225,7 @@
struct module *owner;
unsigned int id;/* == is algo->id | hwdep.struct->id, */
/* for registered values see below */
+ unsigned int class;
struct i2c_algorithm *algo;/* the algorithm to access the bus */
void *algo_data;

@@ -278,6 +279,12 @@
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */

+/* i2c adapter classes (bitmask) */
+#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
+#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
+#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2) /* dbv cards */
+#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+
/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the
* command line

2003-05-06 19:42:58

by Gerd Knorr

[permalink] [raw]
Subject: [patch] i2c #2/3: add i2c_clients_command

Hi,

This is the second of three patches for i2c.

Changes:

* adds a i2c_clients_command() function to i2c-core which calls
the ->command() callback of all clients attached to a adapter.
* make bttv + saa7134 drivers use that function instead of mucking
with the i2c_adapter struct themself.

Please apply,

Gerd

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/drivers/i2c/i2c-core.c linux-i2c-2-2.5.69/drivers/i2c/i2c-core.c
--- linux-i2c-1-2.5.69/drivers/i2c/i2c-core.c 2003-05-06 13:42:07.000000000 +0200
+++ linux-i2c-2-2.5.69/drivers/i2c/i2c-core.c 2003-05-06 16:25:40.000000000 +0200
@@ -411,6 +411,27 @@
return 0;
}

+void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
+{
+ struct list_head *item;
+ struct i2c_client *client;
+
+ down(&adap->clist_lock);
+ list_for_each(item,&adap->clients) {
+ client = list_entry(item, struct i2c_client, list);
+ if (!try_module_get(client->driver->owner))
+ continue;
+ if (NULL != client->driver->command) {
+ up(&adap->clist_lock);
+ client->driver->command(client,cmd,arg);
+ down(&adap->clist_lock);
+ }
+ module_put(client->driver->owner);
+ }
+ up(&adap->clist_lock);
+}
+
+
/* match always succeeds, as we want the probe() to tell if we really accept this match */
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
@@ -1183,6 +1204,7 @@
EXPORT_SYMBOL(i2c_detach_client);
EXPORT_SYMBOL(i2c_use_client);
EXPORT_SYMBOL(i2c_release_client);
+EXPORT_SYMBOL(i2c_clients_command);
EXPORT_SYMBOL(i2c_check_addr);

EXPORT_SYMBOL(i2c_master_send);
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/drivers/media/video/bttv-if.c linux-i2c-2-2.5.69/drivers/media/video/bttv-if.c
--- linux-i2c-1-2.5.69/drivers/media/video/bttv-if.c 2003-05-06 10:22:00.000000000 +0200
+++ linux-i2c-2-2.5.69/drivers/media/video/bttv-if.c 2003-05-06 16:57:13.000000000 +0200
@@ -7,7 +7,7 @@

Copyright (C) 1996,97,98 Ralph Metzler ([email protected])
& Marcus Metzler ([email protected])
- (c) 1999,2000 Gerd Knorr <[email protected]>
+ (c) 1999-2003 Gerd Knorr <[email protected]>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -195,51 +195,21 @@
static int attach_inform(struct i2c_client *client)
{
struct bttv *btv = i2c_get_adapdata(client->adapter);
- int i;

- for (i = 0; i < I2C_CLIENTS_MAX; i++) {
- if (btv->i2c_clients[i] == NULL) {
- btv->i2c_clients[i] = client;
- break;
- }
- }
- if (btv->tuner_type != -1)
+ if (btv->tuner_type != UNSET)
bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
- if (bttv_verbose)
- printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr,
- client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
- return 0;
-}
-
-static int detach_inform(struct i2c_client *client)
-{
- struct bttv *btv = i2c_get_adapdata(client->adapter);
- int i;

- for (i = 0; i < I2C_CLIENTS_MAX; i++) {
- if (btv->i2c_clients[i] == client) {
- btv->i2c_clients[i] = NULL;
- break;
- }
- }
- if (bttv_verbose)
- printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr,
- client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed");
+ if (bttv_debug)
+ printk("bttv%d: i2c attach [client=%s]\n",
+ btv->nr, i2c_clientname(client));
return 0;
}

void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg)
{
- int i;
-
- for (i = 0; i < I2C_CLIENTS_MAX; i++) {
- if (NULL == btv->i2c_clients[i])
- continue;
- if (NULL == btv->i2c_clients[i]->driver->command)
- continue;
- btv->i2c_clients[i]->driver->command(
- btv->i2c_clients[i],cmd,arg);
- }
+ if (0 != btv->i2c_rc)
+ return;
+ i2c_clients_command(&btv->i2c_adap, cmd, arg);
}

void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg)
@@ -260,20 +230,15 @@
};

static struct i2c_adapter bttv_i2c_adap_template = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
+ I2C_DEVNAME("bt848"),
.id = I2C_HW_B_BT848,
.client_register = attach_inform,
- .client_unregister = detach_inform,
- .dev = {
- .name = "bt848",
- },
};

static struct i2c_client bttv_i2c_client_template = {
- .id = -1,
- .dev = {
- .name = "bttv internal",
- },
+ I2C_DEVNAME("bttv internal"),
+ .id = -1,
};


@@ -347,8 +312,8 @@
memcpy(&btv->i2c_client, &bttv_i2c_client_template,
sizeof(struct i2c_client));

- sprintf(btv->i2c_adap.dev.name+strlen(btv->i2c_adap.dev.name),
- " #%d", btv->nr);
+ sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr);
+
btv->i2c_algo.data = btv;
i2c_set_adapdata(&btv->i2c_adap, btv);
btv->i2c_adap.algo_data = &btv->i2c_algo;
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/drivers/media/video/bttv.h linux-i2c-2-2.5.69/drivers/media/video/bttv.h
--- linux-i2c-1-2.5.69/drivers/media/video/bttv.h 2003-05-06 10:22:00.000000000 +0200
+++ linux-i2c-2-2.5.69/drivers/media/video/bttv.h 2003-05-06 17:00:34.000000000 +0200
@@ -243,7 +243,6 @@


/* i2c */
-#define I2C_CLIENTS_MAX 16
extern void bttv_bit_setscl(void *data, int state);
extern void bttv_bit_setsda(void *data, int state);
extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/drivers/media/video/bttvp.h linux-i2c-2-2.5.69/drivers/media/video/bttvp.h
--- linux-i2c-1-2.5.69/drivers/media/video/bttvp.h 2003-05-06 10:22:26.000000000 +0200
+++ linux-i2c-2-2.5.69/drivers/media/video/bttvp.h 2003-05-06 16:55:01.000000000 +0200
@@ -62,6 +62,8 @@
#define RAW_LINES 640
#define RAW_BPL 1024

+#define UNSET (-1U)
+
/* ---------------------------------------------------------- */

struct bttv_tvnorm
@@ -276,7 +278,6 @@
struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client;
int i2c_state, i2c_rc;
- struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];

/* video4linux (1) */
struct video_device video_dev;
diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c linux-i2c-2-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c
--- linux-i2c-1-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c 2003-05-06 10:22:02.000000000 +0200
+++ linux-i2c-2-2.5.69/drivers/media/video/saa7134/saa7134-i2c.c 2003-05-06 16:51:55.000000000 +0200
@@ -334,19 +334,15 @@

static struct i2c_adapter saa7134_adap_template = {
.owner = THIS_MODULE,
+ I2C_DEVNAME("saa7134"),
.id = I2C_ALGO_SAA7134,
.algo = &saa7134_algo,
.client_register = attach_inform,
- .dev = {
- .name = "saa7134",
- },
};

static struct i2c_client saa7134_client_template = {
- .id = -1,
- .dev = {
- .name = "saa7134 internal",
- },
+ I2C_DEVNAME("saa7134 internal"),
+ .id = -1,
};

/* ----------------------------------------------------------- */
@@ -399,22 +395,13 @@
void saa7134_i2c_call_clients(struct saa7134_dev *dev,
unsigned int cmd, void *arg)
{
- int i;
-
- for (i = 0; i < I2C_CLIENT_MAX; i++) {
- if (NULL == dev->i2c_adap.clients[i])
- continue;
- if (NULL == dev->i2c_adap.clients[i]->driver->command)
- continue;
- dev->i2c_adap.clients[i]->driver->command
- (dev->i2c_adap.clients[i],cmd,arg);
- }
+ i2c_clients_command(&dev->i2c_adap, cmd, arg);
}

int saa7134_i2c_register(struct saa7134_dev *dev)
{
dev->i2c_adap = saa7134_adap_template;
- strncpy(dev->i2c_adap.dev.name, dev->name, DEVICE_NAME_SIZE);
+ strcpy(dev->i2c_adap.dev.name,dev->name);
dev->i2c_adap.algo_data = dev;
i2c_add_adapter(&dev->i2c_adap);

diff -urN -X /home/kraxel/.kdontdiff linux-i2c-1-2.5.69/include/linux/i2c.h linux-i2c-2-2.5.69/include/linux/i2c.h
--- linux-i2c-1-2.5.69/include/linux/i2c.h 2003-05-06 13:41:07.000000000 +0200
+++ linux-i2c-2-2.5.69/include/linux/i2c.h 2003-05-06 14:03:04.000000000 +0200
@@ -334,6 +334,11 @@
extern int i2c_use_client(struct i2c_client *);
extern int i2c_release_client(struct i2c_client *);

+/* call the i2c_client->command() of all attached clients with
+ * the given arguments */
+extern void i2c_clients_command(struct i2c_adapter *adap,
+ unsigned int cmd, void *arg);
+
/* returns -EBUSY if address has been taken, 0 if not. Note that the only
other place at which this is called is within i2c_attach_client; so
you can cheat by simply not registering. Not recommended, of course! */

2003-05-07 00:03:45

by Greg KH

[permalink] [raw]
Subject: Re: [patch] i2c #1/3: listify i2c core

On Tue, May 06, 2003 at 09:34:30PM +0200, Gerd Knorr wrote:
> Hi,
>
> 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).

Thanks for the patches, I've applied all three to my tree, and fixed up
a small compile error if DEBUG is enabled. I'll send them all on to
Linus in a bit, with some other i2c changes.

thanks,

greg k-h

2003-05-07 10:01:52

by Mark McClelland

[permalink] [raw]
Subject: Re: [patch] i2c #3/3: add class field to i2c_adapter


Add I2C classes for analog and digital cameras, and fix a typo.

diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h Wed May 7 01:29:59 2003
+++ b/include/linux/i2c.h Wed May 7 01:29:59 2003
@@ -280,10 +280,12 @@
/* Must equal I2C_M_TEN below */

/* i2c adapter classes (bitmask) */
-#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
-#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
-#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2) /* dbv cards */
-#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */
+#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */
+#define I2C_ADAP_CLASS_TV_DIGITAL (1<<2) /* dbv cards */
+#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */
+#define I2C_ADAP_CLASS_CAM_ANALOG (1<<4) /* camera with analog CCD */
+#define I2C_ADAP_CLASS_CAM_DIGITAL (1<<5) /* most webcams */

/* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the


Attachments:
i2c_adap_class_cam-2.5.69.patch (1.13 kB)

2003-05-09 21:46:40

by Greg KH

[permalink] [raw]
Subject: Re: [patch] i2c #3/3: add class field to i2c_adapter

On Wed, May 07, 2003 at 03:12:56AM -0700, Mark McClelland wrote:
> I've attached a patch that adds classes for analog and digital cameras
> (webcams, etc...). I plan to submit one such driver in the next few days.
>
> The patch also fixes a typo ("DIGINAL").

I've applied this, thanks.

greg k-h