USB: xhci: Device context array allocation.
authorSarah Sharp <sarah.a.sharp@linux.intel.com>
Tue, 28 Apr 2009 02:53:42 +0000 (19:53 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 16 Jun 2009 04:44:48 +0000 (21:44 -0700)
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@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.h

index 7cf15ca854be51c34034af88aaf1cc1dedd13271..be5a05b2021c1c58b1aaedde7e6c993104a66bd0 100644 (file)
@@ -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;
 }
@@ -262,6 +268,21 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
                        (unsigned int) val);
        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,
index ed331310f1a8c010da49fd81572fdc2716382850..f168fcac59990bb725771a494911685148c14725 100644 (file)
@@ -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;