DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/1] net/mana: add device reset support
From: Wei Hu @ 2026-05-09  6:01 UTC (permalink / raw)
  To: dev, stephen; +Cc: longli, weh

From: Wei Hu <weh@microsoft.com>

Add support for handling hardware service reset events in the
MANA driver. When the MANA kernel driver receives a hardware
service event, it initiates a device reset and notifies userspace
via IBV_EVENT_DEVICE_FATAL. The MANA PMD handles this by
performing an automatic teardown and recovery sequence.

The driver uses ethdev recovery events (ERR_RECOVERING,
RECOVERY_SUCCESS, RECOVERY_FAILED) to notify upper layers of
the reset lifecycle, and a PCI device removal event callback
to distinguish hot-remove from service reset.

Changes since v1:
- Removed net/netvsc patch from this series (will be submitted
  separately)
- Simplified reset exit: mana_reset_exit now calls
  mana_reset_exit_delay directly instead of spawning a separate
  thread, since it already runs on mana_reset_thread
- Added __rte_no_thread_safety_analysis annotations to fix clang
  -Wthread-safety build errors
- Switched from rte_thread_create_control to
  rte_thread_create_internal_control per DPDK preference
- Fixed declaration-after-statement style issues
- Fixed stale comments and removed unnecessary blank lines
- Added comments explaining intentionally ignored return values

Wei Hu (1):
  net/mana: add device reset support

 drivers/net/mana/mana.c      | 928 +++++++++++++++++++++++++++++++----
 drivers/net/mana/mana.h      |  33 +-
 drivers/net/mana/meson.build |   2 +-
 drivers/net/mana/mp.c        |  89 +++-
 drivers/net/mana/mr.c        |   6 +-
 drivers/net/mana/rx.c        |  24 +-
 drivers/net/mana/tx.c        |  40 +-
 7 files changed, 1016 insertions(+), 106 deletions(-)

-- 
2.34.1


^ permalink raw reply

* [PATCH v4 2/2] net/iavf: reuse device alarm for PHC sync
From: Soumyadeep Hore @ 2026-05-09 10:14 UTC (permalink / raw)
  To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev; +Cc: stable
In-Reply-To: <20260509101447.42093-1-soumyadeep.hore@intel.com>

Reuse existing iavf device alarm cadence to drive periodic PHC sync
instead of a dedicated PHC alarm callback.

Keep PHC start/stop hooks as pause/resume controls around queue
reconfiguration and device lifecycle paths.

Bugzilla ID: 1898
Fixes: 61b6874b9224 ("net/iavf: support Rx timestamp offload on AVX512")
Fixes: 6ad2944f4e82 ("net/iavf: support Rx timestamp offload on AVX2")
Fixes: 33db16136e55 ("net/iavf: improve performance of Rx timestamp offload")
Cc: stable@dpdk.org

Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
---
 drivers/net/intel/iavf/iavf.h        |  5 ++
 drivers/net/intel/iavf/iavf_ethdev.c | 70 ++++++++++++++++++++++++++++
 drivers/net/intel/iavf/iavf_vchnl.c  |  4 ++
 3 files changed, 79 insertions(+)

diff --git a/drivers/net/intel/iavf/iavf.h b/drivers/net/intel/iavf/iavf.h
index 403c61e2e8..2f1779d47b 100644
--- a/drivers/net/intel/iavf/iavf.h
+++ b/drivers/net/intel/iavf/iavf.h
@@ -76,6 +76,7 @@
 #define IAVF_QUEUE_ITR_INTERVAL_MAX     8160 /* 8160 us */
 
 #define IAVF_ALARM_INTERVAL 50000 /* us */
+#define IAVF_PHC_SYNC_ALARM_INTERVAL_US 200000
 
 /* The overhead from MTU to max frame size.
  * Considering QinQ packet, the VLAN tag needs to be counted twice.
@@ -383,6 +384,8 @@ struct iavf_adapter {
 	enum iavf_rx_func_type rx_func_type;
 	enum iavf_tx_func_type tx_func_type;
 	uint16_t fdir_ref_cnt;
+	uint8_t phc_sync_ticks;
+	bool phc_sync_paused;
 	struct iavf_devargs devargs;
 	bool mac_primary_set;
 };
@@ -517,6 +520,8 @@ void iavf_add_del_all_mac_addr(struct iavf_adapter *adapter, bool add);
 int iavf_dev_link_update(struct rte_eth_dev *dev,
 			__rte_unused int wait_to_complete);
 void iavf_dev_alarm_handler(void *param);
+void iavf_phc_sync_alarm_start(struct rte_eth_dev *dev);
+void iavf_phc_sync_alarm_stop(struct rte_eth_dev *dev);
 int iavf_query_stats(struct iavf_adapter *adapter,
 		    struct virtchnl_eth_stats **pstats);
 int iavf_config_promisc(struct iavf_adapter *adapter, bool enable_unicast,
diff --git a/drivers/net/intel/iavf/iavf_ethdev.c b/drivers/net/intel/iavf/iavf_ethdev.c
index 1eca20bc9a..02272d45c1 100644
--- a/drivers/net/intel/iavf/iavf_ethdev.c
+++ b/drivers/net/intel/iavf/iavf_ethdev.c
@@ -21,6 +21,7 @@
 #include <rte_pci.h>
 #include <rte_alarm.h>
 #include <rte_atomic.h>
+#include <rte_cycles.h>
 #include <rte_eal.h>
 #include <rte_ether.h>
 #include <ethdev_driver.h>
@@ -145,6 +146,7 @@ static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
 static void iavf_dev_interrupt_handler(void *param);
 static void iavf_disable_irq0(struct iavf_hw *hw);
+static bool iavf_phc_sync_alarm_needed(struct rte_eth_dev *dev);
 static int iavf_dev_flow_ops_get(struct rte_eth_dev *dev,
 				 const struct rte_flow_ops **ops);
 static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
@@ -1056,6 +1058,8 @@ iavf_dev_start(struct rte_eth_dev *dev)
 		goto error;
 	}
 
+	iavf_phc_sync_alarm_start(dev);
+
 	return 0;
 
 error:
@@ -1082,6 +1086,8 @@ iavf_dev_stop(struct rte_eth_dev *dev)
 	if (adapter->stopped == 1)
 		return 0;
 
+	iavf_phc_sync_alarm_stop(dev);
+
 	/* Disable the interrupt for Rx */
 	rte_intr_efd_disable(intr_handle);
 	/* Rx interrupt vector mapping free */
@@ -2705,9 +2711,11 @@ void
 iavf_dev_alarm_handler(void *param)
 {
 	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+	struct iavf_adapter *adapter;
 	if (dev == NULL || dev->data == NULL || dev->data->dev_private == NULL)
 		return;
 
+	adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	uint32_t icr0;
 
@@ -2723,10 +2731,70 @@ iavf_dev_alarm_handler(void *param)
 
 	iavf_enable_irq0(hw);
 
+	if (iavf_phc_sync_alarm_needed(dev) && !adapter->phc_sync_paused) {
+		adapter->phc_sync_ticks++;
+		if (adapter->phc_sync_ticks >=
+		    IAVF_PHC_SYNC_ALARM_INTERVAL_US / IAVF_ALARM_INTERVAL) {
+			struct ci_rx_queue *rxq = dev->data->rx_queues[0];
+
+			adapter->phc_sync_ticks = 0;
+			if (iavf_get_phc_time(rxq) == 0)
+				rxq->hw_time_update = rte_get_timer_cycles() /
+					(rte_get_timer_hz() / 1000);
+		}
+	} else {
+		adapter->phc_sync_ticks = 0;
+	}
+
 	rte_eal_alarm_set(IAVF_ALARM_INTERVAL,
 			  iavf_dev_alarm_handler, dev);
 }
 
+static bool
+iavf_phc_sync_alarm_needed(struct rte_eth_dev *dev)
+{
+	struct iavf_adapter *adapter;
+
+	adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+
+	if (adapter->closed || adapter->stopped)
+		return false;
+
+	if (!(dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP))
+		return false;
+
+	if (dev->data->nb_rx_queues == 0 || dev->data->rx_queues[0] == NULL)
+		return false;
+
+	return true;
+}
+
+void
+iavf_phc_sync_alarm_start(struct rte_eth_dev *dev)
+{
+	struct iavf_adapter *adapter;
+
+	if (!iavf_phc_sync_alarm_needed(dev))
+		return;
+
+	adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	adapter->phc_sync_paused = false;
+	adapter->phc_sync_ticks = 0;
+}
+
+void
+iavf_phc_sync_alarm_stop(struct rte_eth_dev *dev)
+{
+	struct iavf_adapter *adapter;
+
+	if (dev == NULL || dev->data == NULL || dev->data->dev_private == NULL)
+		return;
+
+	adapter = IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	adapter->phc_sync_paused = true;
+	adapter->phc_sync_ticks = 0;
+}
+
 static int
 iavf_dev_flow_ops_get(struct rte_eth_dev *dev,
 		      const struct rte_flow_ops **ops)
@@ -2912,6 +2980,7 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
 	} else {
 		rte_eal_alarm_cancel(iavf_dev_alarm_handler, eth_dev);
 	}
+	iavf_phc_sync_alarm_stop(eth_dev);
 
 	rte_free(eth_dev->data->mac_addrs);
 	eth_dev->data->mac_addrs = NULL;
@@ -2986,6 +3055,7 @@ iavf_dev_close(struct rte_eth_dev *dev)
 	} else {
 		rte_eal_alarm_cancel(iavf_dev_alarm_handler, dev);
 	}
+	iavf_phc_sync_alarm_stop(dev);
 	iavf_disable_irq0(hw);
 
 	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_QOS)
diff --git a/drivers/net/intel/iavf/iavf_vchnl.c b/drivers/net/intel/iavf/iavf_vchnl.c
index 08dd6f2d7f..82943472e1 100644
--- a/drivers/net/intel/iavf/iavf_vchnl.c
+++ b/drivers/net/intel/iavf/iavf_vchnl.c
@@ -2133,12 +2133,16 @@ iavf_request_queues(struct rte_eth_dev *dev, uint16_t num)
 	args.out_size = IAVF_AQ_BUF_SZ;
 
 	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_WB_ON_ITR) {
+		iavf_phc_sync_alarm_stop(dev);
 		err = iavf_execute_vf_cmd_safe(adapter, &args, 0);
+		iavf_phc_sync_alarm_start(dev);
 	} else {
 		rte_eal_alarm_cancel(iavf_dev_alarm_handler, dev);
+		iavf_phc_sync_alarm_stop(dev);
 		err = iavf_execute_vf_cmd_safe(adapter, &args, 0);
 		rte_eal_alarm_set(IAVF_ALARM_INTERVAL,
 				  iavf_dev_alarm_handler, dev);
+		iavf_phc_sync_alarm_start(dev);
 	}
 
 	if (err) {
-- 
2.47.1


^ permalink raw reply related

* [PATCH v4 1/2] net/iavf: remove PHC polling from Rx datapath
From: Soumyadeep Hore @ 2026-05-09 10:14 UTC (permalink / raw)
  To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev; +Cc: stable
In-Reply-To: <20260509101447.42093-1-soumyadeep.hore@intel.com>

Remove periodic PHC read/update checks from scalar and vector flex
RX paths, keeping timestamp conversion based on queue PHC state.

This avoids hot-path PHC polling overhead and preserves the latency
fix for RX timestamp-enabled traffic.

Bugzilla ID: 1898
Fixes: 61b6874b9224 ("net/iavf: support Rx timestamp offload on AVX512")
Fixes: 6ad2944f4e82 ("net/iavf: support Rx timestamp offload on AVX2")
Fixes: 33db16136e55 ("net/iavf: improve performance of Rx timestamp offload")
Cc: stable@dpdk.org

Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com>
---
 drivers/net/intel/iavf/iavf_rxtx.c            | 34 -------------------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 ++-------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 16 ++-------
 3 files changed, 4 insertions(+), 62 deletions(-)

diff --git a/drivers/net/intel/iavf/iavf_rxtx.c b/drivers/net/intel/iavf/iavf_rxtx.c
index 4ff6c18dc4..fabccc89bf 100644
--- a/drivers/net/intel/iavf/iavf_rxtx.c
+++ b/drivers/net/intel/iavf/iavf_rxtx.c
@@ -1507,16 +1507,6 @@ iavf_recv_pkts_flex_rxd(void *rx_queue,
 	rx_ring = rxq->rx_flex_ring;
 	ptype_tbl = rxq->iavf_vsi->adapter->ptype_tbl;
 
-	if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
-		uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
-
-		if (sw_cur_time - rxq->hw_time_update > 4) {
-			if (iavf_get_phc_time(rxq))
-				PMD_DRV_LOG(ERR, "get physical time failed");
-			rxq->hw_time_update = sw_cur_time;
-		}
-	}
-
 	while (nb_rx < nb_pkts) {
 		rxdp = &rx_ring[rx_id];
 		rx_stat_err0 = rte_le_to_cpu_16(rxdp->wb.status_error0);
@@ -1585,7 +1575,6 @@ iavf_recv_pkts_flex_rxd(void *rx_queue,
 				rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high));
 
 			rxq->phc_time = ts_ns;
-			rxq->hw_time_update = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
 
 			*RTE_MBUF_DYNFIELD(rxm,
 				iavf_timestamp_dynfield_offset,
@@ -1627,16 +1616,6 @@ iavf_recv_scattered_pkts_flex_rxd(void *rx_queue, struct rte_mbuf **rx_pkts,
 	volatile union ci_rx_flex_desc *rxdp;
 	const uint32_t *ptype_tbl = rxq->iavf_vsi->adapter->ptype_tbl;
 
-	if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
-		uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
-
-		if (sw_cur_time - rxq->hw_time_update > 4) {
-			if (iavf_get_phc_time(rxq))
-				PMD_DRV_LOG(ERR, "get physical time failed");
-			rxq->hw_time_update = sw_cur_time;
-		}
-	}
-
 	while (nb_rx < nb_pkts) {
 		rxdp = &rx_ring[rx_id];
 		rx_stat_err0 = rte_le_to_cpu_16(rxdp->wb.status_error0);
@@ -1755,7 +1734,6 @@ iavf_recv_scattered_pkts_flex_rxd(void *rx_queue, struct rte_mbuf **rx_pkts,
 				rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high));
 
 			rxq->phc_time = ts_ns;
-			rxq->hw_time_update = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
 
 			*RTE_MBUF_DYNFIELD(first_seg,
 				iavf_timestamp_dynfield_offset,
@@ -1969,16 +1947,6 @@ iavf_rx_scan_hw_ring_flex_rxd(struct ci_rx_queue *rxq,
 	if (!(stat_err0 & (1 << IAVF_RX_FLEX_DESC_STATUS0_DD_S)))
 		return 0;
 
-	if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
-		uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
-
-		if (sw_cur_time - rxq->hw_time_update > 4) {
-			if (iavf_get_phc_time(rxq))
-				PMD_DRV_LOG(ERR, "get physical time failed");
-			rxq->hw_time_update = sw_cur_time;
-		}
-	}
-
 	/* Scan LOOK_AHEAD descriptors at a time to determine which
 	 * descriptors reference packets that are ready to be received.
 	 */
@@ -2041,8 +2009,6 @@ iavf_rx_scan_hw_ring_flex_rxd(struct ci_rx_queue *rxq,
 					rte_le_to_cpu_32(rxdp[j].wb.flex_ts.ts_high));
 
 				rxq->phc_time = ts_ns;
-				rxq->hw_time_update = rte_get_timer_cycles() /
-					(rte_get_timer_hz() / 1000);
 
 				*RTE_MBUF_DYNFIELD(mb,
 					iavf_timestamp_dynfield_offset,
diff --git a/drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c b/drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c
index db0462f0f5..9349646d55 100644
--- a/drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c
+++ b/drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c
@@ -514,18 +514,10 @@ _iavf_recv_raw_pkts_vec_avx2_flex_rxd(struct ci_rx_queue *rxq,
 	if (!(rxdp->wb.status_error0 &
 			rte_cpu_to_le_32(1 << IAVF_RX_FLEX_DESC_STATUS0_DD_S)))
 		return 0;
-	bool is_tsinit = false;
 	uint8_t inflection_point = 0;
 	__m256i hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, rxq->phc_time);
 	if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
-		uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
-
-		if (unlikely(sw_cur_time - rxq->hw_time_update > 4)) {
-			hw_low_last = _mm256_setzero_si256();
-			is_tsinit = 1;
-		} else {
-			hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, rxq->phc_time);
-		}
+		hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, rxq->phc_time);
 	}
 
 	/* constants used in processing loop */
@@ -1152,10 +1144,8 @@ _iavf_recv_raw_pkts_vec_avx2_flex_rxd(struct ci_rx_queue *rxq,
 					*RTE_MBUF_DYNFIELD(rx_pkts[i + 7],
 						iavf_timestamp_dynfield_offset, uint32_t *) = _mm256_extract_epi32(ts_low1, 7);
 
-					if (unlikely(is_tsinit)) {
+					{
 						uint32_t in_timestamp;
-						if (iavf_get_phc_time(rxq))
-							PMD_DRV_LOG(ERR, "get physical time failed");
 						in_timestamp = *RTE_MBUF_DYNFIELD(rx_pkts[i + 0],
 								iavf_timestamp_dynfield_offset, uint32_t *);
 						rxq->phc_time = iavf_tstamp_convert_32b_64b(rxq->phc_time, in_timestamp);
@@ -1388,8 +1378,6 @@ _iavf_recv_raw_pkts_vec_avx2_flex_rxd(struct ci_rx_queue *rxq,
 				PMD_DRV_LOG(ERR, "invalid inflection point for rx timestamp");
 				break;
 			}
-
-			rxq->hw_time_update = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
 		}
 		if (burst != IAVF_VPMD_DESCS_PER_LOOP_WIDE)
 			break;
diff --git a/drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c b/drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c
index 4e8bf94fa0..1bb3e9746b 100644
--- a/drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c
+++ b/drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c
@@ -615,18 +615,10 @@ _iavf_recv_raw_pkts_vec_avx512_flex_rxd(struct ci_rx_queue *rxq,
 
 #ifdef IAVF_RX_TS_OFFLOAD
 	uint8_t inflection_point = 0;
-	bool is_tsinit = false;
 	__m256i hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (uint32_t)rxq->phc_time);
 
 	if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
-		uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
-
-		if (unlikely(sw_cur_time - rxq->hw_time_update > 4)) {
-			hw_low_last = _mm256_setzero_si256();
-			is_tsinit = 1;
-		} else {
-			hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (uint32_t)rxq->phc_time);
-		}
+		hw_low_last = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (uint32_t)rxq->phc_time);
 	}
 #endif
 
@@ -1343,11 +1335,9 @@ _iavf_recv_raw_pkts_vec_avx512_flex_rxd(struct ci_rx_queue *rxq,
 					*RTE_MBUF_DYNFIELD(rx_pkts[i + 7],
 						iavf_timestamp_dynfield_offset, uint32_t *) = _mm256_extract_epi32(ts_low1, 7);
 
-					if (unlikely(is_tsinit)) {
+					{
 						uint32_t in_timestamp;
 
-						if (iavf_get_phc_time(rxq))
-							PMD_DRV_LOG(ERR, "get physical time failed");
 						in_timestamp = *RTE_MBUF_DYNFIELD(rx_pkts[i + 0],
 										iavf_timestamp_dynfield_offset, uint32_t *);
 						rxq->phc_time = iavf_tstamp_convert_32b_64b(rxq->phc_time, in_timestamp);
@@ -1584,8 +1574,6 @@ _iavf_recv_raw_pkts_vec_avx512_flex_rxd(struct ci_rx_queue *rxq,
 				PMD_DRV_LOG(ERR, "invalid inflection point for rx timestamp");
 				break;
 			}
-
-			rxq->hw_time_update = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
 		}
 #endif
 		if (burst != IAVF_VPMD_DESCS_PER_LOOP_WIDE)
-- 
2.47.1


^ permalink raw reply related

* [PATCH v4 0/2] Update Rx Timestamp in IAVF PMD
From: Soumyadeep Hore @ 2026-05-09 10:14 UTC (permalink / raw)
  To: bruce.richardson, manoj.kumar.subbarao, aman.deep.singh, dev
In-Reply-To: <20260406212208.1562899-1-soumyadeep.hore@intel.com>

PHC Polling from Rx Datapath is removed and existing alarm handlers are
used to fix latency issues in IAVF PMD.
---
v4:
- Addressed Bruce's comments
---
v3:
- Addressed AI code reviews
---
v2:
- Fixed patch apply issues
---

Soumyadeep Hore (2):
  net/iavf: remove PHC polling from Rx datapath
  net/iavf: reuse device alarm for PHC sync

 drivers/net/intel/iavf/iavf.h                 |  5 ++
 drivers/net/intel/iavf/iavf_ethdev.c          | 70 +++++++++++++++++++
 drivers/net/intel/iavf/iavf_rxtx.c            | 34 ---------
 drivers/net/intel/iavf/iavf_rxtx_vec_avx2.c   | 16 +----
 drivers/net/intel/iavf/iavf_rxtx_vec_avx512.c | 16 +----
 drivers/net/intel/iavf/iavf_vchnl.c           |  4 ++
 6 files changed, 83 insertions(+), 62 deletions(-)

-- 
2.47.1


^ permalink raw reply

* [PATCH 20/20] examples: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev
  Cc: Stephen Hemminger, Nicolas Chautru, Akhil Goyal, Fan Zhang,
	Anatoly Burakov, Jingjing Wu, Volodymyr Fialko, Yipeng Wang,
	Maxime Coquelin, Chenbo Xia
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 examples/bbdev_app/main.c                            |  4 +---
 examples/l2fwd-crypto/main.c                         |  4 ++--
 .../client_server_mp/mp_client/client.c              |  7 +++----
 .../multi_process/client_server_mp/mp_server/main.c  |  5 ++---
 examples/ntb/ntb_fwd.c                               | 12 +++++-------
 examples/packet_ordering/main.c                      |  5 +----
 examples/server_node_efd/efd_node/node.c             |  7 +++----
 examples/server_node_efd/efd_server/main.c           |  5 ++---
 examples/vhost/main.c                                |  3 +--
 9 files changed, 20 insertions(+), 32 deletions(-)

diff --git a/examples/bbdev_app/main.c b/examples/bbdev_app/main.c
index 03f15f91cc..4602f8012d 100644
--- a/examples/bbdev_app/main.c
+++ b/examples/bbdev_app/main.c
@@ -291,9 +291,7 @@ print_mac(unsigned int portid, struct rte_ether_addr *bbdev_ports_eth_address)
 static inline void
 pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int nb_to_free)
 {
-	unsigned int i;
-	for (i = 0; i < nb_to_free; ++i)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, nb_to_free);
 }
 
 static inline void
diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c
index a441312f55..3b2c23f29a 100644
--- a/examples/l2fwd-crypto/main.c
+++ b/examples/l2fwd-crypto/main.c
@@ -931,8 +931,8 @@ l2fwd_main_loop(struct l2fwd_crypto_options *options)
 						RTE_CRYPTO_OP_TYPE_SYMMETRIC,
 						ops_burst, nb_rx) !=
 								nb_rx) {
-					for (j = 0; j < nb_rx; j++)
-						rte_pktmbuf_free(pkts_burst[j]);
+					rte_pktmbuf_free_bulk(pkts_burst,
+							      nb_rx);
 
 					nb_rx = 0;
 				}
diff --git a/examples/multi_process/client_server_mp/mp_client/client.c b/examples/multi_process/client_server_mp/mp_client/client.c
index 087c38ef73..9353ab7fda 100644
--- a/examples/multi_process/client_server_mp/mp_client/client.c
+++ b/examples/multi_process/client_server_mp/mp_client/client.c
@@ -117,15 +117,14 @@ parse_app_args(int argc, char *argv[])
  */
 static void
 flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,
-		void *userdata) {
-	int i;
+		void *userdata)
+{
 	uint16_t port_id = (uintptr_t)userdata;
 
 	tx_stats->tx_drop[port_id] += count;
 
 	/* free the mbufs which failed from transmit */
-	for (i = 0; i < count; i++)
-		rte_pktmbuf_free(unsent[i]);
+	rte_pktmbuf_free_bulk(unsent, count);
 
 }
 
diff --git a/examples/multi_process/client_server_mp/mp_server/main.c b/examples/multi_process/client_server_mp/mp_server/main.c
index 691d453d0e..aa8b759aca 100644
--- a/examples/multi_process/client_server_mp/mp_server/main.c
+++ b/examples/multi_process/client_server_mp/mp_server/main.c
@@ -195,7 +195,6 @@ clear_stats(void)
 static void
 flush_rx_queue(uint16_t client)
 {
-	uint16_t j;
 	struct client *cl;
 
 	if (cl_rx_buf[client].count == 0)
@@ -204,8 +203,8 @@ flush_rx_queue(uint16_t client)
 	cl = &clients[client];
 	if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[client].buffer,
 			cl_rx_buf[client].count, NULL) == 0){
-		for (j = 0; j < cl_rx_buf[client].count; j++)
-			rte_pktmbuf_free(cl_rx_buf[client].buffer[j]);
+		rte_pktmbuf_free_bulk(cl_rx_buf[client].buffer,
+				      cl_rx_buf[client].count);
 		cl->stats.rx_drop += cl_rx_buf[client].count;
 	}
 	else
diff --git a/examples/ntb/ntb_fwd.c b/examples/ntb/ntb_fwd.c
index 33f3c1ef17..fe2b1e6b2b 100644
--- a/examples/ntb/ntb_fwd.c
+++ b/examples/ntb/ntb_fwd.c
@@ -253,8 +253,7 @@ cmd_send_parsed(void *parsed_result,
 						(void *)queue_id);
 		if (ret < 0) {
 			printf("Enqueue failed with err %d\n", ret);
-			for (j = 0; j < nb_pkt; j++)
-				rte_pktmbuf_free(mbuf_send[j]);
+			rte_pktmbuf_free_bulk(mbuf_send, nb_pkt);
 			goto clean;
 		}
 		nb_tx = ret;
@@ -387,8 +386,8 @@ start_iofwd_per_lcore(void *param)
 				if (ret < 0) {
 					printf("Enqueue failed with err %d\n",
 						ret);
-					for (j = 0; j < nb_rx; j++)
-						rte_pktmbuf_free(pkts_burst[j]);
+					rte_pktmbuf_free_bulk(pkts_burst,
+							      nb_rx);
 					goto clean;
 				}
 				nb_tx = ret;
@@ -476,7 +475,7 @@ start_txonly_per_lcore(void *param)
 	struct ntb_fwd_lcore_conf *conf = param;
 	struct ntb_fwd_stream fs;
 	uint16_t nb_pkt, nb_tx;
-	int i, j, ret;
+	int i, ret;
 
 	for (i = 0; i < NTB_MAX_PKT_BURST; i++)
 		ntb_buf[i] = (struct rte_rawdev_buf *)
@@ -517,8 +516,7 @@ start_txonly_per_lcore(void *param)
 					nb_pkt, (void *)(size_t)fs.qp_id);
 			if (ret < 0) {
 				printf("Enqueue failed with err %d\n", ret);
-				for (j = 0; j < nb_pkt; j++)
-					rte_pktmbuf_free(pkts_burst[j]);
+				rte_pktmbuf_free_bulk(pkts_burst, nb_pkt);
 				goto clean;
 			}
 			nb_tx = ret;
diff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c
index 748fe0826a..f2097a90d4 100644
--- a/examples/packet_ordering/main.c
+++ b/examples/packet_ordering/main.c
@@ -128,10 +128,7 @@ get_previous_lcore_id(unsigned int id)
 static inline void
 pktmbuf_free_bulk(struct rte_mbuf *mbuf_table[], unsigned n)
 {
-	unsigned int i;
-
-	for (i = 0; i < n; i++)
-		rte_pktmbuf_free(mbuf_table[i]);
+	rte_pktmbuf_free_bulk(mbuf_table, n);
 }
 
 /* display usage */
diff --git a/examples/server_node_efd/efd_node/node.c b/examples/server_node_efd/efd_node/node.c
index fc2aa5ffef..5805e049b2 100644
--- a/examples/server_node_efd/efd_node/node.c
+++ b/examples/server_node_efd/efd_node/node.c
@@ -121,15 +121,14 @@ parse_app_args(int argc, char *argv[])
  */
 static void
 flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,
-		void *userdata) {
-	int i;
+		void *userdata)
+{
 	uint16_t port_id = (uintptr_t)userdata;
 
 	tx_stats->tx_drop[port_id] += count;
 
 	/* free the mbufs which failed from transmit */
-	for (i = 0; i < count; i++)
-		rte_pktmbuf_free(unsent[i]);
+	rte_pktmbuf_free_bulk(unsent, count);
 
 }
 
diff --git a/examples/server_node_efd/efd_server/main.c b/examples/server_node_efd/efd_server/main.c
index 70a7372d4a..384bcfa780 100644
--- a/examples/server_node_efd/efd_server/main.c
+++ b/examples/server_node_efd/efd_server/main.c
@@ -218,7 +218,6 @@ clear_stats(void)
 static void
 flush_rx_queue(uint16_t node)
 {
-	uint16_t j;
 	struct node *cl;
 
 	if (cl_rx_buf[node].count == 0)
@@ -227,8 +226,8 @@ flush_rx_queue(uint16_t node)
 	cl = &nodes[node];
 	if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[node].buffer,
 			cl_rx_buf[node].count, NULL) != cl_rx_buf[node].count){
-		for (j = 0; j < cl_rx_buf[node].count; j++)
-			rte_pktmbuf_free(cl_rx_buf[node].buffer[j]);
+		rte_pktmbuf_free_bulk(cl_rx_buf[node].buffer,
+				      cl_rx_buf[node].count);
 		cl->stats.rx_drop += cl_rx_buf[node].count;
 	} else
 		cl->stats.rx += cl_rx_buf[node].count;
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index ac888348d2..79561d6de0 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1006,8 +1006,7 @@ unlink_vmdq(struct vhost_dev *vdev)
 					(uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
 
 		while (rx_count) {
-			for (i = 0; i < rx_count; i++)
-				rte_pktmbuf_free(pkts_burst[i]);
+			rte_pktmbuf_free_bulk(pkts_burst, rx_count);
 
 			rx_count = rte_eth_rx_burst(ports[0],
 					(uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
-- 
2.53.0


^ permalink raw reply related

* [PATCH 19/20] app/test-compress-perf: remove unnecessary null check
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Remove unnecessary if check before calling rte_free
and rte_pktmbuf_free_bulk.

Generated by devtools/cocci/null_free.cocci

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test-compress-perf/comp_perf_test_common.c | 6 ++----
 app/test-compress-perf/main.c                  | 6 ++----
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/app/test-compress-perf/comp_perf_test_common.c b/app/test-compress-perf/comp_perf_test_common.c
index 12c2a7bbd0..90eb98166e 100644
--- a/app/test-compress-perf/comp_perf_test_common.c
+++ b/app/test-compress-perf/comp_perf_test_common.c
@@ -83,11 +83,9 @@ comp_perf_free_memory(struct comp_test_data *test_data,
 {
 	uint32_t i;
 
-	if (mem->decomp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
-	if (mem->comp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 
 	rte_free(mem->decomp_bufs);
 	rte_free(mem->comp_bufs);
diff --git a/app/test-compress-perf/main.c b/app/test-compress-perf/main.c
index c9ead02cb4..bc2b185da4 100644
--- a/app/test-compress-perf/main.c
+++ b/app/test-compress-perf/main.c
@@ -392,15 +392,13 @@ comp_perf_dump_dictionary_data(struct comp_test_data *td)
 
 		if (fread(data, data_to_read, 1, f) != 1) {
 			RTE_LOG(ERR, USER1, "Input file could not be read\n");
-			if (td->dictionary_data)
-				rte_free(td->dictionary_data);
+			rte_free(td->dictionary_data);
 			goto end;
 		}
 		if (fseek(f, 0, SEEK_SET) != 0) {
 			RTE_LOG(ERR, USER1,
 				"Size of input could not be calculated\n");
-			if (td->dictionary_data)
-				rte_free(td->dictionary_data);
+			rte_free(td->dictionary_data);
 			goto end;
 		}
 		remaining_data -= data_to_read;
-- 
2.53.0


^ permalink raw reply related

* [PATCH 18/20] app/test-dma-perf: remove unnecessary null check
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Cheng Jiang, Chengwen Feng
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Remove unnecessary if check before calling rte_pktmbuf_free_bulk.

Generated by devtools/cocci/null_free.cocci

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test-dma-perf/benchmark.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/app/test-dma-perf/benchmark.c b/app/test-dma-perf/benchmark.c
index c0ffc859bd..576c59faff 100644
--- a/app/test-dma-perf/benchmark.c
+++ b/app/test-dma-perf/benchmark.c
@@ -690,10 +690,8 @@ teardown_memory_env(uint32_t nr_buf, struct rte_mbuf **srcs, struct rte_mbuf **d
 		    struct rte_dma_op **dma_ops)
 {
 	/* free mbufs used in the test */
-	if (srcs != NULL)
-		rte_pktmbuf_free_bulk(srcs, nr_buf);
-	if (dsts != NULL)
-		rte_pktmbuf_free_bulk(dsts, nr_buf);
+	rte_pktmbuf_free_bulk(srcs, nr_buf);
+	rte_pktmbuf_free_bulk(dsts, nr_buf);
 
 	/* free the points for the mbufs */
 	rte_free(srcs);
-- 
2.53.0


^ permalink raw reply related

* [PATCH 17/20] test: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev
  Cc: Stephen Hemminger, Reshma Pattan, Chengwen Feng, Kevin Laatz,
	Bruce Richardson, Konstantin Ananyev, Chas Williams,
	Min Hu (Connor), Volodymyr Fialko, Cristian Dumitrescu
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test/sample_packet_forward.c |  5 +----
 app/test/test_distributor.c      |  4 +---
 app/test/test_dmadev.c           |  6 ++----
 app/test/test_ipfrag.c           |  4 +---
 app/test/test_link_bonding.c     | 13 ++++---------
 app/test/test_pmd_perf.c         |  3 +--
 app/test/test_pmd_tap.c          |  3 +--
 app/test/test_reorder.c          | 12 ++++--------
 app/test/test_table_ports.c      | 12 ++++--------
 app/test/test_table_tables.c     | 21 +++++++--------------
 10 files changed, 26 insertions(+), 57 deletions(-)

diff --git a/app/test/sample_packet_forward.c b/app/test/sample_packet_forward.c
index aa897274d8..70bb75e321 100644
--- a/app/test/sample_packet_forward.c
+++ b/app/test/sample_packet_forward.c
@@ -115,10 +115,7 @@ test_get_mbuf_from_pool(struct rte_mempool **mp, struct rte_mbuf **pbuf,
 void
 test_put_mbuf_to_pool(struct rte_mempool *mp, struct rte_mbuf **pbuf)
 {
-	int itr = 0;
-
-	for (itr = 0; itr < NUM_PACKETS; itr++)
-		rte_pktmbuf_free(pbuf[itr]);
+	rte_pktmbuf_free_bulk(pbuf, NUM_PACKETS);
 	rte_mempool_free(mp);
 }
 
diff --git a/app/test/test_distributor.c b/app/test/test_distributor.c
index da0a21ea83..ed37ca80f1 100644
--- a/app/test/test_distributor.c
+++ b/app/test/test_distributor.c
@@ -309,7 +309,6 @@ handle_work_with_free_mbufs(void *arg)
 	alignas(RTE_CACHE_LINE_SIZE) struct rte_mbuf *buf[8];
 	struct worker_params *wp = arg;
 	struct rte_distributor *d = wp->dist;
-	unsigned int i;
 	unsigned int num;
 	unsigned int id = rte_atomic_fetch_add_explicit(&worker_idx, 1, rte_memory_order_relaxed);
 
@@ -317,8 +316,7 @@ handle_work_with_free_mbufs(void *arg)
 	while (!quit) {
 		rte_atomic_fetch_add_explicit(&worker_stats[id].handled_packets, num,
 				rte_memory_order_relaxed);
-		for (i = 0; i < num; i++)
-			rte_pktmbuf_free(buf[i]);
+		rte_pktmbuf_free_bulk(buf, num);
 		num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 	}
 	rte_atomic_fetch_add_explicit(&worker_stats[id].handled_packets, num,
diff --git a/app/test/test_dmadev.c b/app/test/test_dmadev.c
index 5488a1af33..a5772cc843 100644
--- a/app/test/test_dmadev.c
+++ b/app/test/test_dmadev.c
@@ -499,10 +499,8 @@ test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
 				ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
 						id, 0);
 
-			for (i = 0; i < n_src; i++)
-				rte_pktmbuf_free(src[i]);
-			for (i = 0; i < n_dst; i++)
-				rte_pktmbuf_free(dst[i]);
+			rte_pktmbuf_free_bulk(src, n_src);
+			rte_pktmbuf_free_bulk(dst, n_dst);
 
 			/* Verify that completion returns nothing more */
 			if (rte_dma_completed(dev_id, 0, 1, NULL, NULL) != 0)
diff --git a/app/test/test_ipfrag.c b/app/test/test_ipfrag.c
index 247575d6c5..2c553222c2 100644
--- a/app/test/test_ipfrag.c
+++ b/app/test/test_ipfrag.c
@@ -240,9 +240,7 @@ v6_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, uint8_t ttl,
 static inline void
 test_free_fragments(struct rte_mbuf *mb[], uint32_t num)
 {
-	uint32_t i;
-	for (i = 0; i < num; i++)
-		rte_pktmbuf_free(mb[i]);
+	rte_pktmbuf_free_bulk(mb, num);
 }
 
 static inline void
diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 19b064771a..eac785610a 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -1476,10 +1476,7 @@ verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
 static void
 free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)
 {
-	int i;
-
-	for (i = 0; i < nb_mbufs; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, nb_mbufs);
 }
 
 #define TEST_RR_MEMBER_TX_FAIL_MEMBER_COUNT		(2)
@@ -4193,7 +4190,7 @@ testsuite_teardown(void)
 static void
 free_virtualpmd_tx_queue(void)
 {
-	int i, member_port, to_free_cnt;
+	int member_port, to_free_cnt;
 	struct rte_mbuf *pkts_to_free[MAX_PKT_BURST];
 
 	/* Free tx queue of virtual pmd */
@@ -4202,8 +4199,7 @@ free_virtualpmd_tx_queue(void)
 		to_free_cnt = virtual_ethdev_get_mbufs_from_tx_queue(
 				test_params->member_port_ids[member_port],
 				pkts_to_free, MAX_PKT_BURST);
-		for (i = 0; i < to_free_cnt; i++)
-			rte_pktmbuf_free(pkts_to_free[i]);
+		rte_pktmbuf_free_bulk(pkts_to_free, to_free_cnt);
 	}
 }
 
@@ -4381,8 +4377,7 @@ test_tlb_rx_burst(void)
 		}
 
 		/* free mbufs */
-		for (i = 0; i < burst_size; i++)
-			rte_pktmbuf_free(rx_pkt_burst[i]);
+		rte_pktmbuf_free_bulk(rx_pkt_burst, burst_size);
 
 		/* reset bonding device stats */
 		rte_eth_stats_reset(test_params->bonding_port_id);
diff --git a/app/test/test_pmd_perf.c b/app/test/test_pmd_perf.c
index 995b0a6f20..dab1751b9a 100644
--- a/app/test/test_pmd_perf.c
+++ b/app/test/test_pmd_perf.c
@@ -602,8 +602,7 @@ poll_burst(void *args)
 	       total, MAX_IDLE - timeout);
 	/* clean up */
 	total = pkt_per_port * conf->nb_ports - total;
-	for (i = 0; i < total; i++)
-		rte_pktmbuf_free(pkts_burst[i]);
+	rte_pktmbuf_free_bulk(pkts_burst, total);
 
 	rte_free(pkts_burst);
 
diff --git a/app/test/test_pmd_tap.c b/app/test/test_pmd_tap.c
index 6d0e8b4f54..f48b69de3b 100644
--- a/app/test/test_pmd_tap.c
+++ b/app/test/test_pmd_tap.c
@@ -192,8 +192,7 @@ test_tap_send_receive(void)
 	printf("Received %u packets on port %d\n", nb_rx, tap_port0);
 
 	/* Free received packets */
-	for (i = 0; i < nb_rx; i++)
-		rte_pktmbuf_free(rx_mbufs[i]);
+	rte_pktmbuf_free_bulk(rx_mbufs, nb_rx);
 
 	return TEST_SUCCESS;
 }
diff --git a/app/test/test_reorder.c b/app/test/test_reorder.c
index 8c68e00869..fc922650d6 100644
--- a/app/test/test_reorder.c
+++ b/app/test/test_reorder.c
@@ -208,8 +208,7 @@ test_reorder_insert(void)
 	ret = 0;
 exit:
 	rte_reorder_free(b);
-	for (i = 0; i < INSERT_NUM_BUFS; i++)
-		rte_pktmbuf_free(bufs[i]);
+	rte_pktmbuf_free_bulk(bufs, INSERT_NUM_BUFS);
 
 	return ret;
 }
@@ -382,8 +381,7 @@ test_reorder_drain_up_to_seqn(void)
 		ret = -1;
 		goto exit;
 	}
-	for (i = 0; i < 2; i++)
-		rte_pktmbuf_free(robufs[i]);
+	rte_pktmbuf_free_bulk(robufs, 2);
 	memset(robufs, 0, sizeof(robufs));
 
 	/* Insert more packets
@@ -406,8 +404,7 @@ test_reorder_drain_up_to_seqn(void)
 		ret = -1;
 		goto exit;
 	}
-	for (i = 0; i < 2; i++)
-		rte_pktmbuf_free(robufs[i]);
+	rte_pktmbuf_free_bulk(robufs, 2);
 	memset(robufs, 0, sizeof(robufs));
 
 	ret = 0;
@@ -483,8 +480,7 @@ test_reorder_set_seqn(void)
 	ret = 0;
 exit:
 	rte_reorder_free(b);
-	for (i = 0; i < SET_SEQN_NUM_BUFS; i++)
-		rte_pktmbuf_free(bufs[i]);
+	rte_pktmbuf_free_bulk(bufs, SET_SEQN_NUM_BUFS);
 
 	return ret;
 }
diff --git a/app/test/test_table_ports.c b/app/test/test_table_ports.c
index 282ec2a3d2..d617e73810 100644
--- a/app/test/test_table_ports.c
+++ b/app/test/test_table_ports.c
@@ -73,8 +73,7 @@ test_port_ring_reader(void)
 	if (received_pkts < expected_pkts)
 		return -6;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
@@ -156,8 +155,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -8;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	/* TX Bulk */
 	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
@@ -171,8 +169,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -8;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
 		mbuf[i] = rte_pktmbuf_alloc(pool);
@@ -186,8 +183,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -9;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
diff --git a/app/test/test_table_tables.c b/app/test/test_table_tables.c
index 920aa555cb..d2c09c360f 100644
--- a/app/test/test_table_tables.c
+++ b/app/test/test_table_tables.c
@@ -162,8 +162,7 @@ test_table_stub(void)
 		return -2;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
@@ -276,8 +275,7 @@ test_table_array(void)
 				return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_array_ops.f_free(table);
 
@@ -442,8 +440,7 @@ test_table_lpm(void)
 		return -23;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_lpm_ops.f_free(table);
 
@@ -620,8 +617,7 @@ test_table_lpm_ipv6(void)
 		return -24;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_lpm_ipv6_ops.f_free(table);
 
@@ -723,8 +719,7 @@ test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
 		return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = ops->f_free(table);
 
@@ -833,8 +828,7 @@ test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
 		return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = ops->f_free(table);
 
@@ -1047,8 +1041,7 @@ test_table_hash_cuckoo(void)
 		return -20;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_hash_cuckoo_ops.f_free(table);
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 16/20] net/bnxt: remove unnecessary null check
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Kishore Padmanabha, Ajit Khaparde
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Remove unnecessary if check before calling rte_free.

Generated by devtools/cocci/null_free.cocci

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/bnxt/tf_core/v3/tfo.c    | 6 ++----
 drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c | 6 ++----
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/net/bnxt/tf_core/v3/tfo.c b/drivers/net/bnxt/tf_core/v3/tfo.c
index 4b1f545476..681d1dd8d3 100644
--- a/drivers/net/bnxt/tf_core/v3/tfo.c
+++ b/drivers/net/bnxt/tf_core/v3/tfo.c
@@ -183,13 +183,11 @@ void tfo_close(void **tfo)
 				}
 			}
 		}
-		if (tim)
-			rte_free(tim);
+		rte_free(tim);
 		tfco->ts_tim = NULL;
 		tfco->tfgo = NULL;
 
-		if (*tfo)
-			rte_free(*tfo);
+		rte_free(*tfo);
 		*tfo = NULL;
 	}
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c b/drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c
index 23e1b59ca4..3707cd1a2d 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c
@@ -169,11 +169,9 @@ ulp_sc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_sc_mgr_thread_cancel(ctxt);
 
-	if (ulp_sc_info->stats_cache_tbl)
-		rte_free(ulp_sc_info->stats_cache_tbl);
+	rte_free(ulp_sc_info->stats_cache_tbl);
 
-	if (ulp_sc_info->read_data)
-		rte_free(ulp_sc_info->read_data);
+	rte_free(ulp_sc_info->read_data);
 
 	rte_free(ulp_sc_info);
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 15/20] net/ice: remove unnecessary null check
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson, Anatoly Burakov
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Remove unnecessary if check before calling free.

Generated by devtools/cocci/null_free.cocci

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/intel/ice/ice_dcf_sched.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/intel/ice/ice_dcf_sched.c b/drivers/net/intel/ice/ice_dcf_sched.c
index 948774a282..14e902edbe 100644
--- a/drivers/net/intel/ice/ice_dcf_sched.c
+++ b/drivers/net/intel/ice/ice_dcf_sched.c
@@ -877,10 +877,8 @@ static int ice_dcf_hierarchy_commit(struct rte_eth_dev *dev,
 	return ret_val;
 
 fail_clear:
-	if (vf_bw != NULL)
-		free(vf_bw);
-	if (tc_bw != NULL)
-		free(tc_bw);
+	free(vf_bw);
+	free(tc_bw);
 
 	/* clear all the traffic manager configuration */
 	if (clear_on_fail) {
-- 
2.53.0


^ permalink raw reply related

* [PATCH 14/20] net/zxdh: remove unnecessary null check
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Junlong Wang, Lijie Shan
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Remove unnecessary if check before calling free.

Generated by devtools/cocci/null_free.cocci

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/zxdh/zxdh_np.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/zxdh/zxdh_np.c b/drivers/net/zxdh/zxdh_np.c
index efb57e34f2..b078ec5b6c 100644
--- a/drivers/net/zxdh/zxdh_np.c
+++ b/drivers/net/zxdh/zxdh_np.c
@@ -12383,8 +12383,7 @@ zxdh_np_dtb_acl_data_clear(uint32_t dev_id, uint32_t queue_id,
 				&element_id);
 	free(data_buff);
 	free(mask_buff);
-	if (eram_buff)
-		free(eram_buff);
+	free(eram_buff);
 
 	free(p_entry_arr);
 	ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "zxdh_np_dtb_acl_dma_insert");
-- 
2.53.0


^ permalink raw reply related

* [PATCH 13/20] mbuf: allow NULL array in rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Morten Brørup
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

This allows callers to avoid NULL checks and just call
rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 devtools/cocci/nullfree.cocci          | 5 ++++-
 doc/guides/rel_notes/release_26_07.rst | 5 +++++
 lib/mbuf/rte_mbuf.c                    | 3 +++
 lib/mbuf/rte_mbuf.h                    | 1 +
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/devtools/cocci/nullfree.cocci b/devtools/cocci/nullfree.cocci
index e7417b69ff..78e30f730a 100644
--- a/devtools/cocci/nullfree.cocci
+++ b/devtools/cocci/nullfree.cocci
@@ -4,7 +4,7 @@
 // free(NULL) as a no-op.
 //
 @@
-expression E;
+expression E, N;
 @@
 (
 - if (E != NULL) cmdline_free(E);
@@ -79,6 +79,9 @@ expression E;
 - if (E != NULL) rte_pktmbuf_free(E);
 + rte_pktmbuf_free(E);
 |
+- if (E != NULL) rte_pktmbuf_free_bulk(E, N);
++ rte_pktmbuf_free_bulk(E, N);
+|
 - if (E != NULL) rte_rib_free(E);
 + rte_rib_free(E);
 |
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index f012d47a4b..6f2f7f849f 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -63,6 +63,11 @@ New Features
     ``rte_eal_init`` and the application is responsible for probing each device,
   * ``--auto-probing`` enables the initial bus probing, which is the current default behavior.
 
+* **mbuf: rte_pktmbuf_free_bulk now accepts NULL array pointer.**
+
+  Calling ``rte_pktmbuf_free_bulk`` with a NULL ``mbufs`` argument  is a no-op,
+  matching the behavior of ``rte_pktmbuf_free()`` and ``rte_free()``.
+
 
 Removed Items
 -------------
diff --git a/lib/mbuf/rte_mbuf.c b/lib/mbuf/rte_mbuf.c
index c2476e7704..8ec3bb53bb 100644
--- a/lib/mbuf/rte_mbuf.c
+++ b/lib/mbuf/rte_mbuf.c
@@ -562,6 +562,9 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count)
 	struct rte_mbuf *m, *m_next, *pending[RTE_PKTMBUF_FREE_PENDING_SZ];
 	unsigned int idx, nb_pending = 0;
 
+	if (mbufs == NULL)
+		return;
+
 	rte_mbuf_history_mark_bulk(mbufs, count, RTE_MBUF_HISTORY_OP_LIB_FREE);
 
 	for (idx = 0; idx < count; idx++) {
diff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h
index e7c3bbadd4..e9f8932e80 100644
--- a/lib/mbuf/rte_mbuf.h
+++ b/lib/mbuf/rte_mbuf.h
@@ -1534,6 +1534,7 @@ static inline void rte_pktmbuf_free(struct rte_mbuf *m)
  *  @param mbufs
  *    Array of pointers to packet mbufs.
  *    The array may contain NULL pointers.
+ *    The array pointer is NULL function does nothing.
  *  @param count
  *    Array size.
  */
-- 
2.53.0


^ permalink raw reply related

* [PATCH 12/20] app/compress-perf: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 app/test-compress-perf/comp_perf_test_common.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/app/test-compress-perf/comp_perf_test_common.c b/app/test-compress-perf/comp_perf_test_common.c
index 78487196ad..12c2a7bbd0 100644
--- a/app/test-compress-perf/comp_perf_test_common.c
+++ b/app/test-compress-perf/comp_perf_test_common.c
@@ -84,12 +84,10 @@ comp_perf_free_memory(struct comp_test_data *test_data,
 	uint32_t i;
 
 	if (mem->decomp_bufs != NULL)
-		for (i = 0; i < mem->total_bufs; i++)
-			rte_pktmbuf_free(mem->decomp_bufs[i]);
+		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
 	if (mem->comp_bufs != NULL)
-		for (i = 0; i < mem->total_bufs; i++)
-			rte_pktmbuf_free(mem->comp_bufs[i]);
+		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 
 	rte_free(mem->decomp_bufs);
 	rte_free(mem->comp_bufs);
-- 
2.53.0


^ permalink raw reply related

* [PATCH 11/20] net/zxdh: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Junlong Wang, Lijie Shan
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/zxdh/zxdh_queue.c | 7 ++-----
 drivers/net/zxdh/zxdh_rxtx.c  | 3 +--
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/net/zxdh/zxdh_queue.c b/drivers/net/zxdh/zxdh_queue.c
index 7162593b16..543f626e6f 100644
--- a/drivers/net/zxdh/zxdh_queue.c
+++ b/drivers/net/zxdh/zxdh_queue.c
@@ -445,11 +445,8 @@ int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_i
 
 		if (likely(rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt) == 0)) {
 			error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
-			if (unlikely(error)) {
-				int32_t i;
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
-			}
+			if (unlikely(error))
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 		} else {
 			PMD_DRV_LOG(ERR, "port %d rxq %d allocated bufs from %s failed",
 				hw->port_id, logic_qidx, rxvq->mpool->name);
diff --git a/drivers/net/zxdh/zxdh_rxtx.c b/drivers/net/zxdh/zxdh_rxtx.c
index db86922aea..cb324336d0 100644
--- a/drivers/net/zxdh/zxdh_rxtx.c
+++ b/drivers/net/zxdh/zxdh_rxtx.c
@@ -970,8 +970,7 @@ zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
 		if (!rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt)) {
 			error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 
 			if (unlikely(zxdh_queue_kick_prepare_packed(vq)))
-- 
2.53.0


^ permalink raw reply related

* [PATCH 10/20] net/virtio: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Maxime Coquelin, Chenbo Xia
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/virtio/virtio_rxtx.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index edecd2011f..a1fbdd9f34 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -723,7 +723,7 @@ virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_idx)
 	struct virtnet_rx *rxvq = &vq->rxq;
 	struct rte_mbuf *m;
 	uint16_t desc_idx;
-	int error, nbufs, i;
+	int error, nbufs;
 	bool in_order = virtio_with_feature(hw, VIRTIO_F_IN_ORDER);
 
 	PMD_INIT_FUNC_TRACE();
@@ -764,8 +764,7 @@ virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_idx)
 						pkts,
 						free_cnt);
 				if (unlikely(error)) {
-					for (i = 0; i < free_cnt; i++)
-						rte_pktmbuf_free(pkts[i]);
+					rte_pktmbuf_free_bulk(pkts, free_cnt);
 				} else {
 					nbufs += free_cnt;
 				}
@@ -1071,8 +1070,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 			error = virtqueue_enqueue_recv_refill(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1176,8 +1174,7 @@ virtio_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
 			error = virtqueue_enqueue_recv_refill_packed(vq,
 					new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1358,8 +1355,7 @@ virtio_recv_pkts_inorder(void *rx_queue,
 			error = virtqueue_enqueue_refill_inorder(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1535,8 +1531,7 @@ virtio_recv_mergeable_pkts(void *rx_queue,
 			error = virtqueue_enqueue_recv_refill(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1707,8 +1702,7 @@ virtio_recv_mergeable_pkts_packed(void *rx_queue,
 			error = virtqueue_enqueue_recv_refill_packed(vq,
 					new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
-- 
2.53.0


^ permalink raw reply related

* [PATCH 09/20] net/pfe: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Gagandeep Singh
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/pfe/pfe_ethdev.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/pfe/pfe_ethdev.c b/drivers/net/pfe/pfe_ethdev.c
index 1efa17539e..4c0f9e63a0 100644
--- a/drivers/net/pfe/pfe_ethdev.c
+++ b/drivers/net/pfe/pfe_ethdev.c
@@ -281,9 +281,7 @@ pfe_eth_open(struct rte_eth_dev *dev)
 			ret = hif_lib_receive_pkt(&client->rx_q[0],
 						  hif_shm->pool, rx_pkts, 32);
 			while (ret) {
-				int i;
-				for (i = 0; i < ret; i++)
-					rte_pktmbuf_free(rx_pkts[i]);
+				rte_pktmbuf_free_bulk(rx_pkts, ret);
 				ret = hif_lib_receive_pkt(&client->rx_q[0],
 							  hif_shm->pool,
 							  rx_pkts, 32);
-- 
2.53.0


^ permalink raw reply related

* [PATCH 08/20] net/cnxk: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev
  Cc: Stephen Hemminger, Nithin Dabilpuram, Kiran Kumar K,
	Sunil Kumar Kori, Satha Rao, Harman Kalra
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/cnxk/cnxk_ethdev.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/cnxk/cnxk_ethdev.c b/drivers/net/cnxk/cnxk_ethdev.c
index 06d1c9b362..3330dd5051 100644
--- a/drivers/net/cnxk/cnxk_ethdev.c
+++ b/drivers/net/cnxk/cnxk_ethdev.c
@@ -1913,7 +1913,7 @@ cnxk_nix_dev_stop(struct rte_eth_dev *eth_dev)
 	const struct eth_dev_ops *dev_ops = eth_dev->dev_ops;
 	struct rte_mbuf *rx_pkts[32];
 	struct rte_eth_link link;
-	int count, i, j, rc;
+	int count, i, rc;
 	void *rxq;
 
 	/* In case of Inline IPSec, will need to avoid disabling the MCAM rules and NPC Rx
@@ -1951,8 +1951,7 @@ cnxk_nix_dev_stop(struct rte_eth_dev *eth_dev)
 		rxq = eth_dev->data->rx_queues[i];
 		count = dev->rx_pkt_burst_no_offload(rxq, rx_pkts, 32);
 		while (count) {
-			for (j = 0; j < count; j++)
-				rte_pktmbuf_free(rx_pkts[j]);
+			rte_pktmbuf_free_bulk(rx_pkts, count);
 			count = dev->rx_pkt_burst_no_offload(rxq, rx_pkts, 32);
 		}
 	}
-- 
2.53.0


^ permalink raw reply related

* [PATCH 07/20] net/af_xdp: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Ciara Loftus, Maryam Tahhan
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 drivers/net/af_xdp/rte_eth_af_xdp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 10dbcf1333..4f55887963 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -263,8 +263,7 @@ reserve_fill_queue_zc(struct xsk_umem_info *umem, uint16_t reserve_size,
 	uint16_t i;
 
 	if (unlikely(!xsk_ring_prod__reserve(fq, reserve_size, &idx))) {
-		for (i = 0; i < reserve_size; i++)
-			rte_pktmbuf_free(bufs[i]);
+		rte_pktmbuf_free_bulk(bufs, reserve_size);
 		AF_XDP_LOG_LINE(DEBUG, "Failed to reserve enough fq descs.");
 		return -1;
 	}
-- 
2.53.0


^ permalink raw reply related

* [PATCH 06/20] port: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Cristian Dumitrescu
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/port/rte_port_fd.c              | 6 ++----
 lib/port/rte_swx_port_fd.c          | 8 ++------
 lib/port/rte_swx_port_source_sink.c | 6 +-----
 3 files changed, 5 insertions(+), 15 deletions(-)

diff --git a/lib/port/rte_port_fd.c b/lib/port/rte_port_fd.c
index dbc9efef1b..2b021710d4 100644
--- a/lib/port/rte_port_fd.c
+++ b/lib/port/rte_port_fd.c
@@ -212,8 +212,7 @@ send_burst(struct rte_port_fd_writer *p)
 
 	RTE_PORT_FD_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - i);
 
-	for (i = 0; i < p->tx_buf_count; i++)
-		rte_pktmbuf_free(p->tx_buf[i]);
+	rte_pktmbuf_free_bulk(p->tx_buf, p->tx_buf_count);
 
 	p->tx_buf_count = 0;
 }
@@ -397,8 +396,7 @@ send_burst_nodrop(struct rte_port_fd_writer_nodrop *p)
 
 	RTE_PORT_FD_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - i);
 
-	for (i = 0; i < p->tx_buf_count; i++)
-		rte_pktmbuf_free(p->tx_buf[i]);
+	rte_pktmbuf_free_bulk(p->tx_buf, p->tx_buf_count);
 
 	p->tx_buf_count = 0;
 }
diff --git a/lib/port/rte_swx_port_fd.c b/lib/port/rte_swx_port_fd.c
index 72783d2b0f..937b1e0945 100644
--- a/lib/port/rte_swx_port_fd.c
+++ b/lib/port/rte_swx_port_fd.c
@@ -73,14 +73,11 @@ static void
 reader_free(void *port)
 {
 	struct reader *p = port;
-	uint32_t i;
 
 	if (!p)
 		return;
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
-
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 	free(p->pkts);
 	free(p);
 }
@@ -218,8 +215,7 @@ __writer_flush(struct writer *p)
 		(uint32_t)p->params.fd,
 		p->n_pkts);
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 
 	p->n_pkts = 0;
 }
diff --git a/lib/port/rte_swx_port_source_sink.c b/lib/port/rte_swx_port_source_sink.c
index af8b9ec68d..f651d5b5ad 100644
--- a/lib/port/rte_swx_port_source_sink.c
+++ b/lib/port/rte_swx_port_source_sink.c
@@ -52,16 +52,12 @@ static void
 source_free(void *port)
 {
 	struct source *p = port;
-	uint32_t i;
 
 	if (!p)
 		return;
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
-
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 	free(p->pkts);
-
 	free(p);
 }
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 05/20] pipeline: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Cristian Dumitrescu
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/pipeline/rte_pipeline.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/pipeline/rte_pipeline.c b/lib/pipeline/rte_pipeline.c
index fa3c8b77ee..1fadae01d8 100644
--- a/lib/pipeline/rte_pipeline.c
+++ b/lib/pipeline/rte_pipeline.c
@@ -1305,10 +1305,8 @@ rte_pipeline_action_handler_drop(struct rte_pipeline *p, uint64_t pkts_mask)
 {
 	if ((pkts_mask & (pkts_mask + 1)) == 0) {
 		uint64_t n_pkts = rte_popcount64(pkts_mask);
-		uint32_t i;
 
-		for (i = 0; i < n_pkts; i++)
-			rte_pktmbuf_free(p->pkts[i]);
+		rte_pktmbuf_free_bulk(p->pkts, n_pkts);
 	} else {
 		uint32_t i;
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 04/20] ip_frag: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Konstantin Ananyev
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/ip_frag/rte_ipv6_fragmentation.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/ip_frag/rte_ipv6_fragmentation.c b/lib/ip_frag/rte_ipv6_fragmentation.c
index c81f2402e3..4d8fb05233 100644
--- a/lib/ip_frag/rte_ipv6_fragmentation.c
+++ b/lib/ip_frag/rte_ipv6_fragmentation.c
@@ -38,9 +38,7 @@ __fill_ipv6hdr_frag(struct rte_ipv6_hdr *dst,
 static inline void
 __free_fragments(struct rte_mbuf *mb[], uint32_t num)
 {
-	uint32_t i;
-	for (i = 0; i < num; i++)
-		rte_pktmbuf_free(mb[i]);
+	rte_pktmbuf_free_bulk(mb, num);
 }
 
 /**
-- 
2.53.0


^ permalink raw reply related

* [PATCH 03/20] gso: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Jiayu Hu
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/gso/gso_common.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/lib/gso/gso_common.c b/lib/gso/gso_common.c
index 378bf2c6aa..6ccaa7103a 100644
--- a/lib/gso/gso_common.c
+++ b/lib/gso/gso_common.c
@@ -31,10 +31,7 @@ hdr_segment_init(struct rte_mbuf *hdr_segment, struct rte_mbuf *pkt,
 static inline void
 free_gso_segment(struct rte_mbuf **pkts, uint16_t nb_pkts)
 {
-	uint16_t i;
-
-	for (i = 0; i < nb_pkts; i++)
-		rte_pktmbuf_free(pkts[i]);
+	rte_pktmbuf_free_bulk(pkts, nb_pkts);
 }
 
 int
-- 
2.53.0


^ permalink raw reply related

* [PATCH 02/20] eventdev: use rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Naga Harish K S V, Jerin Jacob
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eventdev/rte_event_eth_tx_adapter.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/eventdev/rte_event_eth_tx_adapter.c b/lib/eventdev/rte_event_eth_tx_adapter.c
index 91c7be55c7..2de96a02c2 100644
--- a/lib/eventdev/rte_event_eth_tx_adapter.c
+++ b/lib/eventdev/rte_event_eth_tx_adapter.c
@@ -914,12 +914,10 @@ static inline void
 txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
 {
 	struct rte_eth_dev_tx_buffer *b;
-	uint16_t i;
 
 	b = tqi->tx_buf;
 
-	for (i = 0; i < b->length; i++)
-		rte_pktmbuf_free(b->pkts[i]);
+	rte_pktmbuf_free_bulk(b->pkts, b->length);
 
 	b->length = 0;
 }
-- 
2.53.0


^ permalink raw reply related

* [PATCH 01/20] devtools/cocci: add transform for rte_pktmbuf_free_bulk
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger
In-Reply-To: <20260508203607.1003036-1-stephen@networkplumber.org>

Convert simple loops freeing mbufs one at a time into a
single rte_pktmbuf_free_bulk() call.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 devtools/cocci/free_bulk.cocci | 57 ++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 devtools/cocci/free_bulk.cocci

diff --git a/devtools/cocci/free_bulk.cocci b/devtools/cocci/free_bulk.cocci
new file mode 100644
index 0000000000..51ce58400a
--- /dev/null
+++ b/devtools/cocci/free_bulk.cocci
@@ -0,0 +1,57 @@
+//
+// Replace simple loops freeing mbufs one-by-one with rte_pktmbuf_free_bulk().
+//
+// rte_pktmbuf_free_bulk() handles NULL entries internally, so per-element
+// NULL guards are folded in as well.  Loops whose body does more than the
+// free (clearing the slot, bookkeeping, etc.) are not matched.
+//
+@@
+expression A, N;
+identifier i;
+@@
+
+(
+- for (i = 0; i < N; i++)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; ++i)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; i++)
+-     if (A[i] != NULL)
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; i++)
+-     if (A[i])
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+)
+
+@@
+expression A, N;
+identifier i;
+type T;
+@@
+
+(
+- for (T i = 0; i < N; i++)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; ++i)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; i++)
+-     if (A[i] != NULL)
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; i++)
+-     if (A[i])
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+)
-- 
2.53.0


^ permalink raw reply related

* [PATCH 00/20] pktmbuf free bulk cleanups
From: Stephen Hemminger @ 2026-05-08 20:33 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Looking at one driver noticed that rte_pktmbuf_free_bulk
was not being used. That motivated me to make a coccinelle
script to do a tree wide cleanup.

Then noticed that callers were having to check for NULL
before calling rte_pktmbuf_free_bulk, so changed it to
handle NULL array similar to free() and rte_free().

Do another tree wide pass to fix that and catch some
other unnecessary null checks in code.

Stephen Hemminger (20):
  devtools/cocci: add transform for rte_pktmbuf_free_bulk
  eventdev: use rte_pktmbuf_free_bulk
  gso: use rte_pktmbuf_free_bulk
  ip_frag: use rte_pktmbuf_free_bulk
  pipeline: use rte_pktmbuf_free_bulk
  port: use rte_pktmbuf_free_bulk
  net/af_xdp: use rte_pktmbuf_free_bulk
  net/cnxk: use rte_pktmbuf_free_bulk
  net/pfe: use rte_pktmbuf_free_bulk
  net/virtio: use rte_pktmbuf_free_bulk
  net/zxdh: use rte_pktmbuf_free_bulk
  app/compress-perf: use rte_pktmbuf_free_bulk
  mbuf: allow NULL array in rte_pktmbuf_free_bulk
  net/zxdh: remove unnecessary null check
  net/ice: remove unnecessary null check
  net/bnxt: remove unnecessary null check
  test: use rte_pktmbuf_free_bulk
  app/test-dma-perf: remove unnecessary null check
  app/test-compress-perf: remove unnecessary null check
  examples: use rte_pktmbuf_free_bulk

 .../comp_perf_test_common.c                   |  8 +--
 app/test-compress-perf/main.c                 |  6 +-
 app/test-dma-perf/benchmark.c                 |  6 +-
 app/test/sample_packet_forward.c              |  5 +-
 app/test/test_distributor.c                   |  4 +-
 app/test/test_dmadev.c                        |  6 +-
 app/test/test_ipfrag.c                        |  4 +-
 app/test/test_link_bonding.c                  | 13 ++---
 app/test/test_pmd_perf.c                      |  3 +-
 app/test/test_pmd_tap.c                       |  3 +-
 app/test/test_reorder.c                       | 12 ++--
 app/test/test_table_ports.c                   | 12 ++--
 app/test/test_table_tables.c                  | 21 +++----
 devtools/cocci/free_bulk.cocci                | 57 +++++++++++++++++++
 devtools/cocci/nullfree.cocci                 |  5 +-
 doc/guides/rel_notes/release_26_07.rst        |  5 ++
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  3 +-
 drivers/net/bnxt/tf_core/v3/tfo.c             |  6 +-
 drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c          |  6 +-
 drivers/net/cnxk/cnxk_ethdev.c                |  5 +-
 drivers/net/intel/ice/ice_dcf_sched.c         |  6 +-
 drivers/net/pfe/pfe_ethdev.c                  |  4 +-
 drivers/net/virtio/virtio_rxtx.c              | 20 +++----
 drivers/net/zxdh/zxdh_np.c                    |  3 +-
 drivers/net/zxdh/zxdh_queue.c                 |  7 +--
 drivers/net/zxdh/zxdh_rxtx.c                  |  3 +-
 examples/bbdev_app/main.c                     |  4 +-
 examples/l2fwd-crypto/main.c                  |  4 +-
 .../client_server_mp/mp_client/client.c       |  7 +--
 .../client_server_mp/mp_server/main.c         |  5 +-
 examples/ntb/ntb_fwd.c                        | 12 ++--
 examples/packet_ordering/main.c               |  5 +-
 examples/server_node_efd/efd_node/node.c      |  7 +--
 examples/server_node_efd/efd_server/main.c    |  5 +-
 examples/vhost/main.c                         |  3 +-
 lib/eventdev/rte_event_eth_tx_adapter.c       |  4 +-
 lib/gso/gso_common.c                          |  5 +-
 lib/ip_frag/rte_ipv6_fragmentation.c          |  4 +-
 lib/mbuf/rte_mbuf.c                           |  3 +
 lib/mbuf/rte_mbuf.h                           |  1 +
 lib/pipeline/rte_pipeline.c                   |  4 +-
 lib/port/rte_port_fd.c                        |  6 +-
 lib/port/rte_swx_port_fd.c                    |  8 +--
 lib/port/rte_swx_port_source_sink.c           |  6 +-
 44 files changed, 152 insertions(+), 174 deletions(-)
 create mode 100644 devtools/cocci/free_bulk.cocci

-- 
2.53.0


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox