Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

eth: fbnic: move page pool pointer from NAPI to the ring struct

In preparation for memory providers we need a closer association
between queues and page pools. We used to have a page pool at the
NAPI level to serve all associated queues but with MP the queues
under a NAPI may no longer be created equal.

The "ring" structure in fbnic is a descriptor ring. We have separate
"rings" for payload and header pages ("to device"), as well as a ring
for completions ("from device"). Technically we only need the page
pool pointers in the "to device" rings, so adding the pointer to
the ring struct is a bit wasteful. But it makes passing the structures
around much easier.

For now both "to device" rings store a pointer to the same
page pool. Using more than one queue per NAPI is extremely rare
so don't bother trying to share a single page pool between queues.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20250901211214.1027927-2-kuba@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Jakub Kicinski and committed by
Paolo Abeni
33478dca 61481d72

+55 -44
+45 -38
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
··· 640 640 FBNIC_TWD_TYPE_AL; 641 641 total_bytes += FIELD_GET(FBNIC_TWD_LEN_MASK, twd); 642 642 643 - page_pool_put_page(nv->page_pool, page, -1, pp_allow_direct); 643 + page_pool_put_page(page->pp, page, -1, pp_allow_direct); 644 644 next_desc: 645 645 head++; 646 646 head &= ring->size_mask; ··· 735 735 } 736 736 737 737 static void fbnic_page_pool_drain(struct fbnic_ring *ring, unsigned int idx, 738 - struct fbnic_napi_vector *nv, int budget) 738 + int budget) 739 739 { 740 740 struct fbnic_rx_buf *rx_buf = &ring->rx_buf[idx]; 741 741 struct page *page = rx_buf->page; 742 742 743 743 if (!page_pool_unref_page(page, rx_buf->pagecnt_bias)) 744 - page_pool_put_unrefed_page(nv->page_pool, page, -1, !!budget); 744 + page_pool_put_unrefed_page(ring->page_pool, page, -1, !!budget); 745 745 746 746 rx_buf->page = NULL; 747 747 } ··· 826 826 fbnic_clean_twq(nv, napi_budget, qt, ts_head, head0, head1); 827 827 } 828 828 829 - static void fbnic_clean_bdq(struct fbnic_napi_vector *nv, int napi_budget, 830 - struct fbnic_ring *ring, unsigned int hw_head) 829 + static void fbnic_clean_bdq(struct fbnic_ring *ring, unsigned int hw_head, 830 + int napi_budget) 831 831 { 832 832 unsigned int head = ring->head; 833 833 ··· 835 835 return; 836 836 837 837 do { 838 - fbnic_page_pool_drain(ring, head, nv, napi_budget); 838 + fbnic_page_pool_drain(ring, head, napi_budget); 839 839 840 840 head++; 841 841 head &= ring->size_mask; ··· 865 865 } while (--i); 866 866 } 867 867 868 - static void fbnic_fill_bdq(struct fbnic_napi_vector *nv, struct fbnic_ring *bdq) 868 + static void fbnic_fill_bdq(struct fbnic_ring *bdq) 869 869 { 870 870 unsigned int count = fbnic_desc_unused(bdq); 871 871 unsigned int i = bdq->tail; ··· 876 876 do { 877 877 struct page *page; 878 878 879 - page = page_pool_dev_alloc_pages(nv->page_pool); 879 + page = page_pool_dev_alloc_pages(bdq->page_pool); 880 880 if (!page) { 881 881 u64_stats_update_begin(&bdq->stats.syncp); 882 882 bdq->stats.rx.alloc_failed++; ··· 997 997 } 998 998 } 999 999 1000 - static void fbnic_put_pkt_buff(struct fbnic_napi_vector *nv, 1000 + static void fbnic_put_pkt_buff(struct fbnic_q_triad *qt, 1001 1001 struct fbnic_pkt_buff *pkt, int budget) 1002 1002 { 1003 1003 struct page *page; ··· 1014 1014 1015 1015 while (nr_frags--) { 1016 1016 page = skb_frag_page(&shinfo->frags[nr_frags]); 1017 - page_pool_put_full_page(nv->page_pool, page, !!budget); 1017 + page_pool_put_full_page(qt->sub1.page_pool, page, 1018 + !!budget); 1018 1019 } 1019 1020 } 1020 1021 1021 1022 page = virt_to_page(pkt->buff.data_hard_start); 1022 - page_pool_put_full_page(nv->page_pool, page, !!budget); 1023 + page_pool_put_full_page(qt->sub0.page_pool, page, !!budget); 1023 1024 } 1024 1025 1025 1026 static struct sk_buff *fbnic_build_skb(struct fbnic_napi_vector *nv, ··· 1275 1274 dropped++; 1276 1275 } 1277 1276 1278 - fbnic_put_pkt_buff(nv, pkt, 1); 1277 + fbnic_put_pkt_buff(qt, pkt, 1); 1279 1278 } 1280 1279 1281 1280 pkt->buff.data_hard_start = NULL; ··· 1308 1307 1309 1308 /* Unmap and free processed buffers */ 1310 1309 if (head0 >= 0) 1311 - fbnic_clean_bdq(nv, budget, &qt->sub0, head0); 1312 - fbnic_fill_bdq(nv, &qt->sub0); 1310 + fbnic_clean_bdq(&qt->sub0, head0, budget); 1311 + fbnic_fill_bdq(&qt->sub0); 1313 1312 1314 1313 if (head1 >= 0) 1315 - fbnic_clean_bdq(nv, budget, &qt->sub1, head1); 1316 - fbnic_fill_bdq(nv, &qt->sub1); 1314 + fbnic_clean_bdq(&qt->sub1, head1, budget); 1315 + fbnic_fill_bdq(&qt->sub1); 1317 1316 1318 1317 /* Record the current head/tail of the queue */ 1319 1318 if (rcq->head != head) { ··· 1463 1462 fbn->rx[rxr->q_idx] = NULL; 1464 1463 } 1465 1464 1465 + static void fbnic_free_qt_page_pools(struct fbnic_q_triad *qt) 1466 + { 1467 + page_pool_destroy(qt->sub0.page_pool); 1468 + page_pool_destroy(qt->sub1.page_pool); 1469 + } 1470 + 1466 1471 static void fbnic_free_napi_vector(struct fbnic_net *fbn, 1467 1472 struct fbnic_napi_vector *nv) 1468 1473 { ··· 1486 1479 fbnic_remove_rx_ring(fbn, &nv->qt[i].sub0); 1487 1480 fbnic_remove_rx_ring(fbn, &nv->qt[i].sub1); 1488 1481 fbnic_remove_rx_ring(fbn, &nv->qt[i].cmpl); 1482 + fbnic_free_qt_page_pools(&nv->qt[i]); 1489 1483 } 1490 1484 1491 1485 fbnic_napi_free_irq(fbd, nv); 1492 - page_pool_destroy(nv->page_pool); 1493 1486 netif_napi_del(&nv->napi); 1494 1487 fbn->napi[fbnic_napi_idx(nv)] = NULL; 1495 1488 kfree(nv); ··· 1507 1500 #define FBNIC_PAGE_POOL_FLAGS \ 1508 1501 (PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV) 1509 1502 1510 - static int fbnic_alloc_nv_page_pool(struct fbnic_net *fbn, 1511 - struct fbnic_napi_vector *nv) 1503 + static int 1504 + fbnic_alloc_qt_page_pools(struct fbnic_net *fbn, struct fbnic_napi_vector *nv, 1505 + struct fbnic_q_triad *qt) 1512 1506 { 1513 1507 struct page_pool_params pp_params = { 1514 1508 .order = 0, 1515 1509 .flags = FBNIC_PAGE_POOL_FLAGS, 1516 - .pool_size = (fbn->hpq_size + fbn->ppq_size) * nv->rxt_count, 1510 + .pool_size = fbn->hpq_size + fbn->ppq_size, 1517 1511 .nid = NUMA_NO_NODE, 1518 1512 .dev = nv->dev, 1519 1513 .dma_dir = DMA_BIDIRECTIONAL, ··· 1541 1533 if (IS_ERR(pp)) 1542 1534 return PTR_ERR(pp); 1543 1535 1544 - nv->page_pool = pp; 1536 + qt->sub0.page_pool = pp; 1537 + page_pool_get(pp); 1538 + qt->sub1.page_pool = pp; 1545 1539 1546 1540 return 0; 1547 1541 } ··· 1609 1599 /* Tie nv back to PCIe dev */ 1610 1600 nv->dev = fbd->dev; 1611 1601 1612 - /* Allocate page pool */ 1613 - if (rxq_count) { 1614 - err = fbnic_alloc_nv_page_pool(fbn, nv); 1615 - if (err) 1616 - goto napi_del; 1617 - } 1618 - 1619 1602 /* Request the IRQ for napi vector */ 1620 1603 err = fbnic_napi_request_irq(fbd, nv); 1621 1604 if (err) 1622 - goto pp_destroy; 1605 + goto napi_del; 1623 1606 1624 1607 /* Initialize queue triads */ 1625 1608 qt = nv->qt; ··· 1682 1679 fbnic_ring_init(&qt->cmpl, db, rxq_idx, FBNIC_RING_F_STATS); 1683 1680 fbn->rx[rxq_idx] = &qt->cmpl; 1684 1681 1682 + err = fbnic_alloc_qt_page_pools(fbn, nv, qt); 1683 + if (err) 1684 + goto free_ring_cur_qt; 1685 + 1685 1686 err = xdp_rxq_info_reg(&qt->xdp_rxq, fbn->netdev, rxq_idx, 1686 1687 nv->napi.napi_id); 1687 1688 if (err) 1688 - goto free_ring_cur_qt; 1689 + goto free_qt_pp; 1689 1690 1690 1691 /* Update Rx queue index */ 1691 1692 rxt_count--; ··· 1705 1698 qt--; 1706 1699 1707 1700 xdp_rxq_info_unreg(&qt->xdp_rxq); 1701 + free_qt_pp: 1702 + fbnic_free_qt_page_pools(qt); 1708 1703 free_ring_cur_qt: 1709 1704 fbnic_remove_rx_ring(fbn, &qt->sub0); 1710 1705 fbnic_remove_rx_ring(fbn, &qt->sub1); ··· 1723 1714 txt_count++; 1724 1715 } 1725 1716 fbnic_napi_free_irq(fbd, nv); 1726 - pp_destroy: 1727 - page_pool_destroy(nv->page_pool); 1728 1717 napi_del: 1729 1718 netif_napi_del(&nv->napi); 1730 1719 fbn->napi[fbnic_napi_idx(nv)] = NULL; ··· 2026 2019 /* Register XDP memory model for completion queue */ 2027 2020 err = xdp_reg_mem_model(&nv->qt[i].xdp_rxq.mem, 2028 2021 MEM_TYPE_PAGE_POOL, 2029 - nv->page_pool); 2022 + nv->qt[i].sub0.page_pool); 2030 2023 if (err) 2031 2024 goto xdp_unreg_mem_model; 2032 2025 ··· 2340 2333 struct fbnic_q_triad *qt = &nv->qt[t]; 2341 2334 2342 2335 /* Clean the work queues of unprocessed work */ 2343 - fbnic_clean_bdq(nv, 0, &qt->sub0, qt->sub0.tail); 2344 - fbnic_clean_bdq(nv, 0, &qt->sub1, qt->sub1.tail); 2336 + fbnic_clean_bdq(&qt->sub0, qt->sub0.tail, 0); 2337 + fbnic_clean_bdq(&qt->sub1, qt->sub1.tail, 0); 2345 2338 2346 2339 /* Reset completion queue descriptor ring */ 2347 2340 memset(qt->cmpl.desc, 0, qt->cmpl.size); 2348 2341 2349 - fbnic_put_pkt_buff(nv, qt->cmpl.pkt, 0); 2342 + fbnic_put_pkt_buff(qt, qt->cmpl.pkt, 0); 2350 2343 memset(qt->cmpl.pkt, 0, sizeof(struct fbnic_pkt_buff)); 2351 2344 } 2352 2345 } ··· 2367 2360 struct fbnic_q_triad *qt = &nv->qt[t]; 2368 2361 2369 2362 /* Populate the header and payload BDQs */ 2370 - fbnic_fill_bdq(nv, &qt->sub0); 2371 - fbnic_fill_bdq(nv, &qt->sub1); 2363 + fbnic_fill_bdq(&qt->sub0); 2364 + fbnic_fill_bdq(&qt->sub1); 2372 2365 } 2373 2366 } 2374 2367 }
+10 -6
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
··· 121 121 122 122 u32 head, tail; /* Head/Tail of ring */ 123 123 124 - /* Deferred_head is used to cache the head for TWQ1 if an attempt 125 - * is made to clean TWQ1 with zero napi_budget. We do not use it for 126 - * any other ring. 127 - */ 128 - s32 deferred_head; 124 + union { 125 + /* Rx BDQs only */ 126 + struct page_pool *page_pool; 127 + 128 + /* Deferred_head is used to cache the head for TWQ1 if 129 + * an attempt is made to clean TWQ1 with zero napi_budget. 130 + * We do not use it for any other ring. 131 + */ 132 + s32 deferred_head; 133 + }; 129 134 130 135 struct fbnic_queue_stats stats; 131 136 ··· 147 142 struct fbnic_napi_vector { 148 143 struct napi_struct napi; 149 144 struct device *dev; /* Device for DMA unmapping */ 150 - struct page_pool *page_pool; 151 145 struct fbnic_dev *fbd; 152 146 153 147 u16 v_idx;