|
@@ -2678,6 +2678,20 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci,
|
|
|
+ struct xhci_virt_device *vdev, int i)
|
|
|
+{
|
|
|
+ struct xhci_virt_ep *ep = &vdev->eps[i];
|
|
|
+
|
|
|
+ if (ep->ep_state & EP_HAS_STREAMS) {
|
|
|
+ xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on set_interface, freeing streams.\n",
|
|
|
+ xhci_get_endpoint_address(i));
|
|
|
+ xhci_free_stream_info(xhci, ep->stream_info);
|
|
|
+ ep->stream_info = NULL;
|
|
|
+ ep->ep_state &= ~EP_HAS_STREAMS;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* Called after one or more calls to xhci_add_endpoint() or
|
|
|
* xhci_drop_endpoint(). If this call fails, the USB core is expected
|
|
|
* to call xhci_reset_bandwidth().
|
|
@@ -2742,8 +2756,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
/* Free any rings that were dropped, but not changed. */
|
|
|
for (i = 1; i < 31; ++i) {
|
|
|
if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
|
|
|
- !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))))
|
|
|
+ !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1)))) {
|
|
|
xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
|
|
|
+ xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
|
|
|
+ }
|
|
|
}
|
|
|
xhci_zero_in_ctx(xhci, virt_dev);
|
|
|
/*
|
|
@@ -2759,6 +2775,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
if (virt_dev->eps[i].ring) {
|
|
|
xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
|
|
|
}
|
|
|
+ xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
|
|
|
virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
|
|
|
virt_dev->eps[i].new_ring = NULL;
|
|
|
}
|
|
@@ -3519,6 +3536,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
|
|
|
struct xhci_virt_ep *ep = &virt_dev->eps[i];
|
|
|
|
|
|
if (ep->ep_state & EP_HAS_STREAMS) {
|
|
|
+ xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on device reset, freeing streams.\n",
|
|
|
+ xhci_get_endpoint_address(i));
|
|
|
xhci_free_stream_info(xhci, ep->stream_info);
|
|
|
ep->stream_info = NULL;
|
|
|
ep->ep_state &= ~EP_HAS_STREAMS;
|