This patch assign devices to different interrupters based on its slot_id. However, it's not mandatory that a device should use the same interrupter. A device can assign its control transfer to one interrupter and bulk/intr/ isoc transfer to another interrupter. The interrupter usage policy is flexible. The policy in this patch may be replaced by better approach in the future. Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx> --- drivers/usb/host/xhci-mem.c | 3 +++ drivers/usb/host/xhci-ring.c | 22 ++++++++++++++-------- drivers/usb/host/xhci.h | 2 ++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index f1f64a4..dd0f27d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -781,6 +781,9 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, INIT_LIST_HEAD(&dev->cmd_list); dev->udev = udev; + /* Decide the interrupter target */ + dev->intr_target = slot_id % xhci->intr_num; + /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma); xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n", diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fc3c9d8..f3e49af 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2702,6 +2702,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, bool first_trb; u64 addr; bool more_trbs_coming; + int intr; struct xhci_generic_trb *start_trb; int start_cycle; @@ -2724,6 +2725,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb_priv = urb->hcpriv; td = urb_priv->td[0]; + intr = xhci->devs[slot_id]->intr_target; /* * Don't give the first TRB to the hardware (by toggling the cycle bit) * until we've finished creating all the other TRBs. The ring's cycle @@ -2806,7 +2808,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } length_field = TRB_LEN(trb_buff_len) | remainder | - TRB_INTR_TARGET(0); + TRB_INTR_TARGET(intr); if (num_trbs > 1) more_trbs_coming = true; @@ -2862,10 +2864,10 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, bool more_trbs_coming; int start_cycle; u32 field, length_field; - int running_total, trb_buff_len, ret; unsigned int total_packet_count; u64 addr; + int intr; if (urb->num_sgs) return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); @@ -2910,6 +2912,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb_priv = urb->hcpriv; td = urb_priv->td[0]; + intr = xhci->devs[slot_id]->intr_target; /* * Don't give the first TRB to the hardware (by toggling the cycle bit) * until we've finished creating all the other TRBs. The ring's cycle @@ -2969,7 +2972,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } length_field = TRB_LEN(trb_buff_len) | remainder | - TRB_INTR_TARGET(0); + TRB_INTR_TARGET(intr); if (num_trbs > 1) more_trbs_coming = true; @@ -3009,6 +3012,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u32 field, length_field; struct urb_priv *urb_priv; struct xhci_td *td; + int intr; ep_ring = xhci_urb_to_transfer_ring(xhci, urb); if (!ep_ring) @@ -3042,6 +3046,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, urb_priv = urb->hcpriv; td = urb_priv->td[0]; + intr = xhci->devs[slot_id]->intr_target; /* * Don't give the first TRB to the hardware (by toggling the cycle bit) * until we've finished creating all the other TRBs. The ring's cycle @@ -3071,7 +3076,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, queue_trb(xhci, ep_ring, false, true, setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16, le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16, - TRB_LEN(8) | TRB_INTR_TARGET(0), + TRB_LEN(8) | TRB_INTR_TARGET(intr), /* Immediate data in pointer */ field); @@ -3084,7 +3089,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, length_field = TRB_LEN(urb->transfer_buffer_length) | xhci_td_remainder(urb->transfer_buffer_length) | - TRB_INTR_TARGET(0); + TRB_INTR_TARGET(intr); if (urb->transfer_buffer_length > 0) { if (setup->bRequestType & USB_DIR_IN) field |= TRB_DIR_IN; @@ -3107,7 +3112,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, queue_trb(xhci, ep_ring, false, false, 0, 0, - TRB_INTR_TARGET(0), + TRB_INTR_TARGET(intr), /* Event on completion */ field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state); @@ -3209,7 +3214,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u32 field, length_field; int running_total, trb_buff_len, td_len, td_remain_len, ret; u64 start_addr, addr; - int i, j; + int i, j, intr; bool more_trbs_coming; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; @@ -3233,6 +3238,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_trb = &ep_ring->enqueue->generic; start_cycle = ep_ring->cycle_state; + intr = xhci->devs[slot_id]->intr_target; /* Queue the first TRB, even if it's zero-length */ for (i = 0; i < num_tds; i++) { unsigned int total_packet_count; @@ -3322,7 +3328,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } length_field = TRB_LEN(trb_buff_len) | remainder | - TRB_INTR_TARGET(0); + TRB_INTR_TARGET(intr); queue_trb(xhci, ep_ring, false, more_trbs_coming, lower_32_bits(addr), diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index a18cf6b..84c0edb 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -792,6 +792,8 @@ struct xhci_virt_device { int num_rings_cached; /* Store xHC assigned device address */ int address; + /* Store the interrupter target */ + int intr_target; #define XHCI_MAX_RINGS_CACHED 31 struct xhci_virt_ep eps[31]; struct completion cmd_completion; -- 1.7.1 -- 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