[lm-sensors] [PATCH 1/3] i2c: allow i2c core to instantiate clients
Mark M. Hoffman
mhoffman at lightlink.com
Thu Jun 1 14:02:54 CEST 2006
Hi Nathan:
* Nathan Lutchansky <lutchann at litech.org> [2006-05-31 01:49:25 -0400]:
> I was hoping I'd have more time to finish this up, but it's becoming
> apparent that it's not going to fit anywhere in my schedule. I'm sorry I
> have to drop this in a really unfinished state, but ignoring your emails
> isn't helping anything.
Hrm, I hope I haven't put you off somehow.
> I'll try to address your major questions below, though:
>
> On Sat, 27 May 2006, Mark M. Hoffman wrote:
>
> > Summary: the biggest immediate problem here is that i2c_add_client()
> > leaks a struct i2c_client by design, AFAICT.
>
> Right, clients added with i2c_add_client() remain present until the bus is
> removed from the system, even if the driver for that client is removed.
> This is the behavior you would expect from i2c buses with a fixed, known
> list of clients present. However, for auto-probed clients, it is a change
> in behavior that users probably would not appreciate.
I meant leak literally... as in never kfree'ed. But now I see that it would
get kfree'ed from within i2c_del_adapter(). I'm not sure how I missed that.
> > I do see that this approach addresses a requirement of embedded systems
> > and others who know a priori what hardware is present. It is also nice
> > that it does not force any changes to current drivers.
> >
> > However, I think the i2c_add_client() function is awkward. You say that
> > this function could be called by an adapter that knows what devices it
> > has... but what if the adapter is a generic driver like i2c-i801? For
> > the embedded scenario, it would be preferable to further decouple these
> > two pieces:
> >
> > [ adapter driver for bus foo ]
> > [ bus foo has devices x, y & z ]
>
> Yes, it would be nice to be able to pass a list of attached devices to
> some adapter drivers. Possibly this could be passed in as a module
> parameter or as a field in the platform data structure for platform
> devices. However, this list might be dependent upon the contents of an
> EEPROM device located on that bus, so it would be good to leave this part
> as flexible as possible.
In the embedded scenario, would it be appropriate to pass such a list
from platform_notify()? That looks like the right place to me.
> > I would argue against a general move to this method for hwmon and others.
> > There would be no benefit that I can tell; in the long term I would expect
> > the i2c_add_client() function to disappear anyway.
>
> What do you expect would be a more suitable method for hwmon to
> instantiate clients? The current i2c_probe() mechanism is rather lacking;
> requiring users to pass arcane module parameters to each chip module is
> not ideal,
It may not be ideal, but it's rarely necessary for hwmon at any rate.
[see below for an answer to "what do you expect..."]
> and is completely impossible to use where the client drivers
> are compiled directly into the kernel.
Documentation/kernel-parameters.txt: 3rd paragraph
> I suspect you'll eventually need
> to go to a system where drivers can be bound at runtime to specific
> addresses using sysfs, similar to the SCSI subsystem where new devices can
> be probed by echoing "scsi add-single-device 4 0 6 0" to /proc/scsi/scsi.
> Such a mechanism would probably use something like i2c_add_client on the
> backend.
There are some i2c devices that are 100% not detectable by probing. This
would be a good alternative for those.
> > > static int i2c_device_match(struct device *dev, struct device_driver *drv)
> > > {
> > > - return 1;
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct i2c_driver *driver = to_i2c_driver(drv);
> > > +
> > > + return client->driver_id == driver->id;
> > > }
> >
> > As I mentioned previously - I think this function will ultimately
> > need to change. As you have it, it short-circuits the driver model
> > probing for any client without a specific driver ID. I understand
> > that this doesn't matter at the moment.
>
> I'm still not sure I understand why some drivers would not have IDs
> assigned. For embedded systems or V4L devices, where there is a fixed
> list of clients known to be present, how else would the proper client
> driver for each address be specified?
I will try to answer this and "What do you expect ..." above at the same
time, but it probably takes a patch to make it clear.
If we're going to better integrate the i2c subsystem with the driver model,
I think the i2c core has to instantiate all client structs. It would
enumerate through the i2c address space looking to match (i2c_device_match)
at each address. The client->driver_id may or may not be filled in at
that point; depends on whether the adapter has a known list of devices.
If the client does have a driver_id, that will serve the purpose of
*ruling out* all other devices. That is why I suggested (the equivalent
to) this earlier:
if (client->driver_id)
return client->driver_id == driver->id;
If we make it past that, we look for a match with the driver's address
data. Assuming that's good, we'll do i2c_device_probe() much as you
have it. We would continue to use adapter->class to restrict or modify
probing behavior, but we might be able to reduce it to PROBE and NOPROBE.
At least for the embedded scenario, there should be an I2C_CLASS_NONE.
That's my vision for now. I will send patches as soon as I can.
> > > static int i2c_device_probe(struct device *dev)
> > > {
> > > - return -ENODEV;
> > > + struct i2c_client *client = to_i2c_client(dev);
> > > + struct i2c_driver *driver = to_i2c_driver(dev->driver);
> > > + int error = -ENODEV;
> > > +
> > > + if (driver->probe) {
> > > + client->driver = driver;
> > > + error = driver->probe(client);
> > > + if (error < 0)
> > > + client->driver = NULL;
> > > + else
> > > + i2c_notify_adapter(client);
> > > + }
> > > + return error < 0 ? error : 0;
> > > }
> >
> > What's wrong with "if (error)" here? Likewise "return error" at the end?
>
> I believe I intended for the driver->probe() function to return either 0
> or a positive value on success, although I don't remember what those would
> have indicated. But i2c_device_probe() would always need to return only 0
> on success, which is why the strange comparisons are there.
>
> > > +static int __i2c_detach_client(struct i2c_client *client)
> > > +{
> > > + struct i2c_driver *driver = client->driver;
> > > + int error;
> > > +
> > > + if (driver && driver->detach_client)
> > > + return driver->detach_client(client);
> > > +
> >
> > [ (!driver) is impossible there, i.e. indicates a bug, no? ]
>
> No, it's perfectly fine for a client to exist on a bus with no associated
> client driver. This will happen if a client is instantiated with
> i2c_add_client() and the indicated driver ID does not correspond to an
> existing driver, perhaps because a module is not loaded or the driver is
> not compiled into the kernel. Allowing driverless clients to exist was
> the point of the patch, really...
OK, thanks. Your second patch had no examples of calling i2c_add_client()
from an adapter rather than from a driver, so I didn't consider that case.
> > ... to here you're just making the driver->detach_client() callback
> > optional. That's a problem: I don't see where you're going to
> > kfree the struct i2c_client that i2c_add_client() allocates. This might
> > explain the "can't unload then reload a client driver module" caveat
> > that you mentioned earlier.
>
> Right, yes. Any i2c_client struct created by i2c_add_client() will only
> ever get destroyed by i2c_del_adapter(), as discussed above.
>
> > > + error = i2c_add_to_bus(client);
> > > + if (error)
> > > + return error;
> >
> > [ I prefer "if ((error = i2c_add_to_bus(client)))" here ]
>
> I'm not fond of hiding assignments in if() statements, but I think that's
> just personal style.
>
> > > - module_put(client->driver->driver.owner);
> > > + if (client->driver)
> > > + module_put(client->driver->driver.owner);
> >
> > As Jean Delvare pointed out... !(client->driver) is a bug. In this
> > case "BUG_ON" is no better than just leaving it as it was - it will
> > oops either way.
>
> Yeah, I didn't think about the module reference counting, it definitely
> needs to be fixed.
>
> Again, I'm really sorry to have to drop this, but I have too much going on
> at the moment. I'd still be interested in following future discussion on
> the topic, though. -Nathan
No problem. I'm sorry it took so long to review as well.
Regards,
--
Mark M. Hoffman
mhoffman at lightlink.com
More information about the lm-sensors
mailing list