Commit b433c4c7 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman

usb: Iterator for ports

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.
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20210407065555.88110-4-heikki.krogerus@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 63cd7861
...@@ -398,6 +398,52 @@ int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) ...@@ -398,6 +398,52 @@ int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *))
} }
EXPORT_SYMBOL_GPL(usb_for_each_dev); EXPORT_SYMBOL_GPL(usb_for_each_dev);
struct each_hub_arg {
void *data;
int (*fn)(struct device *, void *);
};
static int __each_hub(struct usb_device *hdev, void *data)
{
struct each_hub_arg *arg = (struct each_hub_arg *)data;
struct usb_hub *hub;
int ret = 0;
int i;
hub = usb_hub_to_struct_hub(hdev);
if (!hub)
return 0;
mutex_lock(&usb_port_peer_mutex);
for (i = 0; i < hdev->maxchild; i++) {
ret = arg->fn(&hub->ports[i]->dev, arg->data);
if (ret)
break;
}
mutex_unlock(&usb_port_peer_mutex);
return ret;
}
/**
* usb_for_each_port - interate over all USB ports in the system
* @data: data pointer that will be handed to the callback function
* @fn: callback function to be called for each USB port
*
* Iterate over all USB ports and call @fn for each, passing it @data. If it
* returns anything other than 0, we break the iteration prematurely and return
* that value.
*/
int usb_for_each_port(void *data, int (*fn)(struct device *, void *))
{
struct each_hub_arg arg = {data, fn};
return usb_for_each_dev(&arg, __each_hub);
}
EXPORT_SYMBOL_GPL(usb_for_each_port);
/** /**
* usb_release_dev - free a usb device structure when all users of it are finished. * usb_release_dev - free a usb device structure when all users of it are finished.
* @dev: device that's been disconnected * @dev: device that's been disconnected
......
...@@ -882,6 +882,15 @@ extern struct usb_host_interface *usb_find_alt_setting( ...@@ -882,6 +882,15 @@ extern struct usb_host_interface *usb_find_alt_setting(
unsigned int iface_num, unsigned int iface_num,
unsigned int alt_num); unsigned int alt_num);
#if IS_REACHABLE(CONFIG_USB)
int usb_for_each_port(void *data, int (*fn)(struct device *, void *));
#else
static inline int usb_for_each_port(void *data, int (*fn)(struct device *, void *))
{
return 0;
}
#endif
/* port claiming functions */ /* port claiming functions */
int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, int usb_hub_claim_port(struct usb_device *hdev, unsigned port1,
struct usb_dev_state *owner); struct usb_dev_state *owner);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment