Message ID | 20221202224744.1447448-2-allenwebb@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v6,1/5] module: Add empty modalias sysfs attribute | expand |
Le 02/12/2022 à 23:47, Allen Webb a écrit : > In order to print the match-id-based modaliases it must be possible to > reach the match id tables of each driver. With this function it becomes > possible to iterate over each subsystem which can be paired with > iterating over each driver. > > Signed-off-by: Allen Webb <allenwebb@google.com> > --- > drivers/base/bus.c | 42 ++++++++++++++++++++++++++++++++++++++ > include/linux/device/bus.h | 1 + > 2 files changed, 43 insertions(+) > > diff --git a/drivers/base/bus.c b/drivers/base/bus.c > index 7ca47e5b3c1f4..4e0c5925545e5 100644 > --- a/drivers/base/bus.c > +++ b/drivers/base/bus.c > @@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = { > > static struct kset *bus_kset; > > +/** > + * bus_for_each - bus iterator. > + * @start: bus to start iterating from. > + * @data: data for the callback. > + * @fn: function to be called for each device. > + * > + * Iterate over list of buses, and call @fn for each, > + * passing it @data. If @start is not NULL, we use that bus to > + * begin iterating from. > + * > + * We check the return of @fn each time. If it returns anything > + * other than 0, we break out and return that value. > + * > + * NOTE: The bus that returns a non-zero value is not retained > + * in any way, nor is its refcount incremented. If the caller needs > + * to retain this data, it should do so, and increment the reference > + * count in the supplied callback. > + */ > +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *)) > +{ > + int error = 0; > + struct bus_type *bus; > + struct subsys_private *bus_prv; > + struct kset *subsys; > + struct kobject *k; Those vars are not used outside of the list_for_each_entry() block, they should be declared inside the block. > + > + spin_lock(&bus_kset->list_lock); > + > + list_for_each_entry(k, &bus_kset->list, entry) { > + subsys = container_of(k, struct kset, kobj); > + bus_prv = container_of(subsys, struct subsys_private, subsys); > + bus = bus_prv->bus; > + error = fn(bus, data); > + if (error) > + break; > + } > + > + spin_unlock(&bus_kset->list_lock); > + return error; > +} > +EXPORT_SYMBOL_GPL(bus_for_each); > + > /* Manually detach a device from its associated driver. */ > static ssize_t unbind_store(struct device_driver *drv, const char *buf, > size_t count) > diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h > index d8b29ccd07e56..82a5583437099 100644 > --- a/include/linux/device/bus.h > +++ b/include/linux/device/bus.h > @@ -161,6 +161,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter, > struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); > void subsys_dev_iter_exit(struct subsys_dev_iter *iter); > > +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *)); > int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, > int (*fn)(struct device *dev, void *data)); > struct device *bus_find_device(struct bus_type *bus, struct device *start,
On Fri, Dec 02, 2022 at 04:47:41PM -0600, Allen Webb wrote: > In order to print the match-id-based modaliases it must be possible to > reach the match id tables of each driver. With this function it becomes > possible to iterate over each subsystem which can be paired with > iterating over each driver. > > Signed-off-by: Allen Webb <allenwebb@google.com> > --- > drivers/base/bus.c | 42 ++++++++++++++++++++++++++++++++++++++ > include/linux/device/bus.h | 1 + > 2 files changed, 43 insertions(+) > > diff --git a/drivers/base/bus.c b/drivers/base/bus.c > index 7ca47e5b3c1f4..4e0c5925545e5 100644 > --- a/drivers/base/bus.c > +++ b/drivers/base/bus.c > @@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = { > > static struct kset *bus_kset; > > +/** > + * bus_for_each - bus iterator. > + * @start: bus to start iterating from. > + * @data: data for the callback. > + * @fn: function to be called for each device. > + * > + * Iterate over list of buses, and call @fn for each, > + * passing it @data. If @start is not NULL, we use that bus to > + * begin iterating from. Where is there a list of all busses in the system? This feels very odd. A bus can list all devices on it, but busses have no relationship to each other at all and are independent. So to iterate over all busses in the system feels very wrong, and again, a layering violation as that would allow non-dependant busses to poke around in other busses. Not something you want to do at all. I guess I don't understand why this is needed, so some justification is required. thanks, greg k-h
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 7ca47e5b3c1f4..4e0c5925545e5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = { static struct kset *bus_kset; +/** + * bus_for_each - bus iterator. + * @start: bus to start iterating from. + * @data: data for the callback. + * @fn: function to be called for each device. + * + * Iterate over list of buses, and call @fn for each, + * passing it @data. If @start is not NULL, we use that bus to + * begin iterating from. + * + * We check the return of @fn each time. If it returns anything + * other than 0, we break out and return that value. + * + * NOTE: The bus that returns a non-zero value is not retained + * in any way, nor is its refcount incremented. If the caller needs + * to retain this data, it should do so, and increment the reference + * count in the supplied callback. + */ +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *)) +{ + int error = 0; + struct bus_type *bus; + struct subsys_private *bus_prv; + struct kset *subsys; + struct kobject *k; + + spin_lock(&bus_kset->list_lock); + + list_for_each_entry(k, &bus_kset->list, entry) { + subsys = container_of(k, struct kset, kobj); + bus_prv = container_of(subsys, struct subsys_private, subsys); + bus = bus_prv->bus; + error = fn(bus, data); + if (error) + break; + } + + spin_unlock(&bus_kset->list_lock); + return error; +} +EXPORT_SYMBOL_GPL(bus_for_each); + /* Manually detach a device from its associated driver. */ static ssize_t unbind_store(struct device_driver *drv, const char *buf, size_t count) diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h index d8b29ccd07e56..82a5583437099 100644 --- a/include/linux/device/bus.h +++ b/include/linux/device/bus.h @@ -161,6 +161,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter); void subsys_dev_iter_exit(struct subsys_dev_iter *iter); +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *)); int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *dev, void *data)); struct device *bus_find_device(struct bus_type *bus, struct device *start,
In order to print the match-id-based modaliases it must be possible to reach the match id tables of each driver. With this function it becomes possible to iterate over each subsystem which can be paired with iterating over each driver. Signed-off-by: Allen Webb <allenwebb@google.com> --- drivers/base/bus.c | 42 ++++++++++++++++++++++++++++++++++++++ include/linux/device/bus.h | 1 + 2 files changed, 43 insertions(+)