>From 2e6cefeb1f24bf6d39c8a2bec10425c9d7ec5712 Mon Sep 17 00:00:00 2001 From: Andiry Xu <andiry.xu@xxxxxxx> Date: Thu, 25 Feb 2010 17:03:22 +0800 Subject: [PATCH 3/7] xHCI: update isoc URB interval and start_frame This patch updates isoc URB interval and start_frame. These two fields are not used as input. Assume URB_ISO_ASAP is always set, and do not specify the Frame ID field in Isoc TRB. Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx> Signed-off-by: Libin Yang <libin.yang@xxxxxxx> --- drivers/usb/host/xhci-hcd.c | 2 +- drivers/usb/host/xhci-ring.c | 50 ++++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 2 + 3 files changed, 53 insertions(+), 1 deletions(-) diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index acd620b..a708cf0 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -771,7 +771,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) spin_lock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto dying; - ret = xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, + ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb, slot_id, ep_index); spin_unlock_irqrestore(&xhci->lock, flags); } diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 8815210..6b0bd40 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2148,6 +2148,56 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return 0; } +/* + * Update ISO URB start_frame and interval. + * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to + * update the urb->start_frame by now. + * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input. + */ +int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, + struct urb *urb, int slot_id, unsigned int ep_index) +{ + struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, + xhci->devs[slot_id]->out_ctx, ep_index); + int start_frame; + int xhci_interval; + int ep_interval; + + start_frame = xhci_readl(xhci, &xhci->run_regs->microframe_index); + start_frame &= 0x3fff; + + urb->start_frame = start_frame; + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) + urb->start_frame >>= 3; + + xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); + ep_interval = urb->interval; + /* Convert to microframes */ + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) + ep_interval *= 8; + /* FIXME change this to a warning and a suggestion to use the new API + * to set the polling interval (once the API is added). + */ + if (xhci_interval != ep_interval) { + if (!printk_ratelimit()) + dev_dbg(&urb->dev->dev, "Driver uses different interval" + " (%d microframe%s) than xHCI " + "(%d microframe%s)\n", + ep_interval, + ep_interval == 1 ? "" : "s", + xhci_interval, + xhci_interval == 1 ? "" : "s"); + urb->interval = xhci_interval; + /* Convert back to frames for LS/FS devices */ + if (urb->dev->speed == USB_SPEED_LOW || + urb->dev->speed == USB_SPEED_FULL) + urb->interval /= 8; + } + return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); +} + static int count_isoc_trbs_needed(struct xhci_hcd *xhci, struct urb *urb, int i) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 980f08b..e66083c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1305,6 +1305,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); +int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, + struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html