i2c: guard against oopses from bad init sequences
Subsystems (2)
PATCH 1/1 i2c: guard against oopses from bad init sequences
From: David Brownell <[email protected]>
Guard I2C against oopsing because of init sequence problems, by verifying that i2c_init() has been called before calling any routines that rely on that initialization. This specific test just requires that bus_register(&i2c_bus_type) was called.
Examples of this kind of oopsing come from subystems and drivers which register I2C drivers in their subsys_initcall code but which are statically linked before I2C by drivers/Makefile.
---
Alternatively have postcore_initcall(i2c_init), which may be better ... the initcall levels are pretty limited, and in these cases the "subsystem" of interest builds on I2C and needs to work before device_initcall. Having I2C use subsys_initcall kind of forces things into fs_initcall.
I'd encourage the anti-oopsing paranoia in any case, even if i2c switches to postcore_initcall (or earlier).
drivers/i2c/i2c-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/i2c/i2c-core.c +10 -0
@@ -443,6 +443,12 @@ static int i2c_register_adapter(struct imutex_lock (&core_lock); +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) { + res = -ENOENT ; + goto out_list; + } +/* Add the adapter to the driver core. * If the parent pointer is not set up, * we add this adapter to the host bus.
@@ -696,6 +702,10 @@ int i2c_register_driver(struct module *o {int res; +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -ENOENT ; +/* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver (driver)) { if (driver->attach_adapter || driver->detach_adapter
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
A message that is not in the archive (sent off-list or not yet received): 200809231138.19583.david-b-yBeKhBN/[email protected]
Hi David,
Quoted 19 lines · David Brownell
From: David Brownell <[email protected]>
Guard I2C against oopsing because of init sequence problems, by verifying that
i2c_init()has been called before calling any routines that rely on that initialization. This specific test just requires thatbus_register(&i2c_bus_type)was called.Examples of this kind of oopsing come from subystems and drivers which register I2C drivers in their
subsys_initcallcode but which are statically linked before I2C bydrivers/Makefile.Signed-off-by David Brownell <[email protected]>---
Alternatively havepostcore_initcall(i2c_init), which may be better ... the initcall levels are pretty limited, and in these cases the "subsystem" of interest builds on I2C and needs to work beforedevice_initcall. Having I2C usesubsys_initcallkind of forces things intofs_initcall.
Quoted 2 lines
I'd encourage the anti-oopsing paranoia in any case, even if i2c switches to
postcore_initcall(or earlier).
I'm confused. If i2c_register_adapter() is called before i2c_init(), your patch prevents an oops, but things will still not work, right? So this doesn't seem to add much value. In any case we need to fix the init sequence, so let's just do that.
Quoted 30 lines
drivers/i2c/i2c-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+)drivers/i2c/i2c-core.c +10
-0@@ -443,6 +443,12 @@ static int i2c_register_adapter(struct imutex_lock (&core_lock); +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) { + res = -ENOENT ; + goto out_list; + } +/* Add the adapter to the driver core. * If the parent pointer is not set up, * we add this adapter to the host bus. @@ -696,6 +702,10 @@ int i2c_register_driver(struct module *o {int res; +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -ENOENT ; +/* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver (driver)) { if (driver->attach_adapter || driver->detach_adapter
Signature · 6 lines
Jean Delvare _______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 13 lines · Jean Delvare
Hi David,
Quoted 10 lines · David Brownell
From: David Brownell <[email protected]>
Guard I2C against oopsing because of init sequence problems...
Alternatively have
postcore_initcall(i2c_init), which may be better ... the initcall levels are pretty limited, and in these cases the "subsystem" of interest builds on I2C and needs to work beforedevice_initcall. Having I2C usesubsys_initcallkind of forces things intofs_initcall.
Quoted 5 lines
Quoted 2 lines
I'd encourage the anti-oopsing paranoia in any case, even if i2c switches to
postcore_initcall(or earlier).I'm confused. If
i2c_register_adapter()is called beforei2c_init(), your patch prevents an oops, but things will still not work, right?
And it warns about exactly where the problem came from, because of the WARN_ON. That addresses a long-standing debuggability problem which has afflicted these issues.
Quoted 3 lines
So
this doesn't seem to add much value. In any case we need to fix the init sequence, so let's just do that.
I'll send in a separate patch switching the driver model init to a postcore_initcall() -- it's not arch-specific and there seems no reason to have it earlier.
Semi-related: that module init/exit code is at a wierd place, in the middle of that file ... vs the conventional location at the end. OK to change that? In the same patch, or separate?
- Dave
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c
Hi David,
Quoted 28 lines · David Brownell
From: David Brownell <[email protected]>
Guard I2C against oopsing because of init sequence problems, by verifying that
i2c_init()has been called before calling any routines that rely on that initialization. This specific test just requires thatbus_register(&i2c_bus_type)was called.Examples of this kind of oopsing come from subystems and drivers which register I2C drivers in their
subsys_initcallcode but which are statically linked before I2C bydrivers/Makefile.Signed-off-by David Brownell <[email protected]>---
Alternatively havepostcore_initcall(i2c_init), which may be better ... the initcall levels are pretty limited, and in these cases the "subsystem" of interest builds on I2C and needs to work beforedevice_initcall. Having I2C usesubsys_initcallkind of forces things intofs_initcall.I'd encourage the anti-oopsing paranoia in any case, even if i2c switches to
postcore_initcall(or earlier).drivers/i2c/i2c-core.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/i2c/i2c-core.c static int i2c_register_adapter(struct i · line 451
Quoted 9 lines
drivers/i2c/i2c-core.c +6
-0@@ -443,6 +443,12 @@ static int i2c_register_adapter(struct imutex_lock (&core_lock); +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) { + res = -ENOENT ; + goto out_list; + } +
Why don't you test before acquiring core_lock? Or even, before doing anything else, as you do in i2c_register_driver. That's more consistent and makes the error path lighter.
Quoted 4 lines
drivers/i2c/i2c-core.c +0
-0/* Add the adapter to the driver core. * If the parent pointer is not set up, * we add this adapter to the host bus.
drivers/i2c/i2c-core.c int i2c_register_driver(struct module *o · line 711
Quoted 10 lines
drivers/i2c/i2c-core.c +4
-0@@ -696,6 +702,10 @@ int i2c_register_driver(struct module *o {int res; +/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -ENOENT ; +/* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver (driver)) { if (driver->attach_adapter || driver->detach_adapter
Also, I see that you still have some love for unique error codes even where they don't match the actual error. There's hardly a file or directory involved here... I think -EAGAIN would make more sense, as the i2c bus type will become available at some later point in time.
So, I would apply the following patch if that's OK with you:
drivers/i2c/i2c-core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/i2c/i2c-core.c +8 -0
@@ -437,6 +437,10 @@ static int i2c_register_adapter(struct i {int res =0 , dummy; +/* Can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -EAGAIN ; +mutex_init (&adap->bus_lock);mutex_init (&adap->clist_lock);INIT_LIST_HEAD (&adap->clients);
@@ -696,6 +700,10 @@ int i2c_register_driver(struct module *o {int res; +/* Can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -EAGAIN ; +/* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver (driver)) { if (driver->attach_adapter || driver->detach_adapter
Signature · 6 lines
Jean Delvare _______________________________________________ i2c mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/i2c
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 6 lines · Jean Delvare
Quoted 6 lines
drivers/i2c/i2c-core.c +0
-0@@ -443,6 +443,12 @@ static int i2c_register_adapter(struct imutex_lock (&core_lock);
Quoted 10 lines
drivers/i2c/i2c-core.c static int i2c_register_adapter(struct i · line 451
Quoted 6 lines
drivers/i2c/i2c-core.c +6
-0+/* can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) { + res = -ENOENT ; + goto out_list; + } +Why don't you test before acquiring
core_lock? Or even, before doing anything else, as you do ini2c_register_driver. That's more consistent and makes the error path lighter.
One or the other was an afterthought. I don't recall which one. ;)
Quoted 1 line
So, I would apply the following patch if that's OK with you:
Sure ... I'll be happy to have such issues be more diagnosable.
- Dave
Quoted 19 lines
drivers/i2c/i2c-core.c | 8 ++++++++ 1 file changed, 8 insertions(+)drivers/i2c/i2c-core.c +4
-0@@ -437,6 +437,10 @@ static int i2c_register_adapter(struct i {int res =0 , dummy; +/* Can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -EAGAIN ; +mutex_init (&adap->bus_lock);mutex_init (&adap->clist_lock);INIT_LIST_HEAD (&adap->clients);
drivers/i2c/i2c-core.c int i2c_register_driver(struct module *o · line 709
Quoted 10 lines
drivers/i2c/i2c-core.c +4
-0@@ -696,6 +700,10 @@ int i2c_register_driver(struct module *o {int res; +/* Can't register until after driver model init */ +if (WARN_ON (!i2c_bus_type.p)) +return -EAGAIN ; +/* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver (driver)) { if (driver->attach_adapter || driver->detach_adapter
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c