aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-dbg.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2009-04-27 22:52:34 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:48 -0400
commit0ebbab37422315a5d0cb29792271085bafdf38c0 (patch)
treeb638a71f004c27b49ea09f64ed80596078cc6167 /drivers/usb/host/xhci-dbg.c
parent66d4eadd8d067269ea8fead1a50fe87c2979a80d (diff)
USB: xhci: Ring allocation and initialization.
Allocate basic xHCI host controller data structures. For every xHC, there is a command ring, an event ring, and a doorbell array. The doorbell array is used to notify the host controller that work has been enqueued onto one of the rings. The host controller driver enqueues commands on the command ring. The HW enqueues command completion events on the event ring and interrupts the system (currently using PCI interrupts, although the xHCI HW will use MSI interrupts eventually). All rings and the doorbell array must be allocated by the xHCI host controller driver. Each ring is comprised of one or more segments, which consists of 16-byte Transfer Request Blocks (TRBs) that can be chained to form a Transfer Descriptor (TD) that represents a multiple-buffer request. Segments are linked into a ring using Link TRBs, which means they are dynamically growable. The producer of the ring enqueues a TD by writing one or more TRBs in the ring and toggling the TRB cycle bit for each TRB. The consumer knows it can process the TRB when the cycle bit matches its internal consumer cycle state for the ring. The consumer cycle state is toggled an odd amount of times in the ring. An example ring (a ring must have a minimum of 16 TRBs on it, but that's too big to draw in ASCII art): chain cycle bit bit ------------------------ | TD A TRB 1 | 1 | 1 |<------------- <-- consumer dequeue ptr ------------------------ | consumer cycle state = 1 | TD A TRB 2 | 1 | 1 | | ------------------------ | | TD A TRB 3 | 0 | 1 | segment 1 | ------------------------ | | TD B TRB 1 | 1 | 1 | | ------------------------ | | TD B TRB 2 | 0 | 1 | | ------------------------ | | Link TRB | 0 | 1 |----- | ------------------------ | | | | chain cycle | | bit bit | | ------------------------ | | | TD C TRB 1 | 0 | 1 |<---- | ------------------------ | | TD D TRB 1 | 1 | 1 | | ------------------------ | | TD D TRB 2 | 1 | 1 | segment 2 | ------------------------ | | TD D TRB 3 | 1 | 1 | | ------------------------ | | TD D TRB 4 | 1 | 1 | | ------------------------ | | Link TRB | 1 | 1 |----- | ------------------------ | | | | chain cycle | | bit bit | | ------------------------ | | | TD D TRB 5 | 1 | 1 |<---- | ------------------------ | | TD D TRB 6 | 0 | 1 | | ------------------------ | | TD E TRB 1 | 0 | 1 | segment 3 | ------------------------ | | | 0 | 0 | | <-- producer enqueue ptr ------------------------ | | | 0 | 0 | | ------------------------ | | Link TRB | 0 | 0 |--------------- ------------------------ Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-dbg.c')
-rw-r--r--drivers/usb/host/xhci-dbg.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index a7798b460492..5724683cef16 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -56,6 +56,8 @@ void xhci_dbg_regs(struct xhci_hcd *xhci)
56 temp = xhci_readl(xhci, &xhci->cap_regs->db_off); 56 temp = xhci_readl(xhci, &xhci->cap_regs->db_off);
57 xhci_dbg(xhci, "// @%x = 0x%x DBOFF\n", 57 xhci_dbg(xhci, "// @%x = 0x%x DBOFF\n",
58 (unsigned int) &xhci->cap_regs->db_off, temp); 58 (unsigned int) &xhci->cap_regs->db_off, temp);
59 xhci_dbg(xhci, "// Doorbell array at 0x%x:\n",
60 (unsigned int) xhci->dba);
59} 61}
60 62
61void xhci_print_cap_regs(struct xhci_hcd *xhci) 63void xhci_print_cap_regs(struct xhci_hcd *xhci)
@@ -227,3 +229,82 @@ void xhci_print_registers(struct xhci_hcd *xhci)
227 xhci_print_cap_regs(xhci); 229 xhci_print_cap_regs(xhci);
228 xhci_print_op_regs(xhci); 230 xhci_print_op_regs(xhci);
229} 231}
232
233
234/**
235 * Debug a segment with an xHCI ring.
236 *
237 * @return The Link TRB of the segment, or NULL if there is no Link TRB
238 * (which is a bug, since all segments must have a Link TRB).
239 *
240 * Prints out all TRBs in the segment, even those after the Link TRB.
241 *
242 * XXX: should we print out TRBs that the HC owns? As long as we don't
243 * write, that should be fine... We shouldn't expect that the memory pointed to
244 * by the TRB is valid at all. Do we care about ones the HC owns? Probably,
245 * for HC debugging.
246 */
247void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
248{
249 int i;
250 u32 addr = (u32) seg->dma;
251 union xhci_trb *trb = seg->trbs;
252
253 for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
254 trb = &seg->trbs[i];
255 xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
256 (unsigned int) trb->link.segment_ptr[0],
257 (unsigned int) trb->link.segment_ptr[1],
258 (unsigned int) trb->link.intr_target,
259 (unsigned int) trb->link.control);
260 addr += sizeof(*trb);
261 }
262}
263
264/**
265 * Debugging for an xHCI ring, which is a queue broken into multiple segments.
266 *
267 * Print out each segment in the ring. Check that the DMA address in
268 * each link segment actually matches the segment's stored DMA address.
269 * Check that the link end bit is only set at the end of the ring.
270 * Check that the dequeue and enqueue pointers point to real data in this ring
271 * (not some other ring).
272 */
273void xhci_debug_ring(struct xhci_hcd *xhci, struct xhci_ring *ring)
274{
275 /* FIXME: Throw an error if any segment doesn't have a Link TRB */
276 struct xhci_segment *seg;
277 struct xhci_segment *first_seg = ring->first_seg;
278 xhci_debug_segment(xhci, first_seg);
279
280 for (seg = first_seg->next; seg != first_seg; seg = seg->next)
281 xhci_debug_segment(xhci, seg);
282}
283
284void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
285{
286 u32 addr = (u32) erst->erst_dma_addr;
287 int i;
288 struct xhci_erst_entry *entry;
289
290 for (i = 0; i < erst->num_entries; ++i) {
291 entry = &erst->entries[i];
292 xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
293 (unsigned int) addr,
294 (unsigned int) entry->seg_addr[0],
295 (unsigned int) entry->seg_addr[1],
296 (unsigned int) entry->seg_size,
297 (unsigned int) entry->rsvd);
298 addr += sizeof(*entry);
299 }
300}
301
302void xhci_dbg_cmd_ptrs(struct xhci_hcd *xhci)
303{
304 u32 val;
305
306 val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[0]);
307 xhci_dbg(xhci, "// xHC command ring deq ptr low bits + flags = 0x%x\n", val);
308 val = xhci_readl(xhci, &xhci->op_regs->cmd_ring[1]);
309 xhci_dbg(xhci, "// xHC command ring deq ptr high bits = 0x%x\n", val);
310}