Re: [PATCH 1/6] usb: Iterator for ports
From: Alan Stern <stern@rowland.harvard.edu>
Date: 2021-03-25 15:32:41
Also in:
lkml
On Thu, Mar 25, 2021 at 05:14:42PM +0200, Heikki Krogerus wrote:
On Thu, Mar 25, 2021 at 10:41:09AM -0400, Alan Stern wrote:quoted
On Thu, Mar 25, 2021 at 03:29:21PM +0300, Heikki Krogerus wrote:quoted
Introducing usb_for_each_port(). It works the same way as usb_for_each_dev(), but instead of going through every USB device in the system, it walks through the USB ports in the system. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>This has a couple of nasty errors.quoted
--- drivers/usb/core/usb.c | 43 ++++++++++++++++++++++++++++++++++++++++++ include/linux/usb.h | 1 + 2 files changed, 44 insertions(+)diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 2ce3667ec6fae..6d49db9a1b208 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c@@ -398,6 +398,49 @@ int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) } EXPORT_SYMBOL_GPL(usb_for_each_dev); +struct each_hub_arg { + void *data; + int (*fn)(struct device *, void *); +}; + +static int __each_hub(struct device *dev, void *data) +{ + struct each_hub_arg *arg = (struct each_hub_arg *)data; + struct usb_device *hdev = to_usb_device(dev);to_usb_device() won't work properly if the struct device isn't embedded in an actual usb_device structure. And that will happen, since the USB bus type holds usb_interface structures as well as usb_devices.OK, so I need to filter them out.quoted
In fact, you should use usb_for_each_dev here; it already does what you want.Unfortunately I can't use usb_for_each_dev here, because it deals with struct usb_device while I need to deal with struct device in the callback.
I see; the prototypes of arg->fn are different. Oh well, it's a shame the code can't be reused. In any case, you should copy what usb.c:__each_dev() does. Alan Stern
quoted
quoted
+ struct usb_hub *hub; + int ret; + int i; + + hub = usb_hub_to_struct_hub(hdev); + if (!hub) + return 0; + + for (i = 0; i < hdev->maxchild; i++) { + ret = arg->fn(&hub->ports[i]->dev, arg->data); + if (ret) + return ret; + } + + return 0; +}Don't you need some sort of locking or refcounting here? What would happen if this hub got removed while the routine was running?I'll use a lock then. thanks, -- heikki