netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible
@ 2019-05-29 22:15 Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag() Sebastian Andrzej Siewior
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller

The first two patches remove local_irq_save() around
`netdev_alloc_cache' which does not work on -RT. Besides helping -RT it
whould benefit the users of the function since they can avoid disabling
interrupts and save a few cycles.
The remaining patches are from a time when I tried to remove
`netdev_alloc_cache' but then noticed that we still have non-NAPI
drivers using netdev_alloc_skb() and I dropped that idea. Using
napi_alloc_frag() over netdev_alloc_frag() would skip the not required
local_bh_disable() around the allocation.

Sebastian


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-29 22:48   ` Eric Dumazet
  2019-05-29 22:15 ` [PATCH net-next 2/7] net: Don't disable interrupts in __netdev_alloc_skb() Sebastian Andrzej Siewior
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller, Sebastian Andrzej Siewior

netdev_alloc_frag() can be used from any context and is used by NAPI
and non-NAPI drivers. Non-NAPI drivers use it in interrupt context
and NAPI drivers use it during initial allocation (->ndo_open() or
->ndo_change_mtu()). Some NAPI drivers share the same function for the
initial allocation and the allocation in their NAPI callback.

The interrupts are disabled in order to ensure locked access from every
context to `netdev_alloc_cache'.

Let netdev_alloc_frag() check if interrupts are disabled. If they are,
use `netdev_alloc_cache' otherwise disable BH and invoke
__napi_alloc_frag() for the allocation. The IRQ check is cheaper
compared to disabling & enabling interrupts and memory allocation with
disabled interrupts does not work on -RT.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 net/core/skbuff.c | 53 ++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 28 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e89be62826937..8a5ff67e14d90 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -369,34 +369,6 @@ struct napi_alloc_cache {
 static DEFINE_PER_CPU(struct page_frag_cache, netdev_alloc_cache);
 static DEFINE_PER_CPU(struct napi_alloc_cache, napi_alloc_cache);
 
-static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
-{
-	struct page_frag_cache *nc;
-	unsigned long flags;
-	void *data;
-
-	local_irq_save(flags);
-	nc = this_cpu_ptr(&netdev_alloc_cache);
-	data = page_frag_alloc(nc, fragsz, gfp_mask);
-	local_irq_restore(flags);
-	return data;
-}
-
-/**
- * netdev_alloc_frag - allocate a page fragment
- * @fragsz: fragment size
- *
- * Allocates a frag from a page for receive buffer.
- * Uses GFP_ATOMIC allocations.
- */
-void *netdev_alloc_frag(unsigned int fragsz)
-{
-	fragsz = SKB_DATA_ALIGN(fragsz);
-
-	return __netdev_alloc_frag(fragsz, GFP_ATOMIC);
-}
-EXPORT_SYMBOL(netdev_alloc_frag);
-
 static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
 {
 	struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache);
@@ -412,6 +384,31 @@ void *napi_alloc_frag(unsigned int fragsz)
 }
 EXPORT_SYMBOL(napi_alloc_frag);
 
+/**
+ * netdev_alloc_frag - allocate a page fragment
+ * @fragsz: fragment size
+ *
+ * Allocates a frag from a page for receive buffer.
+ * Uses GFP_ATOMIC allocations.
+ */
+void *netdev_alloc_frag(unsigned int fragsz)
+{
+	struct page_frag_cache *nc;
+	void *data;
+
+	fragsz = SKB_DATA_ALIGN(fragsz);
+	if (irqs_disabled()) {
+		nc = this_cpu_ptr(&netdev_alloc_cache);
+		data = page_frag_alloc(nc, fragsz, GFP_ATOMIC);
+	} else {
+		local_bh_disable();
+		data = __napi_alloc_frag(fragsz, GFP_ATOMIC);
+		local_bh_enable();
+	}
+	return data;
+}
+EXPORT_SYMBOL(netdev_alloc_frag);
+
 /**
  *	__netdev_alloc_skb - allocate an skbuff for rx on a specific device
  *	@dev: network device to receive on
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 2/7] net: Don't disable interrupts in __netdev_alloc_skb()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag() Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool() Sebastian Andrzej Siewior
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller, Sebastian Andrzej Siewior

__netdev_alloc_skb() can be used from any context and is used by NAPI
and non-NAPI drivers. Non-NAPI drivers use it in interrupt context and
NAPI drivers use it during initial allocation (->ndo_open() or
->ndo_change_mtu()). Some NAPI drivers share the same function for the
initial allocation and the allocation in their NAPI callback.

The interrupts are disabled in order to ensure locked access from every
context to `netdev_alloc_cache'.

Let __netdev_alloc_skb() check if interrupts are disabled. If they are, use
`netdev_alloc_cache'. Otherwise disable BH and use `napi_alloc_cache.page'.
The IRQ check is cheaper compared to disabling & enabling interrupts and
memory allocation with disabled interrupts does not work on -RT.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 net/core/skbuff.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 8a5ff67e14d90..7f714a1196b90 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -426,7 +426,6 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
 				   gfp_t gfp_mask)
 {
 	struct page_frag_cache *nc;
-	unsigned long flags;
 	struct sk_buff *skb;
 	bool pfmemalloc;
 	void *data;
@@ -447,13 +446,17 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
 	if (sk_memalloc_socks())
 		gfp_mask |= __GFP_MEMALLOC;
 
-	local_irq_save(flags);
-
-	nc = this_cpu_ptr(&netdev_alloc_cache);
-	data = page_frag_alloc(nc, len, gfp_mask);
-	pfmemalloc = nc->pfmemalloc;
-
-	local_irq_restore(flags);
+	if (irqs_disabled()) {
+		nc = this_cpu_ptr(&netdev_alloc_cache);
+		data = page_frag_alloc(nc, len, gfp_mask);
+		pfmemalloc = nc->pfmemalloc;
+	} else {
+		local_bh_disable();
+		nc = this_cpu_ptr(&napi_alloc_cache.page);
+		data = page_frag_alloc(nc, len, gfp_mask);
+		pfmemalloc = nc->pfmemalloc;
+		local_bh_enable();
+	}
 
 	if (unlikely(!data))
 		return NULL;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag() Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 2/7] net: Don't disable interrupts in __netdev_alloc_skb() Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-30  9:24   ` Ioana Ciocoi Radulescu
  2019-05-29 22:15 ` [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag() Sebastian Andrzej Siewior
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller, Sebastian Andrzej Siewior, Ioana Radulescu

According to the comment, the preempt_disable() statement is required
due to synchronisation in napi_alloc_frag(). The awful truth is that
local_bh_disable() is required because otherwise the NAPI poll callback
can be invoked while the open function setup buffers. This isn't
unlikely since the dpaa2 provides multiple devices.

The usage of napi_alloc_frag() has been removed in commit

 27c874867c4e9 ("dpaa2-eth: Use a single page per Rx buffer")

which means that the comment is not accurate and the preempt_disable()
statement is not required.

Remove the outdated comment and the no longer required
preempt_disable().

Cc: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 63b1ecc18c26f..f9ae97ba63334 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -997,13 +997,6 @@ static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid)
 	int i, j;
 	int new_count;
 
-	/* This is the lazy seeding of Rx buffer pools.
-	 * dpaa2_add_bufs() is also used on the Rx hotpath and calls
-	 * napi_alloc_frag(). The trouble with that is that it in turn ends up
-	 * calling this_cpu_ptr(), which mandates execution in atomic context.
-	 * Rather than splitting up the code, do a one-off preempt disable.
-	 */
-	preempt_disable();
 	for (j = 0; j < priv->num_channels; j++) {
 		for (i = 0; i < DPAA2_ETH_NUM_BUFS;
 		     i += DPAA2_ETH_BUFS_PER_CMD) {
@@ -1011,12 +1004,10 @@ static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid)
 			priv->channel[j]->buf_count += new_count;
 
 			if (new_count < DPAA2_ETH_BUFS_PER_CMD) {
-				preempt_enable();
 				return -ENOMEM;
 			}
 		}
 	}
-	preempt_enable();
 
 	return 0;
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
                   ` (2 preceding siblings ...)
  2019-05-29 22:15 ` [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool() Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-30  9:25   ` Ioana Ciocoi Radulescu
  2019-05-29 22:15 ` [PATCH net-next 5/7] bnx2x: " Sebastian Andrzej Siewior
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller, Sebastian Andrzej Siewior, Ioana Radulescu

The driver is using netdev_alloc_frag() for allocation in the
->ndo_start_xmit() path. That one is always invoked in a BH disabled
region so we could also use napi_alloc_frag().

Use napi_alloc_frag() for skb allocation.

Cc: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index f9ae97ba63334..ffeec89c0985e 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -555,7 +555,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
 	/* Prepare the HW SGT structure */
 	sgt_buf_size = priv->tx_data_offset +
 		       sizeof(struct dpaa2_sg_entry) *  num_dma_bufs;
-	sgt_buf = netdev_alloc_frag(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN);
+	sgt_buf = napi_alloc_frag(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN);
 	if (unlikely(!sgt_buf)) {
 		err = -ENOMEM;
 		goto sgt_buf_alloc_failed;
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 5/7] bnx2x: Use napi_alloc_frag()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
                   ` (3 preceding siblings ...)
  2019-05-29 22:15 ` [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag() Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 6/7] tg3: " Sebastian Andrzej Siewior
  2019-05-29 22:15 ` [PATCH net-next 7/7] net: hwbm: Make the hwbm_pool lock a mutex Sebastian Andrzej Siewior
  6 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev
  Cc: tglx, David S. Miller, Sebastian Andrzej Siewior, Ariel Elior,
	Sudarsana Kalluru, GR-everest-linux-l2

SKB allocation via bnx2x_frag_alloc() is always performed in NAPI
context. Preemptible context passes GFP_KERNEL and bnx2x_frag_alloc()
uses then __get_free_page() for the allocation.

Use napi_alloc_frag() for memory allocation.

Cc: Ariel Elior <aelior@marvell.com>
Cc: Sudarsana Kalluru <skalluru@marvell.com>
Cc: GR-everest-linux-l2@marvell.com
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 008ad0ca89ba0..c4986b5191916 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -684,7 +684,7 @@ static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp, gfp_t gfp_mask)
 		if (unlikely(gfpflags_allow_blocking(gfp_mask)))
 			return (void *)__get_free_page(gfp_mask);
 
-		return netdev_alloc_frag(fp->rx_frag_size);
+		return napi_alloc_frag(fp->rx_frag_size);
 	}
 
 	return kmalloc(fp->rx_buf_size + NET_SKB_PAD, gfp_mask);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 6/7] tg3: Use napi_alloc_frag()
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
                   ` (4 preceding siblings ...)
  2019-05-29 22:15 ` [PATCH net-next 5/7] bnx2x: " Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  2019-05-30  8:51   ` Sergei Shtylyov
  2019-05-29 22:15 ` [PATCH net-next 7/7] net: hwbm: Make the hwbm_pool lock a mutex Sebastian Andrzej Siewior
  6 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev
  Cc: tglx, David S. Miller, Sebastian Andrzej Siewior,
	Siva Reddy Kallam, Prashant Sreedharan, Michael Chan

tg3_alloc_rx_data() uses netdev_alloc_frag() for sbk allocation. All
callers of tg3_alloc_rx_data() either hold the tp->lock lock (which is
held with BH disabled) or run in NAPI context.

Use napi_alloc_frag() for skb allocations.

Cc: Siva Reddy Kallam <siva.kallam@broadcom.com>
Cc: Prashant Sreedharan <prashant@broadcom.com>
Cc: Michael Chan <mchan@broadcom.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/net/ethernet/broadcom/tg3.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 6d1f9c822548e..4c404d2213f98 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6710,7 +6710,7 @@ static int tg3_alloc_rx_data(struct tg3 *tp, struct tg3_rx_prodring_set *tpr,
 	skb_size = SKB_DATA_ALIGN(data_size + TG3_RX_OFFSET(tp)) +
 		   SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 	if (skb_size <= PAGE_SIZE) {
-		data = netdev_alloc_frag(skb_size);
+		data = napi_alloc_frag(skb_size);
 		*frag_size = skb_size;
 	} else {
 		data = kmalloc(skb_size, GFP_ATOMIC);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH net-next 7/7] net: hwbm: Make the hwbm_pool lock a mutex
  2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
                   ` (5 preceding siblings ...)
  2019-05-29 22:15 ` [PATCH net-next 6/7] tg3: " Sebastian Andrzej Siewior
@ 2019-05-29 22:15 ` Sebastian Andrzej Siewior
  6 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-29 22:15 UTC (permalink / raw)
  To: netdev; +Cc: tglx, David S. Miller, Sebastian Andrzej Siewior, Thomas Petazzoni

Based on review, `lock' is only acquired in hwbm_pool_add() which is
invoked via ->probe(), ->resume() and ->ndo_change_mtu(). Based on this
the lock can become a mutex and there is no need to disable interrupts
during the procedure.
Now that the lock is a mutex, hwbm_pool_add() no longer invokes
hwbm_pool_refill() in an atomic context so we can pass GFP_KERNEL to
hwbm_pool_refill() and remove the `gfp' argument from hwbm_pool_add().

Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 drivers/net/ethernet/marvell/mvneta.c    |  2 +-
 drivers/net/ethernet/marvell/mvneta_bm.c |  4 ++--
 include/net/hwbm.h                       |  6 +++---
 net/core/hwbm.c                          | 15 +++++++--------
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index e758650b2c26e..256d57ad42b76 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1118,7 +1118,7 @@ static void mvneta_bm_update_mtu(struct mvneta_port *pp, int mtu)
 			SKB_DATA_ALIGN(MVNETA_RX_BUF_SIZE(bm_pool->pkt_size));
 
 	/* Fill entire long pool */
-	num = hwbm_pool_add(hwbm_pool, hwbm_pool->size, GFP_ATOMIC);
+	num = hwbm_pool_add(hwbm_pool, hwbm_pool->size);
 	if (num != hwbm_pool->size) {
 		WARN(1, "pool %d: %d of %d allocated\n",
 		     bm_pool->id, num, hwbm_pool->size);
diff --git a/drivers/net/ethernet/marvell/mvneta_bm.c b/drivers/net/ethernet/marvell/mvneta_bm.c
index de468e1bdba9f..82ee2bcca6fd2 100644
--- a/drivers/net/ethernet/marvell/mvneta_bm.c
+++ b/drivers/net/ethernet/marvell/mvneta_bm.c
@@ -190,7 +190,7 @@ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
 			SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 		hwbm_pool->construct = mvneta_bm_construct;
 		hwbm_pool->priv = new_pool;
-		spin_lock_init(&hwbm_pool->lock);
+		mutex_init(&hwbm_pool->buf_lock);
 
 		/* Create new pool */
 		err = mvneta_bm_pool_create(priv, new_pool);
@@ -201,7 +201,7 @@ struct mvneta_bm_pool *mvneta_bm_pool_use(struct mvneta_bm *priv, u8 pool_id,
 		}
 
 		/* Allocate buffers for this pool */
-		num = hwbm_pool_add(hwbm_pool, hwbm_pool->size, GFP_ATOMIC);
+		num = hwbm_pool_add(hwbm_pool, hwbm_pool->size);
 		if (num != hwbm_pool->size) {
 			WARN(1, "pool %d: %d of %d allocated\n",
 			     new_pool->id, num, hwbm_pool->size);
diff --git a/include/net/hwbm.h b/include/net/hwbm.h
index 89085e2e2da5e..81643cf8a1c43 100644
--- a/include/net/hwbm.h
+++ b/include/net/hwbm.h
@@ -12,18 +12,18 @@ struct hwbm_pool {
 	/* constructor called during alocation */
 	int (*construct)(struct hwbm_pool *bm_pool, void *buf);
 	/* protect acces to the buffer counter*/
-	spinlock_t lock;
+	struct mutex buf_lock;
 	/* private data */
 	void *priv;
 };
 #ifdef CONFIG_HWBM
 void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf);
 int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp);
-int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp);
+int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num);
 #else
 void hwbm_buf_free(struct hwbm_pool *bm_pool, void *buf) {}
 int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp) { return 0; }
-int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
+int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num)
 { return 0; }
 #endif /* CONFIG_HWBM */
 #endif /* _HWBM_H */
diff --git a/net/core/hwbm.c b/net/core/hwbm.c
index 2cab489ae62e6..f784be14d38fe 100644
--- a/net/core/hwbm.c
+++ b/net/core/hwbm.c
@@ -47,34 +47,33 @@ int hwbm_pool_refill(struct hwbm_pool *bm_pool, gfp_t gfp)
 }
 EXPORT_SYMBOL_GPL(hwbm_pool_refill);
 
-int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
+int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num)
 {
 	int err, i;
-	unsigned long flags;
 
-	spin_lock_irqsave(&bm_pool->lock, flags);
+	mutex_lock(&bm_pool->buf_lock);
 	if (bm_pool->buf_num == bm_pool->size) {
 		pr_warn("pool already filled\n");
-		spin_unlock_irqrestore(&bm_pool->lock, flags);
+		mutex_unlock(&bm_pool->buf_lock);
 		return bm_pool->buf_num;
 	}
 
 	if (buf_num + bm_pool->buf_num > bm_pool->size) {
 		pr_warn("cannot allocate %d buffers for pool\n",
 			buf_num);
-		spin_unlock_irqrestore(&bm_pool->lock, flags);
+		mutex_unlock(&bm_pool->buf_lock);
 		return 0;
 	}
 
 	if ((buf_num + bm_pool->buf_num) < bm_pool->buf_num) {
 		pr_warn("Adding %d buffers to the %d current buffers will overflow\n",
 			buf_num,  bm_pool->buf_num);
-		spin_unlock_irqrestore(&bm_pool->lock, flags);
+		mutex_unlock(&bm_pool->buf_lock);
 		return 0;
 	}
 
 	for (i = 0; i < buf_num; i++) {
-		err = hwbm_pool_refill(bm_pool, gfp);
+		err = hwbm_pool_refill(bm_pool, GFP_KERNEL);
 		if (err < 0)
 			break;
 	}
@@ -83,7 +82,7 @@ int hwbm_pool_add(struct hwbm_pool *bm_pool, unsigned int buf_num, gfp_t gfp)
 	bm_pool->buf_num += i;
 
 	pr_debug("hwpm pool: %d of %d buffers added\n", i, buf_num);
-	spin_unlock_irqrestore(&bm_pool->lock, flags);
+	mutex_unlock(&bm_pool->buf_lock);
 
 	return i;
 }
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag()
  2019-05-29 22:15 ` [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag() Sebastian Andrzej Siewior
@ 2019-05-29 22:48   ` Eric Dumazet
  2019-05-31 18:14     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2019-05-29 22:48 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev; +Cc: tglx, David S. Miller



On 5/29/19 3:15 PM, Sebastian Andrzej Siewior wrote:
> netdev_alloc_frag() can be used from any context and is used by NAPI
> and non-NAPI drivers. Non-NAPI drivers use it in interrupt context
> and NAPI drivers use it during initial allocation (->ndo_open() or
> ->ndo_change_mtu()). Some NAPI drivers share the same function for the
> initial allocation and the allocation in their NAPI callback.

...

> +
> +	fragsz = SKB_DATA_ALIGN(fragsz);
> +	if (irqs_disabled()) {


What is the difference between this prior test, and the following ?

if (in_irq() || irqs_disabled())

I am asking because I see the latter being used in __dev_kfree_skb_any()


> +		nc = this_cpu_ptr(&netdev_alloc_cache);
> +		data = page_frag_alloc(nc, fragsz, GFP_ATOMIC);
> +	} else {
> +		local_bh_disable();
> +		data = __napi_alloc_frag(fragsz, GFP_ATOMIC);
> +		local_bh_enable();
> +	}
> +	return data;
> +}
> +EXPORT_SYMBOL(netdev_alloc_frag);
> +
>  /**
>   *	__netdev_alloc_skb - allocate an skbuff for rx on a specific device
>   *	@dev: network device to receive on
> 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 6/7] tg3: Use napi_alloc_frag()
  2019-05-29 22:15 ` [PATCH net-next 6/7] tg3: " Sebastian Andrzej Siewior
@ 2019-05-30  8:51   ` Sergei Shtylyov
  0 siblings, 0 replies; 13+ messages in thread
From: Sergei Shtylyov @ 2019-05-30  8:51 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev
  Cc: tglx, David S. Miller, Siva Reddy Kallam, Prashant Sreedharan,
	Michael Chan

Hello!

On 30.05.2019 1:15, Sebastian Andrzej Siewior wrote:

> tg3_alloc_rx_data() uses netdev_alloc_frag() for sbk allocation. All
                                                    ^^^ skb?

> callers of tg3_alloc_rx_data() either hold the tp->lock lock (which is
                                                      ^^^^^^^^^
    Sort of tautological.

> held with BH disabled) or run in NAPI context.
> 
> Use napi_alloc_frag() for skb allocations.
> 
> Cc: Siva Reddy Kallam <siva.kallam@broadcom.com>
> Cc: Prashant Sreedharan <prashant@broadcom.com>
> Cc: Michael Chan <mchan@broadcom.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
[...]

MBR, Sergei

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool()
  2019-05-29 22:15 ` [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool() Sebastian Andrzej Siewior
@ 2019-05-30  9:24   ` Ioana Ciocoi Radulescu
  0 siblings, 0 replies; 13+ messages in thread
From: Ioana Ciocoi Radulescu @ 2019-05-30  9:24 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev; +Cc: tglx, David S. Miller

> -----Original Message-----
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Sent: Thursday, May 30, 2019 1:15 AM
> To: netdev@vger.kernel.org
> Cc: tglx@linutronix.de; David S. Miller <davem@davemloft.net>; Sebastian
> Andrzej Siewior <bigeasy@linutronix.de>; Ioana Ciocoi Radulescu
> <ruxandra.radulescu@nxp.com>
> Subject: [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from
> seed_pool()
> 
> According to the comment, the preempt_disable() statement is required
> due to synchronisation in napi_alloc_frag(). The awful truth is that
> local_bh_disable() is required because otherwise the NAPI poll callback
> can be invoked while the open function setup buffers. This isn't
> unlikely since the dpaa2 provides multiple devices.
> 
> The usage of napi_alloc_frag() has been removed in commit
> 
>  27c874867c4e9 ("dpaa2-eth: Use a single page per Rx buffer")
> 
> which means that the comment is not accurate and the preempt_disable()
> statement is not required.
> 
> Remove the outdated comment and the no longer required
> preempt_disable().
> 
> Cc: Ioana Radulescu <ruxandra.radulescu@nxp.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Acked-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>

Thanks,
Ioana

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag()
  2019-05-29 22:15 ` [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag() Sebastian Andrzej Siewior
@ 2019-05-30  9:25   ` Ioana Ciocoi Radulescu
  0 siblings, 0 replies; 13+ messages in thread
From: Ioana Ciocoi Radulescu @ 2019-05-30  9:25 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior, netdev; +Cc: tglx, David S. Miller

> -----Original Message-----
> From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> Sent: Thursday, May 30, 2019 1:15 AM
> To: netdev@vger.kernel.org
> Cc: tglx@linutronix.de; David S. Miller <davem@davemloft.net>; Sebastian
> Andrzej Siewior <bigeasy@linutronix.de>; Ioana Ciocoi Radulescu
> <ruxandra.radulescu@nxp.com>
> Subject: [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag()
> 
> The driver is using netdev_alloc_frag() for allocation in the
> ->ndo_start_xmit() path. That one is always invoked in a BH disabled
> region so we could also use napi_alloc_frag().
> 
> Use napi_alloc_frag() for skb allocation.
> 
> Cc: Ioana Radulescu <ruxandra.radulescu@nxp.com>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

Acked-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>

Thanks,
Ioana

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag()
  2019-05-29 22:48   ` Eric Dumazet
@ 2019-05-31 18:14     ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2019-05-31 18:14 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: netdev, tglx, David S. Miller

On 2019-05-29 15:48:51 [-0700], Eric Dumazet wrote:
> > +
> > +	fragsz = SKB_DATA_ALIGN(fragsz);
> > +	if (irqs_disabled()) {
> 
> 
> What is the difference between this prior test, and the following ?
> 
> if (in_irq() || irqs_disabled())
> 
> I am asking because I see the latter being used in __dev_kfree_skb_any()

in_irq() is always true in hardirq context which is true for non-NAPI
drivers. If in_irq() is true, irqs_disabled() will also be true.
So I *think* I could replace the irqs_disabled() check with in_irq()
which should be cheaper because it just checks the preempt counter.

Sebastian

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-05-31 18:14 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-29 22:15 [PATCH net-next 0/7] Avoid local_irq_save() and use napi_alloc_frag() where possible Sebastian Andrzej Siewior
2019-05-29 22:15 ` [PATCH net-next 1/7] net: Don't disable interrupts in napi_alloc_frag() Sebastian Andrzej Siewior
2019-05-29 22:48   ` Eric Dumazet
2019-05-31 18:14     ` Sebastian Andrzej Siewior
2019-05-29 22:15 ` [PATCH net-next 2/7] net: Don't disable interrupts in __netdev_alloc_skb() Sebastian Andrzej Siewior
2019-05-29 22:15 ` [PATCH net-next 3/7] dpaa2-eth: Remove preempt_disable() from seed_pool() Sebastian Andrzej Siewior
2019-05-30  9:24   ` Ioana Ciocoi Radulescu
2019-05-29 22:15 ` [PATCH net-next 4/7] dpaa2-eth: Use napi_alloc_frag() Sebastian Andrzej Siewior
2019-05-30  9:25   ` Ioana Ciocoi Radulescu
2019-05-29 22:15 ` [PATCH net-next 5/7] bnx2x: " Sebastian Andrzej Siewior
2019-05-29 22:15 ` [PATCH net-next 6/7] tg3: " Sebastian Andrzej Siewior
2019-05-30  8:51   ` Sergei Shtylyov
2019-05-29 22:15 ` [PATCH net-next 7/7] net: hwbm: Make the hwbm_pool lock a mutex Sebastian Andrzej Siewior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).