diff options
Diffstat (limited to 'net/core/page_pool.c')
| -rw-r--r-- | net/core/page_pool.c | 28 | 
1 files changed, 26 insertions, 2 deletions
diff --git a/net/core/page_pool.c b/net/core/page_pool.c index e212e9d7edcb..a3e12a61d456 100644 --- a/net/core/page_pool.c +++ b/net/core/page_pool.c @@ -134,6 +134,29 @@ EXPORT_SYMBOL(page_pool_ethtool_stats_get);  #define recycle_stat_add(pool, __stat, val)  #endif +static bool page_pool_producer_lock(struct page_pool *pool) +	__acquires(&pool->ring.producer_lock) +{ +	bool in_softirq = in_softirq(); + +	if (in_softirq) +		spin_lock(&pool->ring.producer_lock); +	else +		spin_lock_bh(&pool->ring.producer_lock); + +	return in_softirq; +} + +static void page_pool_producer_unlock(struct page_pool *pool, +				      bool in_softirq) +	__releases(&pool->ring.producer_lock) +{ +	if (in_softirq) +		spin_unlock(&pool->ring.producer_lock); +	else +		spin_unlock_bh(&pool->ring.producer_lock); +} +  static int page_pool_init(struct page_pool *pool,  			  const struct page_pool_params *params)  { @@ -617,6 +640,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,  			     int count)  {  	int i, bulk_len = 0; +	bool in_softirq;  	for (i = 0; i < count; i++) {  		struct page *page = virt_to_head_page(data[i]); @@ -635,7 +659,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,  		return;  	/* Bulk producer into ptr_ring page_pool cache */ -	page_pool_ring_lock(pool); +	in_softirq = page_pool_producer_lock(pool);  	for (i = 0; i < bulk_len; i++) {  		if (__ptr_ring_produce(&pool->ring, data[i])) {  			/* ring full */ @@ -644,7 +668,7 @@ void page_pool_put_page_bulk(struct page_pool *pool, void **data,  		}  	}  	recycle_stat_add(pool, ring, i); -	page_pool_ring_unlock(pool); +	page_pool_producer_unlock(pool, in_softirq);  	/* Hopefully all pages was return into ptr_ring */  	if (likely(i == bulk_len))  | 
