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
next prev parent 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).