diff --git a/drivers/common/mlx5/mlx5_devx_cmds.c b/drivers/common/mlx5/mlx5_devx_cmds.c
index 10a02d13ee..56407cc332 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.c
+++ b/drivers/common/mlx5/mlx5_devx_cmds.c
@@ -819,6 +819,8 @@ mlx5_devx_cmd_query_hca_attr(void *ctx,
 	attr->roce = MLX5_GET(cmd_hca_cap, hcattr, roce);
 	attr->rq_ts_format = MLX5_GET(cmd_hca_cap, hcattr, rq_ts_format);
 	attr->sq_ts_format = MLX5_GET(cmd_hca_cap, hcattr, sq_ts_format);
+	attr->steering_format_version =
+		MLX5_GET(cmd_hca_cap, hcattr, steering_format_version);
 	attr->regex = MLX5_GET(cmd_hca_cap, hcattr, regexp);
 	attr->regexp_num_of_engines = MLX5_GET(cmd_hca_cap, hcattr,
 					       regexp_num_of_engines);
diff --git a/drivers/common/mlx5/mlx5_devx_cmds.h b/drivers/common/mlx5/mlx5_devx_cmds.h
index c11ca6586f..e576e30f24 100644
--- a/drivers/common/mlx5/mlx5_devx_cmds.h
+++ b/drivers/common/mlx5/mlx5_devx_cmds.h
@@ -141,6 +141,7 @@ struct mlx5_hca_attr {
 	uint32_t roce:1;
 	uint32_t rq_ts_format:2;
 	uint32_t sq_ts_format:2;
+	uint32_t steering_format_version:4;
 	uint32_t qp_ts_format:2;
 	uint32_t regex:1;
 	uint32_t reg_c_preserve:1;
diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index 7950070976..915fcb66a2 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -1317,6 +1317,10 @@ enum {
 #define MLX5_HCA_FLEX_ICMP_ENABLED (1UL << 8)
 #define MLX5_HCA_FLEX_ICMPV6_ENABLED (1UL << 9)
 
+/* The device steering logic format. */
+#define MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5 0x0
+#define MLX5_STEERING_LOGIC_FORMAT_CONNECTX_6DX 0x1
+
 struct mlx5_ifc_cmd_hca_cap_bits {
 	u8 reserved_at_0[0x30];
 	u8 vhca_id[0x10];
@@ -1585,7 +1589,8 @@ struct mlx5_ifc_cmd_hca_cap_bits {
 	u8 general_obj_types[0x40];
 	u8 sq_ts_format[0x2];
 	u8 rq_ts_format[0x2];
-	u8 reserved_at_444[0x1C];
+	u8 steering_format_version[0x4];
+	u8 reserved_at_448[0x18];
 	u8 reserved_at_460[0x8];
 	u8 aes_xts[0x1];
 	u8 crypto[0x1];
diff --git a/drivers/net/mlx5/linux/mlx5_os.c b/drivers/net/mlx5/linux/mlx5_os.c
index aa5210fa45..1dbb51da0c 100644
--- a/drivers/net/mlx5/linux/mlx5_os.c
+++ b/drivers/net/mlx5/linux/mlx5_os.c
@@ -1357,6 +1357,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		}
 		sh->rq_ts_format = config->hca_attr.rq_ts_format;
 		sh->sq_ts_format = config->hca_attr.sq_ts_format;
+		sh->steering_format_version =
+			config->hca_attr.steering_format_version;
 		sh->qp_ts_format = config->hca_attr.qp_ts_format;
 		/* Check for LRO support. */
 		if (config->dest_tir && config->hca_attr.lro_cap &&
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 94618e10fa..61898e8ea1 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -1113,6 +1113,8 @@ struct mlx5_dev_ctx_shared {
 	uint32_t flow_hit_aso_en:1; /* Flow Hit ASO is supported. */
 	uint32_t rq_ts_format:2; /* RQ timestamp formats supported. */
 	uint32_t sq_ts_format:2; /* SQ timestamp formats supported. */
+	uint32_t steering_format_version:4;
+	/* Indicates the device steering logic format. */
 	uint32_t qp_ts_format:2; /* QP timestamp formats supported. */
 	uint32_t meter_aso_en:1; /* Flow Meter ASO is supported. */
 	uint32_t ct_aso_en:1; /* Connection Tracking ASO is supported. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index d250486950..3f9726d1c3 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2790,20 +2790,30 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
 				 struct rte_flow_error *error)
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_dev_ctx_shared *sh = priv->sh;
+	bool direction_error = false;
 
-	(void)action;
-	(void)attr;
 	if (!priv->sh->pop_vlan_action)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL,
 					  "pop vlan action is not supported");
-	if (attr->egress)
+	/* Pop VLAN is not supported in egress except for CX6 FDB mode. */
+	if (attr->transfer) {
+		bool fdb_tx = priv->representor_id != UINT16_MAX;
+		bool is_cx5 = sh->steering_format_version ==
+		    MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
+
+		if (fdb_tx && is_cx5)
+			direction_error = true;
+	} else if (attr->egress) {
+		direction_error = true;
+	}
+	if (direction_error)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
 					  NULL,
-					  "pop vlan action not supported for "
-					  "egress");
+					  "pop vlan action not supported for egress");
 	if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -2927,6 +2937,8 @@ flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
 {
 	const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
 	const struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_dev_ctx_shared *sh = priv->sh;
+	bool direction_error = false;
 
 	if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) &&
 	    push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ))
@@ -2938,6 +2950,22 @@ flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "wrong action order, port_id should "
 					  "be after push VLAN");
+	/* Push VLAN is not supported in ingress except for CX6 FDB mode. */
+	if (attr->transfer) {
+		bool fdb_tx = priv->representor_id != UINT16_MAX;
+		bool is_cx5 = sh->steering_format_version ==
+		    MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
+
+		if (!fdb_tx && is_cx5)
+			direction_error = true;
+	} else if (attr->ingress) {
+		direction_error = true;
+	}
+	if (direction_error)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+					  NULL,
+					  "push vlan action not supported for ingress");
 	if (!attr->transfer && priv->representor)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
