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: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Luis R. Rodriguez 2008-12-03 03:35:29 -08:00 committed by John W. Linville
parent 73a5267087
commit f8316df10c
3 changed files with 53 additions and 3 deletions

View file

@ -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,
skb->len,
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);
@ -392,11 +399,18 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
memcpy(&hdr[1], &val, sizeof(val));
}
bf->bf_mpdu = skb;
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
skb->len,
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;
}

View file

@ -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,
sc->sc_rxbufsize,
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;
}
sc->sc_rxlink = NULL;
@ -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,
sc->sc_rxbufsize,
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;
/*

View file

@ -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 ath_tx_control *txctl)
{
@ -1701,9 +1701,18 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
/* DMA setup */
bf->bf_mpdu = skb;
bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
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;
return 0;
}
/* FIXME: tx power */
@ -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);
}
/* Upon failure caller should free skb */
int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
struct ath_tx_control *txctl)
{
struct ath_buf *bf;
int r;
/* Check if a tx buffer is available */
@ -1788,7 +1799,15 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
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);
return 0;