i2c: Warn when adapters have no parent
Subsystems (3)
PATCH 1/1 i2c: Warn when adapters have no parent
Warn more loudly when an i2c-adapter is registered without a parent. There should be almost no driver left in this case, and it's about time to fix these.
--- drivers/i2c/i2c-core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/i2c/i2c-core.c +3 -2
@@ -457,8 +457,9 @@ static int i2c_register_adapter(struct i*/ if (adap->dev.parent ==NULL ) { adap->dev.parent = &platform_bus; -pr_debug ("I2C adapter driver [%s] forgot to specify " -"physical device\n" , adap->name); +pr_warning ("I2C adapter driver [%s] forgot to specify " +"physical device\n" , adap->name); +pr_warning ("Fix it now, it will soon break!\n" ); }/* Set default timeout to 1 second if not already set */
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 i2c: Do not give adapters a default parent
We don't need to give adapters a parent if they don't have one. The driver core will put them in the virtual device directory and all will be fine.
---
Much better than my first attempt. Not sure what will happen if we ever turn i2c-adapters into bus devices. I see that the driver core puts class devices without a parent in virtual, but what about _bus_ devices without a parent? Kay?
drivers/i2c/i2c-core.c | 11 ----------- 1 file changed, 11 deletions(-)
drivers/i2c/i2c-core.c +0 -11
@@ -29,7 +29,6 @@#include <linux/i2c.h> #include <linux/init.h> #include <linux/idr.h> -#include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/completion.h> #include <linux/hardirq.h>
@@ -451,16 +450,6 @@ static int i2c_register_adapter(struct imutex_lock (&core_lock); -/* Add the adapter to the driver core. -* If the parent pointer is not set up, -* we add this adapter to the host bus. -*/ -if (adap->dev.parent ==NULL ) { - adap->dev.parent = &platform_bus; -pr_debug ("I2C adapter driver [%s] forgot to specify " -"physical device\n" , adap->name); - } -/* Set default timeout to 1 second if not already set */ if (adap->timeout ==0 ) adap->timeout =HZ ;
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 9 lines · Jean Delvare
We don't need to give adapters a parent if they don't have one. The driver core will put them in the virtual device directory and all will be fine.
Signed-off-by Jean Delvare <[email protected]>---
Much better than my first attempt. Not sure what will happen if we ever turn i2c-adapters into bus devices. I see that the driver core puts class devices without a parent in virtual, but what about _bus_ devices
I'm sure, that "virtual" logic could be done for bus devices too, if it's needed. I don't see any reason why that wouldn't be fine.
(The less difference between classes and buses the better. It is wrong to have two types of subsystems, doing almost the same thing. One could argue that it could be useful inside the kernel, which it isn't, I think, but exporting them to userspace was definitely the wrong thing.)
Thanks,
Kay
A message that is not in the archive (sent off-list or not yet received): ac3eb2510905040540k65afe3f8k7e6c696d11bf7e1d-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Sorry for the late reply...
Quoted 11 lines · Kay Sievers
Quoted 9 lines · Jean Delvare
We don't need to give adapters a parent if they don't have one. The driver core will put them in the virtual device directory and all will be fine.
Signed-off-by Jean Delvare <[email protected]>---
Much better than my first attempt. Not sure what will happen if we ever turn i2c-adapters into bus devices. I see that the driver core puts class devices without a parent in virtual, but what about _bus_ devices
Quoted 8 lines
I'm sure, that "virtual" logic could be done for bus devices too, if it's needed. I don't see any reason why that wouldn't be fine.
(The less difference between classes and buses the better. It is wrong to have two types of subsystems, doing almost the same thing. One could argue that it could be useful inside the kernel, which it isn't, I think, but exporting them to userspace was definitely the wrong thing.)
I finally took a stab at this. The resulting patch is below. I have used device_type to differentiate between I2C clients and I2C adapters. Is this what you had in mind?
It seems to work reasonably well, with the following issues remaining:
* The change breaks at least sensors-detect and libsensors. I can easily modify them so that they work again, but we still have a compatibility issue. Is it possible to have a compatibility option that would add symbolic links from class/i2c-adapter/i2c-* to bus/i2c/devices/i2c-* for a couple years?
* Now that i2c-core makes use of device_type, I tried to move the power management handling callbacks there from bus_type, to save a test in each function, however I found that the callback set is different between bus_type and device_type.pm. Why is it so? Is there a document explaining the difference? Is the whole world (including bus_type) eventually moving to dev_pm_ops?
* When i2c-adapters were class devices, virtual ones (for example i2c-stub) appeared in sysfs as devices/virtual/i2c-adapter/i2c-*, which made sense and seemed safe. Now that I have turned them into bus devices, virtual ones appear in sysfs as devices/i2c-* directly, which looks dirty and could result in collisions someday. What should be done about this? I wanted to use virtual_device_parent() but it is internal to the driver core at the moment, and doesn't even exist if CONFIG_SYSFS_DEPRECATED=y.
I would be grateful if you can advise on any of the above points. Thanks.
* * * * *
* Introduce two device types for i2c: i2c_client_type and i2c_adapter_type.
* Remove i2c-adapter class and use i2c_adapter_type instead.
* Many callbacks had to be modified to check whether the device that is passed has the correct type, now that clients and adapters live in the same namespace.
--- drivers/i2c/i2c-core.c | 140 ++++++++++++++++++++++++++++++------------------- 1 file changed, 86 insertions(+), 54 deletions(-)
drivers/i2c/i2c-core.c +86 -54
@@ -46,6 +46,7 @@ static DEFINE_MUTEX(core_lock);static DEFINE_IDR (i2c_adapter_idr);static LIST_HEAD (userspace_devices); +static struct device_type i2c_client_type;static int i2c_check_addr (struct i2c_adapter *adapter,int addr);static int i2c_detect (struct i2c_adapter *adapter,struct i2c_driver *driver);
@@ -64,9 +65,13 @@ static const struct i2c_device_id *i2c_mstatic int i2c_device_match (struct device *dev,struct device_driver *drv) { -struct i2c_client *client =to_i2c_client (dev); -struct i2c_driver *driver =to_i2c_driver (drv); +struct i2c_client *client =i2c_verify_client (dev); +struct i2c_driver *driver; + +if (!client) +return 0 ; + driver =to_i2c_driver (drv);/* match on an id table if there is one */ if (driver->id_table)return i2c_match_id (driver->id_table, client) !=NULL ;
@@ -94,10 +99,14 @@ static int i2c_device_uevent(struct devistatic int i2c_device_probe (struct device *dev) { -struct i2c_client *client =to_i2c_client (dev); -struct i2c_driver *driver =to_i2c_driver (dev->driver); +struct i2c_client *client =i2c_verify_client (dev); +struct i2c_driver *driver;int status; +if (!client) +return 0 ; + + driver =to_i2c_driver (dev->driver);if (!driver->probe || !driver->id_table)return -ENODEV ; client->driver = driver;
@@ -114,11 +123,11 @@ static int i2c_device_probe(struct devicstatic int i2c_device_remove (struct device *dev) { -struct i2c_client *client =to_i2c_client (dev); +struct i2c_client *client =i2c_verify_client (dev);struct i2c_driver *driver;int status; -if (!dev->driver) +if (!client || !dev->driver)return 0 ; driver =to_i2c_driver (dev->driver);
@@ -136,37 +145,40 @@ static int i2c_device_remove(struct devistatic void i2c_device_shutdown (struct device *dev) { +struct i2c_client *client =i2c_verify_client (dev);struct i2c_driver *driver; -if (!dev->driver) +if (!client || !dev->driver)return ; driver =to_i2c_driver (dev->driver);if (driver->shutdown) - driver->shutdown (to_i2c_client (dev)); + driver->shutdown (client); }static int i2c_device_suspend (struct device *dev,pm_message_t mesg) { +struct i2c_client *client =i2c_verify_client (dev);struct i2c_driver *driver; -if (!dev->driver) +if (!client || !dev->driver)return 0 ; driver =to_i2c_driver (dev->driver);if (!driver->suspend)return 0 ; -return driver->suspend (to_i2c_client (dev), mesg); +return driver->suspend (client, mesg); }static int i2c_device_resume (struct device *dev) { +struct i2c_client *client =i2c_verify_client (dev);struct i2c_driver *driver; -if (!dev->driver) +if (!client || !dev->driver)return 0 ; driver =to_i2c_driver (dev->driver);if (!driver->resume)return 0 ; -return driver->resume (to_i2c_client (dev)); +return driver->resume (client); }static void i2c_client_dev_release (struct device *dev)
@@ -175,10 +187,10 @@ static void i2c_client_dev_release(struc }static ssize_t -show_client_name (struct device *dev,struct device_attribute *attr,char *buf) +show_name (struct device *dev,struct device_attribute *attr,char *buf) { -struct i2c_client *client =to_i2c_client (dev); -return sprintf (buf,"%s\n" , client->name); +return sprintf (buf,"%s\n" , dev->type == &i2c_client_type ? +to_i2c_client (dev)->name :to_i2c_adapter (dev)->name); } static ssize_t
@@ -188,18 +200,28 @@ show_modalias(struct device *dev, structreturn sprintf (buf,"%s%s\n" ,I2C_MODULE_PREFIX , client->name); } -static struct device_attribute i2c_dev_attrs[] = { -__ATTR (name,S_IRUGO , show_client_name,NULL ), +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); + +static struct attribute *i2c_dev_attrs[] = { + &dev_attr_name.attr,/* modalias helps coldplug: modprobe $(cat .../modalias) */ -__ATTR (modalias,S_IRUGO , show_modalias,NULL ), - { }, + &dev_attr_modalias.attr, +NULL +}; + +static struct attribute_group i2c_dev_attr_group = { + .attrs = i2c_dev_attrs, +}; + +static struct attribute_group *i2c_dev_attr_groups[] = { + &i2c_dev_attr_group, +NULL };struct bus_type i2c_bus_type = { .name ="i2c" , - .dev_attrs = i2c_dev_attrs, .match = i2c_device_match, - .uevent = i2c_device_uevent, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown,
@@ -208,6 +230,12 @@ struct bus_type i2c_bus_type = { };EXPORT_SYMBOL_GPL (i2c_bus_type); +static struct device_type i2c_client_type = { + .groups = i2c_dev_attr_groups, + .uevent = i2c_device_uevent, + .release = i2c_client_dev_release, +}; +/** * i2c_verify_client - return parameter as i2c_client, or NULL
@@ -220,7 +248,7 @@ EXPORT_SYMBOL_GPL(i2c_bus_type);*/ struct i2c_client *i2c_verify_client (struct device *dev) { -return (dev->bus == &i2c_bus_type) +return (dev->type == &i2c_client_type) ?to_i2c_client (dev) :NULL ; }
@@ -273,7 +301,7 @@ i2c_new_device(struct i2c_adapter *adap, client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; - client->dev.release = i2c_client_dev_release; + client->dev.type = &i2c_client_type;dev_set_name (&client->dev,"%d-%04x" ,i2c_adapter_id (adap), client->addr);
@@ -368,13 +396,6 @@ static void i2c_adapter_dev_release(strucomplete (&adap->dev_released); } -static ssize_t -show_adapter_name (struct device *dev,struct device_attribute *attr,char *buf) -{ -struct i2c_adapter *adap =to_i2c_adapter (dev); -return sprintf (buf,"%s\n" , adap->name); -} -/* * Let users instantiate I2C devices through sysfs. This can be used when * platform initialization code doesn't contain the proper data for
@@ -493,17 +514,28 @@ i2c_sysfs_delete_device(struct device *dreturn res; } -static struct device_attribute i2c_adapter_attrs[] = { -__ATTR (name,S_IRUGO , show_adapter_name,NULL ), -__ATTR (new_device,S_IWUSR ,NULL , i2c_sysfs_new_device), -__ATTR (delete_device,S_IWUSR ,NULL , i2c_sysfs_delete_device), - { }, +static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); +static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device); + +static struct attribute *i2c_adapter_attrs[] = { + &dev_attr_name.attr, + &dev_attr_new_device.attr, + &dev_attr_delete_device.attr, +NULL }; -static struct class i2c_adapter_class = { - .owner =THIS_MODULE , - .name ="i2c-adapter" , - .dev_attrs = i2c_adapter_attrs, +static struct attribute_group i2c_adapter_attr_group = { + .attrs = i2c_adapter_attrs, +}; + +static struct attribute_group *i2c_adapter_attr_groups[] = { + &i2c_adapter_attr_group, +NULL +}; + +static struct device_type i2c_adapter_type = { + .groups = i2c_adapter_attr_groups, + .release = i2c_adapter_dev_release, };static void i2c_scan_static_board_info (struct i2c_adapter *adapter)
@@ -555,8 +587,8 @@ static int i2c_register_adapter(struct i adap->timeout =HZ ;dev_set_name (&adap->dev,"i2c-%d" , adap->nr); - adap->dev.release = &i2c_adapter_dev_release; - adap->dev.class = &i2c_adapter_class; + adap->dev.bus = &i2c_bus_type; + adap->dev.type = &i2c_adapter_type; res =device_register (&adap->dev);if (res) goto out_list;
@@ -768,9 +800,13 @@ EXPORT_SYMBOL(i2c_del_adapter);static int __attach_adapter (struct device *dev,void *data) { -struct i2c_adapter *adapter =to_i2c_adapter (dev); +struct i2c_adapter *adapter;struct i2c_driver *driver = data; +if (dev->type != &i2c_adapter_type) +return 0 ; + adapter =to_i2c_adapter (dev); +i2c_detect (adapter, driver);/* Legacy drivers scan i2c busses directly */
@@ -809,8 +845,7 @@ int i2c_register_driver(struct module *oINIT_LIST_HEAD (&driver->clients);/* Walk the adapters that are already present */ mutex_lock (&core_lock); -class_for_each_device (&i2c_adapter_class,NULL , driver, - __attach_adapter); +bus_for_each_dev (&i2c_bus_type,NULL , driver, __attach_adapter);mutex_unlock (&core_lock);return 0 ;
@@ -819,10 +854,14 @@ EXPORT_SYMBOL(i2c_register_driver);static int __detach_adapter (struct device *dev,void *data) { -struct i2c_adapter *adapter =to_i2c_adapter (dev); +struct i2c_adapter *adapter;struct i2c_driver *driver = data;struct i2c_client *client, *_n; +if (dev->type != &i2c_adapter_type) +return 0 ; + adapter =to_i2c_adapter (dev); +/* Remove the devices we created ourselves as the result of hardware * probing (using a driver's detect method) */ list_for_each_entry_safe (client, _n, &driver->clients, detected) {
@@ -850,8 +889,7 @@ static int __detach_adapter(struct devicvoid i2c_del_driver (struct i2c_driver *driver) {mutex_lock (&core_lock); -class_for_each_device (&i2c_adapter_class,NULL , driver, - __detach_adapter); +bus_for_each_dev (&i2c_bus_type,NULL , driver, __detach_adapter);mutex_unlock (&core_lock);driver_unregister (&driver->driver);
@@ -940,16 +978,11 @@ static int __init i2c_init(void) retval =bus_register (&i2c_bus_type);if (retval)return retval; - retval =class_register (&i2c_adapter_class); -if (retval) - goto bus_err; retval =i2c_add_driver (&dummy_driver);if (retval) - goto class_err; + goto bus_err;return 0 ; -class_err: -class_unregister (&i2c_adapter_class); bus_err:bus_unregister (&i2c_bus_type);return retval;
@@ -958,7 +991,6 @@ bus_err: static void __exit i2c_exit(void) {i2c_del_driver (&dummy_driver); -class_unregister (&i2c_adapter_class);bus_unregister (&i2c_bus_type); }
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 11 lines · Jean Delvare
Quoted 5 lines · Kay Sievers
(The less difference between classes and buses the better. It is wrong to have two types of subsystems, doing almost the same thing. One could argue that it could be useful inside the kernel, which it isn't, I think, but exporting them to userspace was definitely the wrong thing.)
I finally took a stab at this. The resulting patch is below. I have used
device_typeto differentiate between I2C clients and I2C adapters. Is this what you had in mind?
Looks fine, by just looking at the patch.
Quoted 7 lines
It seems to work reasonably well, with the following issues remaining:
* The change breaks at least sensors-detect and libsensors. I can easily modify them so that they work again, but we still have a compatibility issue. Is it possible to have a compatibility option that would add symbolic links from class/i2c-adapter/i2c-* to bus/i2c/devices/i2c-* for a couple years?
Yeah, we can add that. I guess others will need that too, if we convert things from class to bus. How would that look like? Like a device_add_class_compat_link(*dev, *class)?
Quoted 6 lines
* Now that i2c-core makes use of
device_type, I tried to move the power management handling callbacks there frombus_type, to save a test in each function, however I found that the callback set is different betweenbus_typeand device_type.pm. Why is it so? Is there a document explaining the difference? Is the whole world (includingbus_type) eventually moving todev_pm_ops?
I think this is already removed in the current git tree, and all should use dev_pm_ops, yes.
Quoted 8 lines
* When i2c-adapters were class devices, virtual ones (for example i2c-stub) appeared in sysfs as devices/virtual/i2c-adapter/i2c-*, which made sense and seemed safe. Now that I have turned them into bus devices, virtual ones appear in sysfs as devices/i2c-* directly, which looks dirty and could result in collisions someday. What should be done about this? I wanted to use
virtual_device_parent()but it is internal to the driver core at the moment, and doesn't even exist ifCONFIG_SYSFS_DEPRECATED=y.
Yeah, we just need to apply the /sys/devices/virtual logic to bus devices too, it's currently limited to class devices, because there was no bus device so far who needed this, but should be an easy change.
Quoted 1 line
I would be grateful if you can advise on any of the above points.
If you decide to do it that way, you would need the driver core to be able:
- to create a link from an otherwise empty "struct class" to an
existing bus-device
- put bus devices without a parent into the /sys/devices/virtual logic
right? Let me know, I can look into that, if you need that.
Thanks,
Kay
A message that is not in the archive (sent off-list or not yet received): ac3eb2510907051319i414a5e78r74d623ebb0508d0-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Quoted 23 lines · Kay Sievers
Quoted 11 lines · Jean Delvare
Quoted 5 lines · Kay Sievers
(The less difference between classes and buses the better. It is wrong to have two types of subsystems, doing almost the same thing. One could argue that it could be useful inside the kernel, which it isn't, I think, but exporting them to userspace was definitely the wrong thing.)
I finally took a stab at this. The resulting patch is below. I have used
device_typeto differentiate between I2C clients and I2C adapters. Is this what you had in mind?Looks fine, by just looking at the patch.
Quoted 7 lines
It seems to work reasonably well, with the following issues remaining:
* The change breaks at least sensors-detect and libsensors. I can easily modify them so that they work again, but we still have a compatibility issue. Is it possible to have a compatibility option that would add symbolic links from class/i2c-adapter/i2c-* to bus/i2c/devices/i2c-* for a couple years?
Quoted 3 lines
Yeah, we can add that. I guess others will need that too, if we convert things from class to bus. How would that look like? Like a
device_add_class_compat_link(*dev, *class)?
Yes. I'm not just sure what "class" would be exactly... either a "real" fake class, or a mere string representing the fake class name?
Quoted 9 lines
Quoted 6 lines
* Now that i2c-core makes use of
device_type, I tried to move the power management handling callbacks there frombus_type, to save a test in each function, however I found that the callback set is different betweenbus_typeand device_type.pm. Why is it so? Is there a document explaining the difference? Is the whole world (includingbus_type) eventually moving todev_pm_ops?I think this is already removed in the current git tree, and all should use
dev_pm_ops, yes.
In which git tree? In Linus' tree, struct bus_type definitely doesn't use dev_pm_ops yet.
Quoted 9 lines
Quoted 8 lines
* When i2c-adapters were class devices, virtual ones (for example i2c-stub) appeared in sysfs as devices/virtual/i2c-adapter/i2c-*, which made sense and seemed safe. Now that I have turned them into bus devices, virtual ones appear in sysfs as devices/i2c-* directly, which looks dirty and could result in collisions someday. What should be done about this? I wanted to use
virtual_device_parent()but it is internal to the driver core at the moment, and doesn't even exist ifCONFIG_SYSFS_DEPRECATED=y.
Quoted 4 lines
Yeah, we just need to apply the
/sys/devices/virtuallogic to bus devices too, it's currently limited to class devices, because there was no bus device so far who needed this, but should be an easy change.
It will probably have do be a little different, as it is valid to register a device without a parent, to have it appear at the root (actually 1st level) of the device tree. So we'll need a way to differentiate between this case and the virtual device case.
I admit I am a little surprised that I am the first person asking for virtual bus devices, especially given how you like to repeat that i2c was doing things differently from the rest of the world so far and I am merely changing i2c to fit in the common model.
Quoted 7 lines
Quoted 1 line
I would be grateful if you can advise on any of the above points.
If you decide to do it that way, you would need the driver core to be able:
- to create a link from an otherwise empty "struct class" to an
existing bus-device
- put bus devices without a parent into the/sys/devices/virtuallogic
right? Let me know, I can look into that, if you need that.
Yes, this is a good summary of my needs. With some room for discussion on both points:
* Do we need an actually struct class for each fake class, or just a class name?
* Do we want to put virtual devices in devices/virtual directly, or do we want separate namespaces?
But these are details which can be solved on the way, and I have no strong opinion about them anyway.
Thanks,
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 9 lines · Jean Delvare
Quoted 7 lines · Kay Sievers
Quoted 6 lines
* Now that i2c-core makes use of
device_type, I tried to move the power management handling callbacks there frombus_type, to save a test in each function, however I found that the callback set is different betweenbus_typeand device_type.pm. Why is it so? Is there a document explaining the difference? Is the whole world (includingbus_type) eventually moving todev_pm_ops?
Quoted 5 lines
Quoted 2 lines
I think this is already removed in the current git tree, and all should use
dev_pm_ops, yes.In which git tree? In Linus' tree, struct
bus_typedefinitely doesn't usedev_pm_opsyet.
But it removed all the other stuff:
commit 00725787511e20dbd1fdc1fb233606120ae5c8cf
Author: Magnus Damm <damm-AlSX/UN32fvPDbFq/[email protected]>
Date: Thu Jun 4 22:13:25 2009 +0200
PM: Remove device_type suspend()/resume()
Quoted 19 lines
Quoted 9 lines
Quoted 8 lines
* When i2c-adapters were class devices, virtual ones (for example i2c-stub) appeared in sysfs as devices/virtual/i2c-adapter/i2c-*, which made sense and seemed safe. Now that I have turned them into bus devices, virtual ones appear in sysfs as devices/i2c-* directly, which looks dirty and could result in collisions someday. What should be done about this? I wanted to use
virtual_device_parent()but it is internal to the driver core at the moment, and doesn't even exist ifCONFIG_SYSFS_DEPRECATED=y.Quoted 4 lines
Yeah, we just need to apply the
/sys/devices/virtuallogic to bus devices too, it's currently limited to class devices, because there was no bus device so far who needed this, but should be an easy change.It will probably have do be a little different, as it is valid to register a device without a parent, to have it appear at the root (actually 1st level) of the device tree. So we'll need a way to differentiate between this case and the virtual device case.
Quoted 4 lines
I admit I am a little surprised that I am the first person asking for virtual bus devices, especially given how you like to repeat that i2c was doing things differently from the rest of the world so far and I am merely changing i2c to fit in the common model.
Usually bus devices are a child of root device like pci or some platform stuff. If i2c does not have any parents like this, and is by itself a root for other stuff, maybe we get /sys/devices/i2c, like we have for pci, acpi, ccw (IBM s390), and all these device roots.
Quoted 8 lines
Quoted 7 lines
Quoted 1 line
I would be grateful if you can advise on any of the above points.
If you decide to do it that way, you would need the driver core to be able:
- to create a link from an otherwise empty "struct class" to an existing bus-device
- put bus devices without a parent into the/sys/devices/virtuallogic right? Let me know, I can look into that, if you need that.
Quoted 4 lines
Yes, this is a good summary of my needs. With some room for discussion on both points:
* Do we need an actually struct class for each fake class, or just a class name?
We will need to create a kobject for the compat class directory, we will not need a "struct class" for it and can just use a simple pointer to the registered kobject. If we use a string, we would need to find the registered kobject with every call to create a link there, not necessarily bad, but an explicitely registered object might be easier.
Quoted 4 lines
* Do we want to put virtual devices in devices/virtual directly, or do we want separate namespaces?
But these are details which can be solved on the way, and I have no strong opinion about them anyway.
It's basically the question if these objects usually represent real hardware or not. If the root i2c device just happens to have no other existing bus as a parent, we might just want: /sys/devices/i2c/.
Thanks,
Kay
A message that is not in the archive (sent off-list or not yet received): ac3eb2510907051434i4ee351cbk3db17b50c7e7618b-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Quoted 8 lines · Kay Sievers
Quoted 6 lines · Jean Delvare
Quoted 2 lines · Kay Sievers
I think this is already removed in the current git tree, and all should use
dev_pm_ops, yes.In which git tree? In Linus' tree, struct
bus_typedefinitely doesn't usedev_pm_opsyet.
Quoted 6 lines
But it removed all the other stuff:
commit00725787511e20dbd1fdc1fb233606120ae5c8cf
Author: Magnus Damm <damm-AlSX/UN32fvPDbFq/[email protected]>
Date: Thu Jun 4 22:13:25 2009 +0200PM: Remove
device_typesuspend()/resume()
This is correct but only for device_type. For bus_type, I still can see both suspend/resume and dev_pm_ops. And right now the i2c core is using the suspend/resume flavor. So my question is: how do I convert from suspend/resume to dev_pm_ops? I'm fairly sure I am not the first developer who has to do this, so my hope was that there was either a document explaining the process, or a commit doing this for another subsystem, which I could simply stare at and copy from.
Quoted 15 lines
Quoted 10 lines
Quoted 4 lines
Yeah, we just need to apply the
/sys/devices/virtuallogic to bus devices too, it's currently limited to class devices, because there was no bus device so far who needed this, but should be an easy change.It will probably have do be a little different, as it is valid to register a device without a parent, to have it appear at the root (actually 1st level) of the device tree. So we'll need a way to differentiate between this case and the virtual device case.
Quoted 4 lines
I admit I am a little surprised that I am the first person asking for virtual bus devices, especially given how you like to repeat that i2c was doing things differently from the rest of the world so far and I am merely changing i2c to fit in the common model.
Quoted 4 lines
Usually bus devices are a child of root device like pci or some platform stuff. If i2c does not have any parents like this, and is by itself a root for other stuff, maybe we get
/sys/devices/i2c, like we have for pci, acpi, ccw (IBM s390), and all these device roots.
For physical I2C controller devices, I do expect them to have a parent (either platform or pci in most cases.) i2c-stub is different, it's a software-only driver. So I do not expect that we have /sys/devices/i2c, but I do expect us to have /sys/devices/virtual/i2c or some such.
Quoted 11 lines
Quoted 10 lines
Quoted 5 lines
If you decide to do it that way, you would need the driver core to be able:
- to create a link from an otherwise empty "struct class" to an existing bus-device
- put bus devices without a parent into the/sys/devices/virtuallogic right? Let me know, I can look into that, if you need that.Yes, this is a good summary of my needs. With some room for discussion on both points:
* Do we need an actually struct class for each fake class, or just a class name?
Quoted 6 lines
We will need to create a kobject for the compat class directory, we will not need a "struct class" for it and can just use a simple pointer to the registered kobject. If we use a string, we would need to find the registered kobject with every call to create a link there, not necessarily bad, but an explicitely registered object might be easier.
Any progress on this? I have just committed the patches to sensors-detect and libsensors, and the kernel patch is ready to go, but without the compatibility links it doesn't make any sense to push it upstream, not even in linux-next: lm-sensors would be broken for almost all users.
Quoted 8 lines
Quoted 4 lines
* Do we want to put virtual devices in devices/virtual directly, or do we want separate namespaces?
But these are details which can be solved on the way, and I have no strong opinion about them anyway.It's basically the question if these objects usually represent real hardware or not. If the root i2c device just happens to have no other existing bus as a parent, we might just want:
/sys/devices/i2c/.
In the only case I am aware of at the moment, i2c-stub, no it doesn't represent real hardware.
Note that I don't really care how we handle i2c-stub, BTW. It's really only a developer tool so we don't have to care too much about backwards compatibility etc.
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 10 lines · Jean Delvare
Quoted 9 lines
Quoted 2 lines
* Do we need an actually struct class for each fake class, or just a class name?
We will need to create a kobject for the compat class directory, we will not need a "struct class" for it and can just use a simple pointer to the registered kobject. If we use a string, we would need to find the registered kobject with every call to create a link there, not necessarily bad, but an explicitely registered object might be easier.
Quoted 4 lines
Any progress on this? I have just committed the patches to sensors-detect and libsensors, and the kernel patch is ready to go, but without the compatibility links it doesn't make any sense to push it upstream
Something like this? Please change it as you need. I did only a very quick test.
The only important part is that the kobject of the class directly is not exposed, so nobody else can do weird things with it.
Thanks,
Kay
drivers/base/class.c +39 -0
@@ -488,6 +488,45 @@ void class_interface_unregister(struct cclass_put (parent); } +struct class_compat { +struct kobject *kobj; +}; + +struct class_compat *class_compat_register (const char *name) +{ +struct class_compat *cls; + + cls =kmalloc (sizeof (struct class_compat ),GFP_KERNEL ); +if (!cls) +return NULL ; + cls->kobj =kobject_create_and_add (name, &class_kset->kobj); +if (!cls->kobj) { +kfree (cls); +return NULL ; + } +return cls; +} +EXPORT_SYMBOL_GPL (class_compat_register); + +void class_compat_unregister (struct class_compat *cls) +{ +kobject_put (cls->kobj); +kfree (cls); +} +EXPORT_SYMBOL_GPL (class_compat_unregister); + +int class_compat_create_link (struct class_compat *cls,struct device *dev) +{ +return sysfs_create_link (cls->kobj, &dev->kobj,dev_name (dev)); +} +EXPORT_SYMBOL_GPL (class_compat_create_link); + +void class_compat_remove_link (struct class_compat *cls,struct device *dev) +{ +return sysfs_remove_link (cls->kobj,dev_name (dev)); +} +EXPORT_SYMBOL_GPL (class_compat_remove_link); +int __init classes_init (void ) { class_kset =kset_create_and_add ("class" ,NULL ,NULL );
include/linux/device.h +6 -0
@@ -223,6 +223,12 @@ extern void class_unregister(struct clas__class_register (class, &__key); \ }) +struct class_compat ; +struct class_compat *class_compat_register (const char *name); +void class_compat_unregister (struct class_compat *cls); +int class_compat_create_link (struct class_compat *cls,struct device *dev); +void class_compat_remove_link (struct class_compat *cls,struct device *dev); + extern void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, struct device *start,
A message that is not in the archive (sent off-list or not yet received): 1248296688.2065.4.camel-2/[email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Quoted 44 lines · Kay Sievers
Quoted 4 lines · Jean Delvare
Any progress on this? I have just committed the patches to sensors-detect and libsensors, and the kernel patch is ready to go, but without the compatibility links it doesn't make any sense to push it upstream
Something like this? Please change it as you need. I did only a very quick test.
The only important part is that the kobject of the class directly is not exposed, so nobody else can do weird things with it.
(...)drivers/base/class.c +26
-0@@ -488,6 +488,45 @@ void class_interface_unregister(struct cclass_put (parent); } +struct class_compat { +struct kobject *kobj; +}; + +struct class_compat *class_compat_register (const char *name) +{ +struct class_compat *cls; + + cls =kmalloc (sizeof (struct class_compat ),GFP_KERNEL ); +if (!cls) +return NULL ; + cls->kobj =kobject_create_and_add (name, &class_kset->kobj); +if (!cls->kobj) { +kfree (cls); +return NULL ; + } +return cls; +} +EXPORT_SYMBOL_GPL (class_compat_register); + +void class_compat_unregister (struct class_compat *cls) +{ +kobject_put (cls->kobj); +kfree (cls); +} +EXPORT_SYMBOL_GPL (class_compat_unregister);
drivers/base/class.c void class_interface_unregister(struct c · line 526
Quoted 10 lines
drivers/base/class.c +10
-0+ +int class_compat_create_link (struct class_compat *cls,struct device *dev) +{ +return sysfs_create_link (cls->kobj, &dev->kobj,dev_name (dev)); +} +EXPORT_SYMBOL_GPL (class_compat_create_link); + +void class_compat_remove_link (struct class_compat *cls,struct device *dev) +{ +return sysfs_remove_link (cls->kobj,dev_name (dev));
I don't think you need the "return" here, as sysfs_remove_link returns void.
Quoted 12 lines
drivers/base/class.c +3
-0+} +EXPORT_SYMBOL_GPL (class_compat_remove_link); +int __init classes_init (void ) { class_kset =kset_create_and_add ("class" ,NULL ,NULL );include/linux/device.h +0
-0@@ -223,6 +223,12 @@ extern void class_unregister(struct clas__class_register (class, &__key); \ })
include/linux/device.h extern void class_unregister(struct clas · line 234
Quoted 10 lines
include/linux/device.h +6
-0+struct class_compat ; +struct class_compat *class_compat_register (const char *name); +void class_compat_unregister (struct class_compat *cls); +int class_compat_create_link (struct class_compat *cls,struct device *dev); +void class_compat_remove_link (struct class_compat *cls,struct device *dev); + extern void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, struct device *start,
Other than that (and in practice even with that) your patch works just fine for me. Thanks! Unfortunately it doesn't provide perfect compatibility, because sensors-detect likes to query attributes of the i2c-adapter's parent device (when it is a PCI device) and the lack of device link (now that i2c adapters are bus devices) prevent it from doing so. I will have to check how bad it is for older versions of the script (when I am done moving to my new place, that is.) For the current version, it prevents sensors-detect from being smart on default answers, but that's about it, so it isn't a blocker IMHO. And I'm not really sure if/how this could be addressed anyway. Would it be OK to add this device link (pointing to "..") temporarily or would that be too confusing?
libsensors only needs the adapter's name so the compatibility layer works perfectly there.
Another thing we have to discuss is the compatibility option. For now I've made it i2c-specific and enabled by default:
config I2C_COMPAT
boolean "Enable compatibility bits for old user-space" default y
help
Say Y here if you intend to run lm-sensors 3.1.1 or older.
But this means a lot of ifdefs in my code (6). With a system-wide option, we could provide empty stubs I could get rid of them. OTOH, It is easier to control the lifetime, and change the default value, of a subsystem specific option. So I'm not too sure what do to. Maybe it depends on how many subsystems will need the compatibility layer... Do you have an opinion?
Thanks,
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 6 lines · Jean Delvare
Quoted 1 line · Kay Sievers
+ return
sysfs_remove_link(cls->kobj, dev_name(dev));I don't think you need the "return" here, as
sysfs_remove_linkreturns void.
Fixed. Thanks.
Quoted 4 lines
Other than that (and in practice even with that) your patch works just fine for me. Thanks! Unfortunately it doesn't provide perfect compatibility, [...] to add this device link (pointing to "..") temporarily or would that be too confusing?
I think that's ok, if it solves a real problem. The entire idea of _a_ "device" link is pretty flawed, and the reason we ripped all the "struct class_device" devices out.
Quoted 9 lines
Another thing we have to discuss is the compatibility option. For now I've made it i2c-specific and enabled by default:
config
I2C_COMPAT
boolean "Enable compatibility bits for old user-space" default y
help
Say Y here if you intend to run lm-sensors 3.1.1 or older.
Quoted 4 lines
But this means a lot of ifdefs in my code (6). With a system-wide option, we could provide empty stubs I could get rid of them. OTOH, It is easier to control the lifetime, and change the default value, of a subsystem specific option. So I'm not too sure what do to.
I'm not sure too. I think it's fine to have it per-subsytem, as only the subsystem knows for how long it is needed, and it can probably be dropped some day.
Quoted 3 lines
Maybe it
depends on how many subsystems will need the compatibility layer... Do you have an opinion?
I don't know of any other subsytem needing that, I've seen some just moving things around without taking care about that. :)
Thanks,
Kay
A message that is not in the archive (sent off-list or not yet received): ac3eb2510907230819g1b8edf63g42ffc4c87dbc0cb5-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Quoted 5 lines · Kay Sievers
Quoted 2 lines · Jean Delvare
I don't think you need the "return" here, as
sysfs_remove_linkreturns void.Fixed. Thanks.
What's the merge timeline for this patch?
Quoted 8 lines
Quoted 4 lines
Other than that (and in practice even with that) your patch works just fine for me. Thanks! Unfortunately it doesn't provide perfect compatibility, [...] to add this device link (pointing to "..") temporarily or would that be too confusing?
I think that's ok, if it solves a real problem. The entire idea of _a_ "device" link is pretty flawed, and the reason we ripped all the "struct
class_device" devices out.
OK, I've added the "device" link and now compatibility works perfectly. I'll post the updated patch series soon, if you want to take a look.
Would it make sense to move the "device" link creation into class_compat_create_link()? I suspect other users of a compatibility class may need it as well.
Quoted 9 lines
Quoted 9 lines
Another thing we have to discuss is the compatibility option. For now I've made it i2c-specific and enabled by default:
config
I2C_COMPAT
boolean "Enable compatibility bits for old user-space" default y
help
Say Y here if you intend to run lm-sensors 3.1.1 or older.
Quoted 8 lines
Quoted 4 lines
But this means a lot of ifdefs in my code (6). With a system-wide option, we could provide empty stubs I could get rid of them. OTOH, It is easier to control the lifetime, and change the default value, of a subsystem specific option. So I'm not too sure what do to.
I'm not sure too. I think it's fine to have it per-subsytem, as only the subsystem knows for how long it is needed, and it can probably be dropped some day.
OK, fine with me.
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Quoted 2 lines · Jean Delvare
What's the merge timeline for this patch?
I just did it in the moment you asked, there are no other users so far. Just submit it with your changes that need it, if Greg is ok with that?
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
Other than that (and in practice even with that) your patch works just fine for me. Thanks! Unfortunately it doesn't provide perfect compatibility, [...] to add this device link (pointing to "..") temporarily or would that be too confusing?
I think that's ok, if it solves a real problem. The entire idea of _a_ "device" link is pretty flawed, and the reason we ripped all the "struct
class_device" devices out.OK, I've added the "device" link and now compatibility works perfectly. I'll post the updated patch series soon, if you want to take a look.
Sounds great.
Quoted 3 lines
Would it make sense to move the "device" link creation into
class_compat_create_link()? I suspect other users of a compatibility class may need it as well.
Might make sense, as long as it's not the built-in default.
Sometimes we need to insert devices into the devpath, and then the "device" link does not point to the direct parent, but the next one. So it would need to take another device parameter, if we do that, and also accept NULL, if no such link is really needed.
The "device" link itself is a pretty broken concept, and should be avoided wherever possible, so it should be as optional as we can do it. :)
Thanks,
Kay
A message that is not in the archive (sent off-list or not yet received): ac3eb2510907300812q2d848108ofe1d25801f7b990f-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org
Re: [PATCH] i2c: Do not give adapters a default parent
Hi Kay,
Quoted 7 lines · Kay Sievers
Quoted 2 lines · Jean Delvare
What's the merge timeline for this patch?
I just did it in the moment you asked, there are no other users so far. Just submit it with your changes that need it, if Greg is ok with that?
OK, will do.
Quoted 20 lines
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
Other than that (and in practice even with that) your patch works just fine for me. Thanks! Unfortunately it doesn't provide perfect compatibility, [...] to add this device link (pointing to "..") temporarily or would that be too confusing?
I think that's ok, if it solves a real problem. The entire idea of _a_ "device" link is pretty flawed, and the reason we ripped all the "struct
class_device" devices out.OK, I've added the "device" link and now compatibility works perfectly. I'll post the updated patch series soon, if you want to take a look.
Sounds great.
Quoted 3 lines
Would it make sense to move the "device" link creation into
class_compat_create_link()? I suspect other users of a compatibility class may need it as well.Might make sense, as long as it's not the built-in default.
Quoted 8 lines
Sometimes we need to insert devices into the devpath, and then the "device" link does not point to the direct parent, but the next one. So it would need to take another device parameter, if we do that, and also accept NULL, if no such link is really needed.
The "device" link itself is a pretty broken concept, and should be avoided wherever possible, so it should be as optional as we can do it. :)
Yes, you are perfectly right. I have come up with the following implementation, would that be OK with you? If it is, please add your Signed-off-by.
From: Kay Sievers <[email protected]>
Subject: Add support for compatibility classes
When turning class devices into bus devices, we may need to temporarily add links in sysfs so that user-space applications are not confused. This is done by adding the following API:
* Functions to register and unregister compatibility classes. These appear in sysfs at the same location as regular classes, but instead of class devices, they contain links to bus devices.
* Functions to create and delete such links. Additionally, the caller can optionally pass a target device to which a "device" link should point (typically that would be the device's parent), to fully emulate the original class device.
The i2c subsystem will be the first user of this API, as i2c adapters are being converted from class devices to bus devices.
--- drivers/base/class.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 8 ++++ 2 files changed, 95 insertions(+)
drivers/base/class.c +87 -0
@@ -488,6 +488,93 @@ void class_interface_unregister(struct cclass_put (parent); } +struct class_compat { +struct kobject *kobj; +}; + +/** +* class_compat_register - register a compatibility class +* @name: the name of the class +* +* Compatibility class are meant as a temporary user-space compatibility +* workaround when converting a family of class devices to a bus devices. +*/ +struct class_compat *class_compat_register (const char *name) +{ +struct class_compat *cls; + + cls =kmalloc (sizeof (struct class_compat ),GFP_KERNEL ); +if (!cls) +return NULL ; + cls->kobj =kobject_create_and_add (name, &class_kset->kobj); +if (!cls->kobj) { +kfree (cls); +return NULL ; + } +return cls; +} +EXPORT_SYMBOL_GPL (class_compat_register); + +/** +* class_compat_unregister - unregister a compatibility class +* @cls: the class to unregister +*/ +void class_compat_unregister (struct class_compat *cls) +{ +kobject_put (cls->kobj); +kfree (cls); +} +EXPORT_SYMBOL_GPL (class_compat_unregister); + +/** +* class_compat_create_link - create a compatibility class device link to +* a bus device +* @cls: the compatibility class +* @dev: the target bus device +* @device_link: an optional device to which a "device" link should be created +*/ +int class_compat_create_link (struct class_compat *cls,struct device *dev, +struct device *device_link) +{ +int error; + + error =sysfs_create_link (cls->kobj, &dev->kobj,dev_name (dev)); +if (error) +return error; + +/* +* Optionally add a "device" link (typically to the parent), as a +* class device would have one and we want to provide as much +* backwards compatibility as possible. +*/ +if (device_link) { + error =sysfs_create_link (&dev->kobj, &device_link->kobj, +"device" ); +if (error) +sysfs_remove_link (cls->kobj,dev_name (dev)); + } + +return error; +} +EXPORT_SYMBOL_GPL (class_compat_create_link); + +/** +* class_compat_remove_link - remove a compatibility class device link to +* a bus device +* @cls: the compatibility class +* @dev: the target bus device +* @device_link: an optional device to which a "device" link was previously +* created +*/ +void class_compat_remove_link (struct class_compat *cls,struct device *dev, +struct device *device_link) +{ +if (device_link) +sysfs_remove_link (&dev->kobj,"device" ); +sysfs_remove_link (cls->kobj,dev_name (dev)); +} +EXPORT_SYMBOL_GPL (class_compat_remove_link); +int __init classes_init (void ) { class_kset =kset_create_and_add ("class" ,NULL ,NULL );
include/linux/device.h +8 -0
@@ -223,6 +223,14 @@ extern void class_unregister(struct clas__class_register (class, &__key); \ }) +struct class_compat ; +struct class_compat *class_compat_register (const char *name); +void class_compat_unregister (struct class_compat *cls); +int class_compat_create_link (struct class_compat *cls,struct device *dev, +struct device *device_link); +void class_compat_remove_link (struct class_compat *cls,struct device *dev, +struct device *device_link); + extern void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, struct device *start,
Signature · 1 line
Jean Delvare
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH] i2c: Do not give adapters a default parent
Hey Jean,
Quoted 3 lines · Jean Delvare
I have come up with the following
implementation, would that be OK with you? If it is, please add your Signed-off-by.
Looks all good to me. Feel free to add:
Thanks,
Kay