|
@@ -2476,6 +2476,11 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
|
|
|
return -ENOMEM;
|
|
|
mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
|
|
|
PCI_DMA_FROMDEVICE);
|
|
|
+ if (pci_dma_mapping_error(bp->pdev, mapping)) {
|
|
|
+ __free_page(page);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+
|
|
|
rx_pg->page = page;
|
|
|
pci_unmap_addr_set(rx_pg, mapping, mapping);
|
|
|
rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
|
|
@@ -2518,6 +2523,10 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
|
|
|
|
|
|
mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
|
|
|
PCI_DMA_FROMDEVICE);
|
|
|
+ if (pci_dma_mapping_error(bp->pdev, mapping)) {
|
|
|
+ dev_kfree_skb(skb);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
|
|
|
rx_buf->skb = skb;
|
|
|
pci_unmap_addr_set(rx_buf, mapping, mapping);
|
|
@@ -2592,7 +2601,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
|
|
sw_cons = txr->tx_cons;
|
|
|
|
|
|
while (sw_cons != hw_cons) {
|
|
|
- struct sw_bd *tx_buf;
|
|
|
+ struct sw_tx_bd *tx_buf;
|
|
|
struct sk_buff *skb;
|
|
|
int i, last;
|
|
|
|
|
@@ -2617,21 +2626,13 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping),
|
|
|
- skb_headlen(skb), PCI_DMA_TODEVICE);
|
|
|
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
|
|
|
|
|
|
tx_buf->skb = NULL;
|
|
|
last = skb_shinfo(skb)->nr_frags;
|
|
|
|
|
|
for (i = 0; i < last; i++) {
|
|
|
sw_cons = NEXT_TX_BD(sw_cons);
|
|
|
-
|
|
|
- pci_unmap_page(bp->pdev,
|
|
|
- pci_unmap_addr(
|
|
|
- &txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
|
|
|
- mapping),
|
|
|
- skb_shinfo(skb)->frags[i].size,
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
}
|
|
|
|
|
|
sw_cons = NEXT_TX_BD(sw_cons);
|
|
@@ -2672,11 +2673,31 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
|
|
|
{
|
|
|
struct sw_pg *cons_rx_pg, *prod_rx_pg;
|
|
|
struct rx_bd *cons_bd, *prod_bd;
|
|
|
- dma_addr_t mapping;
|
|
|
int i;
|
|
|
- u16 hw_prod = rxr->rx_pg_prod, prod;
|
|
|
+ u16 hw_prod, prod;
|
|
|
u16 cons = rxr->rx_pg_cons;
|
|
|
|
|
|
+ cons_rx_pg = &rxr->rx_pg_ring[cons];
|
|
|
+
|
|
|
+ /* The caller was unable to allocate a new page to replace the
|
|
|
+ * last one in the frags array, so we need to recycle that page
|
|
|
+ * and then free the skb.
|
|
|
+ */
|
|
|
+ if (skb) {
|
|
|
+ struct page *page;
|
|
|
+ struct skb_shared_info *shinfo;
|
|
|
+
|
|
|
+ shinfo = skb_shinfo(skb);
|
|
|
+ shinfo->nr_frags--;
|
|
|
+ page = shinfo->frags[shinfo->nr_frags].page;
|
|
|
+ shinfo->frags[shinfo->nr_frags].page = NULL;
|
|
|
+
|
|
|
+ cons_rx_pg->page = page;
|
|
|
+ dev_kfree_skb(skb);
|
|
|
+ }
|
|
|
+
|
|
|
+ hw_prod = rxr->rx_pg_prod;
|
|
|
+
|
|
|
for (i = 0; i < count; i++) {
|
|
|
prod = RX_PG_RING_IDX(hw_prod);
|
|
|
|
|
@@ -2685,20 +2706,6 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
|
|
|
cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
|
|
|
prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
|
|
|
|
|
|
- if (i == 0 && skb) {
|
|
|
- struct page *page;
|
|
|
- struct skb_shared_info *shinfo;
|
|
|
-
|
|
|
- shinfo = skb_shinfo(skb);
|
|
|
- shinfo->nr_frags--;
|
|
|
- page = shinfo->frags[shinfo->nr_frags].page;
|
|
|
- shinfo->frags[shinfo->nr_frags].page = NULL;
|
|
|
- mapping = pci_map_page(bp->pdev, page, 0, PAGE_SIZE,
|
|
|
- PCI_DMA_FROMDEVICE);
|
|
|
- cons_rx_pg->page = page;
|
|
|
- pci_unmap_addr_set(cons_rx_pg, mapping, mapping);
|
|
|
- dev_kfree_skb(skb);
|
|
|
- }
|
|
|
if (prod != cons) {
|
|
|
prod_rx_pg->page = cons_rx_pg->page;
|
|
|
cons_rx_pg->page = NULL;
|
|
@@ -2784,6 +2791,8 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
|
|
|
skb_put(skb, hdr_len);
|
|
|
|
|
|
for (i = 0; i < pages; i++) {
|
|
|
+ dma_addr_t mapping_old;
|
|
|
+
|
|
|
frag_len = min(frag_size, (unsigned int) PAGE_SIZE);
|
|
|
if (unlikely(frag_len <= 4)) {
|
|
|
unsigned int tail = 4 - frag_len;
|
|
@@ -2806,9 +2815,10 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
|
|
|
}
|
|
|
rx_pg = &rxr->rx_pg_ring[pg_cons];
|
|
|
|
|
|
- pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping),
|
|
|
- PAGE_SIZE, PCI_DMA_FROMDEVICE);
|
|
|
-
|
|
|
+ /* Don't unmap yet. If we're unable to allocate a new
|
|
|
+ * page, we need to recycle the page and the DMA addr.
|
|
|
+ */
|
|
|
+ mapping_old = pci_unmap_addr(rx_pg, mapping);
|
|
|
if (i == pages - 1)
|
|
|
frag_len -= 4;
|
|
|
|
|
@@ -2825,6 +2835,9 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, struct sk_buff *skb,
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+ pci_unmap_page(bp->pdev, mapping_old,
|
|
|
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
|
|
|
+
|
|
|
frag_size -= frag_len;
|
|
|
skb->data_len += frag_len;
|
|
|
skb->truesize += frag_len;
|
|
@@ -4971,31 +4984,20 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
|
|
|
continue;
|
|
|
|
|
|
for (j = 0; j < TX_DESC_CNT; ) {
|
|
|
- struct sw_bd *tx_buf = &txr->tx_buf_ring[j];
|
|
|
+ struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
|
|
|
struct sk_buff *skb = tx_buf->skb;
|
|
|
- int k, last;
|
|
|
|
|
|
if (skb == NULL) {
|
|
|
j++;
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- pci_unmap_single(bp->pdev,
|
|
|
- pci_unmap_addr(tx_buf, mapping),
|
|
|
- skb_headlen(skb), PCI_DMA_TODEVICE);
|
|
|
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
|
|
|
|
|
|
tx_buf->skb = NULL;
|
|
|
|
|
|
- last = skb_shinfo(skb)->nr_frags;
|
|
|
- for (k = 0; k < last; k++) {
|
|
|
- tx_buf = &txr->tx_buf_ring[j + k + 1];
|
|
|
- pci_unmap_page(bp->pdev,
|
|
|
- pci_unmap_addr(tx_buf, mapping),
|
|
|
- skb_shinfo(skb)->frags[j].size,
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
- }
|
|
|
+ j += skb_shinfo(skb)->nr_frags + 1;
|
|
|
dev_kfree_skb(skb);
|
|
|
- j += k + 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -5373,8 +5375,11 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
|
|
|
for (i = 14; i < pkt_size; i++)
|
|
|
packet[i] = (unsigned char) (i & 0xff);
|
|
|
|
|
|
- map = pci_map_single(bp->pdev, skb->data, pkt_size,
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
+ if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) {
|
|
|
+ dev_kfree_skb(skb);
|
|
|
+ return -EIO;
|
|
|
+ }
|
|
|
+ map = skb_shinfo(skb)->dma_maps[0];
|
|
|
|
|
|
REG_WR(bp, BNX2_HC_COMMAND,
|
|
|
bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
|
|
@@ -5409,7 +5414,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
|
|
|
|
|
|
udelay(5);
|
|
|
|
|
|
- pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
|
|
|
+ skb_dma_unmap(&bp->pdev->dev, skb, DMA_TO_DEVICE);
|
|
|
dev_kfree_skb(skb);
|
|
|
|
|
|
if (bnx2_get_hw_tx_cons(tx_napi) != txr->tx_prod)
|
|
@@ -5970,13 +5975,14 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
struct bnx2 *bp = netdev_priv(dev);
|
|
|
dma_addr_t mapping;
|
|
|
struct tx_bd *txbd;
|
|
|
- struct sw_bd *tx_buf;
|
|
|
+ struct sw_tx_bd *tx_buf;
|
|
|
u32 len, vlan_tag_flags, last_frag, mss;
|
|
|
u16 prod, ring_prod;
|
|
|
int i;
|
|
|
struct bnx2_napi *bnapi;
|
|
|
struct bnx2_tx_ring_info *txr;
|
|
|
struct netdev_queue *txq;
|
|
|
+ struct skb_shared_info *sp;
|
|
|
|
|
|
/* Determine which tx ring we will be placed on */
|
|
|
i = skb_get_queue_mapping(skb);
|
|
@@ -6041,11 +6047,16 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
} else
|
|
|
mss = 0;
|
|
|
|
|
|
- mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
|
|
|
+ if (skb_dma_map(&bp->pdev->dev, skb, DMA_TO_DEVICE)) {
|
|
|
+ dev_kfree_skb(skb);
|
|
|
+ return NETDEV_TX_OK;
|
|
|
+ }
|
|
|
+
|
|
|
+ sp = skb_shinfo(skb);
|
|
|
+ mapping = sp->dma_maps[0];
|
|
|
|
|
|
tx_buf = &txr->tx_buf_ring[ring_prod];
|
|
|
tx_buf->skb = skb;
|
|
|
- pci_unmap_addr_set(tx_buf, mapping, mapping);
|
|
|
|
|
|
txbd = &txr->tx_desc_ring[ring_prod];
|
|
|
|
|
@@ -6064,10 +6075,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
|
txbd = &txr->tx_desc_ring[ring_prod];
|
|
|
|
|
|
len = frag->size;
|
|
|
- mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset,
|
|
|
- len, PCI_DMA_TODEVICE);
|
|
|
- pci_unmap_addr_set(&txr->tx_buf_ring[ring_prod],
|
|
|
- mapping, mapping);
|
|
|
+ mapping = sp->dma_maps[i + 1];
|
|
|
|
|
|
txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
|
|
|
txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
|