Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: xhci: Support interrupt transfers.

Interrupt transfers are submitted to the xHCI hardware using the same TRB
type as bulk transfers. Re-use the bulk transfer enqueueing code to
enqueue interrupt transfers.

Interrupt transfers are a bit different than bulk transfers. When the
interrupt endpoint is to be serviced, the xHC will consume (at most) one
TD. A TD (comprised of sg list entries) can take several service
intervals to transmit. The important thing for device drivers to note is
that if they use the scatter gather interface to submit interrupt
requests, they will not get data sent from two different scatter gather
lists in the same service interval.

For now, the xHCI driver will use the service interval from the endpoint's
descriptor (bInterval). Drivers will need a hook to poll at a more
frequent interval. Set urb->interval to the interval that the xHCI
hardware will use.

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>

authored by

Sarah Sharp and committed by
Greg Kroah-Hartman
624defa1 2f697f6c

+55 -1
+5
drivers/usb/host/xhci-hcd.c
··· 727 727 ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, 728 728 slot_id, ep_index); 729 729 spin_unlock_irqrestore(&xhci->lock, flags); 730 + } else if (usb_endpoint_xfer_int(&urb->ep->desc)) { 731 + spin_lock_irqsave(&xhci->lock, flags); 732 + ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, 733 + slot_id, ep_index); 734 + spin_unlock_irqrestore(&xhci->lock, flags); 730 735 } else { 731 736 ret = -EINVAL; 732 737 }
+47 -1
drivers/usb/host/xhci-ring.c
··· 1072 1072 else 1073 1073 status = 0; 1074 1074 } else { 1075 - xhci_dbg(xhci, "Successful bulk transfer!\n"); 1075 + if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) 1076 + xhci_dbg(xhci, "Successful bulk " 1077 + "transfer!\n"); 1078 + else 1079 + xhci_dbg(xhci, "Successful interrupt " 1080 + "transfer!\n"); 1076 1081 status = 0; 1077 1082 } 1078 1083 break; ··· 1467 1462 wmb(); 1468 1463 start_trb->field[3] |= start_cycle; 1469 1464 ring_ep_doorbell(xhci, slot_id, ep_index); 1465 + } 1466 + 1467 + /* 1468 + * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt 1469 + * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD 1470 + * (comprised of sg list entries) can take several service intervals to 1471 + * transmit. 1472 + */ 1473 + int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, 1474 + struct urb *urb, int slot_id, unsigned int ep_index) 1475 + { 1476 + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, 1477 + xhci->devs[slot_id]->out_ctx, ep_index); 1478 + int xhci_interval; 1479 + int ep_interval; 1480 + 1481 + xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); 1482 + ep_interval = urb->interval; 1483 + /* Convert to microframes */ 1484 + if (urb->dev->speed == USB_SPEED_LOW || 1485 + urb->dev->speed == USB_SPEED_FULL) 1486 + ep_interval *= 8; 1487 + /* FIXME change this to a warning and a suggestion to use the new API 1488 + * to set the polling interval (once the API is added). 1489 + */ 1490 + if (xhci_interval != ep_interval) { 1491 + if (!printk_ratelimit()) 1492 + dev_dbg(&urb->dev->dev, "Driver uses different interval" 1493 + " (%d microframe%s) than xHCI " 1494 + "(%d microframe%s)\n", 1495 + ep_interval, 1496 + ep_interval == 1 ? "" : "s", 1497 + xhci_interval, 1498 + xhci_interval == 1 ? "" : "s"); 1499 + urb->interval = xhci_interval; 1500 + /* Convert back to frames for LS/FS devices */ 1501 + if (urb->dev->speed == USB_SPEED_LOW || 1502 + urb->dev->speed == USB_SPEED_FULL) 1503 + urb->interval /= 8; 1504 + } 1505 + return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); 1470 1506 } 1471 1507 1472 1508 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+3
drivers/usb/host/xhci.h
··· 581 581 /* bit 15 is Linear Stream Array */ 582 582 /* Interval - period between requests to an endpoint - 125u increments. */ 583 583 #define EP_INTERVAL(p) ((p & 0xff) << 16) 584 + #define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) 584 585 585 586 /* ep_info2 bitmasks */ 586 587 /* ··· 1223 1222 int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 1224 1223 int slot_id, unsigned int ep_index); 1225 1224 int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 1225 + int slot_id, unsigned int ep_index); 1226 + int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 1226 1227 int slot_id, unsigned int ep_index); 1227 1228 int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, 1228 1229 u32 slot_id);