Re: [Resend PATCH V3 2/4] usb: move struct usb_device->children to struct usb_hub_port->child

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 13 Jun 2012, Lan Tianyu wrote:

> Move child's pointer to the struct usb_hub_port since the child device
> is directly associated with the port. Provide usb_get_hub_child()
> to get child's pointer and macrio macro usb_get_hub_each_child to
> iterate all child devices on the hub. The child device's refcount will
> be increased before return. The caller should invoke usb_put_dev() to
> decrease the device's refcount when the child will not be used.
> 
> In the usb_get_hub_child(), still check the port1 param since the
> usb_get_hub_each_child() will pass maxchild+1 as port1 at end of last
> loop.
> 
> v3
> add marco usb_get_hub_each_child() to iterate all hub devices
> usb_get_hub_child() increases child's refcount before return

> --- a/drivers/usb/core/devices.c
> +++ b/drivers/usb/core/devices.c

> @@ -589,20 +590,20 @@ 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_get_hub_each_child(usbdev, chix, childdev)
> +		pr_info("%s: %d\n", __func__, chix);
>  		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);
> +			usb_put_dev(childdev);
>  			if (ret == -EFAULT)
>  				return total_written;
>  			total_written += ret;
>  		}
> -	}
> +

This is wrong.  Without any {}'s, only the pr_info() statement is
inside the loop.

Why did you add the pr_info() statement, anyway?

> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c

> @@ -4904,3 +4905,31 @@ void usb_queue_reset_device(struct usb_interface *iface)
>  	schedule_work(&iface->reset_ws);
>  }
>  EXPORT_SYMBOL_GPL(usb_queue_reset_device);
> +
> +/**
> + * usb_get_hub_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. The child device's refcount will be increased
> + * before return. The caller should invoke usb_put_dev() to
> + * decrease the device's refcount when the child will not be
> + * used.

Why bother to do this?  If there's a race, and the child could be
removed after this function returns, then in fact the child could be
removed even while this function is running.  usb_get_dev() won't
protect against that.

> + *
> + * Return NULL if input param is invalid and
> + * child's usb_device pointer if non-NULL.
> + */
> +struct usb_device *usb_get_hub_child(struct usb_device *hdev,
> +	int port1)
> +{
> +	struct usb_hub *hub = hdev_to_hub(hdev);
> +
> +	if (port1 < 1 || port1 > hdev->maxchild)
> +		return NULL;
> +	return usb_get_dev(hub->port_data[port1 - 1].child);

What is the reason for calling usb_get_dev() here?  If the old code
didn't need it, why does the new code?

> --- a/drivers/usb/host/r8a66597-hcd.c
> +++ b/drivers/usb/host/r8a66597-hcd.c
> @@ -2033,18 +2033,18 @@ 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];
> -
> -		if (childdev)
> +	usb_get_hub_each_child(udev, chix, childdev)
> +		if (childdev) {
>  			collect_usb_address_map(childdev, map);
> -	}
> +			usb_put_dev(childdev);
> +		}

The braces you removed aren't strictly necessary, but the code looks
funny without them.  IMO you should keep them.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux