--- zzzz-none-000/linux-2.6.32.61/drivers/usb/core/hcd.c 2013-06-10 09:43:48.000000000 +0000 +++ ar10-7272-687/linux-2.6.32.61/drivers/usb/core/hcd.c 2015-04-09 11:31:23.000000000 +0000 @@ -45,7 +45,11 @@ #include "hcd.h" #include "hub.h" - +extern struct usb_host_interface *usb_find_alt_setting( + struct usb_host_config *config, + unsigned int iface_num, + unsigned int alt_num); + /*-------------------------------------------------------------------------*/ /* @@ -1375,6 +1379,9 @@ atomic_inc(&urb->use_count); atomic_inc(&urb->dev->urbnum); usbmon_urb_submit(&hcd->self, urb); +#ifdef AVM_USB_TRACE + avm_usb_trace_submit(hcd, urb); +#endif /* NOTE requirements on root-hub callers (usbfs and the hub * driver, for now): URBs' urb->transfer_buffer must be @@ -1386,6 +1393,9 @@ status = map_urb_for_dma(hcd, urb, mem_flags); if (unlikely(status)) { usbmon_urb_submit_error(&hcd->self, urb, status); +#ifdef AVM_USB_TRACE + avm_usb_trace_error(hcd, urb, status); +#endif goto error; } @@ -1396,6 +1406,9 @@ if (unlikely(status)) { usbmon_urb_submit_error(&hcd->self, urb, status); +#ifdef AVM_USB_TRACE + avm_usb_trace_error(hcd, urb, status); +#endif unmap_urb_for_dma(hcd, urb); error: urb->hcpriv = NULL; @@ -1500,6 +1513,10 @@ unmap_urb_for_dma(hcd, urb); usbmon_urb_complete(&hcd->self, urb, status); +#ifdef AVM_USB_TRACE + avm_usb_trace_complete(hcd, urb, status); +#endif + usb_unanchor_urb(urb); /* pass ownership to the completion handler */ @@ -1589,19 +1606,35 @@ } } -/* Check whether a new configuration or alt setting for an interface - * will exceed the bandwidth for the bus (or the host controller resources). - * Only pass in a non-NULL config or interface, not both! - * Passing NULL for both new_config and new_intf means the device will be - * de-configured by issuing a set configuration 0 command. +/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/ +/** + * usb_hcd_alloc_bandwidth - check whether a new bandwidth setting exceeds + * the bus bandwidth + * @udev: target &usb_device + * @new_config: new configuration to install + * @cur_alt: the current alternate interface setting + * @new_alt: alternate interface setting that is being installed + * + * To change configurations, pass in the new configuration in new_config, + * and pass NULL for cur_alt and new_alt. + * + * To reset a device's configuration (put the device in the ADDRESSED state), + * pass in NULL for new_config, cur_alt, and new_alt. + * + * To change alternate interface settings, pass in NULL for new_config, + * pass in the current alternate interface setting in cur_alt, + * and pass in the new alternate interface setting in new_alt. + * + * Returns an error if the requested bandwidth change exceeds the + * bus bandwidth or host controller internal resources. */ -int usb_hcd_check_bandwidth(struct usb_device *udev, +int usb_hcd_alloc_bandwidth(struct usb_device *udev, struct usb_host_config *new_config, - struct usb_interface *new_intf) + struct usb_host_interface *cur_alt, + struct usb_host_interface *new_alt) { int num_intfs, i, j; - struct usb_interface_cache *intf_cache; - struct usb_host_interface *alt = 0; + struct usb_host_interface *alt = NULL; int ret = 0; struct usb_hcd *hcd; struct usb_host_endpoint *ep; @@ -1611,7 +1644,7 @@ return 0; /* Configuration is being removed - set configuration 0 */ - if (!new_config && !new_intf) { + if (!new_config && !cur_alt) { for (i = 1; i < 16; ++i) { ep = udev->ep_out[i]; if (ep) @@ -1648,19 +1681,17 @@ } } for (i = 0; i < num_intfs; ++i) { + struct usb_host_interface *first_alt; + int iface_num; + + first_alt = &new_config->intf_cache[i]->altsetting[0]; + iface_num = first_alt->desc.bInterfaceNumber; + /* Set up endpoints for alternate interface setting 0 */ + alt = usb_find_alt_setting(new_config, iface_num, 0); + if (!alt) + /* No alt setting 0? Pick the first setting. */ + alt = first_alt; - /* Dig the endpoints for alt setting 0 out of the - * interface cache for this interface - */ - intf_cache = new_config->intf_cache[i]; - for (j = 0; j < intf_cache->num_altsetting; j++) { - if (intf_cache->altsetting[j].desc.bAlternateSetting == 0) - alt = &intf_cache->altsetting[j]; - } - if (!alt) { - printk(KERN_DEBUG "Did not find alt setting 0 for intf %d\n", i); - continue; - } for (j = 0; j < alt->desc.bNumEndpoints; j++) { ret = hcd->driver->add_endpoint(hcd, udev, &alt->endpoint[j]); if (ret < 0) @@ -1668,6 +1699,44 @@ } } } +/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/ + if (cur_alt && new_alt) { + struct usb_interface *iface = usb_ifnum_to_if(udev, + cur_alt->desc.bInterfaceNumber); + + if (!iface) + return -EINVAL; + + if (iface->resetting_device) { + /* + * The USB core just reset the device, so the xHCI host + * and the device will think alt setting 0 is installed. + * However, the USB core will pass in the alternate + * setting installed before the reset as cur_alt. Dig + * out the alternate setting 0 structure, or the first + * alternate setting if a broken device doesn't have alt + * setting 0. + */ + cur_alt = usb_altnum_to_altsetting(iface, 0); + if (!cur_alt) + cur_alt = &iface->altsetting[0]; + } + + /* Drop all the endpoints in the current alt setting */ + for (i = 0; i < cur_alt->desc.bNumEndpoints; i++) { + ret = hcd->driver->drop_endpoint(hcd, udev, + &cur_alt->endpoint[i]); + if (ret < 0) + goto reset; + } + /* Add all the endpoints in the new alt setting */ + for (i = 0; i < new_alt->desc.bNumEndpoints; i++) { + ret = hcd->driver->add_endpoint(hcd, udev, + &new_alt->endpoint[i]); + if (ret < 0) + goto reset; + } + } ret = hcd->driver->check_bandwidth(hcd, udev); reset: if (ret < 0) @@ -1984,6 +2053,8 @@ #ifdef CONFIG_PM INIT_WORK(&hcd->wakeup_work, hcd_resume_work); #endif +/* -- 20140828 AVM/WK XHCI reset patch from newer kernel --*/ + mutex_init(&hcd->bandwidth_mutex); hcd->driver = driver; hcd->product_desc = (driver->product_desc) ? driver->product_desc : @@ -2052,6 +2123,7 @@ retval = -ENOMEM; goto err_allocate_root_hub; } + hcd->self.root_hub = rhdev; switch (hcd->driver->flags & HCD_MASK) { case HCD_USB11: @@ -2064,9 +2136,9 @@ rhdev->speed = USB_SPEED_SUPER; break; default: - goto err_allocate_root_hub; + retval = -EINVAL; + goto err_set_rh_speed; } - hcd->self.root_hub = rhdev; /* wakeup flag init defaults to "everything works" for root hubs, * but drivers can override it in reset() if needed, along with @@ -2137,6 +2209,11 @@ } if (hcd->uses_new_polling && hcd->poll_rh) usb_hcd_poll_rh_status(hcd); + +#ifdef AVM_USB_TRACE + avm_usb_register_trace_device (hcd); +#endif + return retval; error_create_attr_group: @@ -2150,8 +2227,8 @@ free_irq(irqnum, hcd); err_request_irq: err_hcd_driver_setup: - hcd->self.root_hub = NULL; - usb_put_dev(rhdev); +err_set_rh_speed: + usb_put_dev(hcd->self.root_hub); err_allocate_root_hub: usb_deregister_bus(&hcd->self); err_register_bus: @@ -2197,6 +2274,11 @@ if (hcd->irq >= 0) free_irq(hcd->irq, hcd); + +#ifdef AVM_USB_TRACE + avm_usb_deregister_trace_device (hcd); +#endif + usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); }