aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-hcd.c')
-rw-r--r--drivers/usb/host/xhci-hcd.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index a01d2ee7435a..5d94b4ffac92 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -509,6 +509,99 @@ void xhci_shutdown(struct usb_hcd *hcd)
509 509
510/*-------------------------------------------------------------------------*/ 510/*-------------------------------------------------------------------------*/
511 511
512/**
513 * xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and
514 * HCDs. Find the index for an endpoint given its descriptor. Use the return
515 * value to right shift 1 for the bitmask.
516 *
517 * Index = (epnum * 2) + direction - 1,
518 * where direction = 0 for OUT, 1 for IN.
519 * For control endpoints, the IN index is used (OUT index is unused), so
520 * index = (epnum * 2) + direction - 1 = (epnum * 2) + 1 - 1 = (epnum * 2)
521 */
522unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc)
523{
524 unsigned int index;
525 if (usb_endpoint_xfer_control(desc))
526 index = (unsigned int) (usb_endpoint_num(desc)*2);
527 else
528 index = (unsigned int) (usb_endpoint_num(desc)*2) +
529 (usb_endpoint_dir_in(desc) ? 1 : 0) - 1;
530 return index;
531}
532
533/* Returns 1 if the arguments are OK;
534 * returns 0 this is a root hub; returns -EINVAL for NULL pointers.
535 */
536int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev,
537 struct usb_host_endpoint *ep, int check_ep, const char *func) {
538 if (!hcd || (check_ep && !ep) || !udev) {
539 printk(KERN_DEBUG "xHCI %s called with invalid args\n",
540 func);
541 return -EINVAL;
542 }
543 if (!udev->parent) {
544 printk(KERN_DEBUG "xHCI %s called for root hub\n",
545 func);
546 return 0;
547 }
548 if (!udev->slot_id) {
549 printk(KERN_DEBUG "xHCI %s called with unaddressed device\n",
550 func);
551 return -EINVAL;
552 }
553 return 1;
554}
555
556/*
557 * non-error returns are a promise to giveback() the urb later
558 * we drop ownership so next owner (or urb unlink) can get it
559 */
560int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags)
561{
562 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
563 unsigned long flags;
564 int ret = 0;
565 unsigned int slot_id, ep_index;
566
567 if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0)
568 return -EINVAL;
569
570 slot_id = urb->dev->slot_id;
571 ep_index = xhci_get_endpoint_index(&urb->ep->desc);
572 /* Only support ep 0 control transfers for now */
573 if (ep_index != 0) {
574 xhci_dbg(xhci, "WARN: urb submitted to unsupported ep %x\n",
575 urb->ep->desc.bEndpointAddress);
576 return -ENOSYS;
577 }
578
579 spin_lock_irqsave(&xhci->lock, flags);
580 if (!xhci->devs || !xhci->devs[slot_id]) {
581 if (!in_interrupt())
582 dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n");
583 return -EINVAL;
584 }
585 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
586 if (!in_interrupt())
587 xhci_dbg(xhci, "urb submitted during PCI suspend\n");
588 ret = -ESHUTDOWN;
589 goto exit;
590 }
591 ret = queue_ctrl_tx(xhci, mem_flags, urb, slot_id, ep_index);
592exit:
593 spin_unlock_irqrestore(&xhci->lock, flags);
594 return ret;
595}
596
597/* Remove from hardware lists
598 * completions normally happen asynchronously
599 */
600int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
601{
602 return -ENOSYS;
603}
604
512/* 605/*
513 * At this point, the struct usb_device is about to go away, the device has 606 * 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 607 * disconnected, and all traffic has been stopped and the endpoints have been