All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bob Copeland <me@bobcopeland.com>
To: Hugh Dickins <hugh@veritas.com>
Cc: ath5k-devel@venema.h4ckr.net, linux-wireless@vger.kernel.org,
	Jiri Slaby <jirislaby@gmail.com>,
	maximlevitsky@gmail.com
Subject: Re: [ath5k-devel] ath5k_tasklet_rx BUG_ON(bf->skb == NULL)
Date: Sat, 10 Jan 2009 15:15:47 -0500	[thread overview]
Message-ID: <20090110201547.GA11261@hash.localnet> (raw)
In-Reply-To: <20090110164705.GB10865@hash.localnet>

On Sat, Jan 10, 2009 at 11:47:05AM -0500, Bob Copeland wrote:
> Well I got a lockup doing that, I'll try again later but anyway I see
> the bug already, read on if interested.  I should have a patch shortly.

Err, of course I would get a lockup, it's a BUG_ON.  This patch seems to
fix it for me.  

From: Bob Copeland <me@bobcopeland.com>
Date: Sat, 10 Jan 2009 14:42:54 -0500
Subject: [PATCH] ath5k: fix bf->skb==NULL panic in ath5k_tasklet_rx

Under memory pressure, we may not be able to allocate a new skb for
new packets.  If the allocation fails, ath5k_tasklet_rx will exit but
will leave a buffer in the list with a NULL skb, eventually triggering
a BUG_ON.

Extract the skb allocation from ath5k_rxbuf_setup() and change the
tasklet to allocate the next skb before accepting a packet.

Changes-licensed-under: 3-Clause-BSD

Signed-off-by: Bob Copeland <me@bobcopeland.com>
---
 drivers/net/wireless/ath5k/base.c |   85 +++++++++++++++++++++++--------------
 1 files changed, 53 insertions(+), 32 deletions(-)

diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 2b7b7f6..1c0061a 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1095,6 +1095,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
 * Buffers setup *
 \***************/
 
+static
+struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
+{
+	struct sk_buff *skb;
+	unsigned int off;
+
+	/*
+	 * Allocate buffer with headroom_needed space for the
+	 * fake physical layer header at the start.
+	 */
+	skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
+
+	if (!skb) {
+		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+				sc->rxbufsize + sc->cachelsz - 1);
+		return NULL;
+	}
+	/*
+	 * Cache-line-align.  This is important (for the
+	 * 5210 at least) as not doing so causes bogus data
+	 * in rx'd frames.
+	 */
+	off = ((unsigned long)skb->data) % sc->cachelsz;
+	if (off != 0)
+		skb_reserve(skb, sc->cachelsz - off);
+
+	*skb_addr = pci_map_single(sc->pdev,
+		skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
+	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
+		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+		dev_kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
+}
+
 static int
 ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
@@ -1102,37 +1138,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
 	struct sk_buff *skb = bf->skb;
 	struct ath5k_desc *ds;
 
-	if (likely(skb == NULL)) {
-		unsigned int off;
-
-		/*
-		 * Allocate buffer with headroom_needed space for the
-		 * fake physical layer header at the start.
-		 */
-		skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
-		if (unlikely(skb == NULL)) {
-			ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
-					sc->rxbufsize + sc->cachelsz - 1);
+	if (!skb) {
+		skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr);
+		if (!skb)
 			return -ENOMEM;
-		}
-		/*
-		 * Cache-line-align.  This is important (for the
-		 * 5210 at least) as not doing so causes bogus data
-		 * in rx'd frames.
-		 */
-		off = ((unsigned long)skb->data) % sc->cachelsz;
-		if (off != 0)
-			skb_reserve(skb, sc->cachelsz - off);
-
 		bf->skb = skb;
-		bf->skbaddr = pci_map_single(sc->pdev,
-			skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
-		if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) {
-			ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
-			dev_kfree_skb(skb);
-			bf->skb = NULL;
-			return -ENOMEM;
-		}
 	}
 
 	/*
@@ -1661,7 +1671,8 @@ ath5k_tasklet_rx(unsigned long data)
 {
 	struct ieee80211_rx_status rxs = {};
 	struct ath5k_rx_status rs = {};
-	struct sk_buff *skb;
+	struct sk_buff *skb, *next_skb;
+	dma_addr_t next_skb_addr;
 	struct ath5k_softc *sc = (void *)data;
 	struct ath5k_buf *bf, *bf_last;
 	struct ath5k_desc *ds;
@@ -1746,10 +1757,17 @@ ath5k_tasklet_rx(unsigned long data)
 				goto next;
 		}
 accept:
+		next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
+
+		/*
+		 * If we can't replace bf->skb with a new skb under memory
+		 * pressure, just skip this packet
+		 */
+		if (!next_skb)
+			goto next;
+
 		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
 				PCI_DMA_FROMDEVICE);
-		bf->skb = NULL;
-
 		skb_put(skb, rs.rs_datalen);
 
 		/* The MAC header is padded to have 32-bit boundary if the
@@ -1822,6 +1840,9 @@ accept:
 			ath5k_check_ibss_tsf(sc, skb, &rxs);
 
 		__ieee80211_rx(sc->hw, skb, &rxs);
+
+		bf->skb = next_skb;
+		bf->skbaddr = next_skb_addr;
 next:
 		list_move_tail(&bf->list, &sc->rxbuf);
 	} while (ath5k_rxbuf_setup(sc, bf) == 0);
-- 
1.6.0.6


-- 
Bob Copeland %% www.bobcopeland.com


  reply	other threads:[~2009-01-10 20:16 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-01-08 13:49 ath5k_tasklet_rx BUG_ON(bf->skb == NULL) Hugh Dickins
2009-01-08 14:46 ` [ath5k-devel] " Maxim Levitsky
2009-01-08 16:18   ` Hugh Dickins
2009-01-08 17:10     ` Bob Copeland
2009-01-08 17:55       ` Hugh Dickins
2009-01-08 18:41         ` Bob Copeland
2009-01-09 13:41           ` Bob Copeland
2009-01-09 14:10             ` Hugh Dickins
2009-01-10 16:47               ` Bob Copeland
2009-01-10 20:15                 ` Bob Copeland [this message]
2009-01-13 15:35                   ` Hugh Dickins
2009-01-13 15:56                     ` Bob Copeland
2009-01-13 16:40                       ` Hugh Dickins
2009-01-13 17:45                         ` Luis R. Rodriguez
2009-02-06 13:12                       ` Hugh Dickins
2009-02-06 18:37                         ` Bob Copeland
2009-02-06 18:44                           ` John W. Linville
2009-02-06 19:01                             ` Hugh Dickins
2009-02-06 20:58                               ` Bob Copeland
2009-02-09  2:30                             ` Bob Copeland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090110201547.GA11261@hash.localnet \
    --to=me@bobcopeland.com \
    --cc=ath5k-devel@venema.h4ckr.net \
    --cc=hugh@veritas.com \
    --cc=jirislaby@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=maximlevitsky@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.