Commit f8316df1 authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville

ath9k: Check for pci_map_single() errors

pci_map_single() can fail so detect those errors with
pci_dma_mapping_error() and deal with them accordingly.
Signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 73a52670
...@@ -190,6 +190,13 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) ...@@ -190,6 +190,13 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
pci_map_single(sc->pdev, skb->data, pci_map_single(sc->pdev, skb->data,
skb->len, skb->len,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"pci_dma_mapping_error() on beaconing\n");
return NULL;
}
skb = ieee80211_get_buffered_bc(sc->hw, vif); skb = ieee80211_get_buffered_bc(sc->hw, vif);
...@@ -392,11 +399,18 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) ...@@ -392,11 +399,18 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
memcpy(&hdr[1], &val, sizeof(val)); memcpy(&hdr[1], &val, sizeof(val));
} }
bf->bf_mpdu = skb;
bf->bf_buf_addr = bf->bf_dmacontext = bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data, pci_map_single(sc->pdev, skb->data,
skb->len, skb->len,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
bf->bf_mpdu = skb; if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"pci_dma_mapping_error() on beacon alloc\n");
return -ENOMEM;
}
return 0; return 0;
} }
......
...@@ -304,6 +304,15 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) ...@@ -304,6 +304,15 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data, bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
sc->sc_rxbufsize, sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"pci_dma_mapping_error() on RX init\n");
error = -ENOMEM;
break;
}
bf->bf_dmacontext = bf->bf_buf_addr; bf->bf_dmacontext = bf->bf_buf_addr;
} }
sc->sc_rxlink = NULL; sc->sc_rxlink = NULL;
...@@ -589,6 +598,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) ...@@ -589,6 +598,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data, bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
sc->sc_rxbufsize, sc->sc_rxbufsize,
PCI_DMA_FROMDEVICE); PCI_DMA_FROMDEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(requeue_skb);
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"pci_dma_mapping_error() on RX\n");
break;
}
bf->bf_dmacontext = bf->bf_buf_addr; bf->bf_dmacontext = bf->bf_buf_addr;
/* /*
......
...@@ -1642,7 +1642,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc, ...@@ -1642,7 +1642,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
} }
} }
static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
struct sk_buff *skb, struct sk_buff *skb,
struct ath_tx_control *txctl) struct ath_tx_control *txctl)
{ {
...@@ -1701,9 +1701,18 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1701,9 +1701,18 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
/* DMA setup */ /* DMA setup */
bf->bf_mpdu = skb; bf->bf_mpdu = skb;
bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data, bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
skb->len, PCI_DMA_TODEVICE); skb->len, PCI_DMA_TODEVICE);
if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_dmacontext))) {
bf->bf_mpdu = NULL;
DPRINTF(sc, ATH_DBG_CONFIG,
"pci_dma_mapping_error() on TX\n");
return -ENOMEM;
}
bf->bf_buf_addr = bf->bf_dmacontext; bf->bf_buf_addr = bf->bf_dmacontext;
return 0;
} }
/* FIXME: tx power */ /* FIXME: tx power */
...@@ -1775,10 +1784,12 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, ...@@ -1775,10 +1784,12 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
spin_unlock_bh(&txctl->txq->axq_lock); spin_unlock_bh(&txctl->txq->axq_lock);
} }
/* Upon failure caller should free skb */
int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl) struct ath_tx_control *txctl)
{ {
struct ath_buf *bf; struct ath_buf *bf;
int r;
/* Check if a tx buffer is available */ /* Check if a tx buffer is available */
...@@ -1788,7 +1799,15 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, ...@@ -1788,7 +1799,15 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
return -1; return -1;
} }
ath_tx_setup_buffer(sc, bf, skb, txctl); r = ath_tx_setup_buffer(sc, bf, skb, txctl);
if (unlikely(r)) {
spin_lock_bh(&sc->sc_txbuflock);
DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
list_add_tail(&bf->list, &sc->sc_txbuf);
spin_unlock_bh(&sc->sc_txbuflock);
return r;
}
ath_tx_start_dma(sc, bf, txctl); ath_tx_start_dma(sc, bf, txctl);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment