Skip to content

Commit 7ed816b

Browse files
committed
eth: bnxt: use page pool for head frags
Testing small size RPCs (300B-400B) on a large AMD system suggests that page pool recycling is very useful even for just the head frags. With this patch (and copy break disabled) I see a 30% performance improvement (82Gbps -> 106Gbps). Convert bnxt from normal page frags to page pool frags for head buffers. On systems with small page size we can use the same pool as for TPA pages. On systems with large pages the frag allocation logic of the page pool is already used to split a large page into TPA chunks. TPA chunks are much larger than heads (8k or 64k, AFAICT vs 1kB) and we always allocate the same sized chunks. Mixing allocation of TPA and head pages would lead to sub-optimal memory use. Plus Taehee's work on zero-copy / devmem will need to differentiate between TPA and non-TPA page pool, anyway. Conditionally allocate a new page pool for heads. Link: https://patch.msgid.link/20241109035119.3391864-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 078e0d5 commit 7ed816b

File tree

2 files changed

+51
-48
lines changed

2 files changed

+51
-48
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,11 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
864864
bnapi->events &= ~BNXT_TX_CMP_EVENT;
865865
}
866866

867+
static bool bnxt_separate_head_pool(void)
868+
{
869+
return PAGE_SIZE > BNXT_RX_PAGE_SIZE;
870+
}
871+
867872
static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
868873
struct bnxt_rx_ring_info *rxr,
869874
unsigned int *offset,
@@ -886,27 +891,19 @@ static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
886891
}
887892

888893
static inline u8 *__bnxt_alloc_rx_frag(struct bnxt *bp, dma_addr_t *mapping,
894+
struct bnxt_rx_ring_info *rxr,
889895
gfp_t gfp)
890896
{
891-
u8 *data;
892-
struct pci_dev *pdev = bp->pdev;
897+
unsigned int offset;
898+
struct page *page;
893899

894-
if (gfp == GFP_ATOMIC)
895-
data = napi_alloc_frag(bp->rx_buf_size);
896-
else
897-
data = netdev_alloc_frag(bp->rx_buf_size);
898-
if (!data)
900+
page = page_pool_alloc_frag(rxr->head_pool, &offset,
901+
bp->rx_buf_size, gfp);
902+
if (!page)
899903
return NULL;
900904

901-
*mapping = dma_map_single_attrs(&pdev->dev, data + bp->rx_dma_offset,
902-
bp->rx_buf_use_size, bp->rx_dir,
903-
DMA_ATTR_WEAK_ORDERING);
904-
905-
if (dma_mapping_error(&pdev->dev, *mapping)) {
906-
skb_free_frag(data);
907-
data = NULL;
908-
}
909-
return data;
905+
*mapping = page_pool_get_dma_addr(page) + bp->rx_dma_offset + offset;
906+
return page_address(page) + offset;
910907
}
911908

912909
int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
@@ -928,7 +925,7 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
928925
rx_buf->data = page;
929926
rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
930927
} else {
931-
u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
928+
u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, rxr, gfp);
932929

933930
if (!data)
934931
return -ENOMEM;
@@ -1179,13 +1176,14 @@ static struct sk_buff *bnxt_rx_skb(struct bnxt *bp,
11791176
}
11801177

11811178
skb = napi_build_skb(data, bp->rx_buf_size);
1182-
dma_unmap_single_attrs(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
1183-
bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
1179+
dma_sync_single_for_cpu(&bp->pdev->dev, dma_addr, bp->rx_buf_use_size,
1180+
bp->rx_dir);
11841181
if (!skb) {
1185-
skb_free_frag(data);
1182+
page_pool_free_va(rxr->head_pool, data, true);
11861183
return NULL;
11871184
}
11881185

1186+
skb_mark_for_recycle(skb);
11891187
skb_reserve(skb, bp->rx_offset);
11901188
skb_put(skb, offset_and_len & 0xffff);
11911189
return skb;
@@ -1840,7 +1838,8 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
18401838
u8 *new_data;
18411839
dma_addr_t new_mapping;
18421840

1843-
new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
1841+
new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, rxr,
1842+
GFP_ATOMIC);
18441843
if (!new_data) {
18451844
bnxt_abort_tpa(cpr, idx, agg_bufs);
18461845
cpr->sw_stats->rx.rx_oom_discards += 1;
@@ -1852,16 +1851,16 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
18521851
tpa_info->mapping = new_mapping;
18531852

18541853
skb = napi_build_skb(data, bp->rx_buf_size);
1855-
dma_unmap_single_attrs(&bp->pdev->dev, mapping,
1856-
bp->rx_buf_use_size, bp->rx_dir,
1857-
DMA_ATTR_WEAK_ORDERING);
1854+
dma_sync_single_for_cpu(&bp->pdev->dev, mapping,
1855+
bp->rx_buf_use_size, bp->rx_dir);
18581856

18591857
if (!skb) {
1860-
skb_free_frag(data);
1858+
page_pool_free_va(rxr->head_pool, data, true);
18611859
bnxt_abort_tpa(cpr, idx, agg_bufs);
18621860
cpr->sw_stats->rx.rx_oom_discards += 1;
18631861
return NULL;
18641862
}
1863+
skb_mark_for_recycle(skb);
18651864
skb_reserve(skb, bp->rx_offset);
18661865
skb_put(skb, len);
18671866
}
@@ -3308,28 +3307,22 @@ static void bnxt_free_tx_skbs(struct bnxt *bp)
33083307

33093308
static void bnxt_free_one_rx_ring(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
33103309
{
3311-
struct pci_dev *pdev = bp->pdev;
33123310
int i, max_idx;
33133311

33143312
max_idx = bp->rx_nr_pages * RX_DESC_CNT;
33153313

33163314
for (i = 0; i < max_idx; i++) {
33173315
struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[i];
3318-
dma_addr_t mapping = rx_buf->mapping;
33193316
void *data = rx_buf->data;
33203317

33213318
if (!data)
33223319
continue;
33233320

33243321
rx_buf->data = NULL;
3325-
if (BNXT_RX_PAGE_MODE(bp)) {
3322+
if (BNXT_RX_PAGE_MODE(bp))
33263323
page_pool_recycle_direct(rxr->page_pool, data);
3327-
} else {
3328-
dma_unmap_single_attrs(&pdev->dev, mapping,
3329-
bp->rx_buf_use_size, bp->rx_dir,
3330-
DMA_ATTR_WEAK_ORDERING);
3331-
skb_free_frag(data);
3332-
}
3324+
else
3325+
page_pool_free_va(rxr->head_pool, data, true);
33333326
}
33343327
}
33353328

@@ -3356,7 +3349,6 @@ static void bnxt_free_one_rx_agg_ring(struct bnxt *bp, struct bnxt_rx_ring_info
33563349
static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
33573350
{
33583351
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
3359-
struct pci_dev *pdev = bp->pdev;
33603352
struct bnxt_tpa_idx_map *map;
33613353
int i;
33623354

@@ -3370,13 +3362,8 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
33703362
if (!data)
33713363
continue;
33723364

3373-
dma_unmap_single_attrs(&pdev->dev, tpa_info->mapping,
3374-
bp->rx_buf_use_size, bp->rx_dir,
3375-
DMA_ATTR_WEAK_ORDERING);
3376-
33773365
tpa_info->data = NULL;
3378-
3379-
skb_free_frag(data);
3366+
page_pool_free_va(rxr->head_pool, data, false);
33803367
}
33813368

33823369
skip_rx_tpa_free:
@@ -3592,7 +3579,9 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
35923579
xdp_rxq_info_unreg(&rxr->xdp_rxq);
35933580

35943581
page_pool_destroy(rxr->page_pool);
3595-
rxr->page_pool = NULL;
3582+
if (rxr->page_pool != rxr->head_pool)
3583+
page_pool_destroy(rxr->head_pool);
3584+
rxr->page_pool = rxr->head_pool = NULL;
35963585

35973586
kfree(rxr->rx_agg_bmap);
35983587
rxr->rx_agg_bmap = NULL;
@@ -3610,6 +3599,7 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
36103599
int numa_node)
36113600
{
36123601
struct page_pool_params pp = { 0 };
3602+
struct page_pool *pool;
36133603

36143604
pp.pool_size = bp->rx_agg_ring_size;
36153605
if (BNXT_RX_PAGE_MODE(bp))
@@ -3622,14 +3612,25 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
36223612
pp.max_len = PAGE_SIZE;
36233613
pp.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV;
36243614

3625-
rxr->page_pool = page_pool_create(&pp);
3626-
if (IS_ERR(rxr->page_pool)) {
3627-
int err = PTR_ERR(rxr->page_pool);
3615+
pool = page_pool_create(&pp);
3616+
if (IS_ERR(pool))
3617+
return PTR_ERR(pool);
3618+
rxr->page_pool = pool;
36283619

3629-
rxr->page_pool = NULL;
3630-
return err;
3620+
if (bnxt_separate_head_pool()) {
3621+
pp.pool_size = max(bp->rx_ring_size, 1024);
3622+
pool = page_pool_create(&pp);
3623+
if (IS_ERR(pool))
3624+
goto err_destroy_pp;
36313625
}
3626+
rxr->head_pool = pool;
3627+
36323628
return 0;
3629+
3630+
err_destroy_pp:
3631+
page_pool_destroy(rxr->page_pool);
3632+
rxr->page_pool = NULL;
3633+
return PTR_ERR(pool);
36333634
}
36343635

36353636
static int bnxt_alloc_rx_rings(struct bnxt *bp)
@@ -4180,7 +4181,8 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
41804181
u8 *data;
41814182

41824183
for (i = 0; i < bp->max_tpa; i++) {
4183-
data = __bnxt_alloc_rx_frag(bp, &mapping, GFP_KERNEL);
4184+
data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
4185+
GFP_KERNEL);
41844186
if (!data)
41854187
return -ENOMEM;
41864188

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,7 @@ struct bnxt_rx_ring_info {
11051105
struct bnxt_ring_struct rx_agg_ring_struct;
11061106
struct xdp_rxq_info xdp_rxq;
11071107
struct page_pool *page_pool;
1108+
struct page_pool *head_pool;
11081109
};
11091110

11101111
struct bnxt_rx_sw_stats {

0 commit comments

Comments
 (0)