--- zzzz-none-000/linux-3.10.107/drivers/usb/core/usb.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/usb/core/usb.c 2021-02-04 17:41:59.000000000 +0000 @@ -49,9 +49,30 @@ static bool nousb; /* Disable USB when built into kernel image */ -#ifdef CONFIG_PM_RUNTIME +/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */ +#ifdef MODULE +module_param(nousb, bool, 0444); +#else +core_param(nousb, nousb, bool, 0444); +#endif + +/* + * for external read access to + */ +int usb_disabled(void) +{ + return nousb; +} +EXPORT_SYMBOL_GPL(usb_disabled); + +#ifdef CONFIG_PM +#ifdef CONFIG_AVM_USB_PM +static int usb_autosuspend_delay = 60; /* Default delay value, + * in seconds */ +#else static int usb_autosuspend_delay = 2; /* Default delay value, * in seconds */ +#endif module_param_named(autosuspend, usb_autosuspend_delay, int, 0644); MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); @@ -68,6 +89,8 @@ * @alt_num: alternate interface setting number to search for. * * Search the configuration's interface cache for the given alt setting. + * + * Return: The alternate setting, if found. %NULL otherwise. */ struct usb_host_interface *usb_find_alt_setting( struct usb_host_config *config, @@ -103,8 +126,7 @@ * @ifnum: the desired interface * * This walks the device descriptor for the currently active configuration - * and returns a pointer to the interface with that particular interface - * number, or null. + * to find the interface object with the particular interface number. * * Note that configuration descriptors are not required to assign interface * numbers sequentially, so that it would be incorrect to assume that @@ -115,6 +137,9 @@ * * Don't call this function unless you are bound to one of the interfaces * on this device or you have locked the device! + * + * Return: A pointer to the interface that has @ifnum as interface number, + * if found. %NULL otherwise. */ struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum) @@ -139,8 +164,7 @@ * @altnum: the desired alternate setting number * * This searches the altsetting array of the specified interface for - * an entry with the correct bAlternateSetting value and returns a pointer - * to that entry, or null. + * an entry with the correct bAlternateSetting value. * * Note that altsettings need not be stored sequentially by number, so * it would be incorrect to assume that the first altsetting entry in @@ -149,6 +173,9 @@ * * Don't call this function unless you are bound to the intf interface * or you have locked the device! + * + * Return: A pointer to the entry of the altsetting array of @intf that + * has @altnum as the alternate setting number. %NULL if not found. */ struct usb_host_interface *usb_altnum_to_altsetting( const struct usb_interface *intf, @@ -191,6 +218,8 @@ * This walks the bus device list and returns a pointer to the interface * with the matching minor and driver. Note, this only works for devices * that share the USB major number. + * + * Return: A pointer to the interface with the matching major and @minor. */ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { @@ -209,6 +238,39 @@ } EXPORT_SYMBOL_GPL(usb_find_interface); +struct each_dev_arg { + void *data; + int (*fn)(struct usb_device *, void *); +}; + +static int __each_dev(struct device *dev, void *data) +{ + struct each_dev_arg *arg = (struct each_dev_arg *)data; + + /* There are struct usb_interface on the same bus, filter them out */ + if (!is_usb_device(dev)) + return 0; + + return arg->fn(container_of(dev, struct usb_device, dev), arg->data); +} + +/** + * usb_for_each_dev - iterate over all USB devices in the system + * @data: data pointer that will be handed to the callback function + * @fn: callback function to be called for each USB device + * + * Iterate over all USB devices 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_dev(void *data, int (*fn)(struct usb_device *, void *)) +{ + struct each_dev_arg arg = {data, fn}; + + return bus_for_each_dev(&usb_bus_type, NULL, &arg, __each_dev); +} +EXPORT_SYMBOL_GPL(usb_for_each_dev); + /** * usb_release_dev - free a usb device structure when all users of it are finished. * @dev: device that's been disconnected @@ -307,11 +369,9 @@ .thaw = usb_dev_thaw, .poweroff = usb_dev_poweroff, .restore = usb_dev_restore, -#ifdef CONFIG_PM_RUNTIME .runtime_suspend = usb_runtime_suspend, .runtime_resume = usb_runtime_resume, .runtime_idle = usb_runtime_idle, -#endif }; #endif /* CONFIG_PM */ @@ -357,6 +417,9 @@ * controllers) should ever call this. * * This call may not be used in a non-sleeping context. + * + * Return: On success, a pointer to the allocated usb device. %NULL on + * failure. */ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) @@ -452,11 +515,12 @@ if (root_hub) /* Root hub always ok [and always wired] */ dev->authorized = 1; else { - dev->authorized = usb_hcd->authorized_default; - dev->wusb = usb_bus_is_wusb(bus)? 1 : 0; + dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd); + dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0; } return dev; } +EXPORT_SYMBOL_GPL(usb_alloc_dev); /** * usb_get_dev - increments the reference count of the usb device structure @@ -468,7 +532,7 @@ * their probe() methods, when they bind to an interface, and release * them by calling usb_put_dev(), in their disconnect() methods. * - * A pointer to the device with the incremented reference counter is returned. + * Return: A pointer to the device with the incremented reference counter. */ struct usb_device *usb_get_dev(struct usb_device *dev) { @@ -502,8 +566,7 @@ * their probe() methods, when they bind to an interface, and release * them by calling usb_put_intf(), in their disconnect() methods. * - * A pointer to the interface with the incremented reference counter is - * returned. + * Return: A pointer to the interface with the incremented reference counter. */ struct usb_interface *usb_get_intf(struct usb_interface *intf) { @@ -556,7 +619,7 @@ * disconnect; in some drivers (such as usb-storage) the disconnect() * or suspend() method will block waiting for a device reset to complete. * - * Returns a negative error code for failure, otherwise 0. + * Return: A negative error code for failure, otherwise 0. */ int usb_lock_device_for_reset(struct usb_device *udev, const struct usb_interface *iface) @@ -595,14 +658,15 @@ * usb_get_current_frame_number - return current bus frame number * @dev: the device whose bus is being queried * - * Returns the current frame number for the USB host controller - * used with the given USB device. This can be used when scheduling + * Return: The current frame number for the USB host controller used + * with the given USB device. This can be used when scheduling * isochronous requests. * - * Note that different kinds of host controller have different - * "scheduling horizons". While one type might support scheduling only - * 32 frames into the future, others could support scheduling up to - * 1024 frames into the future. + * Note: Different kinds of host controller have different "scheduling + * horizons". While one type might support scheduling only 32 frames + * into the future, others could support scheduling up to 1024 frames + * into the future. + * */ int usb_get_current_frame_number(struct usb_device *dev) { @@ -617,14 +681,14 @@ */ int __usb_get_extra_descriptor(char *buffer, unsigned size, - unsigned char type, void **ptr) + unsigned char type, void **ptr, size_t minsize) { struct usb_descriptor_header *header; while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; - if (header->bLength < 2) { + if (header->bLength < 2 || header->bLength > size) { printk(KERN_ERR "%s: bogus descriptor, type %d length %d\n", usbcore_name, @@ -633,7 +697,7 @@ return -1; } - if (header->bDescriptorType == type) { + if (header->bDescriptorType == type && header->bLength >= minsize) { *ptr = header; return 0; } @@ -645,6 +709,71 @@ } EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor); +static struct usb_device *match_device_name(struct usb_device *dev, + const char *name) +{ + struct usb_device *ret_dev = NULL; + struct usb_device *childdev = NULL; + int child; + + dev_dbg(&dev->dev, "check for name %s ...\n", name); + + /* see if this device matches */ + if (strcmp(dev_name(&dev->dev), name) == 0 ) { + dev_dbg(&dev->dev, "matched this device!\n"); + ret_dev = usb_get_dev(dev); + goto exit; + } + /* look through all of the children of this device */ + usb_hub_for_each_child(dev, child, childdev) { + if (childdev) { + usb_lock_device(childdev); + ret_dev = match_device_name(childdev, name); + usb_unlock_device(childdev); + if (ret_dev) + goto exit; + } + } +exit: + return ret_dev; +} + +/** + * usb_find_device_by_name - find a specific usb device in the system + * @name: the name of the device to find + * + * Returns a pointer to a struct usb_device if such a specified usb + * device is present in the system currently. The usage count of the + * device will be incremented if a device is found. Make sure to call + * usb_put_dev() when the caller is finished with the device. + * + * If a device with the specified bus id is not found, NULL is returned. + */ +struct usb_device *usb_find_device_by_name(const char *name) +{ + struct list_head *buslist; + struct usb_bus *bus; + struct usb_device *dev = NULL; + + mutex_lock(&usb_bus_list_lock); + for (buslist = usb_bus_list.next; + buslist != &usb_bus_list; + buslist = buslist->next) { + bus = container_of(buslist, struct usb_bus, bus_list); + if (!bus->root_hub) + continue; + usb_lock_device(bus->root_hub); + dev = match_device_name(bus->root_hub, name); + usb_unlock_device(bus->root_hub); + if (dev) + goto exit; + } +exit: + mutex_unlock(&usb_bus_list_lock); + return dev; +} +EXPORT_SYMBOL_GPL(usb_find_device_by_name); + /** * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP * @dev: device the buffer will be used with @@ -652,11 +781,12 @@ * @mem_flags: affect whether allocation may block * @dma: used to return DMA address of buffer * - * Return value is either null (indicating no buffer could be allocated), or - * the cpu-space pointer to a buffer that may be used to perform DMA to the + * Return: Either null (indicating no buffer could be allocated), or the + * cpu-space pointer to a buffer that may be used to perform DMA to the * specified device. Such cpu-space buffers are returned along with the DMA * address (through the pointer provided). * + * Note: * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU * hardware during URB completion/resubmit. The implementation varies between @@ -702,17 +832,18 @@ * usb_buffer_map - create DMA mapping(s) for an urb * @urb: urb whose transfer_buffer/setup_packet will be mapped * - * Return value is either null (indicating no buffer could be mapped), or - * the parameter. URB_NO_TRANSFER_DMA_MAP is - * added to urb->transfer_flags if the operation succeeds. If the device - * is connected to this system through a non-DMA controller, this operation - * always succeeds. + * URB_NO_TRANSFER_DMA_MAP is added to urb->transfer_flags if the operation + * succeeds. If the device is connected to this system through a non-DMA + * controller, this operation always succeeds. * * This call would normally be used for an urb which is reused, perhaps * as the target of a large periodic transfer, with usb_buffer_dmasync() * calls to synchronize memory and dma state. * * Reverse the effect of this call with usb_buffer_unmap(). + * + * Return: Either %NULL (indicating no buffer could be mapped), or @urb. + * */ #if 0 struct urb *usb_buffer_map(struct urb *urb) @@ -817,9 +948,10 @@ * @sg: the scatterlist to map * @nents: the number of entries in the scatterlist * - * Return value is either < 0 (indicating no buffers could be mapped), or - * the number of DMA mapping array entries in the scatterlist. + * Return: Either < 0 (indicating no buffers could be mapped), or the + * number of DMA mapping array entries in the scatterlist. * + * Note: * The caller is responsible for placing the resulting DMA addresses from * the scatterlist into URB transfer buffer pointers, and for setting the * URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs. @@ -918,22 +1050,6 @@ EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg); #endif -/* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */ -#ifdef MODULE -module_param(nousb, bool, 0444); -#else -core_param(nousb, nousb, bool, 0444); -#endif - -/* - * for external read access to - */ -int usb_disabled(void) -{ - return nousb; -} -EXPORT_SYMBOL_GPL(usb_disabled); - /* * Notifications of device and interface registration */ @@ -999,7 +1115,7 @@ static int __init usb_init(void) { int retval; - if (nousb) { + if (usb_disabled()) { pr_info("%s: USB support disabled\n", usbcore_name); return 0; } @@ -1056,7 +1172,7 @@ static void __exit usb_exit(void) { /* This will matter if shutdown/reboot does exitcalls. */ - if (nousb) + if (usb_disabled()) return; usb_deregister_device_driver(&usb_generic_driver);