As of now, HWS drop action used for DROP flow action,
is allocated either on port start or on rte_flow_configure().
This can cause unnecessary FW resource usage
if user does not use any DROP actions.

This patch adds dedicated internal API - mlx5_hws_global_actions -
in mlx5 PMD for lazily allocating HWS drop action, to delay FW resource
allocation until needed.
Instead of allocating HWS drop action supporting all possible domains
(NIC Rx, NIC Tx, FDB if relevant) as it was previously,
separate action will be allocated for each domain as needed
to further minimize FW resource usage.

Follow up commits will extend this API with additional actions
which are pre-allocated on port start or on rte_flow_configure().

Signed-off-by: Dariusz Sosnowski <[email protected]>
Acked-by: Ori Kam <[email protected]>
---
 drivers/net/mlx5/meson.build               |  1 +
 drivers/net/mlx5/mlx5.h                    |  5 +-
 drivers/net/mlx5/mlx5_flow_hw.c            | 27 ++++-----
 drivers/net/mlx5/mlx5_hws_global_actions.c | 68 ++++++++++++++++++++++
 drivers/net/mlx5/mlx5_hws_global_actions.h | 39 +++++++++++++
 5 files changed, 123 insertions(+), 17 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_hws_global_actions.c
 create mode 100644 drivers/net/mlx5/mlx5_hws_global_actions.h

diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 28275bed21..82a7dfe782 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -53,6 +53,7 @@ if is_linux
             'mlx5_flow_quota.c',
             'mlx5_flow_verbs.c',
             'mlx5_hws_cnt.c',
+            'mlx5_hws_global_actions.c',
             'mlx5_nta_split.c',
             'mlx5_nta_sample.c',
     )
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index e9d855e345..54683cce7a 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -39,6 +39,7 @@
 #define HAVE_MLX5_HWS_SUPPORT 1
 #endif
 #include "hws/mlx5dr.h"
+#include "mlx5_hws_global_actions.h"
 #endif
 
 #define MLX5_SH(dev) (((struct mlx5_priv *)(dev)->data->dev_private)->sh)
@@ -2112,8 +2113,8 @@ struct mlx5_priv {
        struct mlx5dr_action *hw_push_vlan[MLX5DR_TABLE_TYPE_MAX];
        struct mlx5dr_action *hw_pop_vlan[MLX5DR_TABLE_TYPE_MAX];
        struct mlx5dr_action **hw_vport;
-       /* HW steering global drop action. */
-       struct mlx5dr_action *hw_drop[2];
+       /* HWS global actions. */
+       struct mlx5_hws_global_actions hw_global_actions;
        /* HW steering global tag action. */
        struct mlx5dr_action *hw_tag[2];
        /* HW steering global default miss action. */
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index b29909f99d..80e156f26a 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2634,6 +2634,7 @@ __flow_hw_translate_actions_template(struct rte_eth_dev 
*dev,
        int ret, err;
        bool is_root = mlx5_group_id_is_root(cfg->attr.flow_attr.group);
        bool unified_fdb = is_unified_fdb(priv);
+       struct mlx5dr_action *dr_action = NULL;
 
        flow_hw_modify_field_init(&mhdr, at);
        type = get_mlx5dr_table_type(attr, cfg->attr.specialize, unified_fdb);
@@ -2672,8 +2673,16 @@ __flow_hw_translate_actions_template(struct rte_eth_dev 
*dev,
                case RTE_FLOW_ACTION_TYPE_VOID:
                        break;
                case RTE_FLOW_ACTION_TYPE_DROP:
-                       acts->rule_acts[dr_pos].action =
-                               priv->hw_drop[!!attr->group];
+                       dr_action = mlx5_hws_global_action_drop_get(priv, type, 
is_root);
+                       if (dr_action == NULL) {
+                               DRV_LOG(ERR, "port %u failed to allocate drop 
action",
+                                       priv->dev_data->port_id);
+                               rte_flow_error_set(&sub_error, ENOMEM,
+                                                  RTE_FLOW_ERROR_TYPE_STATE, 
NULL,
+                                                  "failed to allocate drop 
action");
+                               goto err;
+                       }
+                       acts->rule_acts[dr_pos].action = dr_action;
                        break;
                case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
                        if (is_root) {
@@ -11965,8 +11974,6 @@ __mlx5_flow_hw_resource_release(struct rte_eth_dev 
*dev, bool ctx_close)
                at = temp_at;
        }
        for (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {
-               if (priv->hw_drop[i])
-                       mlx5dr_action_destroy(priv->hw_drop[i]);
                if (priv->hw_tag[i])
                        mlx5dr_action_destroy(priv->hw_tag[i]);
        }
@@ -11995,6 +12002,7 @@ __mlx5_flow_hw_resource_release(struct rte_eth_dev 
*dev, bool ctx_close)
                priv->ct_mng = NULL;
        }
        mlx5_flow_quota_destroy(dev);
+       mlx5_hws_global_actions_cleanup(priv);
        if (priv->hw_q) {
                for (i = 0; i < priv->nb_queue; i++) {
                        struct mlx5_hw_q *hwq = &priv->hw_q[i];
@@ -12345,29 +12353,18 @@ __flow_hw_configure(struct rte_eth_dev *dev,
                        goto err;
        /* Add global actions. */
        for (i = 0; i < MLX5_HW_ACTION_FLAG_MAX; i++) {
-               uint32_t act_flags = 0;
                uint32_t tag_flags = mlx5_hw_act_flag[i][0];
                bool tag_fdb_rx = 
!!priv->sh->cdev->config.hca_attr.fdb_rx_set_flow_tag_stc;
 
-               act_flags = mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_NIC_RX] |
-                           mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_NIC_TX];
                if (is_proxy) {
                        if (unified_fdb) {
-                               act_flags |=
-                                       
(mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB_RX] |
-                                        
mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB_TX] |
-                                        
mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB_UNIFIED]);
                                if (i == MLX5_HW_ACTION_FLAG_NONE_ROOT && 
tag_fdb_rx)
                                        tag_flags |= 
mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB_RX];
                        } else {
-                               act_flags |= 
mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB];
                                if (i == MLX5_HW_ACTION_FLAG_NONE_ROOT && 
tag_fdb_rx)
                                        tag_flags |= 
mlx5_hw_act_flag[i][MLX5DR_TABLE_TYPE_FDB];
                        }
                }
-               priv->hw_drop[i] = mlx5dr_action_create_dest_drop(priv->dr_ctx, 
act_flags);
-               if (!priv->hw_drop[i])
-                       goto err;
                priv->hw_tag[i] = mlx5dr_action_create_tag
                        (priv->dr_ctx, tag_flags);
                if (!priv->hw_tag[i])
diff --git a/drivers/net/mlx5/mlx5_hws_global_actions.c 
b/drivers/net/mlx5/mlx5_hws_global_actions.c
new file mode 100644
index 0000000000..6af5497123
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_hws_global_actions.c
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2026 NVIDIA Corporation & Affiliates
+ */
+
+#include "mlx5_hws_global_actions.h"
+
+#include "mlx5.h"
+
+void
+mlx5_hws_global_actions_init(struct mlx5_priv *priv)
+{
+       rte_spinlock_init(&priv->hw_global_actions.lock);
+}
+
+void
+mlx5_hws_global_actions_cleanup(struct mlx5_priv *priv)
+{
+       rte_spinlock_lock(&priv->hw_global_actions.lock);
+
+       for (int i = 0; i < MLX5_HWS_GLOBAL_ACTION_MAX; ++i) {
+               for (int j = 0; j < MLX5DR_TABLE_TYPE_MAX; ++j) {
+                       int ret;
+
+                       if (priv->hw_global_actions.drop.arr[i][j] == NULL)
+                               continue;
+
+                       ret = 
mlx5dr_action_destroy(priv->hw_global_actions.drop.arr[i][j]);
+                       if (ret != 0)
+                               DRV_LOG(ERR, "port %u failed to free HWS 
action",
+                                       priv->dev_data->port_id);
+                       priv->hw_global_actions.drop.arr[i][j] = NULL;
+               }
+       }
+
+       rte_spinlock_unlock(&priv->hw_global_actions.lock);
+}
+
+struct mlx5dr_action *
+mlx5_hws_global_action_drop_get(struct mlx5_priv *priv,
+                               enum mlx5dr_table_type table_type,
+                               bool is_root)
+{
+       enum mlx5dr_action_flags action_flags;
+       struct mlx5dr_action *action = NULL;
+       int ret;
+
+       ret = mlx5dr_table_type_to_action_flags(table_type, is_root, 
&action_flags);
+       if (ret < 0)
+               return NULL;
+
+       rte_spinlock_lock(&priv->hw_global_actions.lock);
+
+       action = priv->hw_global_actions.drop.arr[!is_root][table_type];
+       if (action != NULL)
+               goto unlock_ret;
+
+       action = mlx5dr_action_create_dest_drop(priv->dr_ctx, action_flags);
+       if (action == NULL) {
+               DRV_LOG(ERR, "port %u failed to create drop HWS action", 
priv->dev_data->port_id);
+               goto unlock_ret;
+       }
+
+       priv->hw_global_actions.drop.arr[!is_root][table_type] = action;
+
+unlock_ret:
+       rte_spinlock_unlock(&priv->hw_global_actions.lock);
+       return action;
+}
diff --git a/drivers/net/mlx5/mlx5_hws_global_actions.h 
b/drivers/net/mlx5/mlx5_hws_global_actions.h
new file mode 100644
index 0000000000..3921004102
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_hws_global_actions.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2026 NVIDIA Corporation & Affiliates
+ */
+
+#ifndef RTE_PMD_MLX5_HWS_GLOBAL_ACTIONS_H_
+#define RTE_PMD_MLX5_HWS_GLOBAL_ACTIONS_H_
+
+#include <stdint.h>
+
+#include <rte_spinlock.h>
+
+#include "hws/mlx5dr.h"
+
+struct mlx5_priv;
+
+enum mlx5_hws_global_action_index {
+       MLX5_HWS_GLOBAL_ACTION_ROOT,
+       MLX5_HWS_GLOBAL_ACTION_NON_ROOT,
+       MLX5_HWS_GLOBAL_ACTION_MAX,
+};
+
+struct mlx5_hws_global_actions_array {
+       struct mlx5dr_action 
*arr[MLX5_HWS_GLOBAL_ACTION_MAX][MLX5DR_TABLE_TYPE_MAX];
+};
+
+struct mlx5_hws_global_actions {
+       struct mlx5_hws_global_actions_array drop;
+       rte_spinlock_t lock;
+};
+
+void mlx5_hws_global_actions_init(struct mlx5_priv *priv);
+
+void mlx5_hws_global_actions_cleanup(struct mlx5_priv *priv);
+
+struct mlx5dr_action *mlx5_hws_global_action_drop_get(struct mlx5_priv *priv,
+                                                     enum mlx5dr_table_type 
table_type,
+                                                     bool is_root);
+
+#endif /* !RTE_PMD_MLX5_HWS_GLOBAL_ACTIONS_H_ */
-- 
2.47.3

Reply via email to