[PATCH 108/143] USB: xhci: Device context array allocation.

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

 



From: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>

Instead of keeping a "frame list" like older host controllers, the xHCI
host controller keeps internal representations of the USB devices, with a
transfer ring per endpoint.  The host controller queues Transfer Request
Blocks (TRBs) to the endpoint ring, and then "rings the doorbell" for that
device.  The host controller processes the transfer, places a transfer
completion event on the event ring, and interrupts the system.

The device context base address array must be allocated by the xHCI host
controller driver, along with the device contexts it points to.

Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/usb/host/xhci-mem.c |   21 +++++
 drivers/usb/host/xhci.h     |  175 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 196 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 7cf15ca..be5a05b 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -220,6 +220,12 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 		dma_pool_destroy(xhci->segment_pool);
 	xhci->segment_pool = NULL;
 	xhci_dbg(xhci, "Freed segment pool\n");
+	xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[1]);
+	xhci_writel(xhci, 0, &xhci->op_regs->dcbaa_ptr[0]);
+	if (xhci->dcbaa)
+		pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
+				xhci->dcbaa, xhci->dcbaa->dma);
+	xhci->dcbaa = NULL;
 	xhci->page_size = 0;
 	xhci->page_shift = 0;
 }
@@ -263,6 +269,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	xhci_writel(xhci, val, &xhci->op_regs->config_reg);
 
 	/*
+	 * Section 5.4.8 - doorbell array must be
+	 * "physically contiguous and 64-byte (cache line) aligned".
+	 */
+	xhci->dcbaa = pci_alloc_consistent(to_pci_dev(dev),
+			sizeof(*xhci->dcbaa), &dma);
+	if (!xhci->dcbaa)
+		goto fail;
+	memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
+	xhci->dcbaa->dma = dma;
+	xhci_dbg(xhci, "// Setting device context base array address to 0x%x\n",
+			xhci->dcbaa->dma);
+	xhci_writel(xhci, (u32) 0, &xhci->op_regs->dcbaa_ptr[1]);
+	xhci_writel(xhci, dma, &xhci->op_regs->dcbaa_ptr[0]);
+
+	/*
 	 * Initialize the ring segment pool.  The ring must be a contiguous
 	 * structure comprised of TRBs.  The TRBs must be 16 byte aligned,
 	 * however, the command ring segment needs 64-byte aligned segments,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index ed33131..f168fca 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -436,6 +436,180 @@ struct xhci_doorbell_array {
 #define	DB_MASK			(0xff << 8)
 
 
+/**
+ * struct xhci_slot_ctx
+ * @dev_info:	Route string, device speed, hub info, and last valid endpoint
+ * @dev_info2:	Max exit latency for device number, root hub port number
+ * @tt_info:	tt_info is used to construct split transaction tokens
+ * @dev_state:	slot state and device address
+ *
+ * Slot Context - section 6.2.1.1.  This assumes the HC uses 32-byte context
+ * structures.  If the HC uses 64-byte contexts, there is an additional 32 bytes
+ * reserved at the end of the slot context for HC internal use.
+ */
+struct xhci_slot_ctx {
+	u32	dev_info;
+	u32	dev_info2;
+	u32	tt_info;
+	u32	dev_state;
+	/* offset 0x10 to 0x1f reserved for HC internal use */
+	u32	reserved[4];
+} __attribute__ ((packed));
+
+/* dev_info bitmasks */
+/* Route String - 0:19 */
+#define ROUTE_STRING_MASK	(0xfffff)
+/* Device speed - values defined by PORTSC Device Speed field - 20:23 */
+#define DEV_SPEED	(0xf << 20)
+/* bit 24 reserved */
+/* Is this LS/FS device connected through a HS hub? - bit 25 */
+#define DEV_MTT		(0x1 << 25)
+/* Set if the device is a hub - bit 26 */
+#define DEV_HUB		(0x1 << 26)
+/* Index of the last valid endpoint context in this device context - 27:31 */
+#define LAST_EP_MASK	(0x1f << 27)
+#define LAST_EP(p)	((p) << 27)
+
+/* dev_info2 bitmasks */
+/* Max Exit Latency (ms) - worst case time to wake up all links in dev path */
+#define MAX_EXIT	(0xffff)
+/* Root hub port number that is needed to access the USB device */
+#define ROOT_HUB_PORT	(0xff << 16)
+
+/* tt_info bitmasks */
+/*
+ * TT Hub Slot ID - for low or full speed devices attached to a high-speed hub
+ * The Slot ID of the hub that isolates the high speed signaling from
+ * this low or full-speed device.  '0' if attached to root hub port.
+ */
+#define TT_SLOT		(0xff)
+/*
+ * The number of the downstream facing port of the high-speed hub
+ * '0' if the device is not low or full speed.
+ */
+#define TT_PORT		(0xff << 8)
+
+/* dev_state bitmasks */
+/* USB device address - assigned by the HC */
+#define DEV_ADDR	(0xff)
+/* bits 8:26 reserved */
+/* Slot state */
+#define SLOT_STATE	(0x1f << 27)
+
+
+/**
+ * struct xhci_ep_ctx
+ * @ep_info:	endpoint state, streams, mult, and interval information.
+ * @ep_info2:	information on endpoint type, max packet size, max burst size,
+ * 		error count, and whether the HC will force an event for all
+ * 		transactions.
+ * @ep_ring:	64-bit ring address.  If the endpoint only defines one flow,
+ * 		this points to the endpoint transfer ring.  Otherwise, it points
+ * 		to a flow context array, which has a ring pointer for each flow.
+ * @intr_target:
+ * 		64-bit address of the Interrupter Target that will receive
+ * 		events from this endpoint.
+ *
+ * Endpoint Context - section 6.2.1.2.  This assumes the HC uses 32-byte context
+ * structures.  If the HC uses 64-byte contexts, there is an additional 32 bytes
+ * reserved at the end of the endpoint context for HC internal use.
+ */
+struct xhci_ep_ctx {
+	u32	ep_info;
+	u32	ep_info2;
+	/* 64-bit endpoint ring address */
+	u32	ep_ring[2];
+	/* 64-bit address of the interrupter target */
+	u32	intr_target[2];
+	/* offset 0x14 - 0x1f reserved for HC internal use */
+	u32	reserved[2];
+} __attribute__ ((packed));
+
+/* ep_info bitmasks */
+/*
+ * Endpoint State - bits 0:2
+ * 0 - disabled
+ * 1 - running
+ * 2 - halted due to halt condition - ok to manipulate endpoint ring
+ * 3 - stopped
+ * 4 - TRB error
+ * 5-7 - reserved
+ */
+#define EP_STATE	(0xf)
+/* Mult - Max number of burtst within an interval, in EP companion desc. */
+#define EP_MULT(p)		((p & 0x3) << 8)
+/* bits 10:14 are Max Primary Streams */
+/* bit 15 is Linear Stream Array */
+/* Interval - period between requests to an endpoint - 125u increments. */
+#define EP_INTERVAL	(0xff << 16)
+
+/* ep_info2 bitmasks */
+/*
+ * Force Event - generate transfer events for all TRBs for this endpoint
+ * This will tell the HC to ignore the IOC and ISP flags (for debugging only).
+ */
+#define	FORCE_EVENT	(0x1)
+#define ERROR_COUNT(p)	(((p) & 0x3) << 1)
+#define EP_TYPE(p)	((p) << 3)
+#define ISOC_OUT_EP	1
+#define BULK_OUT_EP	2
+#define INT_OUT_EP	3
+#define CTRL_EP		4
+#define ISOC_IN_EP	5
+#define BULK_IN_EP	6
+#define INT_IN_EP	7
+/* bit 6 reserved */
+/* bit 7 is Host Initiate Disable - for disabling stream selection */
+#define MAX_BURST(p)	(((p)&0xff) << 8)
+#define MAX_PACKET(p)	(((p)&0xffff) << 16)
+
+
+/**
+ * struct xhci_device_control
+ * Input/Output context; see section 6.2.5.
+ *
+ * @drop_context:	set the bit of the endpoint context you want to disable
+ * @add_context:	set the bit of the endpoint context you want to enable
+ */
+struct xhci_device_control {
+	u32	drop_flags;
+	u32	add_flags;
+	u32	rsvd[6];
+	struct xhci_slot_ctx	slot;
+	struct xhci_ep_ctx	ep[31];
+} __attribute__ ((packed));
+
+/* drop context bitmasks */
+#define	DROP_EP(x)	(0x1 << x)
+/* add context bitmasks */
+#define	ADD_EP(x)	(0x1 << x)
+
+
+/**
+ * struct xhci_device_context_array
+ * @dev_context_ptr	array of 64-bit DMA addresses for device contexts
+ */
+struct xhci_device_context_array {
+	/* 64-bit device addresses; we only write 32-bit addresses */
+	u32			dev_context_ptrs[2*MAX_HC_SLOTS];
+	/* private xHCD pointers */
+	dma_addr_t	dma;
+} __attribute__ ((packed));
+/* TODO: write function to set the 64-bit device DMA address */
+/*
+ * TODO: change this to be dynamically sized at HC mem init time since the HC
+ * might not be able to handle the maximum number of devices possible.
+ */
+
+
+struct xhci_stream_ctx {
+	/* 64-bit stream ring address, cycle state, and stream type */
+	u32	stream_ring[2];
+	/* offset 0x14 - 0x1f reserved for HC internal use */
+	u32	reserved[2];
+} __attribute__ ((packed));
+
+
 struct xhci_transfer_event {
 	/* 64-bit buffer address, or immediate data */
 	u32	buffer[2];
@@ -725,6 +899,7 @@ struct xhci_hcd {
 	int		msix_count;
 	struct msix_entry	*msix_entries;
 	/* data structures */
+	struct xhci_device_context_array *dcbaa;
 	struct xhci_ring	*cmd_ring;
 	struct xhci_ring	*event_ring;
 	struct xhci_erst	erst;
-- 
1.6.3.2

--
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