Merge tag 'usb-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB patches from Greg KH: "Here's the big USB pull request for 3.15-rc1. The normal set of patches, lots of controller driver updates, and a smattering of individual USB driver updates as well. All have been in linux-next for a while" * tag 'usb-3.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (249 commits) xhci: Transition maintainership to Mathias Nyman. USB: disable reset-resume when USB_QUIRK_RESET is set USB: unbind all interfaces before rebinding any usb: phy: Add ulpi IDs for SMSC USB3320 and TI TUSB1210 usb: gadget: tcm_usb_gadget: stop format strings usb: gadget: f_fs: add missing spinlock and mutex unlock usb: gadget: composite: switch over to ERR_CAST() usb: gadget: inode: switch over to memdup_user() usb: gadget: f_subset: switch over to PTR_RET usb: gadget: lpc32xx_udc: fix wrong clk_put() sequence USB: keyspan: remove dead debugging code USB: serial: add missing newlines to dev_<level> messages. USB: serial: add missing braces USB: serial: continue to write on errors USB: serial: continue to read on errors USB: serial: make bulk_out_size a lower limit USB: cypress_m8: fix potential scheduling while atomic devicetree: bindings: document lsi,zevio-usb usb: chipidea: add support for USB OTG controller on LSI Zevio SoCs usb: chipidea: imx: Use dev_name() for ci_hdrc name to distinguish USBs ...
This commit is contained in:
@@ -141,19 +141,27 @@ static int usb_device_supports_lpm(struct usb_device *udev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* All USB 3.0 must support LPM, but we need their max exit latency
|
||||
* information from the SuperSpeed Extended Capabilities BOS descriptor.
|
||||
/*
|
||||
* According to the USB 3.0 spec, all USB 3.0 devices must support LPM.
|
||||
* However, there are some that don't, and they set the U1/U2 exit
|
||||
* latencies to zero.
|
||||
*/
|
||||
if (!udev->bos->ss_cap) {
|
||||
dev_warn(&udev->dev, "No LPM exit latency info found. "
|
||||
"Power management will be impacted.\n");
|
||||
dev_info(&udev->dev, "No LPM exit latency info found, disabling LPM.\n");
|
||||
return 0;
|
||||
}
|
||||
if (udev->parent->lpm_capable)
|
||||
return 1;
|
||||
|
||||
dev_warn(&udev->dev, "Parent hub missing LPM exit latency info. "
|
||||
"Power management will be impacted.\n");
|
||||
if (udev->bos->ss_cap->bU1devExitLat == 0 &&
|
||||
udev->bos->ss_cap->bU2DevExitLat == 0) {
|
||||
if (udev->parent)
|
||||
dev_info(&udev->dev, "LPM exit latency is zeroed, disabling LPM.\n");
|
||||
else
|
||||
dev_info(&udev->dev, "We don't know the algorithms for LPM for this host, disabling LPM.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!udev->parent || udev->parent->lpm_capable)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -499,7 +507,8 @@ static void led_work (struct work_struct *work)
|
||||
changed++;
|
||||
}
|
||||
if (changed)
|
||||
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->leds, LED_CYCLE_PERIOD);
|
||||
}
|
||||
|
||||
/* use a short timeout for hub/port status fetches */
|
||||
@@ -1041,7 +1050,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
if (type == HUB_INIT) {
|
||||
delay = hub_power_on(hub, false);
|
||||
INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
|
||||
schedule_delayed_work(&hub->init_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->init_work,
|
||||
msecs_to_jiffies(delay));
|
||||
|
||||
/* Suppress autosuspend until init is done */
|
||||
@@ -1195,7 +1205,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
/* Don't do a long sleep inside a workqueue routine */
|
||||
if (type == HUB_INIT2) {
|
||||
INIT_DELAYED_WORK(&hub->init_work, hub_init_func3);
|
||||
schedule_delayed_work(&hub->init_work,
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->init_work,
|
||||
msecs_to_jiffies(delay));
|
||||
return; /* Continues at init3: below */
|
||||
} else {
|
||||
@@ -1209,7 +1220,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
|
||||
if (status < 0)
|
||||
dev_err(hub->intfdev, "activate --> %d\n", status);
|
||||
if (hub->has_indicators && blinkenlights)
|
||||
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->leds, LED_CYCLE_PERIOD);
|
||||
|
||||
/* Scan all ports that need attention */
|
||||
kick_khubd(hub);
|
||||
@@ -3095,9 +3107,19 @@ static int finish_port_resume(struct usb_device *udev)
|
||||
* operation is carried out here, after the port has been
|
||||
* resumed.
|
||||
*/
|
||||
if (udev->reset_resume)
|
||||
if (udev->reset_resume) {
|
||||
/*
|
||||
* If the device morphs or switches modes when it is reset,
|
||||
* we don't want to perform a reset-resume. We'll fail the
|
||||
* resume, which will cause a logical disconnect, and then
|
||||
* the device will be rediscovered.
|
||||
*/
|
||||
retry_reset_resume:
|
||||
status = usb_reset_and_verify_device(udev);
|
||||
if (udev->quirks & USB_QUIRK_RESET)
|
||||
status = -ENODEV;
|
||||
else
|
||||
status = usb_reset_and_verify_device(udev);
|
||||
}
|
||||
|
||||
/* 10.5.4.5 says be sure devices in the tree are still there.
|
||||
* For now let's assume the device didn't go crazy on resume,
|
||||
@@ -3960,7 +3982,7 @@ static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
|
||||
connect_type = usb_get_hub_port_connect_type(udev->parent,
|
||||
udev->portnum);
|
||||
|
||||
if ((udev->bos->ext_cap->bmAttributes & USB_BESL_SUPPORT) ||
|
||||
if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
|
||||
connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
|
||||
udev->usb2_hw_lpm_allowed = 1;
|
||||
usb_set_usb2_hardware_lpm(udev, 1);
|
||||
@@ -4109,8 +4131,12 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
|
||||
|
||||
did_new_scheme = true;
|
||||
retval = hub_enable_device(udev);
|
||||
if (retval < 0)
|
||||
if (retval < 0) {
|
||||
dev_err(&udev->dev,
|
||||
"hub failed to enable device, error %d\n",
|
||||
retval);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#define GET_DESCRIPTOR_BUFSIZE 64
|
||||
buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
|
||||
@@ -4313,7 +4339,8 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
|
||||
/* hub LEDs are probably harder to miss than syslog */
|
||||
if (hub->has_indicators) {
|
||||
hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
|
||||
schedule_delayed_work (&hub->leds, 0);
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&hub->leds, 0);
|
||||
}
|
||||
}
|
||||
kfree(qual);
|
||||
@@ -4542,7 +4569,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
|
||||
if (hub->has_indicators) {
|
||||
hub->indicator[port1-1] =
|
||||
INDICATOR_AMBER_BLINK;
|
||||
schedule_delayed_work (&hub->leds, 0);
|
||||
queue_delayed_work(
|
||||
system_power_efficient_wq,
|
||||
&hub->leds, 0);
|
||||
}
|
||||
status = -ENOTCONN; /* Don't retry */
|
||||
goto loop_disable;
|
||||
@@ -4741,6 +4770,8 @@ static void hub_events(void)
|
||||
|
||||
/* deal with port status changes */
|
||||
for (i = 1; i <= hdev->maxchild; i++) {
|
||||
struct usb_device *udev = hub->ports[i - 1]->child;
|
||||
|
||||
if (test_bit(i, hub->busy_bits))
|
||||
continue;
|
||||
connect_change = test_bit(i, hub->change_bits);
|
||||
@@ -4839,8 +4870,6 @@ static void hub_events(void)
|
||||
*/
|
||||
if (hub_port_warm_reset_required(hub, portstatus)) {
|
||||
int status;
|
||||
struct usb_device *udev =
|
||||
hub->ports[i - 1]->child;
|
||||
|
||||
dev_dbg(hub_dev, "warm reset port %d\n", i);
|
||||
if (!udev ||
|
||||
@@ -4857,6 +4886,24 @@ static void hub_events(void)
|
||||
usb_unlock_device(udev);
|
||||
connect_change = 0;
|
||||
}
|
||||
/*
|
||||
* On disconnect USB3 protocol ports transit from U0 to
|
||||
* SS.Inactive to Rx.Detect. If this happens a warm-
|
||||
* reset is not needed, but a (re)connect may happen
|
||||
* before khubd runs and sees the disconnect, and the
|
||||
* device may be an unknown state.
|
||||
*
|
||||
* If the port went through SS.Inactive without khubd
|
||||
* seeing it the C_LINK_STATE change flag will be set,
|
||||
* and we reset the dev to put it in a known state.
|
||||
*/
|
||||
} else if (udev && hub_is_superspeed(hub->hdev) &&
|
||||
(portchange & USB_PORT_STAT_C_LINK_STATE) &&
|
||||
(portstatus & USB_PORT_STAT_CONNECTION)) {
|
||||
usb_lock_device(udev);
|
||||
usb_reset_device(udev);
|
||||
usb_unlock_device(udev);
|
||||
connect_change = 0;
|
||||
}
|
||||
|
||||
if (connect_change)
|
||||
@@ -5114,7 +5161,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct usb_device_descriptor descriptor = udev->descriptor;
|
||||
struct usb_host_bos *bos;
|
||||
int i, ret = 0;
|
||||
int i, j, ret = 0;
|
||||
int port1 = udev->portnum;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED ||
|
||||
@@ -5240,6 +5287,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
||||
ret);
|
||||
goto re_enumerate;
|
||||
}
|
||||
/* Resetting also frees any allocated streams */
|
||||
for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++)
|
||||
intf->cur_altsetting->endpoint[j].streams = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -5342,10 +5392,11 @@ int usb_reset_device(struct usb_device *udev)
|
||||
else if (cintf->condition ==
|
||||
USB_INTERFACE_BOUND)
|
||||
rebind = 1;
|
||||
if (rebind)
|
||||
cintf->needs_binding = 1;
|
||||
}
|
||||
if (ret == 0 && rebind)
|
||||
usb_rebind_intf(cintf);
|
||||
}
|
||||
usb_unbind_and_rebind_marked_interfaces(udev);
|
||||
}
|
||||
|
||||
usb_autosuspend_device(udev);
|
||||
|
||||
Reference in New Issue
Block a user