xref: /linux/Documentation/networking/page_pool.rst (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1.. SPDX-License-Identifier: GPL-2.0
2
3=============
4Page Pool API
5=============
6
7.. kernel-doc:: include/net/page_pool/helpers.h
8   :doc: page_pool allocator
9
10Architecture overview
11=====================
12
13.. code-block:: none
14
15    +------------------+
16    |       Driver     |
17    +------------------+
18            ^
19            |
20            |
21            |
22            v
23    +--------------------------------------------+
24    |                request memory              |
25    +--------------------------------------------+
26        ^                                  ^
27        |                                  |
28        | Pool empty                       | Pool has entries
29        |                                  |
30        v                                  v
31    +-----------------------+     +------------------------+
32    | alloc (and map) pages |     |  get page from cache   |
33    +-----------------------+     +------------------------+
34                                    ^                    ^
35                                    |                    |
36                                    | cache available    | No entries, refill
37                                    |                    | from ptr-ring
38                                    |                    |
39                                    v                    v
40                          +-----------------+     +------------------+
41                          |   Fast cache    |     |  ptr-ring cache  |
42                          +-----------------+     +------------------+
43
44Monitoring
45==========
46Information about page pools on the system can be accessed via the netdev
47genetlink family (see Documentation/netlink/specs/netdev.yaml).
48
49API interface
50=============
51The number of pools created **must** match the number of hardware queues
52unless hardware restrictions make that impossible. This would otherwise beat the
53purpose of page pool, which is allocate pages fast from cache without locking.
54This lockless guarantee naturally comes from running under a NAPI softirq.
55The protection doesn't strictly have to be NAPI, any guarantee that allocating
56a page will cause no race conditions is enough.
57
58.. kernel-doc:: net/core/page_pool.c
59   :identifiers: page_pool_create
60
61.. kernel-doc:: include/net/page_pool/types.h
62   :identifiers: struct page_pool_params
63
64.. kernel-doc:: include/net/page_pool/helpers.h
65   :identifiers: page_pool_put_page page_pool_put_full_page
66		 page_pool_recycle_direct page_pool_free_va
67		 page_pool_dev_alloc_pages page_pool_dev_alloc_frag
68		 page_pool_dev_alloc page_pool_dev_alloc_va
69		 page_pool_get_dma_addr page_pool_get_dma_dir
70
71.. kernel-doc:: net/core/page_pool.c
72   :identifiers: page_pool_put_page_bulk page_pool_get_stats
73
74DMA sync
75--------
76Driver is always responsible for syncing the pages for the CPU.
77Drivers may choose to take care of syncing for the device as well
78or set the ``PP_FLAG_DMA_SYNC_DEV`` flag to request that pages
79allocated from the page pool are already synced for the device.
80
81If ``PP_FLAG_DMA_SYNC_DEV`` is set, the driver must inform the core what portion
82of the buffer has to be synced. This allows the core to avoid syncing the entire
83page when the drivers knows that the device only accessed a portion of the page.
84
85Most drivers will reserve headroom in front of the frame. This part
86of the buffer is not touched by the device, so to avoid syncing
87it drivers can set the ``offset`` field in struct page_pool_params
88appropriately.
89
90For pages recycled on the XDP xmit and skb paths the page pool will
91use the ``max_len`` member of struct page_pool_params to decide how
92much of the page needs to be synced (starting at ``offset``).
93When directly freeing pages in the driver (page_pool_put_page())
94the ``dma_sync_size`` argument specifies how much of the buffer needs
95to be synced.
96
97If in doubt set ``offset`` to 0, ``max_len`` to ``PAGE_SIZE`` and
98pass -1 as ``dma_sync_size``. That combination of arguments is always
99correct.
100
101Note that the syncing parameters are for the entire page.
102This is important to remember when using fragments (``PP_FLAG_PAGE_FRAG``),
103where allocated buffers may be smaller than a full page.
104Unless the driver author really understands page pool internals
105it's recommended to always use ``offset = 0``, ``max_len = PAGE_SIZE``
106with fragmented page pools.
107
108Stats API and structures
109------------------------
110If the kernel is configured with ``CONFIG_PAGE_POOL_STATS=y``, the API
111page_pool_get_stats() and structures described below are available.
112It takes a  pointer to a ``struct page_pool`` and a pointer to a struct
113page_pool_stats allocated by the caller.
114
115Older drivers expose page pool statistics via ethtool or debugfs.
116The same statistics are accessible via the netlink netdev family
117in a driver-independent fashion.
118
119.. kernel-doc:: include/net/page_pool/types.h
120   :identifiers: struct page_pool_recycle_stats
121		 struct page_pool_alloc_stats
122		 struct page_pool_stats
123
124Coding examples
125===============
126
127Registration
128------------
129
130.. code-block:: c
131
132    /* Page pool registration */
133    struct page_pool_params pp_params = { 0 };
134    struct xdp_rxq_info xdp_rxq;
135    int err;
136
137    pp_params.order = 0;
138    /* internal DMA mapping in page_pool */
139    pp_params.flags = PP_FLAG_DMA_MAP;
140    pp_params.pool_size = DESC_NUM;
141    pp_params.nid = NUMA_NO_NODE;
142    pp_params.dev = priv->dev;
143    pp_params.napi = napi; /* only if locking is tied to NAPI */
144    pp_params.dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE;
145    page_pool = page_pool_create(&pp_params);
146
147    err = xdp_rxq_info_reg(&xdp_rxq, ndev, 0);
148    if (err)
149        goto err_out;
150
151    err = xdp_rxq_info_reg_mem_model(&xdp_rxq, MEM_TYPE_PAGE_POOL, page_pool);
152    if (err)
153        goto err_out;
154
155NAPI poller
156-----------
157
158
159.. code-block:: c
160
161    /* NAPI Rx poller */
162    enum dma_data_direction dma_dir;
163
164    dma_dir = page_pool_get_dma_dir(dring->page_pool);
165    while (done < budget) {
166        if (some error)
167            page_pool_recycle_direct(page_pool, page);
168        if (packet_is_xdp) {
169            if XDP_DROP:
170                page_pool_recycle_direct(page_pool, page);
171        } else (packet_is_skb) {
172            skb_mark_for_recycle(skb);
173            new_page = page_pool_dev_alloc_pages(page_pool);
174        }
175    }
176
177Stats
178-----
179
180.. code-block:: c
181
182	#ifdef CONFIG_PAGE_POOL_STATS
183	/* retrieve stats */
184	struct page_pool_stats stats = { 0 };
185	if (page_pool_get_stats(page_pool, &stats)) {
186		/* perhaps the driver reports statistics with ethool */
187		ethtool_print_allocation_stats(&stats.alloc_stats);
188		ethtool_print_recycle_stats(&stats.recycle_stats);
189	}
190	#endif
191
192Driver unload
193-------------
194
195.. code-block:: c
196
197    /* Driver unload */
198    page_pool_put_full_page(page_pool, page, false);
199    xdp_rxq_info_unreg(&xdp_rxq);
200