From: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
To: Jean Delvare <khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org>
Cc: Greg KH <greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>,
i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Subject: Re: i2c-remove-redundant-i2c_client-list.patch
Date: Mon, 14 Jan 2008 14:42:48 -0800 [thread overview]
Message-ID: <200801141442.49220.david-b@pacbell.net> (raw)
In-Reply-To: <20080110143105.456ddaf0-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
On Thursday 10 January 2008, Jean Delvare wrote:
> > (b) But don't remove that list from the deletion path until ...
> >
> > (c) ... We have a solution that removes that wait_for_completion()
> > and its infrastructure. (Note the similar i2c_adapter logic
> > too, sigh.)
> >
> > (d) Meanwhile, come up with a different solution to the deadlock
> > observed with i2c_adapter.clist ... which for some unknown
> > reason has *NOT* shown up for me with lockdep.
> >
> > Of course, if (c) happens soon soon, this problem simplifies. And
> > maybe someone will come up with a non-invasive solution to that
> > problem ... but if nobody does so before, say, Monday, I'm thinking
> > that (d) becomes a priority.
Oh, and for the record ... here's the part of $SUBJECT patch that
does (b) without (c). No (d) yet, sigh. I suspect a few of these
cleanups could become mergable with some work, but certainly not
all of them. Goes on top of what I just posted.
- Dave
============= CUT
Finish removing i2c_adapter.clients and its support.
NOTE: this has self-deadlock issues with legacy drivers. The issue
seems to be an obsolete idiom whereby code deleting devices (in i2c-core
both i2c_client and i2c_adapter nodes have this problem) waits for a
completion event as a kind of synchronization. That's problematic since
the driver model turns that kind of synchronization into a self-deadlock.
---
drivers/i2c/i2c-core.c | 126 +++++++++++++++++++++----------------------------
include/linux/i2c.h | 4 -
2 files changed, 54 insertions(+), 76 deletions(-)
--- at91.orig/drivers/i2c/i2c-core.c 2008-01-14 14:32:00.000000000 -0800
+++ at91/drivers/i2c/i2c-core.c 2008-01-14 14:32:19.000000000 -0800
@@ -275,7 +275,6 @@ EXPORT_SYMBOL_GPL(i2c_new_device);
*/
void i2c_unregister_device(struct i2c_client *client)
{
- struct i2c_adapter *adapter = client->adapter;
struct i2c_driver *driver = client->driver;
if (driver && !is_newstyle_driver(driver)) {
@@ -284,11 +283,6 @@ void i2c_unregister_device(struct i2c_cl
WARN_ON(1);
return;
}
-
- mutex_lock(&adapter->clist_lock);
- list_del(&client->list);
- mutex_unlock(&adapter->clist_lock);
-
device_unregister(&client->dev);
}
EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -400,8 +394,6 @@ static int i2c_register_adapter(struct i
int res = 0, dummy;
mutex_init(&adap->bus_lock);
- mutex_init(&adap->clist_lock);
- INIT_LIST_HEAD(&adap->clients);
mutex_lock(&core_lists);
@@ -544,6 +536,32 @@ static int i2c_do_del_adapter(struct dev
return res;
}
+
+static int detach_all_clients(struct device *dev, void *x)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_driver *driver;
+ int res;
+
+ if (!client)
+ return 0;
+
+ driver = client->driver;
+
+ /* new style, follow standard driver model */
+ if (!driver || is_newstyle_driver(driver)) {
+ i2c_unregister_device(client);
+ return 0;
+ }
+
+ /* legacy drivers create and remove clients themselves */
+ if ((res = driver->detach_client(client)))
+ dev_err(dev, "detach_client [%s] failed at address 0x%02x\n",
+ client->name, client->addr);
+
+ return res;
+}
+
/**
* i2c_del_adapter - unregister I2C adapter
* @adap: the adapter being unregistered
@@ -554,8 +572,6 @@ static int i2c_do_del_adapter(struct dev
*/
int i2c_del_adapter(struct i2c_adapter *adap)
{
- struct list_head *item, *_n;
- struct i2c_client *client;
int res = 0;
mutex_lock(&core_lists);
@@ -576,26 +592,9 @@ int i2c_del_adapter(struct i2c_adapter *
/* detach any active clients. This must be done first, because
* it can fail; in which case we give up. */
- list_for_each_safe(item, _n, &adap->clients) {
- struct i2c_driver *driver;
-
- client = list_entry(item, struct i2c_client, list);
- driver = client->driver;
-
- /* new style, follow standard driver model */
- if (!driver || is_newstyle_driver(driver)) {
- i2c_unregister_device(client);
- continue;
- }
-
- /* legacy drivers create and remove clients themselves */
- if ((res = driver->detach_client(client))) {
- dev_err(&adap->dev, "detach_client failed for client "
- "[%s] at address 0x%02x\n", client->name,
- client->addr);
- goto out_unlock;
- }
- }
+ res = device_for_each_child(&adap->dev, NULL, detach_all_clients);
+ if (res)
+ goto out_unlock;
/* clean up the sysfs representation */
init_completion(&adap->dev_released);
@@ -674,6 +673,20 @@ int i2c_register_driver(struct module *o
}
EXPORT_SYMBOL(i2c_register_driver);
+static int detach_legacy_clients(struct device *dev, void *driver)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+
+ if (client && client->driver == driver) {
+ dev_dbg(dev, "detaching client [%s] at 0x%02x\n",
+ client->name, client->addr);
+ if (client->driver->detach_client(client))
+ dev_err(dev, "failed detach_client [%s] at 0x%02x\n",
+ client->name, client->addr);
+ }
+ return 0;
+}
+
/**
* i2c_del_driver - unregister I2C driver
* @driver: the driver being unregistered
@@ -681,8 +694,6 @@ EXPORT_SYMBOL(i2c_register_driver);
*/
void i2c_del_driver(struct i2c_driver *driver)
{
- struct list_head *item2, *_n;
- struct i2c_client *client;
struct i2c_adapter *adap;
mutex_lock(&core_lists);
@@ -703,22 +714,9 @@ void i2c_del_driver(struct i2c_driver *d
"for driver [%s]\n",
driver->driver.name);
}
- } else {
- list_for_each_safe(item2, _n, &adap->clients) {
- client = list_entry(item2, struct i2c_client, list);
- if (client->driver != driver)
- continue;
- dev_dbg(&adap->dev, "detaching client [%s] "
- "at 0x%02x\n", client->name,
- client->addr);
- if (driver->detach_client(client)) {
- dev_err(&adap->dev, "detach_client "
- "failed for client [%s] at "
- "0x%02x\n", client->name,
- client->addr);
- }
- }
- }
+ } else
+ device_for_each_child(&adap->dev, driver,
+ detach_legacy_clients);
}
up(&i2c_adapter_class.sem);
@@ -752,13 +750,6 @@ int i2c_attach_client(struct i2c_client
struct i2c_adapter *adapter = client->adapter;
int res = 0;
- mutex_lock(&adapter->clist_lock);
- if (i2c_check_addr(client->adapter, client->addr)) {
- res = -EBUSY;
- goto out_unlock;
- }
- list_add_tail(&client->list,&adapter->clients);
-
client->usage_count = 0;
client->dev.parent = &client->adapter->dev;
@@ -775,12 +766,16 @@ int i2c_attach_client(struct i2c_client
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
"%d-%04x", i2c_adapter_id(adapter), client->addr);
+ res = device_register(&client->dev);
+ if (res) {
+ dev_err(&adapter->dev,
+ "Failed to register i2c client %s at 0x%02x (%d)\n",
+ client->name, client->addr, res);
+ return res;
+ }
+
dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
client->name, client->dev.bus_id);
- res = device_register(&client->dev);
- if (res)
- goto out_list;
- mutex_unlock(&adapter->clist_lock);
if (adapter->client_register) {
if (adapter->client_register(client)) {
@@ -791,14 +786,6 @@ int i2c_attach_client(struct i2c_client
}
return 0;
-
-out_list:
- list_del(&client->list);
- dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
- "(%d)\n", client->name, client->addr, res);
-out_unlock:
- mutex_unlock(&adapter->clist_lock);
- return res;
}
EXPORT_SYMBOL(i2c_attach_client);
@@ -823,11 +810,8 @@ int i2c_detach_client(struct i2c_client
}
}
- mutex_lock(&adapter->clist_lock);
- list_del(&client->list);
init_completion(&client->released);
device_unregister(&client->dev);
- mutex_unlock(&adapter->clist_lock);
wait_for_completion(&client->released);
out:
@@ -1165,7 +1149,6 @@ i2c_new_probed_device(struct i2c_adapter
return NULL;
}
- mutex_lock(&adap->clist_lock);
for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
/* Check address validity */
if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
@@ -1203,7 +1186,6 @@ i2c_new_probed_device(struct i2c_adapter
break;
}
}
- mutex_unlock(&adap->clist_lock);
if (addr_list[i] == I2C_CLIENT_END) {
dev_dbg(&adap->dev, "Probing failed, no device found\n");
--- at91.orig/include/linux/i2c.h 2008-01-14 14:32:00.000000000 -0800
+++ at91/include/linux/i2c.h 2008-01-14 14:32:19.000000000 -0800
@@ -159,7 +159,6 @@ struct i2c_driver {
* @irq: indicates the IRQ generated by this device (if any)
* @driver_name: Identifies new-style driver used with this device; also
* used as the module name for hotplug/coldplug modprobe support.
- * @list: list of active/busy clients (DEPRECATED)
* @released: used to synchronize client releases & detaches and references
*
* An i2c_client identifies a single device (i.e. chip) connected to an
@@ -179,7 +178,6 @@ struct i2c_client {
struct device dev; /* the device structure */
int irq; /* irq issued by device (or -1) */
char driver_name[KOBJ_NAME_LEN];
- struct list_head list; /* DEPRECATED */
struct completion released;
};
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -319,14 +317,12 @@ struct i2c_adapter {
/* data fields that are valid for all devices */
u8 level; /* nesting level for lockdep */
struct mutex bus_lock;
- struct mutex clist_lock;
int timeout;
int retries;
struct device dev; /* the adapter device */
int nr;
- struct list_head clients; /* DEPRECATED */
char name[48];
struct completion dev_released;
};
_______________________________________________
i2c mailing list
i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
http://lists.lm-sensors.org/mailman/listinfo/i2c
next prev parent reply other threads:[~2008-01-14 22:42 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20071216052308.A0FB11668D7@adsl-69-226-248-13.dsl.pltn13.pacbell.net>
[not found] ` <20071216052308.A0FB11668D7-ZcXrCSuhvln6VZ3dlLfH/g4gEjPzgfUyLrfjE7I9kuVHxeISYlDBzl6hYfS7NtTn@public.gmane.org>
2007-12-27 20:58 ` [patch 2.6.24-rc5-git] add i2c_new_dummy() utility Byron Bradley
[not found] ` <57e2b00712271258l6ea661ai2bfd6b9e099c71be-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2007-12-27 21:53 ` David Brownell
[not found] ` <200712271353.05857.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-12-27 22:09 ` Byron Bradley
[not found] ` <57e2b00712271409n6c98f76o45116cd92b01f396-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2007-12-27 23:06 ` David Brownell
[not found] ` <200712271506.43069.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-12-27 23:37 ` Byron Bradley
2007-12-27 23:59 ` David Brownell
[not found] ` <200712281230.17840.david-b@pacbell.net>
[not found] ` <57e2b00712281645y70f6ec74s57945dc53f113ec8@mail.gmail.com>
[not found] ` <57e2b00712281645y70f6ec74s57945dc53f113ec8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2007-12-30 3:05 ` David Brownell
[not found] ` <200712291905.15160.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-04 22:16 ` Jean Delvare
[not found] ` <20080104231633.135f2875-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-04 23:48 ` David Brownell
[not found] ` <200801041548.54825.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-06 9:57 ` Jean Delvare
2008-01-06 11:23 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080106122356.78556b8a-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-06 19:30 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801061130.31774.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-08 14:18 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080108151817.35e05c6c-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-08 16:20 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080108172001.33de6afc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-08 19:12 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801081112.46972.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-08 20:50 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080108215042.534e32fa-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-08 21:44 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801081344.45544.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-08 22:04 ` i2c-remove-redundant-i2c_client-list.patch Greg KH
[not found] ` <20080108220445.GB3873-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2008-01-08 22:27 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
2008-01-09 13:29 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080109142906.23a55f5f-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-09 16:19 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080109171934.4f894bdc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-09 21:21 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801091321.29212.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-10 13:31 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080110143105.456ddaf0-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-14 22:20 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801141420.49274.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-17 22:02 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
2008-01-18 10:14 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080118111401.7ffdccc5-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-18 10:30 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
2008-01-14 22:42 ` David Brownell [this message]
2008-01-17 19:35 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801171135.45797.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-17 19:59 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801171159.00291.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-18 9:32 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
[not found] ` <20080118103209.4b92ac76-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2008-01-18 10:16 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801180216.22363.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-18 12:10 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
2008-01-08 18:52 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801081052.31413.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-08 19:57 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
2008-01-09 16:09 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
2008-01-06 19:43 ` i2c-remove-redundant-i2c_client-list.patch David Brownell
[not found] ` <200801061143.34020.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2008-01-08 14:21 ` i2c-remove-redundant-i2c_client-list.patch Jean Delvare
2008-01-17 22:24 ` [patch 2.6.24-rc5-git] add i2c_new_dummy() utility David Brownell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200801141442.49220.david-b@pacbell.net \
--to=david-b-ybekhbn/0ldr7s880joybq@public.gmane.org \
--cc=greg-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org \
--cc=i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org \
--cc=khali-PUYAD+kWke1g9hUCZPvPmw@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.