Patch "page_pool: fix inconsistency for page_pool_ring_[un]lock()" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    page_pool: fix inconsistency for page_pool_ring_[un]lock()

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     page_pool-fix-inconsistency-for-page_pool_ring_-un-l.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 90cd21baba9a4336765bccf5f9049d7bf45de7df
Author: Yunsheng Lin <linyunsheng@xxxxxxxxxx>
Date:   Mon May 22 11:17:14 2023 +0800

    page_pool: fix inconsistency for page_pool_ring_[un]lock()
    
    [ Upstream commit 368d3cb406cdd074d1df2ad9ec06d1bfcb664882 ]
    
    page_pool_ring_[un]lock() use in_softirq() to decide which
    spin lock variant to use, and when they are called in the
    context with in_softirq() being false, spin_lock_bh() is
    called in page_pool_ring_lock() while spin_unlock() is
    called in page_pool_ring_unlock(), because spin_lock_bh()
    has disabled the softirq in page_pool_ring_lock(), which
    causes inconsistency for spin lock pair calling.
    
    This patch fixes it by returning in_softirq state from
    page_pool_producer_lock(), and use it to decide which
    spin lock variant to use in page_pool_producer_unlock().
    
    As pool->ring has both producer and consumer lock, so
    rename it to page_pool_producer_[un]lock() to reflect
    the actual usage. Also move them to page_pool.c as they
    are only used there, and remove the 'inline' as the
    compiler may have better idea to do inlining or not.
    
    Fixes: 7886244736a4 ("net: page_pool: Add bulk support for ptr_ring")
    Signed-off-by: Yunsheng Lin <linyunsheng@xxxxxxxxxx>
    Acked-by: Jesper Dangaard Brouer <brouer@xxxxxxxxxx>
    Acked-by: Ilias Apalodimas <ilias.apalodimas@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230522031714.5089-1-linyunsheng@xxxxxxxxxx
    Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/net/page_pool.h b/include/net/page_pool.h
index 80d987419436e..edcc22605842e 100644
--- a/include/net/page_pool.h
+++ b/include/net/page_pool.h
@@ -282,22 +282,4 @@ static inline void page_pool_nid_changed(struct page_pool *pool, int new_nid)
 		page_pool_update_nid(pool, new_nid);
 }
 
-static inline void page_pool_ring_lock(struct page_pool *pool)
-	__acquires(&pool->ring.producer_lock)
-{
-	if (in_softirq())
-		spin_lock(&pool->ring.producer_lock);
-	else
-		spin_lock_bh(&pool->ring.producer_lock);
-}
-
-static inline void page_pool_ring_unlock(struct page_pool *pool)
-	__releases(&pool->ring.producer_lock)
-{
-	if (in_softirq())
-		spin_unlock(&pool->ring.producer_lock);
-	else
-		spin_unlock_bh(&pool->ring.producer_lock);
-}
-
 #endif /* _NET_PAGE_POOL_H */
diff --git a/net/core/page_pool.c b/net/core/page_pool.c
index 1d520fa1b98a8..069d6ba0e33fb 100644
--- a/net/core/page_pool.c
+++ b/net/core/page_pool.c
@@ -26,6 +26,29 @@
 
 #define BIAS_MAX	LONG_MAX
 
+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)
 {
@@ -489,6 +512,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]);
@@ -503,12 +527,12 @@ 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]))
 			break; /* ring full */
 	}
-	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))



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux