1818
1919#include <trace/events/page_pool.h>
2020
21+ #define DEFER_TIME (msecs_to_jiffies(1000))
22+ #define DEFER_WARN_INTERVAL (60 * HZ)
23+
2124static int page_pool_init (struct page_pool * pool ,
2225 const struct page_pool_params * params )
2326{
@@ -193,29 +196,22 @@ static s32 page_pool_inflight(struct page_pool *pool)
193196{
194197 u32 release_cnt = atomic_read (& pool -> pages_state_release_cnt );
195198 u32 hold_cnt = READ_ONCE (pool -> pages_state_hold_cnt );
196- s32 distance ;
197-
198- distance = _distance (hold_cnt , release_cnt );
199-
200- trace_page_pool_inflight (pool , distance , hold_cnt , release_cnt );
201- return distance ;
202- }
199+ s32 inflight ;
203200
204- static bool __page_pool_safe_to_destroy (struct page_pool * pool )
205- {
206- s32 inflight = page_pool_inflight (pool );
201+ inflight = _distance (hold_cnt , release_cnt );
207202
208- /* The distance should not be able to become negative */
203+ trace_page_pool_inflight ( pool , inflight , hold_cnt , release_cnt );
209204 WARN (inflight < 0 , "Negative(%d) inflight packet-pages" , inflight );
210205
211- return ( inflight == 0 ) ;
206+ return inflight ;
212207}
213208
214209/* Cleanup page_pool state from page */
215210static void __page_pool_clean_page (struct page_pool * pool ,
216211 struct page * page )
217212{
218213 dma_addr_t dma ;
214+ int count ;
219215
220216 if (!(pool -> p .flags & PP_FLAG_DMA_MAP ))
221217 goto skip_dma_unmap ;
@@ -227,9 +223,11 @@ static void __page_pool_clean_page(struct page_pool *pool,
227223 DMA_ATTR_SKIP_CPU_SYNC );
228224 page -> dma_addr = 0 ;
229225skip_dma_unmap :
230- atomic_inc (& pool -> pages_state_release_cnt );
231- trace_page_pool_state_release (pool , page ,
232- atomic_read (& pool -> pages_state_release_cnt ));
226+ /* This may be the last page returned, releasing the pool, so
227+ * it is not safe to reference pool afterwards.
228+ */
229+ count = atomic_inc_return (& pool -> pages_state_release_cnt );
230+ trace_page_pool_state_release (pool , page , count );
233231}
234232
235233/* unmap the page and clean our state */
@@ -338,31 +336,10 @@ static void __page_pool_empty_ring(struct page_pool *pool)
338336 }
339337}
340338
341- static void __warn_in_flight (struct page_pool * pool )
339+ static void page_pool_free (struct page_pool * pool )
342340{
343- u32 release_cnt = atomic_read (& pool -> pages_state_release_cnt );
344- u32 hold_cnt = READ_ONCE (pool -> pages_state_hold_cnt );
345- s32 distance ;
346-
347- distance = _distance (hold_cnt , release_cnt );
348-
349- /* Drivers should fix this, but only problematic when DMA is used */
350- WARN (1 , "Still in-flight pages:%d hold:%u released:%u" ,
351- distance , hold_cnt , release_cnt );
352- }
353-
354- void __page_pool_free (struct page_pool * pool )
355- {
356- /* Only last user actually free/release resources */
357- if (!page_pool_put (pool ))
358- return ;
359-
360- WARN (pool -> alloc .count , "API usage violation" );
361- WARN (!ptr_ring_empty (& pool -> ring ), "ptr_ring is not empty" );
362-
363- /* Can happen due to forced shutdown */
364- if (!__page_pool_safe_to_destroy (pool ))
365- __warn_in_flight (pool );
341+ if (pool -> disconnect )
342+ pool -> disconnect (pool );
366343
367344 ptr_ring_cleanup (& pool -> ring , NULL );
368345
@@ -371,12 +348,8 @@ void __page_pool_free(struct page_pool *pool)
371348
372349 kfree (pool );
373350}
374- EXPORT_SYMBOL (__page_pool_free );
375351
376- /* Request to shutdown: release pages cached by page_pool, and check
377- * for in-flight pages
378- */
379- bool __page_pool_request_shutdown (struct page_pool * pool )
352+ static void page_pool_scrub (struct page_pool * pool )
380353{
381354 struct page * page ;
382355
@@ -393,7 +366,64 @@ bool __page_pool_request_shutdown(struct page_pool *pool)
393366 * be in-flight.
394367 */
395368 __page_pool_empty_ring (pool );
369+ }
370+
371+ static int page_pool_release (struct page_pool * pool )
372+ {
373+ int inflight ;
374+
375+ page_pool_scrub (pool );
376+ inflight = page_pool_inflight (pool );
377+ if (!inflight )
378+ page_pool_free (pool );
379+
380+ return inflight ;
381+ }
382+
383+ static void page_pool_release_retry (struct work_struct * wq )
384+ {
385+ struct delayed_work * dwq = to_delayed_work (wq );
386+ struct page_pool * pool = container_of (dwq , typeof (* pool ), release_dw );
387+ int inflight ;
388+
389+ inflight = page_pool_release (pool );
390+ if (!inflight )
391+ return ;
392+
393+ /* Periodic warning */
394+ if (time_after_eq (jiffies , pool -> defer_warn )) {
395+ int sec = (s32 )((u32 )jiffies - (u32 )pool -> defer_start ) / HZ ;
396+
397+ pr_warn ("%s() stalled pool shutdown %d inflight %d sec\n" ,
398+ __func__ , inflight , sec );
399+ pool -> defer_warn = jiffies + DEFER_WARN_INTERVAL ;
400+ }
401+
402+ /* Still not ready to be disconnected, retry later */
403+ schedule_delayed_work (& pool -> release_dw , DEFER_TIME );
404+ }
405+
406+ void page_pool_use_xdp_mem (struct page_pool * pool , void (* disconnect )(void * ))
407+ {
408+ refcount_inc (& pool -> user_cnt );
409+ pool -> disconnect = disconnect ;
410+ }
411+
412+ void page_pool_destroy (struct page_pool * pool )
413+ {
414+ if (!pool )
415+ return ;
416+
417+ if (!page_pool_put (pool ))
418+ return ;
419+
420+ if (!page_pool_release (pool ))
421+ return ;
422+
423+ pool -> defer_start = jiffies ;
424+ pool -> defer_warn = jiffies + DEFER_WARN_INTERVAL ;
396425
397- return __page_pool_safe_to_destroy (pool );
426+ INIT_DELAYED_WORK (& pool -> release_dw , page_pool_release_retry );
427+ schedule_delayed_work (& pool -> release_dw , DEFER_TIME );
398428}
399- EXPORT_SYMBOL (__page_pool_request_shutdown );
429+ EXPORT_SYMBOL (page_pool_destroy );
0 commit comments