]> git.itanic.dy.fi Git - linux-stable/blobdiff - net/core/page_pool.c
page_pool: fix inconsistency for page_pool_ring_[un]lock()
[linux-stable] / net / core / page_pool.c
index 193c18799865038a76a6863d28604245654fa922..2396c99bedeaa12d35891facb30a6593bc953d35 100644 (file)
@@ -133,6 +133,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)
 {
@@ -615,6 +638,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]);
@@ -633,7 +657,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 */
@@ -642,7 +666,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))