diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-04-27 22:57:38 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-06-16 00:44:49 -0400 |
commit | 3ffbba9511b4148cbe1f6b6238686adaeaca8feb (patch) | |
tree | f69e42d07d596039e049fe2b14b720ddc6be2694 /drivers/usb/host/xhci-hcd.c | |
parent | c6515272b858742962c1de0f3bf497a048b9abd7 (diff) |
USB: xhci: Allocate and address USB devices
xHCI needs to get a "Slot ID" from the host controller and allocate other
data structures for every USB device. Make usb_alloc_dev() and
usb_release_dev() allocate and free these device structures. After
setting up the xHC device structures, usb_alloc_dev() must wait for the
hardware to respond to an Enable Slot command. usb_alloc_dev() fires off
a Disable Slot command and does not wait for it to complete.
When the USB core wants to choose an address for the device, the xHCI
driver must issue a Set Address command and wait for an event for that
command.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-hcd.c')
-rw-r--r-- | drivers/usb/host/xhci-hcd.c | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index d7c2fed55978..a01d2ee7435a 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c | |||
@@ -318,6 +318,16 @@ void event_ring_work(unsigned long arg) | |||
318 | xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); | 318 | xhci_debug_segment(xhci, xhci->cmd_ring->deq_seg); |
319 | xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); | 319 | xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); |
320 | xhci_dbg_cmd_ptrs(xhci); | 320 | xhci_dbg_cmd_ptrs(xhci); |
321 | for (i = 0; i < MAX_HC_SLOTS; ++i) { | ||
322 | if (xhci->devs[i]) { | ||
323 | for (j = 0; j < 31; ++j) { | ||
324 | if (xhci->devs[i]->ep_rings[j]) { | ||
325 | xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j); | ||
326 | xhci_debug_segment(xhci, xhci->devs[i]->ep_rings[j]->deq_seg); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | } | ||
321 | 331 | ||
322 | if (xhci->noops_submitted != NUM_TEST_NOOPS) | 332 | if (xhci->noops_submitted != NUM_TEST_NOOPS) |
323 | if (setup_one_noop(xhci)) | 333 | if (setup_one_noop(xhci)) |
@@ -499,6 +509,197 @@ void xhci_shutdown(struct usb_hcd *hcd) | |||
499 | 509 | ||
500 | /*-------------------------------------------------------------------------*/ | 510 | /*-------------------------------------------------------------------------*/ |
501 | 511 | ||
512 | /* | ||
513 | * At this point, the struct usb_device is about to go away, the device has | ||
514 | * disconnected, and all traffic has been stopped and the endpoints have been | ||
515 | * disabled. Free any HC data structures associated with that device. | ||
516 | */ | ||
517 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) | ||
518 | { | ||
519 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
520 | unsigned long flags; | ||
521 | |||
522 | if (udev->slot_id == 0) | ||
523 | return; | ||
524 | |||
525 | spin_lock_irqsave(&xhci->lock, flags); | ||
526 | if (queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) { | ||
527 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
528 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | ||
529 | return; | ||
530 | } | ||
531 | ring_cmd_db(xhci); | ||
532 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
533 | /* | ||
534 | * Event command completion handler will free any data structures | ||
535 | * associated with the slot | ||
536 | */ | ||
537 | } | ||
538 | |||
539 | /* | ||
540 | * Returns 0 if the xHC ran out of device slots, the Enable Slot command | ||
541 | * timed out, or allocating memory failed. Returns 1 on success. | ||
542 | */ | ||
543 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) | ||
544 | { | ||
545 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
546 | unsigned long flags; | ||
547 | int timeleft; | ||
548 | int ret; | ||
549 | |||
550 | spin_lock_irqsave(&xhci->lock, flags); | ||
551 | ret = queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); | ||
552 | if (ret) { | ||
553 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
554 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | ||
555 | return 0; | ||
556 | } | ||
557 | ring_cmd_db(xhci); | ||
558 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
559 | |||
560 | /* XXX: how much time for xHC slot assignment? */ | ||
561 | timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, | ||
562 | USB_CTRL_SET_TIMEOUT); | ||
563 | if (timeleft <= 0) { | ||
564 | xhci_warn(xhci, "%s while waiting for a slot\n", | ||
565 | timeleft == 0 ? "Timeout" : "Signal"); | ||
566 | /* FIXME cancel the enable slot request */ | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | spin_lock_irqsave(&xhci->lock, flags); | ||
571 | if (!xhci->slot_id) { | ||
572 | xhci_err(xhci, "Error while assigning device slot ID\n"); | ||
573 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
574 | return 0; | ||
575 | } | ||
576 | if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) { | ||
577 | /* Disable slot, if we can do it without mem alloc */ | ||
578 | xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); | ||
579 | if (!queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) | ||
580 | ring_cmd_db(xhci); | ||
581 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
582 | return 0; | ||
583 | } | ||
584 | udev->slot_id = xhci->slot_id; | ||
585 | /* Is this a LS or FS device under a HS hub? */ | ||
586 | /* Hub or peripherial? */ | ||
587 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
588 | return 1; | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Issue an Address Device command (which will issue a SetAddress request to | ||
593 | * the device). | ||
594 | * We should be protected by the usb_address0_mutex in khubd's hub_port_init, so | ||
595 | * we should only issue and wait on one address command at the same time. | ||
596 | * | ||
597 | * We add one to the device address issued by the hardware because the USB core | ||
598 | * uses address 1 for the root hubs (even though they're not really devices). | ||
599 | */ | ||
600 | int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | ||
601 | { | ||
602 | unsigned long flags; | ||
603 | int timeleft; | ||
604 | struct xhci_virt_device *virt_dev; | ||
605 | int ret = 0; | ||
606 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
607 | u32 temp; | ||
608 | |||
609 | if (!udev->slot_id) { | ||
610 | xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); | ||
611 | return -EINVAL; | ||
612 | } | ||
613 | |||
614 | spin_lock_irqsave(&xhci->lock, flags); | ||
615 | virt_dev = xhci->devs[udev->slot_id]; | ||
616 | |||
617 | /* If this is a Set Address to an unconfigured device, setup ep 0 */ | ||
618 | if (!udev->config) | ||
619 | xhci_setup_addressable_virt_dev(xhci, udev); | ||
620 | /* Otherwise, assume the core has the device configured how it wants */ | ||
621 | |||
622 | ret = queue_address_device(xhci, virt_dev->in_ctx_dma, udev->slot_id); | ||
623 | if (ret) { | ||
624 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
625 | xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); | ||
626 | return ret; | ||
627 | } | ||
628 | ring_cmd_db(xhci); | ||
629 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
630 | |||
631 | /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ | ||
632 | timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, | ||
633 | USB_CTRL_SET_TIMEOUT); | ||
634 | /* FIXME: From section 4.3.4: "Software shall be responsible for timing | ||
635 | * the SetAddress() "recovery interval" required by USB and aborting the | ||
636 | * command on a timeout. | ||
637 | */ | ||
638 | if (timeleft <= 0) { | ||
639 | xhci_warn(xhci, "%s while waiting for a slot\n", | ||
640 | timeleft == 0 ? "Timeout" : "Signal"); | ||
641 | /* FIXME cancel the address device command */ | ||
642 | return -ETIME; | ||
643 | } | ||
644 | |||
645 | spin_lock_irqsave(&xhci->lock, flags); | ||
646 | switch (virt_dev->cmd_status) { | ||
647 | case COMP_CTX_STATE: | ||
648 | case COMP_EBADSLT: | ||
649 | xhci_err(xhci, "Setup ERROR: address device command for slot %d.\n", | ||
650 | udev->slot_id); | ||
651 | ret = -EINVAL; | ||
652 | break; | ||
653 | case COMP_TX_ERR: | ||
654 | dev_warn(&udev->dev, "Device not responding to set address.\n"); | ||
655 | ret = -EPROTO; | ||
656 | break; | ||
657 | case COMP_SUCCESS: | ||
658 | xhci_dbg(xhci, "Successful Address Device command\n"); | ||
659 | break; | ||
660 | default: | ||
661 | xhci_err(xhci, "ERROR: unexpected command completion " | ||
662 | "code 0x%x.\n", virt_dev->cmd_status); | ||
663 | ret = -EINVAL; | ||
664 | break; | ||
665 | } | ||
666 | if (ret) { | ||
667 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
668 | return ret; | ||
669 | } | ||
670 | temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[0]); | ||
671 | xhci_dbg(xhci, "Op regs DCBAA ptr[0] = %#08x\n", temp); | ||
672 | temp = xhci_readl(xhci, &xhci->op_regs->dcbaa_ptr[1]); | ||
673 | xhci_dbg(xhci, "Op regs DCBAA ptr[1] = %#08x\n", temp); | ||
674 | xhci_dbg(xhci, "Slot ID %d dcbaa entry[0] @%08x = %#08x\n", | ||
675 | udev->slot_id, | ||
676 | (unsigned int) &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id], | ||
677 | xhci->dcbaa->dev_context_ptrs[2*udev->slot_id]); | ||
678 | xhci_dbg(xhci, "Slot ID %d dcbaa entry[1] @%08x = %#08x\n", | ||
679 | udev->slot_id, | ||
680 | (unsigned int) &xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1], | ||
681 | xhci->dcbaa->dev_context_ptrs[2*udev->slot_id+1]); | ||
682 | xhci_dbg(xhci, "Output Context DMA address = %#08x\n", | ||
683 | virt_dev->out_ctx_dma); | ||
684 | xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id); | ||
685 | xhci_dbg_ctx(xhci, virt_dev->in_ctx, virt_dev->in_ctx_dma, 2); | ||
686 | xhci_dbg(xhci, "Slot ID %d Output Context:\n", udev->slot_id); | ||
687 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, virt_dev->out_ctx_dma, 2); | ||
688 | /* | ||
689 | * USB core uses address 1 for the roothubs, so we add one to the | ||
690 | * address given back to us by the HC. | ||
691 | */ | ||
692 | udev->devnum = (virt_dev->out_ctx->slot.dev_state & DEV_ADDR_MASK) + 1; | ||
693 | /* FIXME: Zero the input context control for later use? */ | ||
694 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
695 | |||
696 | xhci_dbg(xhci, "Device address = %d\n", udev->devnum); | ||
697 | /* XXX Meh, not sure if anyone else but choose_address uses this. */ | ||
698 | set_bit(udev->devnum, udev->bus->devmap.devicemap); | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
502 | int xhci_get_frame(struct usb_hcd *hcd) | 703 | int xhci_get_frame(struct usb_hcd *hcd) |
503 | { | 704 | { |
504 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 705 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |