aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-08-07 17:04:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:17 -0400
commit2d3f1fac7ee8bb4c6fad40f838488edbeabb0c50 (patch)
treeb1887263a969025bb53f801ca18d0c0a5cf9f34e /drivers/usb/host
parent47aded8ade9fee6779b121b2b156235f261239d7 (diff)
USB: xhci: Support full speed devices.
Full speed devices have varying max packet sizes (8, 16, 32, or 64) for endpoint 0. The xHCI hardware needs to know the real max packet size that the USB core discovers after it fetches the first 8 bytes of the device descriptor. In order to fix this without adding a new hook to host controller drivers, the xHCI driver looks for an updated max packet size for control endpoints. If it finds an updated size, it issues an evaluate context command and waits for that command to finish. This should only happen in the initialization and device descriptor fetching steps in the khubd thread, so blocking should be fine. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/xhci-hcd.c88
-rw-r--r--drivers/usb/host/xhci-ring.c4
-rw-r--r--drivers/usb/host/xhci.h2
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
604static 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 */
614static 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 }
645exit: 724exit:
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/**