Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff823c79 authored by Lan Tianyu's avatar Lan Tianyu Committed by Greg Kroah-Hartman
Browse files

usb: move children to struct usb_port



The usb_device structure contains an array of usb_device "children".
This array is only valid if the usb_device is a hub, so it makes no
sense to store it there.  Instead, store the usb_device child
in its parent usb_port structure.

Since usb_port is an internal USB core structure, add a new function to
get the USB device child, usb_hub_find_child().  Add a new macro,
usb_hub_get_each_child(), to iterate over all the children attached to a
particular USB hub.

Remove the printing the USB children array pointer from the usb-ip
driver, since it's really not necessary.

Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarLan Tianyu <tianyu.lan@intel.com>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fa2a9566
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -157,8 +157,7 @@ static void usbip_dump_usb_device(struct usb_device *udev)
	dev_dbg(dev, "have_langid %d, string_langid %d\n",
		udev->have_langid, udev->string_langid);

	dev_dbg(dev, "maxchild %d, children %p\n",
		udev->maxchild, udev->children);
	dev_dbg(dev, "maxchild %d\n", udev->maxchild);
}

static void usbip_dump_request_type(__u8 rt)
+3 −4
Original line number Diff line number Diff line
@@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
	char *pages_start, *data_end, *speed;
	unsigned int length;
	ssize_t total_written = 0;
	struct usb_device *childdev = NULL;

	/* don't bother with anything else if we're not writing any data */
	if (*nbytes <= 0)
@@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
	free_pages((unsigned long)pages_start, 1);

	/* Now look at all of this device's children. */
	for (chix = 0; chix < usbdev->maxchild; chix++) {
		struct usb_device *childdev = usbdev->children[chix];

	usb_hub_for_each_child(usbdev, chix, childdev) {
		if (childdev) {
			usb_lock_device(childdev);
			ret = usb_device_dump(buffer, nbytes, skip_bytes,
					      file_offset, childdev, bus,
					      level + 1, chix, ++cnt);
					      level + 1, chix - 1, ++cnt);
			usb_unlock_device(childdev);
			if (ret == -EFAULT)
				return total_written;
+49 −24
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#endif

struct usb_port {
	struct usb_device *child;
	struct device dev;
	struct dev_state *port_owner;
};
@@ -181,7 +182,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus)
/* Note that hdev or one of its children must be locked! */
static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
{
	if (!hdev || !hdev->actconfig)
	if (!hdev || !hdev->actconfig || !hdev->maxchild)
		return NULL;
	return usb_get_intfdata(hdev->actconfig->interface[0]);
}
@@ -876,8 +877,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
	struct usb_device *hdev = hub->hdev;
	int ret = 0;

	if (hdev->children[port1-1] && set_state)
		usb_set_device_state(hdev->children[port1-1],
	if (hub->ports[port1 - 1]->child && set_state)
		usb_set_device_state(hub->ports[port1 - 1]->child,
				USB_STATE_NOTATTACHED);
	if (!hub->error && !hub_is_superspeed(hub->hdev))
		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
@@ -1033,7 +1034,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
	 * which ports need attention.
	 */
	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
		struct usb_device *udev = hdev->children[port1-1];
		struct usb_device *udev = hub->ports[port1 - 1]->child;
		u16 portstatus, portchange;

		portstatus = portchange = 0;
@@ -1198,8 +1199,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
	if (type != HUB_SUSPEND) {
		/* Disconnect all the children */
		for (i = 0; i < hdev->maxchild; ++i) {
			if (hdev->children[i])
				usb_disconnect(&hdev->children[i]);
			if (hub->ports[i]->child)
				usb_disconnect(&hub->ports[i]->child);
		}
	}

@@ -1324,11 +1325,9 @@ static int hub_configure(struct usb_hub *hub,
	dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
		(hdev->maxchild == 1) ? "" : "s");

	hdev->children = kzalloc(hdev->maxchild *
				sizeof(struct usb_device *), GFP_KERNEL);
	hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *),
			     GFP_KERNEL);
	if (!hdev->children || !hub->ports) {
	if (!hub->ports) {
		ret = -ENOMEM;
		goto fail;
	}
@@ -1591,7 +1590,6 @@ static void hub_disconnect(struct usb_interface *intf)
		highspeed_hubs--;

	usb_free_urb(hub->urb);
	kfree(hdev->children);
	kfree(hub->ports);
	kfree(hub->descriptor);
	kfree(hub->status);
@@ -1679,6 +1677,7 @@ static int
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
	struct usb_device *hdev = interface_to_usbdev (intf);
	struct usb_hub *hub = hdev_to_hub(hdev);

	/* assert ifno == 0 (part of hub spec) */
	switch (code) {
@@ -1692,11 +1691,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
		else {
			info->nports = hdev->maxchild;
			for (i = 0; i < info->nports; i++) {
				if (hdev->children[i] == NULL)
				if (hub->ports[i]->child == NULL)
					info->port[i] = 0;
				else
					info->port[i] =
						hdev->children[i]->devnum;
						hub->ports[i]->child->devnum;
			}
		}
		spin_unlock_irq(&device_state_lock);
@@ -1784,11 +1783,12 @@ bool usb_device_is_owned(struct usb_device *udev)

static void recursively_mark_NOTATTACHED(struct usb_device *udev)
{
	struct usb_hub *hub = hdev_to_hub(udev);
	int i;

	for (i = 0; i < udev->maxchild; ++i) {
		if (udev->children[i])
			recursively_mark_NOTATTACHED(udev->children[i]);
		if (hub->ports[i]->child)
			recursively_mark_NOTATTACHED(hub->ports[i]->child);
	}
	if (udev->state == USB_STATE_SUSPENDED)
		udev->active_duration -= jiffies;
@@ -1952,6 +1952,7 @@ static void hub_free_dev(struct usb_device *udev)
void usb_disconnect(struct usb_device **pdev)
{
	struct usb_device	*udev = *pdev;
	struct usb_hub		*hub = hdev_to_hub(udev);
	int			i;

	/* mark the device as inactive, so any further urb submissions for
@@ -1966,8 +1967,8 @@ void usb_disconnect(struct usb_device **pdev)

	/* Free up all the children before we remove this device */
	for (i = 0; i < udev->maxchild; i++) {
		if (udev->children[i])
			usb_disconnect(&udev->children[i]);
		if (hub->ports[i]->child)
			usb_disconnect(&hub->ports[i]->child);
	}

	/* deallocate hcd/hardware state ... nuking all pending urbs and
@@ -3131,7 +3132,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
		struct usb_device	*udev;

		udev = hdev->children [port1-1];
		udev = hub->ports[port1 - 1]->child;
		if (udev && udev->can_submit) {
			dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
			if (PMSG_IS_AUTO(msg))
@@ -4058,7 +4059,7 @@ hub_power_remaining (struct usb_hub *hub)

	remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
		struct usb_device	*udev = hdev->children[port1 - 1];
		struct usb_device	*udev = hub->ports[port1 - 1]->child;
		int			delta;

		if (!udev)
@@ -4122,7 +4123,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
#endif

	/* Try to resuscitate an existing device */
	udev = hdev->children[port1-1];
	udev = hub->ports[port1 - 1]->child;
	if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
			udev->state != USB_STATE_NOTATTACHED) {
		usb_lock_device(udev);
@@ -4151,7 +4152,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,

	/* Disconnect any existing devices under this port */
	if (udev)
		usb_disconnect(&hdev->children[port1-1]);
		usb_disconnect(&hub->ports[port1 - 1]->child);
	clear_bit(port1, hub->change_bits);

	/* We can forget about a "removed" device when there's a physical
@@ -4287,7 +4288,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
		if (hdev->state == USB_STATE_NOTATTACHED)
			status = -ENOTCONN;
		else
			hdev->children[port1-1] = udev;
			hub->ports[port1 - 1]->child = udev;
		spin_unlock_irq(&device_state_lock);

		/* Run it through the hoops (find a driver, etc) */
@@ -4295,7 +4296,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
			status = usb_new_device(udev);
			if (status) {
				spin_lock_irq(&device_state_lock);
				hdev->children[port1-1] = NULL;
				hub->ports[port1 - 1]->child = NULL;
				spin_unlock_irq(&device_state_lock);
			}
		}
@@ -4341,7 +4342,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
	int ret;

	hdev = hub->hdev;
	udev = hdev->children[port-1];
	udev = hub->ports[port - 1]->child;
	if (!hub_is_superspeed(hdev)) {
		if (!(portchange & USB_PORT_STAT_C_SUSPEND))
			return 0;
@@ -4495,7 +4496,7 @@ static void hub_events(void)
				 */
				if (!(portstatus & USB_PORT_STAT_ENABLE)
				    && !connect_change
				    && hdev->children[i-1]) {
				    && hub->ports[i - 1]->child) {
					dev_err (hub_dev,
					    "port %i "
					    "disabled by hub (EMI?), "
@@ -5052,3 +5053,27 @@ void usb_queue_reset_device(struct usb_interface *iface)
	schedule_work(&iface->reset_ws);
}
EXPORT_SYMBOL_GPL(usb_queue_reset_device);

/**
 * usb_hub_find_child - Get the pointer of child device
 * attached to the port which is specified by @port1.
 * @hdev: USB device belonging to the usb hub
 * @port1: port num to indicate which port the child device
 *	is attached to.
 *
 * USB drivers call this function to get hub's child device
 * pointer.
 *
 * Return NULL if input param is invalid and
 * child's usb_device pointer if non-NULL.
 */
struct usb_device *usb_hub_find_child(struct usb_device *hdev,
		int port1)
{
	struct usb_hub *hub = hdev_to_hub(hdev);

	if (port1 < 1 || port1 > hdev->maxchild)
		return NULL;
	return hub->ports[port1 - 1]->child;
}
EXPORT_SYMBOL_GPL(usb_hub_find_child);
+2 −3
Original line number Diff line number Diff line
@@ -2029,15 +2029,14 @@ static int r8a66597_get_frame(struct usb_hcd *hcd)
static void collect_usb_address_map(struct usb_device *udev, unsigned long *map)
{
	int chix;
	struct usb_device *childdev;

	if (udev->state == USB_STATE_CONFIGURED &&
	    udev->parent && udev->parent->devnum > 1 &&
	    udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB)
		map[udev->devnum/32] |= (1 << (udev->devnum % 32));

	for (chix = 0; chix < udev->maxchild; chix++) {
		struct usb_device *childdev = udev->children[chix];

	usb_hub_for_each_child(udev, chix, childdev) {
		if (childdev)
			collect_usb_address_map(childdev, map);
	}
+13 −2
Original line number Diff line number Diff line
@@ -469,7 +469,6 @@ struct usb3_lpm_parameters {
 *	access from userspace
 * @usbfs_dentry: usbfs dentry entry for the device
 * @maxchild: number of ports if hub
 * @children: child devices - USB devices that are attached to this hub
 * @quirks: quirks of the whole device
 * @urbnum: number of URBs submitted for the whole device
 * @active_duration: total time device is not suspended
@@ -543,7 +542,6 @@ struct usb_device {
	struct list_head filelist;

	int maxchild;
	struct usb_device **children;

	u32 quirks;
	atomic_t urbnum;
@@ -572,6 +570,19 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf)

extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
extern struct usb_device *usb_hub_find_child(struct usb_device *hdev,
	int port1);

/**
 * usb_hub_for_each_child - iterate over all child devices on the hub
 * @hdev:  USB device belonging to the usb hub
 * @port1: portnum associated with child device
 * @child: child device pointer
 */
#define usb_hub_for_each_child(hdev, port1, child) \
	for (port1 = 1,	child =	usb_hub_find_child(hdev, port1); \
		port1 <= hdev->maxchild; \
		child = usb_hub_find_child(hdev, ++port1))

/* USB device locking */
#define usb_lock_device(udev)		device_lock(&(udev)->dev)