aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-09-04 13:53:13 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 09:46:39 -0400
commit913a8a344ffcaf0b4a586d6662a2c66a7106557d (patch)
tree07a2a10118ab15bd4c597c1b1460c8028a3b1adc /drivers/usb/host/xhci-mem.c
parent5270b951b9cd5e50aea55cb52684a171fb10381c (diff)
USB: xhci: Change how xHCI commands are handled.
Some commands to the xHCI hardware cannot be allowed to fail due to out of memory issues or the command ring being full. Add a way to reserve a TRB on the command ring, and make all command queueing functions indicate whether they are using a reserved TRB. Add a way to pre-allocate all the memory a command might need. A command needs an input context, a variable to store the status, and (optionally) a completion for the caller to wait on. Change all code that assumes the input device context, status, and completion for a command is stored in the xhci virtual USB device structure (xhci_virt_device). Store pending completions in a FIFO in xhci_virt_device. Make the event handler for a configure endpoint command check to see whether a pending command in the list has completed. We need to use separate input device contexts for some configure endpoint commands, since multiple drivers can submit requests at the same time that require a configure endpoint 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-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 75458ecc8eab..6e6797a38780 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -319,6 +319,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
319 goto fail; 319 goto fail;
320 320
321 init_completion(&dev->cmd_completion); 321 init_completion(&dev->cmd_completion);
322 INIT_LIST_HEAD(&dev->cmd_list);
322 323
323 /* Point to output device context in dcbaa. */ 324 /* Point to output device context in dcbaa. */
324 xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; 325 xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
@@ -624,13 +625,15 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci,
624 * issue a configure endpoint command. 625 * issue a configure endpoint command.
625 */ 626 */
626void xhci_endpoint_copy(struct xhci_hcd *xhci, 627void xhci_endpoint_copy(struct xhci_hcd *xhci,
627 struct xhci_virt_device *vdev, unsigned int ep_index) 628 struct xhci_container_ctx *in_ctx,
629 struct xhci_container_ctx *out_ctx,
630 unsigned int ep_index)
628{ 631{
629 struct xhci_ep_ctx *out_ep_ctx; 632 struct xhci_ep_ctx *out_ep_ctx;
630 struct xhci_ep_ctx *in_ep_ctx; 633 struct xhci_ep_ctx *in_ep_ctx;
631 634
632 out_ep_ctx = xhci_get_ep_ctx(xhci, vdev->out_ctx, ep_index); 635 out_ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
633 in_ep_ctx = xhci_get_ep_ctx(xhci, vdev->in_ctx, ep_index); 636 in_ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
634 637
635 in_ep_ctx->ep_info = out_ep_ctx->ep_info; 638 in_ep_ctx->ep_info = out_ep_ctx->ep_info;
636 in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2; 639 in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2;
@@ -643,13 +646,15 @@ void xhci_endpoint_copy(struct xhci_hcd *xhci,
643 * issue a configure endpoint command. Only the context entries field matters, 646 * issue a configure endpoint command. Only the context entries field matters,
644 * but we'll copy the whole thing anyway. 647 * but we'll copy the whole thing anyway.
645 */ 648 */
646void xhci_slot_copy(struct xhci_hcd *xhci, struct xhci_virt_device *vdev) 649void xhci_slot_copy(struct xhci_hcd *xhci,
650 struct xhci_container_ctx *in_ctx,
651 struct xhci_container_ctx *out_ctx)
647{ 652{
648 struct xhci_slot_ctx *in_slot_ctx; 653 struct xhci_slot_ctx *in_slot_ctx;
649 struct xhci_slot_ctx *out_slot_ctx; 654 struct xhci_slot_ctx *out_slot_ctx;
650 655
651 in_slot_ctx = xhci_get_slot_ctx(xhci, vdev->in_ctx); 656 in_slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
652 out_slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx); 657 out_slot_ctx = xhci_get_slot_ctx(xhci, out_ctx);
653 658
654 in_slot_ctx->dev_info = out_slot_ctx->dev_info; 659 in_slot_ctx->dev_info = out_slot_ctx->dev_info;
655 in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2; 660 in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2;
@@ -754,6 +759,44 @@ static void scratchpad_free(struct xhci_hcd *xhci)
754 xhci->scratchpad = NULL; 759 xhci->scratchpad = NULL;
755} 760}
756 761
762struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
763 bool allocate_completion, gfp_t mem_flags)
764{
765 struct xhci_command *command;
766
767 command = kzalloc(sizeof(*command), mem_flags);
768 if (!command)
769 return NULL;
770
771 command->in_ctx =
772 xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags);
773 if (!command->in_ctx)
774 return NULL;
775
776 if (allocate_completion) {
777 command->completion =
778 kzalloc(sizeof(struct completion), mem_flags);
779 if (!command->completion) {
780 xhci_free_container_ctx(xhci, command->in_ctx);
781 return NULL;
782 }
783 init_completion(command->completion);
784 }
785
786 command->status = 0;
787 INIT_LIST_HEAD(&command->cmd_list);
788 return command;
789}
790
791void xhci_free_command(struct xhci_hcd *xhci,
792 struct xhci_command *command)
793{
794 xhci_free_container_ctx(xhci,
795 command->in_ctx);
796 kfree(command->completion);
797 kfree(command);
798}
799
757void xhci_mem_cleanup(struct xhci_hcd *xhci) 800void xhci_mem_cleanup(struct xhci_hcd *xhci)
758{ 801{
759 struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); 802 struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);