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

net: page_pool: API cleanup and comments

Functions starting with __ usually indicate those which are exported,
but should not be called directly. Update some of those declared in the
API and make it more readable.

page_pool_unmap_page() and page_pool_release_page() were doing
exactly the same thing calling __page_pool_clean_page(). Let's
rename __page_pool_clean_page() to page_pool_release_page() and
export it in order to show up on perf logs and get rid of
page_pool_unmap_page().

Finally rename __page_pool_put_page() to page_pool_put_page() since we
can now directly call it from drivers and rename the existing
page_pool_put_page() to page_pool_put_full_page() since they do the same
thing but the latter is trying to sync the full DMA area.

This patch also updates netsec, mvneta and stmmac drivers which use
those functions.

Suggested-by: Jonathan Lemon <jonathan.lemon@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Acked-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ilias Apalodimas and committed by
David S. Miller
458de8a9 78c9df81

+74 -80
+9 -10
drivers/net/ethernet/marvell/mvneta.c
··· 1956 1956 if (!data || !(rx_desc->buf_phys_addr)) 1957 1957 continue; 1958 1958 1959 - page_pool_put_page(rxq->page_pool, data, false); 1959 + page_pool_put_full_page(rxq->page_pool, data, false); 1960 1960 } 1961 1961 if (xdp_rxq_info_is_reg(&rxq->xdp_rxq)) 1962 1962 xdp_rxq_info_unreg(&rxq->xdp_rxq); ··· 2154 2154 err = xdp_do_redirect(pp->dev, xdp, prog); 2155 2155 if (err) { 2156 2156 ret = MVNETA_XDP_DROPPED; 2157 - __page_pool_put_page(rxq->page_pool, 2158 - virt_to_head_page(xdp->data), 2159 - len, true); 2157 + page_pool_put_page(rxq->page_pool, 2158 + virt_to_head_page(xdp->data), len, 2159 + true); 2160 2160 } else { 2161 2161 ret = MVNETA_XDP_REDIR; 2162 2162 stats->xdp_redirect++; ··· 2166 2166 case XDP_TX: 2167 2167 ret = mvneta_xdp_xmit_back(pp, xdp); 2168 2168 if (ret != MVNETA_XDP_TX) 2169 - __page_pool_put_page(rxq->page_pool, 2170 - virt_to_head_page(xdp->data), 2171 - len, true); 2169 + page_pool_put_page(rxq->page_pool, 2170 + virt_to_head_page(xdp->data), len, 2171 + true); 2172 2172 break; 2173 2173 default: 2174 2174 bpf_warn_invalid_xdp_action(act); ··· 2177 2177 trace_xdp_exception(pp->dev, prog, act); 2178 2178 /* fall through */ 2179 2179 case XDP_DROP: 2180 - __page_pool_put_page(rxq->page_pool, 2181 - virt_to_head_page(xdp->data), 2182 - len, true); 2180 + page_pool_put_page(rxq->page_pool, 2181 + virt_to_head_page(xdp->data), len, true); 2183 2182 ret = MVNETA_XDP_DROPPED; 2184 2183 stats->xdp_drop++; 2185 2184 break;
+11 -12
drivers/net/ethernet/socionext/netsec.c
··· 896 896 case XDP_TX: 897 897 ret = netsec_xdp_xmit_back(priv, xdp); 898 898 if (ret != NETSEC_XDP_TX) 899 - __page_pool_put_page(dring->page_pool, 900 - virt_to_head_page(xdp->data), 901 - len, true); 899 + page_pool_put_page(dring->page_pool, 900 + virt_to_head_page(xdp->data), len, 901 + true); 902 902 break; 903 903 case XDP_REDIRECT: 904 904 err = xdp_do_redirect(priv->ndev, xdp, prog); ··· 906 906 ret = NETSEC_XDP_REDIR; 907 907 } else { 908 908 ret = NETSEC_XDP_CONSUMED; 909 - __page_pool_put_page(dring->page_pool, 910 - virt_to_head_page(xdp->data), 911 - len, true); 909 + page_pool_put_page(dring->page_pool, 910 + virt_to_head_page(xdp->data), len, 911 + true); 912 912 } 913 913 break; 914 914 default: ··· 919 919 /* fall through -- handle aborts by dropping packet */ 920 920 case XDP_DROP: 921 921 ret = NETSEC_XDP_CONSUMED; 922 - __page_pool_put_page(dring->page_pool, 923 - virt_to_head_page(xdp->data), 924 - len, true); 922 + page_pool_put_page(dring->page_pool, 923 + virt_to_head_page(xdp->data), len, true); 925 924 break; 926 925 } 927 926 ··· 1019 1020 * cache state. Since we paid the allocation cost if 1020 1021 * building an skb fails try to put the page into cache 1021 1022 */ 1022 - __page_pool_put_page(dring->page_pool, page, 1023 - pkt_len, true); 1023 + page_pool_put_page(dring->page_pool, page, pkt_len, 1024 + true); 1024 1025 netif_err(priv, drv, priv->ndev, 1025 1026 "rx failed to build skb\n"); 1026 1027 break; ··· 1194 1195 if (id == NETSEC_RING_RX) { 1195 1196 struct page *page = virt_to_page(desc->addr); 1196 1197 1197 - page_pool_put_page(dring->page_pool, page, false); 1198 + page_pool_put_full_page(dring->page_pool, page, false); 1198 1199 } else if (id == NETSEC_RING_TX) { 1199 1200 dma_unmap_single(priv->dev, desc->dma_addr, desc->len, 1200 1201 DMA_TO_DEVICE);
+2 -2
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
··· 1251 1251 struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; 1252 1252 1253 1253 if (buf->page) 1254 - page_pool_put_page(rx_q->page_pool, buf->page, false); 1254 + page_pool_put_full_page(rx_q->page_pool, buf->page, false); 1255 1255 buf->page = NULL; 1256 1256 1257 1257 if (buf->sec_page) 1258 - page_pool_put_page(rx_q->page_pool, buf->sec_page, false); 1258 + page_pool_put_full_page(rx_q->page_pool, buf->sec_page, false); 1259 1259 buf->sec_page = NULL; 1260 1260 } 1261 1261
+14 -22
include/net/page_pool.h
··· 151 151 #ifdef CONFIG_PAGE_POOL 152 152 void page_pool_destroy(struct page_pool *pool); 153 153 void page_pool_use_xdp_mem(struct page_pool *pool, void (*disconnect)(void *)); 154 + void page_pool_release_page(struct page_pool *pool, struct page *page); 154 155 #else 155 156 static inline void page_pool_destroy(struct page_pool *pool) 156 157 { ··· 161 160 void (*disconnect)(void *)) 162 161 { 163 162 } 163 + static inline void page_pool_release_page(struct page_pool *pool, 164 + struct page *page) 165 + { 166 + } 164 167 #endif 165 168 166 - /* Never call this directly, use helpers below */ 167 - void __page_pool_put_page(struct page_pool *pool, struct page *page, 168 - unsigned int dma_sync_size, bool allow_direct); 169 + void page_pool_put_page(struct page_pool *pool, struct page *page, 170 + unsigned int dma_sync_size, bool allow_direct); 169 171 170 - static inline void page_pool_put_page(struct page_pool *pool, 171 - struct page *page, bool allow_direct) 172 + /* Same as above but will try to sync the entire area pool->max_len */ 173 + static inline void page_pool_put_full_page(struct page_pool *pool, 174 + struct page *page, bool allow_direct) 172 175 { 173 176 /* When page_pool isn't compiled-in, net/core/xdp.c doesn't 174 177 * allow registering MEM_TYPE_PAGE_POOL, but shield linker. 175 178 */ 176 179 #ifdef CONFIG_PAGE_POOL 177 - __page_pool_put_page(pool, page, -1, allow_direct); 180 + page_pool_put_page(pool, page, -1, allow_direct); 178 181 #endif 179 182 } 180 - /* Very limited use-cases allow recycle direct */ 183 + 184 + /* Same as above but the caller must guarantee safe context. e.g NAPI */ 181 185 static inline void page_pool_recycle_direct(struct page_pool *pool, 182 186 struct page *page) 183 187 { 184 - __page_pool_put_page(pool, page, -1, true); 185 - } 186 - 187 - /* Disconnects a page (from a page_pool). API users can have a need 188 - * to disconnect a page (from a page_pool), to allow it to be used as 189 - * a regular page (that will eventually be returned to the normal 190 - * page-allocator via put_page). 191 - */ 192 - void page_pool_unmap_page(struct page_pool *pool, struct page *page); 193 - static inline void page_pool_release_page(struct page_pool *pool, 194 - struct page *page) 195 - { 196 - #ifdef CONFIG_PAGE_POOL 197 - page_pool_unmap_page(pool, page); 198 - #endif 188 + page_pool_put_full_page(pool, page, true); 199 189 } 200 190 201 191 static inline dma_addr_t page_pool_get_dma_addr(struct page *page)
+37 -33
net/core/page_pool.c
··· 96 96 } 97 97 EXPORT_SYMBOL(page_pool_create); 98 98 99 - static void __page_pool_return_page(struct page_pool *pool, struct page *page); 99 + static void page_pool_return_page(struct page_pool *pool, struct page *page); 100 100 101 101 noinline 102 102 static struct page *page_pool_refill_alloc_cache(struct page_pool *pool) ··· 136 136 * (2) break out to fallthrough to alloc_pages_node. 137 137 * This limit stress on page buddy alloactor. 138 138 */ 139 - __page_pool_return_page(pool, page); 139 + page_pool_return_page(pool, page); 140 140 page = NULL; 141 141 break; 142 142 } ··· 274 274 return inflight; 275 275 } 276 276 277 - /* Cleanup page_pool state from page */ 278 - static void __page_pool_clean_page(struct page_pool *pool, 279 - struct page *page) 277 + /* Disconnects a page (from a page_pool). API users can have a need 278 + * to disconnect a page (from a page_pool), to allow it to be used as 279 + * a regular page (that will eventually be returned to the normal 280 + * page-allocator via put_page). 281 + */ 282 + void page_pool_release_page(struct page_pool *pool, struct page *page) 280 283 { 281 284 dma_addr_t dma; 282 285 int count; 283 286 284 287 if (!(pool->p.flags & PP_FLAG_DMA_MAP)) 288 + /* Always account for inflight pages, even if we didn't 289 + * map them 290 + */ 285 291 goto skip_dma_unmap; 286 292 287 293 dma = page->dma_addr; 288 - /* DMA unmap */ 294 + 295 + /* When page is unmapped, it cannot be returned our pool */ 289 296 dma_unmap_page_attrs(pool->p.dev, dma, 290 297 PAGE_SIZE << pool->p.order, pool->p.dma_dir, 291 298 DMA_ATTR_SKIP_CPU_SYNC); ··· 304 297 count = atomic_inc_return(&pool->pages_state_release_cnt); 305 298 trace_page_pool_state_release(pool, page, count); 306 299 } 307 - 308 - /* unmap the page and clean our state */ 309 - void page_pool_unmap_page(struct page_pool *pool, struct page *page) 310 - { 311 - /* When page is unmapped, this implies page will not be 312 - * returned to page_pool. 313 - */ 314 - __page_pool_clean_page(pool, page); 315 - } 316 - EXPORT_SYMBOL(page_pool_unmap_page); 300 + EXPORT_SYMBOL(page_pool_release_page); 317 301 318 302 /* Return a page to the page allocator, cleaning up our state */ 319 - static void __page_pool_return_page(struct page_pool *pool, struct page *page) 303 + static void page_pool_return_page(struct page_pool *pool, struct page *page) 320 304 { 321 - __page_pool_clean_page(pool, page); 305 + page_pool_release_page(pool, page); 322 306 323 307 put_page(page); 324 308 /* An optimization would be to call __free_pages(page, pool->p.order) ··· 318 320 */ 319 321 } 320 322 321 - static bool __page_pool_recycle_into_ring(struct page_pool *pool, 322 - struct page *page) 323 + static bool page_pool_recycle_in_ring(struct page_pool *pool, struct page *page) 323 324 { 324 325 int ret; 325 326 /* BH protection not needed if current is serving softirq */ ··· 335 338 * 336 339 * Caller must provide appropriate safe context. 337 340 */ 338 - static bool __page_pool_recycle_direct(struct page *page, 341 + static bool page_pool_recycle_in_cache(struct page *page, 339 342 struct page_pool *pool) 340 343 { 341 344 if (unlikely(pool->alloc.count == PP_ALLOC_CACHE_SIZE)) ··· 354 357 return !page_is_pfmemalloc(page); 355 358 } 356 359 357 - void __page_pool_put_page(struct page_pool *pool, struct page *page, 358 - unsigned int dma_sync_size, bool allow_direct) 360 + /* If the page refcnt == 1, this will try to recycle the page. 361 + * if PP_FLAG_DMA_SYNC_DEV is set, we'll try to sync the DMA area for 362 + * the configured size min(dma_sync_size, pool->max_len). 363 + * If the page refcnt != 1, then the page will be returned to memory 364 + * subsystem. 365 + */ 366 + void page_pool_put_page(struct page_pool *pool, struct page *page, 367 + unsigned int dma_sync_size, bool allow_direct) 359 368 { 360 369 /* This allocator is optimized for the XDP mode that uses 361 370 * one-frame-per-page, but have fallbacks that act like the ··· 378 375 dma_sync_size); 379 376 380 377 if (allow_direct && in_serving_softirq()) 381 - if (__page_pool_recycle_direct(page, pool)) 378 + if (page_pool_recycle_in_cache(page, pool)) 382 379 return; 383 380 384 - if (!__page_pool_recycle_into_ring(pool, page)) { 381 + if (!page_pool_recycle_in_ring(pool, page)) { 385 382 /* Cache full, fallback to free pages */ 386 - __page_pool_return_page(pool, page); 383 + page_pool_return_page(pool, page); 387 384 } 388 385 return; 389 386 } ··· 400 397 * doing refcnt based recycle tricks, meaning another process 401 398 * will be invoking put_page. 402 399 */ 403 - __page_pool_clean_page(pool, page); 400 + /* Do not replace this with page_pool_return_page() */ 401 + page_pool_release_page(pool, page); 404 402 put_page(page); 405 403 } 406 - EXPORT_SYMBOL(__page_pool_put_page); 404 + EXPORT_SYMBOL(page_pool_put_page); 407 405 408 - static void __page_pool_empty_ring(struct page_pool *pool) 406 + static void page_pool_empty_ring(struct page_pool *pool) 409 407 { 410 408 struct page *page; 411 409 ··· 417 413 pr_crit("%s() page_pool refcnt %d violation\n", 418 414 __func__, page_ref_count(page)); 419 415 420 - __page_pool_return_page(pool, page); 416 + page_pool_return_page(pool, page); 421 417 } 422 418 } 423 419 ··· 447 443 */ 448 444 while (pool->alloc.count) { 449 445 page = pool->alloc.cache[--pool->alloc.count]; 450 - __page_pool_return_page(pool, page); 446 + page_pool_return_page(pool, page); 451 447 } 452 448 } 453 449 ··· 459 455 /* No more consumers should exist, but producers could still 460 456 * be in-flight. 461 457 */ 462 - __page_pool_empty_ring(pool); 458 + page_pool_empty_ring(pool); 463 459 } 464 460 465 461 static int page_pool_release(struct page_pool *pool) ··· 533 529 /* Flush pool alloc cache, as refill will check NUMA node */ 534 530 while (pool->alloc.count) { 535 531 page = pool->alloc.cache[--pool->alloc.count]; 536 - __page_pool_return_page(pool, page); 532 + page_pool_return_page(pool, page); 537 533 } 538 534 } 539 535 EXPORT_SYMBOL(page_pool_update_nid);
+1 -1
net/core/xdp.c
··· 372 372 xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params); 373 373 page = virt_to_head_page(data); 374 374 napi_direct &= !xdp_return_frame_no_direct(); 375 - page_pool_put_page(xa->page_pool, page, napi_direct); 375 + page_pool_put_full_page(xa->page_pool, page, napi_direct); 376 376 rcu_read_unlock(); 377 377 break; 378 378 case MEM_TYPE_PAGE_SHARED: