i2c #1/3: listify i2c core

i2c #1/3: listify i2c core

Post by Gerd Knor » Wed, 07 May 2003 22:10:08



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

read more »

 
 
 

i2c #1/3: listify i2c core

Post by Greg K » Thu, 08 May 2003 02:20:10



>   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
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

1. [I2C] fix unsafe usage of list_for_each in i2c-core

Hi,

i2c-core.c contains 2 loops that iterate over the list of the clients attached
to an adapter and detaches them. Detaching the clients will actually remove
them from the list the loop is iterating over. Therefore the
list_for_each_safe() method has to be used.

Andreas

===== i2c-core.c 1.38 vs edited =====
--- 1.38/drivers/i2c/i2c-core.c Mon May 26 02:00:00 2003

 int i2c_del_adapter(struct i2c_adapter *adap)
 {
-       struct list_head  *item;
+       struct list_head  *item, *_n;
        struct i2c_driver *driver;
        struct i2c_client *client;

        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give upp. */
-       list_for_each(item,&adap->clients) {
+       list_for_each_safe(item, _n, &adap->clients) {
                client = list_entry(item, struct i2c_client, list);


 int i2c_del_driver(struct i2c_driver *driver)
 {
-       struct list_head   *item1;
-       struct list_head   *item2;
+       struct list_head   *item1, *item2, *_n;
        struct i2c_client  *client;
        struct i2c_adapter *adap;

                                goto out_unlock;
                        }
                } else {
-                       list_for_each(item2,&adap->clients) {
+                       list_for_each_safe(item2, _n, &adap->clients) {
                                client = list_entry(item2, struct i2c_client, list);
                                if (client->driver != driver)
                                        continue;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

2. class action against SCO?

3. Four new i2c drivers and __init/__exit cleanup to i2c

4. replace filename with string in way that can fool apps that require a filename

5. 2.5.36 i2c new adapter i2c-pport driver

6. Removing W95 :-) Installing RedHat

7. Four new i2c drivers and __init/__exit cleanup to i2c

8. gimp