|
@@ -4944,7 +4944,8 @@ void usb_hub_cleanup(void)
|
|
|
} /* usb_hub_cleanup() */
|
|
|
|
|
|
static int descriptors_changed(struct usb_device *udev,
|
|
|
- struct usb_device_descriptor *old_device_descriptor)
|
|
|
+ struct usb_device_descriptor *old_device_descriptor,
|
|
|
+ struct usb_host_bos *old_bos)
|
|
|
{
|
|
|
int changed = 0;
|
|
|
unsigned index;
|
|
@@ -4958,6 +4959,16 @@ static int descriptors_changed(struct usb_device *udev,
|
|
|
sizeof(*old_device_descriptor)) != 0)
|
|
|
return 1;
|
|
|
|
|
|
+ if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
|
|
|
+ return 1;
|
|
|
+ if (udev->bos) {
|
|
|
+ len = udev->bos->desc->wTotalLength;
|
|
|
+ if (len != old_bos->desc->wTotalLength)
|
|
|
+ return 1;
|
|
|
+ if (memcmp(udev->bos->desc, old_bos->desc, le16_to_cpu(len)))
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
/* Since the idVendor, idProduct, and bcdDevice values in the
|
|
|
* device descriptor haven't changed, we will assume the
|
|
|
* Manufacturer and Product strings haven't changed either.
|
|
@@ -5054,6 +5065,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|
|
struct usb_hub *parent_hub;
|
|
|
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 port1 = udev->portnum;
|
|
|
|
|
@@ -5071,6 +5083,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|
|
}
|
|
|
parent_hub = usb_hub_to_struct_hub(parent_hdev);
|
|
|
|
|
|
+ bos = udev->bos;
|
|
|
+ udev->bos = NULL;
|
|
|
+
|
|
|
/* Disable LPM and LTM while we reset the device and reinstall the alt
|
|
|
* settings. Device-initiated LPM settings, and system exit latency
|
|
|
* settings are cleared when the device is reset, so we have to set
|
|
@@ -5104,7 +5119,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
|
|
|
goto re_enumerate;
|
|
|
|
|
|
/* Device might have changed firmware (DFU or similar) */
|
|
|
- if (descriptors_changed(udev, &descriptor)) {
|
|
|
+ if (descriptors_changed(udev, &descriptor, bos)) {
|
|
|
dev_info(&udev->dev, "device firmware changed\n");
|
|
|
udev->descriptor = descriptor; /* for disconnect() calls */
|
|
|
goto re_enumerate;
|
|
@@ -5177,11 +5192,15 @@ done:
|
|
|
/* Now that the alt settings are re-installed, enable LTM and LPM. */
|
|
|
usb_unlocked_enable_lpm(udev);
|
|
|
usb_enable_ltm(udev);
|
|
|
+ usb_release_bos_descriptor(udev);
|
|
|
+ udev->bos = bos;
|
|
|
return 0;
|
|
|
|
|
|
re_enumerate:
|
|
|
/* LPM state doesn't matter when we're about to destroy the device. */
|
|
|
hub_port_logical_disconnect(parent_hub, port1);
|
|
|
+ usb_release_bos_descriptor(udev);
|
|
|
+ udev->bos = bos;
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
|