Commit 720908e5 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

bnxt_en: Use page frag RX buffers for better software GRO performance

If NETIF_F_GRO_HW is disabled, the existing driver code uses kmalloc'ed
data for RX buffers.  This causes inefficient SW GRO performance
because the GRO data is merged using the less efficient frag_list.
Use netdev_alloc_frag() and friends instead so that GRO data can be
merged into skb_shinfo(skb)->frags for better performance.

[Use skb_free_frag() - Vikas Gupta]
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Reviewed-by: default avatarPavan Chebbi <pavan.chebbi@broadcom.com>
Reviewed-by: default avatarAndy Gospodarek <gospo@broadcom.com>
Signed-off-by: default avatarVikas Gupta <vikas.gupta@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b976969b
...@@ -741,13 +741,16 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, ...@@ -741,13 +741,16 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
return page; return page;
} }
static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping, static inline u8 *__bnxt_alloc_rx_frag(struct bnxt *bp, dma_addr_t *mapping,
gfp_t gfp) gfp_t gfp)
{ {
u8 *data; u8 *data;
struct pci_dev *pdev = bp->pdev; struct pci_dev *pdev = bp->pdev;
data = kmalloc(bp->rx_buf_size, gfp); if (gfp == GFP_ATOMIC)
data = napi_alloc_frag(bp->rx_buf_size);
else
data = netdev_alloc_frag(bp->rx_buf_size);
if (!data) if (!data)
return NULL; return NULL;
...@@ -756,7 +759,7 @@ static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping, ...@@ -756,7 +759,7 @@ static inline u8 *__bnxt_alloc_rx_data(struct bnxt *bp, dma_addr_t *mapping,
DMA_ATTR_WEAK_ORDERING); DMA_ATTR_WEAK_ORDERING);
if (dma_mapping_error(&pdev->dev, *mapping)) { if (dma_mapping_error(&pdev->dev, *mapping)) {
kfree(data); skb_free_frag(data);
data = NULL; data = NULL;
} }
return data; return data;
...@@ -779,7 +782,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, ...@@ -779,7 +782,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
rx_buf->data = page; rx_buf->data = page;
rx_buf->data_ptr = page_address(page) + bp->rx_offset; rx_buf->data_ptr = page_address(page) + bp->rx_offset;
} else { } else {
u8 *data = __bnxt_alloc_rx_data(bp, &mapping, gfp); u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -1021,11 +1024,11 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp, ...@@ -1021,11 +1024,11 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
return NULL; return NULL;
} }
skb = build_skb(data, 0); skb = build_skb(data, bp->rx_buf_size);
dma_unmap_single_attrs(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size, dma_unmap_single_attrs(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
bp->rx_dir, DMA_ATTR_WEAK_ORDERING); bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
if (!skb) { if (!skb) {
kfree(data); skb_free_frag(data);
return NULL; return NULL;
} }
...@@ -1613,7 +1616,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, ...@@ -1613,7 +1616,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
u8 *new_data; u8 *new_data;
dma_addr_t new_mapping; dma_addr_t new_mapping;
new_data = __bnxt_alloc_rx_data(bp, &new_mapping, GFP_ATOMIC); new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
if (!new_data) { if (!new_data) {
bnxt_abort_tpa(cpr, idx, agg_bufs); bnxt_abort_tpa(cpr, idx, agg_bufs);
cpr->sw_stats.rx.rx_oom_discards += 1; cpr->sw_stats.rx.rx_oom_discards += 1;
...@@ -1624,13 +1627,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, ...@@ -1624,13 +1627,13 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
tpa_info->data_ptr = new_data + bp->rx_offset; tpa_info->data_ptr = new_data + bp->rx_offset;
tpa_info->mapping = new_mapping; tpa_info->mapping = new_mapping;
skb = build_skb(data, 0); skb = build_skb(data, bp->rx_buf_size);
dma_unmap_single_attrs(&bp->pdev->dev, mapping, dma_unmap_single_attrs(&bp->pdev->dev, mapping,
bp->rx_buf_use_size, bp->rx_dir, bp->rx_buf_use_size, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING); DMA_ATTR_WEAK_ORDERING);
if (!skb) { if (!skb) {
kfree(data); skb_free_frag(data);
bnxt_abort_tpa(cpr, idx, agg_bufs); bnxt_abort_tpa(cpr, idx, agg_bufs);
cpr->sw_stats.rx.rx_oom_discards += 1; cpr->sw_stats.rx.rx_oom_discards += 1;
return NULL; return NULL;
...@@ -2796,7 +2799,7 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr) ...@@ -2796,7 +2799,7 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
tpa_info->data = NULL; tpa_info->data = NULL;
kfree(data); skb_free_frag(data);
} }
skip_rx_tpa_free: skip_rx_tpa_free:
...@@ -2822,7 +2825,7 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr) ...@@ -2822,7 +2825,7 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
dma_unmap_single_attrs(&pdev->dev, mapping, dma_unmap_single_attrs(&pdev->dev, mapping,
bp->rx_buf_use_size, bp->rx_dir, bp->rx_buf_use_size, bp->rx_dir,
DMA_ATTR_WEAK_ORDERING); DMA_ATTR_WEAK_ORDERING);
kfree(data); skb_free_frag(data);
} }
} }
...@@ -3526,7 +3529,7 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr) ...@@ -3526,7 +3529,7 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
u8 *data; u8 *data;
for (i = 0; i < bp->max_tpa; i++) { for (i = 0; i < bp->max_tpa; i++) {
data = __bnxt_alloc_rx_data(bp, &mapping, GFP_KERNEL); data = __bnxt_alloc_rx_frag(bp, &mapping, GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
......
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