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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox