* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility
@ 2007-12-22 17:31 Jean Delvare
[not found] ` <kOXVGr9s.1198344701.9162110.khali-IO4AeUl/lkuWVfeAwA7xHQ@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Jean Delvare @ 2007-12-22 17:31 UTC (permalink / raw)
To: david-b-yBeKhBN/0LDR7s880joybQ; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA
Hi David,
Sorry for the non-threaded reply, I do not have access to the original
post at the moment.
David Brownell wrote:
> This adds a i2c_new_dummy() primitive to help work with devices
> that consume multiple addresses, which include many I2C eeproms
> and at least one RTC.
>
> Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
> ---
> [ Apologies for the duplicate message some of you may have seen. ]
>
> Tested with a 24c00 EEPROM ... that's the 16-byte one, which
> ignores a0/a1/a2 and thus consumes 8 addresses.
>
> drivers/i2c/i2c-core.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-
> include/linux/i2c.h | 6 ++++
> 2 files changed, 65 insertions(+), 1 deletion(-)
>
> --- a/drivers/i2c/i2c-core.c 2007-12-15 20:57:54.000000000 -0800
> +++ b/drivers/i2c/i2c-core.c 2007-12-15 21:01:22.000000000 -0800
> @@ -276,6 +276,51 @@ void i2c_unregister_device(struct i2c_cl
> EXPORT_SYMBOL_GPL(i2c_unregister_device);
>
>
> +static int dummy_nop(struct i2c_client *client)
> +{
> + return 0;
> +}
> +
> +static struct i2c_driver dummy_driver = {
> + .driver.name = "dummy",
> + .probe = dummy_nop,
> + .remove = dummy_nop,
> +};
> +
> +
> +/**
> + * i2c_new_dummy - return a new i2c device bound to a dummy driver
> + * @adapter: the adapter managing the device
> + * @address: seven bit address to be used
> + * @type: optional label used for i2c_client.name
Do you have a use case in mind for this feature?
> + * Context: can sleep
> + *
> + * This returns an I2C client bound to the "dummy" driver, intended for use
> + * with devices that consume multiple addresses. Examples of such chips
> + * include various EEPROMS (like 24c04 and 24c08 models).
> + *
> + * These dummy devices have two main uses. First, most I2C and SMBus calls
> + * except i2c_transfer() need a client handle; the dummy will be that handle.
> + * And second, this prevents the specified address from being bound to a
> + * different driver.
> + *
> + * This returns the new i2c client, which may be saved for later use with
> + * i2c_unregister_device(); or NULL to indicate an error.
I'd say it _should_ be saved. Calling i2c_unregister_device() is pretty
much mandatory, unless the driver can't be built as a module.
> + */
> +struct i2c_client *
> +i2c_new_dummy(struct i2c_adapter *adapter, unsigned address, const char *type)
The rest of i2c-core uses an unsigned short for addresses, maybe do the
same here for consistency?
> +{
> + struct i2c_board_info info = {
> + .driver_name = "dummy",
> + .addr = address,
> + };
> +
> + if (type)
> + strncpy(info.type, type, sizeof info.type);
Please use strlcpy() instead, strncpy() is error-prone.
> + return i2c_new_device(adapter, &info);
> +}
> +EXPORT_SYMBOL_GPL(i2c_new_dummy);
> +
> /* ------------------------------------------------------------------------- */
>
> /* I2C bus adapters -- one roots each I2C or SMBUS segment */
> @@ -848,11 +893,24 @@ static int __init i2c_init(void)
> retval = bus_register(&i2c_bus_type);
> if (retval)
> return retval;
> - return class_register(&i2c_adapter_class);
> + retval = class_register(&i2c_adapter_class);
> + if (retval)
> + goto bus_err;
> + retval = i2c_add_driver(&dummy_driver);
> + if (retval)
> + goto class_err;
> + return 0;
> +
> +class_err:
> + class_unregister(&i2c_adapter_class);
> +bus_err:
> + bus_unregister(&i2c_bus_type);
> + return retval;
> }
Thanks for fixing a broken error path...
>
> static void __exit i2c_exit(void)
> {
> + i2c_del_driver(&dummy_driver);
> class_unregister(&i2c_adapter_class);
> bus_unregister(&i2c_bus_type);
> }
> --- a/include/linux/i2c.h 2007-12-15 20:57:54.000000000 -0800
> +++ b/include/linux/i2c.h 2007-12-15 21:01:22.000000000 -0800
> @@ -261,6 +261,12 @@ i2c_new_probed_device(struct i2c_adapter
> struct i2c_board_info *info,
> unsigned short const *addr_list);
>
> +/* For devices that use several addresses, use i2c_new_dummy() to make
> + * client handles for the exta addresses.
Typo: extra.
> + */
> +extern struct i2c_client *
> +i2c_new_dummy(struct i2c_adapter *adap, unsigned address, const char *type);
> +
> extern void i2c_unregister_device(struct i2c_client *);
>
> /* Mainboard arch_initcall() code should register all its I2C devices.
>
Other than that the patch looks just fine. Please respin it and I'll
apply it.
Thanks,
--
Jean Delvare
^ permalink raw reply [flat|nested] 15+ messages in thread[parent not found: <kOXVGr9s.1198344701.9162110.khali-IO4AeUl/lkuWVfeAwA7xHQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <kOXVGr9s.1198344701.9162110.khali-IO4AeUl/lkuWVfeAwA7xHQ@public.gmane.org> @ 2007-12-23 5:08 ` David Brownell [not found] ` <200712222108.51292.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2007-12-23 5:08 UTC (permalink / raw) To: Jean Delvare; +Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Saturday 22 December 2007, Jean Delvare wrote: > > +/** > > + * i2c_new_dummy - return a new i2c device bound to a dummy driver > > + * @adapter: the adapter managing the device > > + * @address: seven bit address to be used > > + * @type: optional label used for i2c_client.name > > Do you have a use case in mind for this feature? You mean the "type" field? In the at24.c driver I posted, it's the same name used with the "real" i2c_client node. That helps make sense of just what the "dummy" is for; sysfs can show it. Being tied to a "dummy" driver is not very explanatory. > > + * This returns the new i2c client, which may be saved for later use with > > + * i2c_unregister_device(); or NULL to indicate an error. > > I'd say it _should_ be saved. Calling i2c_unregister_device() is pretty > much mandatory, unless the driver can't be built as a module. OK by me, "which should be saved". > > + */ > > +struct i2c_client * > > +i2c_new_dummy(struct i2c_adapter *adapter, unsigned address, const char *type) > > The rest of i2c-core uses an unsigned short for addresses, maybe do the > same here for consistency? It's promoted by C! But no problem. I'll make it u16 to match the SMBus calls and struct i2c_msg ... and be more concise, still fitting on one line. > > +{ > > + struct i2c_board_info info = { > > + .driver_name = "dummy", > > + .addr = address, > > + }; > > + > > + if (type) > > + strncpy(info.type, type, sizeof info.type); > > Please use strlcpy() instead, strncpy() is error-prone. OK. > > @@ -848,11 +893,24 @@ static int __init i2c_init(void) > > retval = bus_register(&i2c_bus_type); > > if (retval) > > return retval; > > - return class_register(&i2c_adapter_class); > > + retval = class_register(&i2c_adapter_class); > > + if (retval) > > + goto bus_err; > > + retval = i2c_add_driver(&dummy_driver); > > + if (retval) > > + goto class_err; > > + return 0; > > + > > +class_err: > > + class_unregister(&i2c_adapter_class); > > +bus_err: > > + bus_unregister(&i2c_bus_type); > > + return retval; > > } > > Thanks for fixing a broken error path... I could hardly avoid it! :) > > --- a/include/linux/i2c.h 2007-12-15 20:57:54.000000000 -0800 > > +++ b/include/linux/i2c.h 2007-12-15 21:01:22.000000000 -0800 > > @@ -261,6 +261,12 @@ i2c_new_probed_device(struct i2c_adapter > > struct i2c_board_info *info, > > unsigned short const *addr_list); > > > > +/* For devices that use several addresses, use i2c_new_dummy() to make > > + * client handles for the exta addresses. > > Typo: extra. Glitchey keyboard. :( > > + */ > > +extern struct i2c_client * > > +i2c_new_dummy(struct i2c_adapter *adap, unsigned address, const char *type); > > + > > extern void i2c_unregister_device(struct i2c_client *); > > > > /* Mainboard arch_initcall() code should register all its I2C devices. > > > > Other than that the patch looks just fine. Please respin it and I'll > apply it. Thanks. Update to follow. - Dave ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712222108.51292.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <200712222108.51292.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> @ 2007-12-23 5:11 ` David Brownell [not found] ` <200712222111.09471.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2007-12-23 5:11 UTC (permalink / raw) To: Jean Delvare; +Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA This adds a i2c_new_dummy() primitive to help work with devices that consume multiple addresses, which include many I2C eeproms and at least one RTC. Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> --- Updated to match Jean's feedback. Tested with 24c00 EEPROM, which takes eight addresses (but stores only 16 bytes total). drivers/i2c/i2c-core.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/i2c.h | 6 ++++ 2 files changed, 65 insertions(+), 1 deletion(-) --- a/drivers/i2c/i2c-core.c 2007-12-22 13:54:04.000000000 -0800 +++ b/drivers/i2c/i2c-core.c 2007-12-22 13:57:15.000000000 -0800 @@ -276,6 +276,51 @@ void i2c_unregister_device(struct i2c_cl EXPORT_SYMBOL_GPL(i2c_unregister_device); +static int dummy_nop(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_driver dummy_driver = { + .driver.name = "dummy", + .probe = dummy_nop, + .remove = dummy_nop, +}; + + +/** + * i2c_new_dummy - return a new i2c device bound to a dummy driver + * @adapter: the adapter managing the device + * @address: seven bit address to be used + * @type: optional label used for i2c_client.name + * Context: can sleep + * + * This returns an I2C client bound to the "dummy" driver, intended for use + * with devices that consume multiple addresses. Examples of such chips + * include various EEPROMS (like 24c04 and 24c08 models). + * + * These dummy devices have two main uses. First, most I2C and SMBus calls + * except i2c_transfer() need a client handle; the dummy will be that handle. + * And second, this prevents the specified address from being bound to a + * different driver. + * + * This returns the new i2c client, which should be saved for later use with + * i2c_unregister_device(); or NULL to indicate an error. + */ +struct i2c_client * +i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type) +{ + struct i2c_board_info info = { + .driver_name = "dummy", + .addr = address, + }; + + if (type) + strlcpy(info.type, type, sizeof info.type); + return i2c_new_device(adapter, &info); +} +EXPORT_SYMBOL_GPL(i2c_new_dummy); + /* ------------------------------------------------------------------------- */ /* I2C bus adapters -- one roots each I2C or SMBUS segment */ @@ -848,11 +893,24 @@ static int __init i2c_init(void) retval = bus_register(&i2c_bus_type); if (retval) return retval; - return class_register(&i2c_adapter_class); + retval = class_register(&i2c_adapter_class); + if (retval) + goto bus_err; + retval = i2c_add_driver(&dummy_driver); + if (retval) + goto class_err; + return 0; + +class_err: + class_unregister(&i2c_adapter_class); +bus_err: + bus_unregister(&i2c_bus_type); + return retval; } static void __exit i2c_exit(void) { + i2c_del_driver(&dummy_driver); class_unregister(&i2c_adapter_class); bus_unregister(&i2c_bus_type); } --- a/include/linux/i2c.h 2007-12-22 13:54:04.000000000 -0800 +++ b/include/linux/i2c.h 2007-12-22 13:57:15.000000000 -0800 @@ -261,6 +261,12 @@ i2c_new_probed_device(struct i2c_adapter struct i2c_board_info *info, unsigned short const *addr_list); +/* For devices that use several addresses, use i2c_new_dummy() to make + * client handles for the extra addresses. + */ +extern struct i2c_client * +i2c_new_dummy(struct i2c_adapter *adap, u16 address, const char *type); + extern void i2c_unregister_device(struct i2c_client *); /* Mainboard arch_initcall() code should register all its I2C devices. ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712222111.09471.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <200712222111.09471.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> @ 2007-12-23 9:03 ` Jean Delvare 0 siblings, 0 replies; 15+ messages in thread From: Jean Delvare @ 2007-12-23 9:03 UTC (permalink / raw) To: david-b-yBeKhBN/0LDR7s880joybQ Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA HI David, Le 23/12/2007, David Brownell a écrit: >This adds a i2c_new_dummy() primitive to help work with devices >that consume multiple addresses, which include many I2C eeproms >and at least one RTC. > >Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> >--- >Updated to match Jean's feedback. Tested with 24c00 EEPROM, >which takes eight addresses (but stores only 16 bytes total). Applied, thanks. -- Jean Delvare ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <20071216052308.A0FB11668D7@adsl-69-226-248-13.dsl.pltn13.pacbell.net>]
[parent not found: <20071216052308.A0FB11668D7-ZcXrCSuhvln6VZ3dlLfH/g4gEjPzgfUyLrfjE7I9kuVHxeISYlDBzl6hYfS7NtTn@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <20071216052308.A0FB11668D7-ZcXrCSuhvln6VZ3dlLfH/g4gEjPzgfUyLrfjE7I9kuVHxeISYlDBzl6hYfS7NtTn@public.gmane.org> @ 2007-12-27 20:58 ` Byron Bradley [not found] ` <57e2b00712271258l6ea661ai2bfd6b9e099c71be-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 15+ messages in thread From: Byron Bradley @ 2007-12-27 20:58 UTC (permalink / raw) To: David Brownell Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Dec 16, 2007 5:23 AM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > This adds a i2c_new_dummy() primitive to help work with devices > that consume multiple addresses, which include many I2C eeproms > and at least one RTC. > > Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> For the S35390A RTC driver I called i2c_new_dummy() in the probe function in a similar style to the at24 eeprom driver. This failed because the probe function is called inside an i2c_attach_device() which has already locked &adap->clist_lock. When you call the i2c_new_dummy() function it will itself call i2c_attach_device() but it will never be able to acquire &adap->clist_lock. Below is the lock detection and backtrace. ============================================= [ INFO: possible recursive locking detected ] 2.6.24-rc5-g7fffe9cc-dirty #38 --------------------------------------------- swapper/1 is trying to acquire lock: (&adap->clist_lock){--..}, at: [<c02b1ba4>] i2c_attach_client+0x28/0x1e8 but task is already holding lock: (&adap->clist_lock){--..}, at: [<c02b1ba4>] i2c_attach_client+0x28/0x1e8 other info that might help us debug this: 3 locks held by swapper/1: #0: (core_lists){--..}, at: [<c02b2294>] i2c_register_adapter+0x50/0x26c #1: (__i2c_board_lock){--..}, at: [<c02b23c4>] i2c_register_adapter+0x180/0x26c #2: (&adap->clist_lock){--..}, at: [<c02b1ba4>] i2c_attach_client+0x28/0x1e8 stack backtrace: [<c002df24>] (dump_stack+0x0/0x14) from [<c0067330>] (__lock_acquire+0x92c/0x10cc) [<c0066a04>] (__lock_acquire+0x0/0x10cc) from [<c0067b38>] (lock_acquire+0x68/0x80) [<c0067ad0>] (lock_acquire+0x0/0x80) from [<c035b880>] (mutex_lock_nested+0x9c/0x2cc) r7:c7c16000 r6:c7c18000 r5:60000013 r4:c7e0e4e8 [<c035b7e4>] (mutex_lock_nested+0x0/0x2cc) from [<c02b1ba4>] (i2c_attach_client+0x28/0x1e8) [<c02b1b7c>] (i2c_attach_client+0x0/0x1e8) from [<c02b2204>] (i2c_new_device+0xa8/0xe8) [<c02b215c>] (i2c_new_device+0x0/0xe8) from [<c02b26cc>] (i2c_new_dummy+0xb0/0xdc) r6:c7e0e488 r5:c036f848 r4:00000000 [<c02b261c>] (i2c_new_dummy+0x0/0xdc) from [<c02b0558>] (s35390a_probe+0x9c/0x330) r6:c7e0e800 r5:c7cbab00 r4:00000001 [<c02b04bc>] (s35390a_probe+0x0/0x330) from [<c02b0b08>] (i2c_device_probe+0x54/0x5c) r7:c0232b64 r6:c044721c r5:c7e0e828 r4:c7e0e800 [<c02b0ab4>] (i2c_device_probe+0x0/0x5c) from [<c0232a50>] (driver_probe_device+0xac/0x1c0) r6:c0447248 r5:c7c19d0c r4:c7e0e828 [<c02329a4>] (driver_probe_device+0x0/0x1c0) from [<c0232b74>] (__device_attach+0x10/0x14) r8:c7e0e628 r7:c0232b64 r6:c7e0e828 r5:c7c19d0c r4:00000000 [<c0232b64>] (__device_attach+0x0/0x14) from [<c0231b94>] (bus_for_each_drv+0x5c/0x88) [<c0231b38>] (bus_for_each_drv+0x0/0x88) from [<c0232c48>] (device_attach+0xa4/0xb0) r7:c7e0e530 r6:00000000 r5:c7e0e93c r4:c7e0e828 [<c0232ba4>] (device_attach+0x0/0xb0) from [<c0231af8>] (bus_attach_device+0x48/0x88) r5:c7e0e828 r4:c04473b0 [<c0231ab0>] (bus_attach_device+0x0/0x88) from [<c0230710>] (device_add+0x470/0x5e8) r5:c7e0e828 r4:c7e0e828 [<c02302a0>] (device_add+0x0/0x5e8) from [<c02308a8>] (device_register+0x20/0x24) [<c0230888>] (device_register+0x0/0x24) from [<c02b1c6c>] (i2c_attach_client+0xf0/0x1e8) r4:c7e0e920 [<c02b1b7c>] (i2c_attach_client+0x0/0x1e8) from [<c02b2204>] (i2c_new_device+0xa8/0xe8) [<c02b215c>] (i2c_new_device+0x0/0xe8) from [<c02b240c>] (i2c_register_adapter+0x1c8/0x26c) r6:c044733c r5:c7e0e488 r4:c7c0a240 [<c02b2244>] (i2c_register_adapter+0x0/0x26c) from [<c02b256c>] (i2c_add_numbered_adapter+0xbc/0x) r8:c042df28 r7:c042df34 r6:00000020 r5:c7e0e488 r4:00000000 [<c02b24b0>] (i2c_add_numbered_adapter+0x0/0xcc) from [<c02b467c>] (mv64xxx_i2c_probe+0x174/0x228) r5:c042dc28 r4:c7e0e400 [<c02b4508>] (mv64xxx_i2c_probe+0x0/0x228) from [<c02344dc>] (platform_drv_probe+0x20/0x24) [<c02344bc>] (platform_drv_probe+0x0/0x24) from [<c0232a50>] (driver_probe_device+0xac/0x1c0) [<c02329a4>] (driver_probe_device+0x0/0x1c0) from [<c0232d58>] (__driver_attach+0x104/0x10c) r8:c04421a8 r7:c0232c54 r6:c04478f4 r5:c042dc30 r4:c042dd44 [<c0232c54>] (__driver_attach+0x0/0x10c) from [<c0231d00>] (bus_for_each_dev+0x54/0x80) r6:c04478f4 r5:c7c19ef4 r4:00000000 [<c0231cac>] (bus_for_each_dev+0x0/0x80) from [<c02328b8>] (driver_attach+0x20/0x28) r7:c0023eb4 r6:00000000 r5:c04478f4 r4:c04478fc [<c0232898>] (driver_attach+0x0/0x28) from [<c0232104>] (bus_add_driver+0x84/0x1e0) [<c0232080>] (bus_add_driver+0x0/0x1e0) from [<c0232fac>] (driver_register+0x54/0x90) r8:c7c18000 r7:c0023eb4 r6:00000000 r5:00000000 r4:c04478f4 [<c0232f58>] (driver_register+0x0/0x90) from [<c0234768>] (platform_driver_register+0x6c/0x88) r4:00000000 [<c02346fc>] (platform_driver_register+0x0/0x88) from [<c001e454>] (mv64xxx_i2c_init+0x14/0x1c) [<c001e440>] (mv64xxx_i2c_init+0x0/0x1c) from [<c0008958>] (kernel_init+0x98/0x2ac) [<c00088c0>] (kernel_init+0x0/0x2ac) from [<c00459b8>] (do_exit+0x0/0x810) -- Byron Bradley ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <57e2b00712271258l6ea661ai2bfd6b9e099c71be-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2007-12-27 21:53 UTC (permalink / raw) To: Byron Bradley Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 27 December 2007, Byron Bradley wrote: > On Dec 16, 2007 5:23 AM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > This adds a i2c_new_dummy() primitive to help work with devices > > that consume multiple addresses, which include many I2C eeproms > > and at least one RTC. > > > > Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> > > For the S35390A RTC driver I called i2c_new_dummy() in the probe > function in a similar style to the at24 eeprom driver. This failed > because the probe function is called inside an i2c_attach_device() > which has already locked &adap->clist_lock. When you call the > i2c_new_dummy() function it will itself call i2c_attach_device() but > it will never be able to acquire &adap->clist_lock. Right ... make the s35390a driver be a new-style driver. Or, Jean has patches in his queue [1] to remove other lists from i2c_core which duplicate driver model core behavior. I think i2c_adapter.children and i2c_adapter.clist_lock have not yet been removed, even though they're redundant given the driver model's device.klist_children records. So if you're ambitious and don't want to just make that RTC driver be a new-style driver, you could just get rid of that functionality duplication. (Me, I'd take the easier route and just make it be a new-style driver!) - Dave [1] http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712271353.05857.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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> 0 siblings, 1 reply; 15+ messages in thread From: Byron Bradley @ 2007-12-27 22:09 UTC (permalink / raw) To: David Brownell Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Dec 27, 2007 9:53 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > On Thursday 27 December 2007, Byron Bradley wrote: > > On Dec 16, 2007 5:23 AM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > > This adds a i2c_new_dummy() primitive to help work with devices > > > that consume multiple addresses, which include many I2C eeproms > > > and at least one RTC. > > > > > > Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> > > > > For the S35390A RTC driver I called i2c_new_dummy() in the probe > > function in a similar style to the at24 eeprom driver. This failed > > because the probe function is called inside an i2c_attach_device() > > which has already locked &adap->clist_lock. When you call the > > i2c_new_dummy() function it will itself call i2c_attach_device() but > > it will never be able to acquire &adap->clist_lock. > > Right ... make the s35390a driver be a new-style driver. > > Or, Jean has patches in his queue [1] to remove other lists > from i2c_core which duplicate driver model core behavior. > I think i2c_adapter.children and i2c_adapter.clist_lock have > not yet been removed, even though they're redundant given the > driver model's device.klist_children records. > > So if you're ambitious and don't want to just make that RTC > driver be a new-style driver, you could just get rid of that > functionality duplication. (Me, I'd take the easier route and > just make it be a new-style driver!) I believe this is already a new-style driver. It uses the RTC framework, the module init calls i2c_add_driver() and the struct i2c_driver provides a .probe and a .remove function. Is there something else that I'm missing? Thanks, -- Byron Bradley ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <57e2b00712271409n6c98f76o45116cd92b01f396-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2007-12-27 23:06 UTC (permalink / raw) To: Byron Bradley Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 27 December 2007, Byron Bradley wrote: > On Dec 27, 2007 9:53 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > On Thursday 27 December 2007, Byron Bradley wrote: > > > On Dec 16, 2007 5:23 AM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > > > This adds a i2c_new_dummy() primitive to help work with devices > > > > that consume multiple addresses, which include many I2C eeproms > > > > and at least one RTC. > > > > > > > > Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> > > > > > > For the S35390A RTC driver I called i2c_new_dummy() in the probe > > > function in a similar style to the at24 eeprom driver. This failed > > > because the probe function is called inside an i2c_attach_device() You mean i2c_attach_client() ... > > > which has already locked &adap->clist_lock. When you call the > > > i2c_new_dummy() function it will itself call i2c_attach_device() but > > > it will never be able to acquire &adap->clist_lock. > > > > Right ... make the s35390a driver be a new-style driver. > > > > ... > > > > So if you're ambitious and don't want to just make that RTC > > driver be a new-style driver, you could just get rid of that > > functionality duplication. (Me, I'd take the easier route and > > just make it be a new-style driver!) > > I believe this is already a new-style driver. It uses the RTC > framework, the module init calls i2c_add_driver() and the struct > i2c_driver provides a .probe and a .remove function. Indeed; sorry, I skimmed over that stacktrace too quickly. > Is there something else that I'm missing? I'm not sure yet. I certainly tested that updated at24 driver with lockdep active, and it didn't report such a warning. It's possible lockdep on that platform isn't fully functional yet; I'll see if that problem triggers on a different arch (after some intentional misconfiguration to call this utility). One thing that looks odd in your stack trace is that it shows i2c_attach_client() calling mutex_lock_nested(), which is most certainly not what it does in rc6-git-current ... in fact, a nested call is made (rather curiously) only in i2c_transfer(). Do you have other I2C patches that may be causing problems? - Dave ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712271506.43069.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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 1 sibling, 0 replies; 15+ messages in thread From: Byron Bradley @ 2007-12-27 23:37 UTC (permalink / raw) To: David Brownell Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Dec 27, 2007 11:06 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > On Thursday 27 December 2007, Byron Bradley wrote: > > On Dec 27, 2007 9:53 PM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > > On Thursday 27 December 2007, Byron Bradley wrote: > > > > On Dec 16, 2007 5:23 AM, David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> wrote: > > > > > This adds a i2c_new_dummy() primitive to help work with devices > > > > > that consume multiple addresses, which include many I2C eeproms > > > > > and at least one RTC. > > > > > > > > > > Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> > > > > > > > > For the S35390A RTC driver I called i2c_new_dummy() in the probe > > > > function in a similar style to the at24 eeprom driver. This failed > > > > because the probe function is called inside an i2c_attach_device() > > You mean i2c_attach_client() ... Yes sorry, not sure where I got device from. > > > > which has already locked &adap->clist_lock. When you call the > > > > i2c_new_dummy() function it will itself call i2c_attach_device() but > > > > it will never be able to acquire &adap->clist_lock. > > > > > > Right ... make the s35390a driver be a new-style driver. > > > > > > ... > > > > > > So if you're ambitious and don't want to just make that RTC > > > driver be a new-style driver, you could just get rid of that > > > functionality duplication. (Me, I'd take the easier route and > > > just make it be a new-style driver!) > > > > I believe this is already a new-style driver. It uses the RTC > > framework, the module init calls i2c_add_driver() and the struct > > i2c_driver provides a .probe and a .remove function. > > Indeed; sorry, I skimmed over that stacktrace too quickly. > > > > Is there something else that I'm missing? > > I'm not sure yet. I certainly tested that updated at24 driver > with lockdep active, and it didn't report such a warning. It's > possible lockdep on that platform isn't fully functional yet; > I'll see if that problem triggers on a different arch (after > some intentional misconfiguration to call this utility). > > One thing that looks odd in your stack trace is that it shows > i2c_attach_client() calling mutex_lock_nested(), which is most > certainly not what it does in rc6-git-current ... in fact, a > nested call is made (rather curiously) only in i2c_transfer(). I'm using the Orion git repo (http://git.kernel.org/?p=linux/kernel/git/nico/orion.git;a=summary) which is being rebased but is currently on 2.6.24-rc5. I will try the latest 2.6-git with the Orion patches and see if that fixes anything. > Do you have other I2C patches that may be causing problems? No other I2C patches. Cheers, -- Byron Bradley ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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 1 sibling, 0 replies; 15+ messages in thread From: David Brownell @ 2007-12-27 23:59 UTC (permalink / raw) To: Byron Bradley Cc: timtimred-f/KTTADhmRsdnm+yROfE0A, i2c-GZX6beZjE8VD60Wz+7aTrA On Thursday 27 December 2007, David Brownell wrote: > > Is there something else that I'm missing? > > I'm not sure yet. I certainly tested that updated at24 driver > with lockdep active, and it didn't report such a warning. It's > possible lockdep on that platform isn't fully functional yet; > I'll see if that problem triggers on a different arch (after > some intentional misconfiguration to call this utility). Just tried it on ARM, and it worked just fine. Lockdep reported no warnings, and that hacked 24c512 EEPROM claims three extra addresses using i2c_new_dummy(). - Dave > One thing that looks odd in your stack trace is that it shows > i2c_attach_client() calling mutex_lock_nested(), which is most > certainly not what it does in rc6-git-current ... in fact, a > nested call is made (rather curiously) only in i2c_transfer(). > > Do you have other I2C patches that may be causing problems? ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712281230.17840.david-b@pacbell.net>]
[parent not found: <57e2b00712281645y70f6ec74s57945dc53f113ec8@mail.gmail.com>]
[parent not found: <57e2b00712281645y70f6ec74s57945dc53f113ec8-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2007-12-30 3:05 UTC (permalink / raw) To: Byron Bradley; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA > > OK, but why don't I get the warnings you get? > > > > That's not just on ARM, note. > > > > > > Making i2c_attach_client() not use the lock that way should be > > easy enough, I'll have a look at that, but I'm concerned about > > the seeming lockdep misbehavior here... as in, if it gets this > > wrong then how else is it broken and what other bugs has it > > been hiding? I still don't know why you get lockdep warnings and I don't ... but here's a patch that should help, by removing that lock! :) - Dave ================ Remove further duplication between i2c core and driver model: the per-adapter list of clients (adapter->clients, client->list) and its lock (adapter->clist_lock) duplicate adapter->dev.children. LIGHTLY TESTED ... goes on top of two patches from Jean's I2C queue, i2c-remove-redundant-i2c_adapter-list.patch i2c-remove-redundant-i2c_driver-list.patch Continuing in that naming scheme, this might be called i2c-remove-redundant-i2c_client-list.patch --- drivers/i2c/i2c-core.c | 189 ++++++++++++++++++++++--------------------------- drivers/i2c/i2c-dev.c | 33 ++++---- include/linux/i2c.h | 4 - 3 files changed, 102 insertions(+), 124 deletions(-) --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -256,7 +256,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)) { @@ -265,11 +264,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); @@ -381,8 +375,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); @@ -525,6 +517,38 @@ static int i2c_do_del_adapter(struct dev return res; } +static struct i2c_client *verify_client(struct device *dev) +{ + if (dev->bus != &i2c_bus_type) + return NULL; + return to_i2c_client(dev); +} + +static int detach_all_clients(struct device *dev, void *x) +{ + struct i2c_client *client = 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 @@ -535,8 +559,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); @@ -557,26 +579,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); @@ -655,6 +660,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 = 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 @@ -662,8 +681,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); @@ -684,22 +701,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); @@ -713,28 +717,19 @@ EXPORT_SYMBOL(i2c_del_driver); /* ------------------------------------------------------------------------- */ -static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) +static int i2c_checkaddr(struct device *dev, void *addrp) { - struct list_head *item; - struct i2c_client *client; + struct i2c_client *client = verify_client(dev); + int addr = *(int *)addrp; - list_for_each(item,&adapter->clients) { - client = list_entry(item, struct i2c_client, list); - if (client->addr == addr) - return -EBUSY; - } + if (client && client->addr == addr) + return -EBUSY; return 0; } static int i2c_check_addr(struct i2c_adapter *adapter, int addr) { - int rval; - - mutex_lock(&adapter->clist_lock); - rval = __i2c_check_addr(adapter, addr); - mutex_unlock(&adapter->clist_lock); - - return rval; + return device_for_each_child(&adapter->dev, &addr, i2c_checkaddr); } int i2c_attach_client(struct i2c_client *client) @@ -742,13 +737,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; @@ -765,12 +753,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)) { @@ -781,14 +773,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); @@ -813,11 +797,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: @@ -873,24 +854,28 @@ int i2c_release_client(struct i2c_client } EXPORT_SYMBOL(i2c_release_client); +struct i2c_cmd_arg { + unsigned cmd; + void *arg; +}; + +static int i2c_cmd(struct device *dev, void *_arg) +{ + struct i2c_client *client = verify_client(dev); + struct i2c_cmd_arg *arg = _arg; + + if (client) + client->driver->command(client, arg->cmd, arg->arg); + return 0; +} + void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) { - struct list_head *item; - struct i2c_client *client; + struct i2c_cmd_arg cmd_arg; - mutex_lock(&adap->clist_lock); - list_for_each(item,&adap->clients) { - client = list_entry(item, struct i2c_client, list); - if (!try_module_get(client->driver->driver.owner)) - continue; - if (NULL != client->driver->command) { - mutex_unlock(&adap->clist_lock); - client->driver->command(client,cmd,arg); - mutex_lock(&adap->clist_lock); - } - module_put(client->driver->driver.owner); - } - mutex_unlock(&adap->clist_lock); + cmd_arg.cmd = cmd; + cmd_arg.arg = arg; + device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd); } EXPORT_SYMBOL(i2c_clients_command); @@ -1151,7 +1136,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) { @@ -1161,7 +1145,7 @@ i2c_new_probed_device(struct i2c_adapter } /* Check address availability */ - if (__i2c_check_addr(adap, addr_list[i])) { + if (i2c_check_addr(adap, addr_list[i])) { dev_dbg(&adap->dev, "Address 0x%02x already in " "use, not probing\n", addr_list[i]); continue; @@ -1189,7 +1173,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"); --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -182,27 +182,26 @@ static ssize_t i2cdev_write (struct file return ret; } -/* This address checking function differs from the one in i2c-core - in that it considers an address with a registered device, but no - bounded driver, as NOT busy. */ -static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) +static int i2cdev_check(struct device *dev, void *addrp) { - struct list_head *item; struct i2c_client *client; - int res = 0; - mutex_lock(&adapter->clist_lock); - list_for_each(item, &adapter->clients) { - client = list_entry(item, struct i2c_client, list); - if (client->addr == addr) { - if (client->driver) - res = -EBUSY; - break; - } - } - mutex_unlock(&adapter->clist_lock); + if (!dev->bus || strcmp("i2c", dev->bus->name) != 0) + return 0; - return res; + client = to_i2c_client(dev); + if (client->addr != *(unsigned int *)addrp) + return 0; + + return dev->driver ? -EBUSY : 0; +} + +/* This address checking function differs from the one in i2c-core + in that it considers an address with a registered device, but no + driver to it, as NOT busy. */ +static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) +{ + return device_for_each_child(&adapter->dev, &addr, i2cdev_check); } static int i2cdev_ioctl(struct inode *inode, struct file *file, --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -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 * @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; struct completion released; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) @@ -317,14 +315,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; char name[48]; struct completion dev_released; }; ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200712291905.15160.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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-17 22:24 ` David Brownell 1 sibling, 1 reply; 15+ messages in thread From: Jean Delvare @ 2008-01-04 22:16 UTC (permalink / raw) To: David Brownell; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA Hi David, On Sat, 29 Dec 2007 19:05:14 -0800, David Brownell wrote: > Remove further duplication between i2c core and driver model: the > per-adapter list of clients (adapter->clients, client->list) and > its lock (adapter->clist_lock) duplicate adapter->dev.children. > > LIGHTLY TESTED ... goes on top of two patches from Jean's I2C queue, > > i2c-remove-redundant-i2c_adapter-list.patch > i2c-remove-redundant-i2c_driver-list.patch > > Continuing in that naming scheme, this might be called > > i2c-remove-redundant-i2c_client-list.patch > > --- > drivers/i2c/i2c-core.c | 189 ++++++++++++++++++++++--------------------------- > drivers/i2c/i2c-dev.c | 33 ++++---- > include/linux/i2c.h | 4 - > 3 files changed, 102 insertions(+), 124 deletions(-) This breaks drivers/media/video/mxb.c, drivers/media/video/dpc7146.c and drivers/media/video/tvmixer.c. These 3 drivers walk the clients list that your patch wants to remove. I guess that we need to replace their code by something equivalent that would walk the driver model's children list instead of i2c-core's internal one? -- Jean Delvare ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <20080104231633.135f2875-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [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> 0 siblings, 1 reply; 15+ messages in thread From: David Brownell @ 2008-01-04 23:48 UTC (permalink / raw) To: Jean Delvare; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA On Friday 04 January 2008, Jean Delvare wrote: > Hi David, > > On Sat, 29 Dec 2007 19:05:14 -0800, David Brownell wrote: > > Remove further duplication between i2c core and driver model: the > > per-adapter list of clients (adapter->clients, client->list) and > > its lock (adapter->clist_lock) duplicate adapter->dev.children. > > > > LIGHTLY TESTED ... goes on top of two patches from Jean's I2C queue, > > > > i2c-remove-redundant-i2c_adapter-list.patch > > i2c-remove-redundant-i2c_driver-list.patch > > > > Continuing in that naming scheme, this might be called > > > > i2c-remove-redundant-i2c_client-list.patch > > > > --- > > drivers/i2c/i2c-core.c | 189 ++++++++++++++++++++++--------------------------- > > drivers/i2c/i2c-dev.c | 33 ++++---- > > include/linux/i2c.h | 4 - > > 3 files changed, 102 insertions(+), 124 deletions(-) > > This breaks drivers/media/video/mxb.c, drivers/media/video/dpc7146.c > and drivers/media/video/tvmixer.c. These 3 drivers walk the clients > list that your patch wants to remove. Whoops. Good thing I warned y'all that it was only lightly tested! Presumably this was the result of a "build every line of I2C code" test. Those all seem to do the same thing: list_for_each_entry() scan to find specific devices connected to their private adapter. > I guess that we need to replace > their code by something equivalent that would walk the driver model's > children list instead of i2c-core's internal one? Like the device_for_each_child() scanning in the i2-core parts of that patch ... yes, that's probably the least invasive change for the moment. Eventually I'd like to see the relevant code using new-style driver binding, but that seems a bit much to change at the moment. Changing the users of i2c_adapter.clients could be safely done before removing that list (and its lock, ignored by most of those drivers if not all of them). Which should simplify testing such changes by a bit. - Dave ^ permalink raw reply [flat|nested] 15+ messages in thread
[parent not found: <200801041548.54825.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>]
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <200801041548.54825.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> @ 2008-01-06 9:57 ` Jean Delvare 0 siblings, 0 replies; 15+ messages in thread From: Jean Delvare @ 2008-01-06 9:57 UTC (permalink / raw) To: David Brownell; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA Hi David, On Fri, 4 Jan 2008 15:48:54 -0800, David Brownell wrote: > On Friday 04 January 2008, Jean Delvare wrote: > > This breaks drivers/media/video/mxb.c, drivers/media/video/dpc7146.c > > and drivers/media/video/tvmixer.c. These 3 drivers walk the clients > > list that your patch wants to remove. > > Whoops. Good thing I warned y'all that it was only lightly tested! > Presumably this was the result of a "build every line of I2C code" > test. This is my default build mode ;) I'm doing changes to i2c all the time so I want to know quickly if a given change breaks some driver. > Those all seem to do the same thing: list_for_each_entry() scan to > find specific devices connected to their private adapter. True. > > I guess that we need to replace > > their code by something equivalent that would walk the driver model's > > children list instead of i2c-core's internal one? > > Like the device_for_each_child() scanning in the i2-core parts of > that patch ... yes, that's probably the least invasive change for > the moment. Eventually I'd like to see the relevant code using > new-style driver binding, but that seems a bit much to change at > the moment. That was pretty much my conclusion as well. > Changing the users of i2c_adapter.clients could be safely done > before removing that list (and its lock, ignored by most of > those drivers if not all of them). Which should simplify testing > such changes by a bit. Agreed, I'll write such patches later today and will send them to the v4l list for review and testing. -- Jean Delvare ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 2.6.24-rc5-git] add i2c_new_dummy() utility [not found] ` <200712291905.15160.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> 2008-01-04 22:16 ` Jean Delvare @ 2008-01-17 22:24 ` David Brownell 1 sibling, 0 replies; 15+ messages in thread From: David Brownell @ 2008-01-17 22:24 UTC (permalink / raw) To: Byron Bradley; +Cc: i2c-GZX6beZjE8VD60Wz+7aTrA On Saturday 29 December 2007, David Brownell wrote: > I still don't know why you get lockdep warnings and I don't ... Theory: my test systems were turning lockdep off because of a lockdep (usage) deficiency that triggers while booting: enable_irq_wake(GPIO_irq) holds irq_desc[GPIO_irq].lock and calls enable_irq_wake(parent_of(GPIO_irq)) which grabs irq_desc[parent_of(GPIO_irq))] Lockdep falsely detects that as a potential recursion, and then turns off all further lockdep calls. I think a genirq patch to make set_irq_chained_handler() put the parent into a different locking class may help resolve that issue. - Dave _______________________________________________ i2c mailing list i2c-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org http://lists.lm-sensors.org/mailman/listinfo/i2c ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-01-17 22:24 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-22 17:31 [patch 2.6.24-rc5-git] add i2c_new_dummy() utility Jean Delvare
[not found] ` <kOXVGr9s.1198344701.9162110.khali-IO4AeUl/lkuWVfeAwA7xHQ@public.gmane.org>
2007-12-23 5:08 ` David Brownell
[not found] ` <200712222108.51292.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-12-23 5:11 ` David Brownell
[not found] ` <200712222111.09471.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-12-23 9:03 ` Jean Delvare
[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 ` 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-17 22:24 ` David Brownell
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox