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: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20210407065555.88110-4-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
63cd786173
commit
b433c4c789
|
@ -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(
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue