diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 06e7023258d0..e5a01713f937 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -1401,6 +1401,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1401 | u32 added_ctxs; | 1401 | u32 added_ctxs; |
1402 | unsigned int last_ctx; | 1402 | unsigned int last_ctx; |
1403 | u32 new_add_flags, new_drop_flags, new_slot_info; | 1403 | u32 new_add_flags, new_drop_flags, new_slot_info; |
1404 | struct xhci_virt_device *virt_dev; | ||
1404 | int ret = 0; | 1405 | int ret = 0; |
1405 | 1406 | ||
1406 | ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); | 1407 | ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); |
@@ -1425,11 +1426,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1425 | return 0; | 1426 | return 0; |
1426 | } | 1427 | } |
1427 | 1428 | ||
1428 | in_ctx = xhci->devs[udev->slot_id]->in_ctx; | 1429 | virt_dev = xhci->devs[udev->slot_id]; |
1429 | out_ctx = xhci->devs[udev->slot_id]->out_ctx; | 1430 | in_ctx = virt_dev->in_ctx; |
1431 | out_ctx = virt_dev->out_ctx; | ||
1430 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | 1432 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); |
1431 | ep_index = xhci_get_endpoint_index(&ep->desc); | 1433 | ep_index = xhci_get_endpoint_index(&ep->desc); |
1432 | ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); | 1434 | ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); |
1435 | |||
1436 | /* If this endpoint is already in use, and the upper layers are trying | ||
1437 | * to add it again without dropping it, reject the addition. | ||
1438 | */ | ||
1439 | if (virt_dev->eps[ep_index].ring && | ||
1440 | !(le32_to_cpu(ctrl_ctx->drop_flags) & | ||
1441 | xhci_get_endpoint_flag(&ep->desc))) { | ||
1442 | xhci_warn(xhci, "Trying to add endpoint 0x%x " | ||
1443 | "without dropping it.\n", | ||
1444 | (unsigned int) ep->desc.bEndpointAddress); | ||
1445 | return -EINVAL; | ||
1446 | } | ||
1447 | |||
1433 | /* If the HCD has already noted the endpoint is enabled, | 1448 | /* If the HCD has already noted the endpoint is enabled, |
1434 | * ignore this request. | 1449 | * ignore this request. |
1435 | */ | 1450 | */ |
@@ -1445,8 +1460,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1445 | * process context, not interrupt context (or so documenation | 1460 | * process context, not interrupt context (or so documenation |
1446 | * for usb_set_interface() and usb_set_configuration() claim). | 1461 | * for usb_set_interface() and usb_set_configuration() claim). |
1447 | */ | 1462 | */ |
1448 | if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id], | 1463 | if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) { |
1449 | udev, ep, GFP_NOIO) < 0) { | ||
1450 | dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", | 1464 | dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n", |
1451 | __func__, ep->desc.bEndpointAddress); | 1465 | __func__, ep->desc.bEndpointAddress); |
1452 | return -ENOMEM; | 1466 | return -ENOMEM; |