diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index e345f15b7d87..b40bc1ac9b8c 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -347,6 +347,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 	struct uhci_qh *qh;
 	struct uhci_td *td;
 	struct list_head *tmp, *head;
+	int nframes, nerrs;
 
 	out += uhci_show_root_hub_state(uhci, out, len - (out - buf));
 	out += sprintf(out, "HC status\n");
@@ -355,23 +356,60 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
 		return out - buf;
 
 	out += sprintf(out, "Frame List\n");
+	nframes = 10;
+	nerrs = 0;
 	for (i = 0; i < UHCI_NUMFRAMES; ++i) {
-		td = uhci->frame_cpu[i];
-		if (!td)
-			continue;
+		__le32 link, qh_dma;
 
-		out += sprintf(out, "- Frame %d\n", i); \
-		if (td->dma_handle != (dma_addr_t)uhci->frame[i])
-			out += sprintf(out, "    frame list does not match td->dma_handle!\n");
+		j = 0;
+		td = uhci->frame_cpu[i];
+		link = uhci->frame[i];
+		if (!td)
+			goto check_link;
+
+		if (nframes > 0) {
+			out += sprintf(out, "- Frame %d -> (%08x)\n",
+					i, le32_to_cpu(link));
+			j = 1;
+		}
 
 		head = &td->fl_list;
 		tmp = head;
 		do {
 			td = list_entry(tmp, struct uhci_td, fl_list);
 			tmp = tmp->next;
-			out += uhci_show_td(td, out, len - (out - buf), 4);
+			if (cpu_to_le32(td->dma_handle) != link) {
+				if (nframes > 0)
+					out += sprintf(out, "    link does "
+						"not match list entry!\n");
+				else
+					++nerrs;
+			}
+			if (nframes > 0)
+				out += uhci_show_td(td, out,
+						len - (out - buf), 4);
+			link = td->link;
 		} while (tmp != head);
+
+check_link:
+		qh_dma = uhci_frame_skel_link(uhci, i);
+		if (link != qh_dma) {
+			if (nframes > 0) {
+				if (!j) {
+					out += sprintf(out,
+						"- Frame %d -> (%08x)\n",
+						i, le32_to_cpu(link));
+					j = 1;
+				}
+				out += sprintf(out, "   link does not match "
+					"QH (%08x)!\n", le32_to_cpu(qh_dma));
+			} else
+				++nerrs;
+		}
+		nframes -= j;
 	}
+	if (nerrs > 0)
+		out += sprintf(out, "Skipped %d bad links\n", nerrs);
 
 	out += sprintf(out, "Skeleton QHs\n");
 
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index e0d4c2358b39..49b9d390b95f 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -92,6 +92,34 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
 static void wakeup_rh(struct uhci_hcd *uhci);
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 
+/*
+ * Calculate the link pointer DMA value for the first Skeleton QH in a frame.
+ */
+static __le32 uhci_frame_skel_link(struct uhci_hcd *uhci, int frame)
+{
+	int skelnum;
+
+	/*
+	 * The interrupt queues will be interleaved as evenly as possible.
+	 * There's not much to be done about period-1 interrupts; they have
+	 * to occur in every frame.  But we can schedule period-2 interrupts
+	 * in odd-numbered frames, period-4 interrupts in frames congruent
+	 * to 2 (mod 4), and so on.  This way each frame only has two
+	 * interrupt QHs, which will help spread out bandwidth utilization.
+	 *
+	 * ffs (Find First bit Set) does exactly what we need:
+	 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
+	 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
+	 * ffs >= 7 => not on any high-period queue, so use
+	 *	skel_int1_qh = skelqh[9].
+	 * Add in UHCI_NUMFRAMES to insure at least one bit is set.
+	 */
+	skelnum = 8 - (int) __ffs(frame | UHCI_NUMFRAMES);
+	if (skelnum <= 1)
+		skelnum = 9;
+	return UHCI_PTR_QH | cpu_to_le32(uhci->skelqh[skelnum]->dma_handle);
+}
+
 #include "uhci-debug.c"
 #include "uhci-q.c"
 #include "uhci-hub.c"
@@ -631,32 +659,11 @@ static int uhci_start(struct usb_hcd *hcd)
 	/*
 	 * Fill the frame list: make all entries point to the proper
 	 * interrupt queue.
-	 *
-	 * The interrupt queues will be interleaved as evenly as possible.
-	 * There's not much to be done about period-1 interrupts; they have
-	 * to occur in every frame.  But we can schedule period-2 interrupts
-	 * in odd-numbered frames, period-4 interrupts in frames congruent
-	 * to 2 (mod 4), and so on.  This way each frame only has two
-	 * interrupt QHs, which will help spread out bandwidth utilization.
 	 */
 	for (i = 0; i < UHCI_NUMFRAMES; i++) {
-		int irq;
-
-		/*
-		 * ffs (Find First bit Set) does exactly what we need:
-		 * 1,3,5,...  => ffs = 0 => use skel_int2_qh = skelqh[8],
-		 * 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[7], etc.
-		 * ffs >= 7 => not on any high-period queue, so use
-		 *	skel_int1_qh = skelqh[9].
-		 * Add UHCI_NUMFRAMES to insure at least one bit is set.
-		 */
-		irq = 8 - (int) __ffs(i + UHCI_NUMFRAMES);
-		if (irq <= 1)
-			irq = 9;
 
 		/* Only place we don't use the frame list routines */
-		uhci->frame[i] = UHCI_PTR_QH |
-				cpu_to_le32(uhci->skelqh[irq]->dma_handle);
+		uhci->frame[i] = uhci_frame_skel_link(uhci, i);
 	}
 
 	/*