diff mbox

[Bugme-new,Bug,14564] New: capture-example sleeping function called from invalid context at arch/x86/mm/fault.c

Message ID Pine.LNX.4.44L0.1001031140460.29885-100000@netrider.rowland.org (mailing list archive)
State Not Applicable
Headers show

Commit Message

Alan Stern Jan. 3, 2010, 5:35 p.m. UTC
None
diff mbox

Patch

Index: usb-2.6/drivers/usb/host/ohci-mem.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ohci-mem.c
+++ usb-2.6/drivers/usb/host/ohci-mem.c
@@ -98,17 +98,56 @@  td_alloc (struct ohci_hcd *hc, gfp_t mem
 	return td;
 }
 
+static void td_check(struct ohci_hcd *hc, int hash, char *msg)
+{
+	struct td	*td, *first;
+
+	first = hc->td_hash[hash];
+	for (td = first; td; td = td->td_hash) {
+		if (td->td_hash == first || td->td_hash == td) {
+			ohci_err(hc, "Circular pointer %s: %d %p %p %p\n",
+					msg, hash, first, td, td->td_hash);
+			td->td_hash = NULL;
+			return;
+		}
+	}
+}
+
+static void td_check_all(struct ohci_hcd *hc, char *msg)
+{
+	int	hash;
+
+	for (hash = 0; hash < TD_HASH_SIZE; ++hash)
+		td_check(hc, hash, msg);
+}
+
 static void
 td_free (struct ohci_hcd *hc, struct td *td)
 {
-	struct td	**prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
+	int 		hash = TD_HASH_FUNC(td->td_dma);
+	struct td	**prev = &hc->td_hash[hash];
 
-	while (*prev && *prev != td)
+	td_check(hc, hash, "#1a");
+	while (*prev && *prev != td) {
+		if ((unsigned long) *prev == 0xa7a7a7a7) {
+			ohci_err(hc, "poisoned hash at %p (%d) %p %p\n", prev,
+				hash, td, hc->td_hash[hash]);
+			return;
+		}
 		prev = &(*prev)->td_hash;
-	if (*prev)
+	}
+	if (*prev) {
 		*prev = td->td_hash;
+		if (*prev == td) {
+			ohci_err(hc, "invalid hash at %p (%d) %p %p\n", prev,
+				hash, td, hc->td_hash[hash]);
+			*prev = NULL;
+		}
+	}
 	else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
 		ohci_dbg (hc, "no hash for td %p\n", td);
+	mb();
+	td_check(hc, hash, "#1b");
 	dma_pool_free (hc->td_cache, td, td->td_dma);
 }
 
Index: usb-2.6/drivers/usb/host/ohci-q.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ohci-q.c
+++ usb-2.6/drivers/usb/host/ohci-q.c
@@ -558,12 +558,14 @@  td_fill (struct ohci_hcd *ohci, u32 info
 
 	/* hash it for later reverse mapping */
 	hash = TD_HASH_FUNC (td->td_dma);
+	td_check(ohci, hash, "#2a");
 	td->td_hash = ohci->td_hash [hash];
 	ohci->td_hash [hash] = td;
 
 	/* HC might read the TD (or cachelines) right away ... */
 	wmb ();
 	td->ed->hwTailP = td->hwNextTD;
+	td_check(ohci, hash, "#2b");
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1127,9 +1129,11 @@  dl_done_list (struct ohci_hcd *ohci)
 {
 	struct td	*td = dl_reverse_done_list (ohci);
 
+	td_check_all(ohci, "#3a");
 	while (td) {
 		struct td	*td_next = td->next_dl_td;
 		takeback_td(ohci, td);
 		td = td_next;
 	}
+	td_check_all(ohci, "#3b");
 }