diff options
| -rw-r--r-- | drivers/usb/host/xhci-hcd.c | 88 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 2 |
3 files changed, 89 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index ddb1a6a118eb..4e18f4edf5aa 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c | |||
| @@ -601,6 +601,70 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, | |||
| 601 | return 1; | 601 | return 1; |
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | static int xhci_configure_endpoint(struct xhci_hcd *xhci, | ||
| 605 | struct usb_device *udev, struct xhci_virt_device *virt_dev, | ||
| 606 | bool ctx_change); | ||
| 607 | |||
| 608 | /* | ||
| 609 | * Full speed devices may have a max packet size greater than 8 bytes, but the | ||
| 610 | * USB core doesn't know that until it reads the first 8 bytes of the | ||
| 611 | * descriptor. If the usb_device's max packet size changes after that point, | ||
| 612 | * we need to issue an evaluate context command and wait on it. | ||
| 613 | */ | ||
| 614 | static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, | ||
| 615 | unsigned int ep_index, struct urb *urb) | ||
| 616 | { | ||
| 617 | struct xhci_container_ctx *in_ctx; | ||
| 618 | struct xhci_container_ctx *out_ctx; | ||
| 619 | struct xhci_input_control_ctx *ctrl_ctx; | ||
| 620 | struct xhci_ep_ctx *ep_ctx; | ||
| 621 | int max_packet_size; | ||
| 622 | int hw_max_packet_size; | ||
| 623 | int ret = 0; | ||
| 624 | |||
| 625 | out_ctx = xhci->devs[slot_id]->out_ctx; | ||
| 626 | ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); | ||
| 627 | hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2); | ||
| 628 | max_packet_size = urb->dev->ep0.desc.wMaxPacketSize; | ||
| 629 | if (hw_max_packet_size != max_packet_size) { | ||
| 630 | xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n"); | ||
| 631 | xhci_dbg(xhci, "Max packet size in usb_device = %d\n", | ||
| 632 | max_packet_size); | ||
| 633 | xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n", | ||
| 634 | hw_max_packet_size); | ||
| 635 | xhci_dbg(xhci, "Issuing evaluate context command.\n"); | ||
| 636 | |||
| 637 | /* Set up the modified control endpoint 0 */ | ||
| 638 | xhci_endpoint_copy(xhci, xhci->devs[slot_id], ep_index); | ||
| 639 | in_ctx = xhci->devs[slot_id]->in_ctx; | ||
| 640 | ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); | ||
| 641 | ep_ctx->ep_info2 &= ~MAX_PACKET_MASK; | ||
| 642 | ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size); | ||
| 643 | |||
| 644 | /* Set up the input context flags for the command */ | ||
| 645 | /* FIXME: This won't work if a non-default control endpoint | ||
| 646 | * changes max packet sizes. | ||
| 647 | */ | ||
| 648 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
| 649 | ctrl_ctx->add_flags = EP0_FLAG; | ||
| 650 | ctrl_ctx->drop_flags = 0; | ||
| 651 | |||
| 652 | xhci_dbg(xhci, "Slot %d input context\n", slot_id); | ||
| 653 | xhci_dbg_ctx(xhci, in_ctx, ep_index); | ||
| 654 | xhci_dbg(xhci, "Slot %d output context\n", slot_id); | ||
| 655 | xhci_dbg_ctx(xhci, out_ctx, ep_index); | ||
| 656 | |||
| 657 | ret = xhci_configure_endpoint(xhci, urb->dev, | ||
| 658 | xhci->devs[slot_id], true); | ||
| 659 | |||
| 660 | /* Clean up the input context for later use by bandwidth | ||
| 661 | * functions. | ||
| 662 | */ | ||
| 663 | ctrl_ctx->add_flags = SLOT_FLAG; | ||
| 664 | } | ||
| 665 | return ret; | ||
| 666 | } | ||
| 667 | |||
| 604 | /* | 668 | /* |
| 605 | * non-error returns are a promise to giveback() the urb later | 669 | * non-error returns are a promise to giveback() the urb later |
| 606 | * we drop ownership so next owner (or urb unlink) can get it | 670 | * we drop ownership so next owner (or urb unlink) can get it |
| @@ -612,13 +676,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | |||
| 612 | int ret = 0; | 676 | int ret = 0; |
| 613 | unsigned int slot_id, ep_index; | 677 | unsigned int slot_id, ep_index; |
| 614 | 678 | ||
| 679 | |||
| 615 | if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) | 680 | if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) |
| 616 | return -EINVAL; | 681 | return -EINVAL; |
| 617 | 682 | ||
| 618 | slot_id = urb->dev->slot_id; | 683 | slot_id = urb->dev->slot_id; |
| 619 | ep_index = xhci_get_endpoint_index(&urb->ep->desc); | 684 | ep_index = xhci_get_endpoint_index(&urb->ep->desc); |
| 620 | 685 | ||
| 621 | spin_lock_irqsave(&xhci->lock, flags); | ||
| 622 | if (!xhci->devs || !xhci->devs[slot_id]) { | 686 | if (!xhci->devs || !xhci->devs[slot_id]) { |
| 623 | if (!in_interrupt()) | 687 | if (!in_interrupt()) |
| 624 | dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n"); | 688 | dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n"); |
| @@ -631,19 +695,33 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) | |||
| 631 | ret = -ESHUTDOWN; | 695 | ret = -ESHUTDOWN; |
| 632 | goto exit; | 696 | goto exit; |
| 633 | } | 697 | } |
| 634 | if (usb_endpoint_xfer_control(&urb->ep->desc)) | 698 | if (usb_endpoint_xfer_control(&urb->ep->desc)) { |
| 699 | /* Check to see if the max packet size for the default control | ||
| 700 | * endpoint changed during FS device enumeration | ||
| 701 | */ | ||
| 702 | if (urb->dev->speed == USB_SPEED_FULL) { | ||
| 703 | ret = xhci_check_maxpacket(xhci, slot_id, | ||
| 704 | ep_index, urb); | ||
| 705 | if (ret < 0) | ||
| 706 | return ret; | ||
| 707 | } | ||
| 708 | |||
| 635 | /* We have a spinlock and interrupts disabled, so we must pass | 709 | /* We have a spinlock and interrupts disabled, so we must pass |
| 636 | * atomic context to this function, which may allocate memory. | 710 | * atomic context to this function, which may allocate memory. |
| 637 | */ | 711 | */ |
| 712 | spin_lock_irqsave(&xhci->lock, flags); | ||
| 638 | ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, | 713 | ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, |
| 639 | slot_id, ep_index); | 714 | slot_id, ep_index); |
| 640 | else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) | 715 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 716 | } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) { | ||
| 717 | spin_lock_irqsave(&xhci->lock, flags); | ||
| 641 | ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, | 718 | ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, |
| 642 | slot_id, ep_index); | 719 | slot_id, ep_index); |
| 643 | else | 720 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 721 | } else { | ||
| 644 | ret = -EINVAL; | 722 | ret = -EINVAL; |
| 723 | } | ||
| 645 | exit: | 724 | exit: |
| 646 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
| 647 | return ret; | 725 | return ret; |
| 648 | } | 726 | } |
| 649 | 727 | ||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index ac5c662368ed..ee7fc4500dfb 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
| @@ -701,6 +701,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, | |||
| 701 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); | 701 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); |
| 702 | complete(&xhci->devs[slot_id]->cmd_completion); | 702 | complete(&xhci->devs[slot_id]->cmd_completion); |
| 703 | break; | 703 | break; |
| 704 | case TRB_TYPE(TRB_EVAL_CONTEXT): | ||
| 705 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); | ||
| 706 | complete(&xhci->devs[slot_id]->cmd_completion); | ||
| 707 | break; | ||
| 704 | case TRB_TYPE(TRB_ADDR_DEV): | 708 | case TRB_TYPE(TRB_ADDR_DEV): |
| 705 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); | 709 | xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); |
| 706 | complete(&xhci->addr_dev); | 710 | complete(&xhci->addr_dev); |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a8fe21762052..6aecede77ff6 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
| @@ -601,6 +601,8 @@ struct xhci_ep_ctx { | |||
| 601 | /* bit 7 is Host Initiate Disable - for disabling stream selection */ | 601 | /* bit 7 is Host Initiate Disable - for disabling stream selection */ |
| 602 | #define MAX_BURST(p) (((p)&0xff) << 8) | 602 | #define MAX_BURST(p) (((p)&0xff) << 8) |
| 603 | #define MAX_PACKET(p) (((p)&0xffff) << 16) | 603 | #define MAX_PACKET(p) (((p)&0xffff) << 16) |
| 604 | #define MAX_PACKET_MASK (0xffff << 16) | ||
| 605 | #define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) | ||
| 604 | 606 | ||
| 605 | 607 | ||
| 606 | /** | 608 | /** |
