[PATCH 5/5] xHCI: assign devices to different interrupters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux