提交 cb71d9ba 编写于 作者: L Luis R. Rodriguez 提交者: John W. Linville

ath9k: Handle -ENOMEM on RX gracefully

We would get an oops on RX on -ENOMEM by passing
NULL to the hardware on ath_rx_buf_link(). The oops
would look something like this:

ath_rx_tasklet+0x515/0x53b
ath9k_tasklet+0x48
tasklet_action
__do_softirq
irq_exit
do_IRQ

RIP: ath_rx_buf_link+0x3a

We correct this by handling the requeue directly on
the ath_rx_tasklet() and trying to allocate an skb
*prior* to sending up the last hardware processed
skb. If we run out of memory this gauranteees we have
skbs to work with while it simply drops new received
frames.
Signed-off-by: NLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: NJohn W. Linville <linville@tuxdriver.com>
上级 24689c85
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -81,29 +81,6 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len)
return skb;
}
static void ath_rx_requeue(struct ath_softc *sc, struct ath_buf *bf)
{
struct sk_buff *skb;
ASSERT(bf != NULL);
if (bf->bf_mpdu == NULL) {
skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
if (skb != NULL) {
bf->bf_mpdu = skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
skb_end_pointer(skb) - skb->head,
PCI_DMA_FROMDEVICE);
bf->bf_dmacontext = bf->bf_buf_addr;
}
}
list_move_tail(&bf->list, &sc->sc_rxbuf);
ath_rx_buf_link(sc, bf);
}
static int ath_rate2idx(struct ath_softc *sc, int rate)
{
int i = 0, cur_band, n_rates;
......@@ -445,7 +422,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ath_buf *bf;
struct ath_desc *ds;
struct sk_buff *skb = NULL;
struct sk_buff *skb = NULL, *requeue_skb;
struct ieee80211_rx_status rx_status;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_hdr *hdr;
......@@ -522,17 +499,28 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* chain it back at the queue without processing it.
*/
if (flush)
goto rx_next;
goto requeue;
if (!ds->ds_rxstat.rs_datalen)
goto rx_next;
goto requeue;
/* The status portion of the descriptor could get corrupted. */
if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
goto rx_next;
goto requeue;
if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
goto rx_next;
goto requeue;
/* Ensure we always have an skb to requeue once we are done
* processing the current buffer's skb */
requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
/* If there is no memory we ignore the current RX'd frame,
* tell hardware it can give us a new frame using the old
* skb and put it at the tail of the sc->sc_rxbuf list for
* processing. */
if (!requeue_skb)
goto requeue;
/* Sync and unmap the frame */
pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
......@@ -569,7 +557,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* Send the frame to mac80211 */
__ieee80211_rx(sc->hw, skb, &rx_status);
bf->bf_mpdu = NULL;
/* We will now give hardware our shiny new allocated skb */
bf->bf_mpdu = requeue_skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE);
bf->bf_dmacontext = bf->bf_buf_addr;
/*
* change the default rx antenna if rx diversity chooses the
......@@ -581,8 +575,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
} else {
sc->sc_rxotherant = 0;
}
rx_next:
ath_rx_requeue(sc, bf);
requeue:
list_move_tail(&bf->list, &sc->sc_rxbuf);
ath_rx_buf_link(sc, bf);
} while (1);
spin_unlock_bh(&sc->sc_rxbuflock);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部