Skip to content

Commit

Permalink
pcnet32: add missing check for pci_dma_mapping_error
Browse files Browse the repository at this point in the history
The pci_map_single calls never checked for error. Add error checking
as requested by someone last year.  Tested on 79c972.

Signed-off-by: Don Fry <pcnet32@frontier.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Don Fry authored and David S. Miller committed Feb 19, 2014
1 parent 60e2e8b commit 4cc5c47
Showing 1 changed file with 81 additions and 27 deletions.
108 changes: 81 additions & 27 deletions drivers/net/ethernet/amd/pcnet32.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,8 +565,7 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
if (!new_dma_addr_list)
goto free_new_rx_ring;

new_skb_list = kcalloc(entries, sizeof(struct sk_buff *),
GFP_ATOMIC);
new_skb_list = kcalloc(entries, sizeof(struct sk_buff *), GFP_ATOMIC);
if (!new_skb_list)
goto free_new_lists;

Expand All @@ -593,15 +592,26 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
new_dma_addr_list[new] =
pci_map_single(lp->pci_dev, rx_skbuff->data,
PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(lp->pci_dev,
new_dma_addr_list[new])) {
netif_err(lp, drv, dev, "%s dma mapping failed\n",
__func__);
dev_kfree_skb(new_skb_list[new]);
goto free_all_new;
}
new_rx_ring[new].base = cpu_to_le32(new_dma_addr_list[new]);
new_rx_ring[new].buf_length = cpu_to_le16(NEG_BUF_SIZE);
new_rx_ring[new].status = cpu_to_le16(0x8000);
}
/* and free any unneeded buffers */
for (; new < lp->rx_ring_size; new++) {
if (lp->rx_skbuff[new]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
if (!pci_dma_mapping_error(lp->pci_dev,
lp->rx_dma_addr[new]))
pci_unmap_single(lp->pci_dev,
lp->rx_dma_addr[new],
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(lp->rx_skbuff[new]);
}
}
Expand All @@ -625,8 +635,12 @@ static void pcnet32_realloc_rx_ring(struct net_device *dev,
free_all_new:
while (--new >= lp->rx_ring_size) {
if (new_skb_list[new]) {
pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
if (!pci_dma_mapping_error(lp->pci_dev,
new_dma_addr_list[new]))
pci_unmap_single(lp->pci_dev,
new_dma_addr_list[new],
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
dev_kfree_skb(new_skb_list[new]);
}
}
Expand All @@ -650,8 +664,12 @@ static void pcnet32_purge_rx_ring(struct net_device *dev)
lp->rx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->rx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i],
PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
if (!pci_dma_mapping_error(lp->pci_dev,
lp->rx_dma_addr[i]))
pci_unmap_single(lp->pci_dev,
lp->rx_dma_addr[i],
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
dev_kfree_skb_any(lp->rx_skbuff[i]);
}
lp->rx_skbuff[i] = NULL;
Expand Down Expand Up @@ -930,6 +948,12 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
lp->tx_dma_addr[x] =
pci_map_single(lp->pci_dev, skb->data, skb->len,
PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(lp->pci_dev, lp->tx_dma_addr[x])) {
netif_printk(lp, hw, KERN_DEBUG, dev,
"DMA mapping error at line: %d!\n",
__LINE__);
goto clean_up;
}
lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]);
wmb(); /* Make sure owner changes after all others are visible */
lp->tx_ring[x].status = cpu_to_le16(status);
Expand Down Expand Up @@ -1142,24 +1166,36 @@ static void pcnet32_rx_entry(struct net_device *dev,

if (pkt_len > rx_copybreak) {
struct sk_buff *newskb;
dma_addr_t new_dma_addr;

newskb = netdev_alloc_skb(dev, PKT_BUF_SKB);
/*
* map the new buffer, if mapping fails, drop the packet and
* reuse the old buffer
*/
if (newskb) {
skb_reserve(newskb, NET_IP_ALIGN);
skb = lp->rx_skbuff[entry];
pci_unmap_single(lp->pci_dev,
lp->rx_dma_addr[entry],
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_len);
lp->rx_skbuff[entry] = newskb;
lp->rx_dma_addr[entry] =
pci_map_single(lp->pci_dev,
newskb->data,
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
rxp->base = cpu_to_le32(lp->rx_dma_addr[entry]);
rx_in_place = 1;
new_dma_addr = pci_map_single(lp->pci_dev,
newskb->data,
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(lp->pci_dev, new_dma_addr)) {
netif_err(lp, rx_err, dev,
"DMA mapping error.\n");
dev_kfree_skb(newskb);
skb = NULL;
} else {
skb = lp->rx_skbuff[entry];
pci_unmap_single(lp->pci_dev,
lp->rx_dma_addr[entry],
PKT_BUF_SIZE,
PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_len);
lp->rx_skbuff[entry] = newskb;
lp->rx_dma_addr[entry] = new_dma_addr;
rxp->base = cpu_to_le32(new_dma_addr);
rx_in_place = 1;
}
} else
skb = NULL;
} else
Expand Down Expand Up @@ -2229,9 +2265,12 @@ static void pcnet32_purge_tx_ring(struct net_device *dev)
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
if (lp->tx_skbuff[i]) {
pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
lp->tx_skbuff[i]->len,
PCI_DMA_TODEVICE);
if (!pci_dma_mapping_error(lp->pci_dev,
lp->tx_dma_addr[i]))
pci_unmap_single(lp->pci_dev,
lp->tx_dma_addr[i],
lp->tx_skbuff[i]->len,
PCI_DMA_TODEVICE);
dev_kfree_skb_any(lp->tx_skbuff[i]);
}
lp->tx_skbuff[i] = NULL;
Expand Down Expand Up @@ -2264,10 +2303,19 @@ static int pcnet32_init_ring(struct net_device *dev)
}

rmb();
if (lp->rx_dma_addr[i] == 0)
if (lp->rx_dma_addr[i] == 0) {
lp->rx_dma_addr[i] =
pci_map_single(lp->pci_dev, rx_skbuff->data,
PKT_BUF_SIZE, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(lp->pci_dev,
lp->rx_dma_addr[i])) {
/* there is not much we can do at this point */
netif_err(lp, drv, dev,
"%s pci dma mapping error\n",
__func__);
return -1;
}
}
lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]);
lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE);
wmb(); /* Make sure owner changes after all others are visible */
Expand Down Expand Up @@ -2397,9 +2445,14 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,

lp->tx_ring[entry].misc = 0x00000000;

lp->tx_skbuff[entry] = skb;
lp->tx_dma_addr[entry] =
pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
if (pci_dma_mapping_error(lp->pci_dev, lp->tx_dma_addr[entry])) {
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
goto drop_packet;
}
lp->tx_skbuff[entry] = skb;
lp->tx_ring[entry].base = cpu_to_le32(lp->tx_dma_addr[entry]);
wmb(); /* Make sure owner changes after all others are visible */
lp->tx_ring[entry].status = cpu_to_le16(status);
Expand All @@ -2414,6 +2467,7 @@ static netdev_tx_t pcnet32_start_xmit(struct sk_buff *skb,
lp->tx_full = 1;
netif_stop_queue(dev);
}
drop_packet:
spin_unlock_irqrestore(&lp->lock, flags);
return NETDEV_TX_OK;
}
Expand Down

0 comments on commit 4cc5c47

Please sign in to comment.