From patchwork Sun Jan 3 17:35:56 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Stern X-Patchwork-Id: 70512 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o03Ha2gl025115 for ; Sun, 3 Jan 2010 17:36:02 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752956Ab0ACRgA (ORCPT ); Sun, 3 Jan 2010 12:36:00 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752953Ab0ACRgA (ORCPT ); Sun, 3 Jan 2010 12:36:00 -0500 Received: from netrider.rowland.org ([192.131.102.5]:45757 "HELO netrider.rowland.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1752936Ab0ACRf6 (ORCPT ); Sun, 3 Jan 2010 12:35:58 -0500 Received: (qmail 30619 invoked by uid 500); 3 Jan 2010 12:35:56 -0500 Received: from localhost (sendmail-bs@127.0.0.1) by localhost with SMTP; 3 Jan 2010 12:35:56 -0500 Date: Sun, 3 Jan 2010 12:35:56 -0500 (EST) From: Alan Stern X-X-Sender: stern@netrider.rowland.org To: Sean cc: Andrew Morton , , , USB list , Ingo Molnar , Thomas Gleixner , "H. Peter Anvin" Subject: Re: [Bugme-new] [Bug 14564] New: capture-example sleeping function called from invalid context at arch/x86/mm/fault.c In-Reply-To: <4B3FF968.6000706@toaster.net> Message-ID: MIME-Version: 1.0 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org 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"); }