mlx5: Fix mlx5dv_create_flow to keep legacy ABI

The commit ID mentioned by the Fixes line increased the layout of struct
mlx5dv_flow_action_attr from 16 to 24 bytes, breaking ABI for users of
the mlx5dv_create_flow() API and caused a SF where more than one action
is supplied.

Fix this ABI break, by keeping the layout for the original symbol
version of mlx5dv_create_flow() while introducing a new symbol to
support a dynamic stride based on the compiled mlx5dv_flow_action_attr
size.

Fixes: 1dc3e8d9866e ("mlx5: Add support for bulk flow counters in mlx5dv_create_flow")
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
diff --git a/debian/ibverbs-providers.symbols b/debian/ibverbs-providers.symbols
index 256d80f..b1ca4a3 100644
--- a/debian/ibverbs-providers.symbols
+++ b/debian/ibverbs-providers.symbols
@@ -33,6 +33,7 @@
  MLX5_1.23@MLX5_1.23 40
  MLX5_1.24@MLX5_1.24 42
  MLX5_1.25@MLX5_1.25 54
+ MLX5_1.25.1@MLX5_1.25.1 61.1
  mlx5dv_init_obj@MLX5_1.0 13
  mlx5dv_init_obj@MLX5_1.2 15
  mlx5dv_query_device@MLX5_1.0 13
@@ -164,6 +165,7 @@
  mlx5dv_dr_action_create_dest_root_table@MLX5_1.24 42
  mlx5dv_get_data_direct_sysfs_path@MLX5_1.25 54
  mlx5dv_reg_dmabuf_mr@MLX5_1.25 54
+ __mlx5dv_create_flow@MLX5_1.25.1 61.1
 libefa.so.1 ibverbs-providers #MINVER#
 * Build-Depends-Package: libibverbs-dev
  EFA_1.0@EFA_1.0 24
diff --git a/providers/mlx5/libmlx5.map b/providers/mlx5/libmlx5.map
index b2a852a..a0f146b 100644
--- a/providers/mlx5/libmlx5.map
+++ b/providers/mlx5/libmlx5.map
@@ -235,3 +235,8 @@
 		mlx5dv_get_data_direct_sysfs_path;
 		mlx5dv_reg_dmabuf_mr;
 } MLX5_1.24;
+
+MLX5_1.25.1 {
+	global:
+		__mlx5dv_create_flow;
+} MLX5_1.25;
diff --git a/providers/mlx5/mlx5.h b/providers/mlx5/mlx5.h
index 34c1808..53dc574 100644
--- a/providers/mlx5/mlx5.h
+++ b/providers/mlx5/mlx5.h
@@ -959,10 +959,11 @@
 };
 
 struct ibv_flow *
-_mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
+___mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
 		    struct mlx5dv_flow_match_parameters *match_value,
 		    size_t num_actions,
-		    struct mlx5dv_flow_action_attr actions_attr[]);
+		    struct mlx5dv_flow_action_attr actions_attr[],
+		    size_t attr_len);
 
 extern int mlx5_stall_num_loop;
 extern int mlx5_stall_cq_poll_min;
@@ -1589,7 +1590,8 @@
 		struct mlx5dv_flow_matcher *flow_matcher,
 		struct mlx5dv_flow_match_parameters *match_value,
 		size_t num_actions,
-		struct mlx5dv_flow_action_attr actions_attr[]);
+		struct mlx5dv_flow_action_attr actions_attr[],
+		size_t attr_len);
 
 	struct mlx5dv_steering_anchor *(*create_steering_anchor)(struct ibv_context *conterxt,
 								 struct mlx5dv_steering_anchor_attr *attr);
diff --git a/providers/mlx5/mlx5dv.h b/providers/mlx5/mlx5dv.h
index a249401..571e531 100644
--- a/providers/mlx5/mlx5dv.h
+++ b/providers/mlx5/mlx5dv.h
@@ -802,10 +802,24 @@
 };
 
 struct ibv_flow *
-mlx5dv_create_flow(struct mlx5dv_flow_matcher *matcher,
-		   struct mlx5dv_flow_match_parameters *match_value,
-		   size_t num_actions,
-		   struct mlx5dv_flow_action_attr actions_attr[]);
+__mlx5dv_create_flow(struct mlx5dv_flow_matcher *matcher,
+		     struct mlx5dv_flow_match_parameters *match_value,
+		     size_t num_actions,
+		     struct mlx5dv_flow_action_attr actions_attr[],
+		     size_t attr_len);
+
+static inline struct ibv_flow *
+_mlx5dv_create_flow(struct mlx5dv_flow_matcher *matcher,
+		    struct mlx5dv_flow_match_parameters *match_value,
+		    size_t num_actions,
+		    struct mlx5dv_flow_action_attr actions_attr[])
+{
+	return __mlx5dv_create_flow(matcher, match_value, num_actions, actions_attr,
+				  sizeof(struct mlx5dv_flow_action_attr));
+}
+
+#define mlx5dv_create_flow(matcher, match_value, num_actions, actions_attr) \
+	_mlx5dv_create_flow(matcher, match_value, num_actions, actions_attr)
 
 struct ibv_flow_action *mlx5dv_create_flow_action_esp(struct ibv_context *ctx,
 						      struct ibv_flow_action_esp_attr *esp,
diff --git a/providers/mlx5/verbs.c b/providers/mlx5/verbs.c
index 06da229..5a377a0 100644
--- a/providers/mlx5/verbs.c
+++ b/providers/mlx5/verbs.c
@@ -59,6 +59,14 @@
 #include "wqe.h"
 #include "mlx5_ifc.h"
 
+#undef mlx5dv_create_flow
+
+struct ibv_flow *
+mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
+		   struct mlx5dv_flow_match_parameters *match_value,
+		   size_t num_actions,
+		   struct mlx5dv_flow_action_attr actions_attr[]);
+
 int mlx5_single_threaded = 0;
 
 static inline int is_xrc_tgt(int type)
@@ -5619,13 +5627,15 @@
 
 #define CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED 8
 struct ibv_flow *
-_mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
+___mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
 		    struct mlx5dv_flow_match_parameters *match_value,
 		    size_t num_actions,
-		    struct mlx5dv_flow_action_attr actions_attr[])
+		    struct mlx5dv_flow_action_attr actions_attr[],
+		    size_t attr_len)
 {
 	uint32_t flow_actions[CREATE_FLOW_MAX_FLOW_ACTIONS_SUPPORTED];
 	struct verbs_flow_action *vaction;
+	struct mlx5dv_flow_action_attr *attr;
 	int num_flow_actions = 0;
 	struct mlx5_flow *mflow;
 	bool have_qp = false;
@@ -5655,8 +5665,9 @@
 		    match_value->match_sz);
 	fill_attr_in_obj(cmd, MLX5_IB_ATTR_CREATE_FLOW_MATCHER, flow_matcher->handle);
 
+	attr = actions_attr;
 	for (i = 0; i < num_actions; i++) {
-		type = actions_attr[i].type;
+		type = attr->type;
 		switch (type) {
 		case MLX5DV_FLOW_ACTION_DEST_IBV_QP:
 			if (have_qp || have_dest_devx || have_default ||
@@ -5665,7 +5676,7 @@
 				goto err;
 			}
 			fill_attr_in_obj(cmd, MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
-					 actions_attr[i].qp->handle);
+					 attr->qp->handle);
 			have_qp = true;
 			break;
 		case MLX5DV_FLOW_ACTION_IBV_FLOW_ACTION:
@@ -5674,7 +5685,7 @@
 				errno = EOPNOTSUPP;
 				goto err;
 			}
-			vaction = container_of(actions_attr[i].action,
+			vaction = container_of(attr->action,
 					       struct verbs_flow_action,
 					       action);
 
@@ -5688,7 +5699,7 @@
 				goto err;
 			}
 			fill_attr_in_obj(cmd, MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
-					 actions_attr[i].obj->handle);
+					 attr->obj->handle);
 			have_dest_devx = true;
 			break;
 		case MLX5DV_FLOW_ACTION_TAG:
@@ -5698,7 +5709,7 @@
 			}
 			fill_attr_in_uint32(cmd,
 					    MLX5_IB_ATTR_CREATE_FLOW_TAG,
-					    actions_attr[i].tag_value);
+					    attr->tag_value);
 			have_flow_tag = true;
 			break;
 		case MLX5DV_FLOW_ACTION_COUNTERS_DEVX:
@@ -5708,7 +5719,7 @@
 			}
 			fill_attr_in_objs_arr(cmd,
 					      MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
-					      &actions_attr[i].obj->handle, 1);
+					      &attr->obj->handle, 1);
 			have_counter = true;
 			break;
 		case MLX5DV_FLOW_ACTION_DEFAULT_MISS:
@@ -5740,16 +5751,18 @@
 			}
 			fill_attr_in_objs_arr(cmd,
 					      MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
-					      &actions_attr[i].bulk_obj.obj->handle, 1);
+					      &attr->bulk_obj.obj->handle, 1);
 			fill_attr_in_ptr_array(cmd,
 					       MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
-					       &actions_attr[i].bulk_obj.offset, 1);
+					       &attr->bulk_obj.offset, 1);
 			have_bulk_counter = true;
 			break;
 		default:
 			errno = EOPNOTSUPP;
 			goto err;
 		}
+
+		attr = (void *)attr + attr_len;
 	}
 
 	if (num_flow_actions)
@@ -5770,10 +5783,11 @@
 }
 
 struct ibv_flow *
-mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
+__mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
 		   struct mlx5dv_flow_match_parameters *match_value,
 		   size_t num_actions,
-		   struct mlx5dv_flow_action_attr actions_attr[])
+		   struct mlx5dv_flow_action_attr actions_attr[],
+		   size_t attr_len)
 {
 	struct mlx5_dv_context_ops *dvops = mlx5_get_dv_ops(flow_matcher->context);
 
@@ -5785,7 +5799,30 @@
 	return dvops->create_flow(flow_matcher,
 				  match_value,
 				  num_actions,
-				  actions_attr);
+				  actions_attr,
+				  attr_len);
+}
+
+struct ibv_flow *
+mlx5dv_create_flow(struct mlx5dv_flow_matcher *flow_matcher,
+		   struct mlx5dv_flow_match_parameters *match_value,
+		   size_t num_actions,
+		   struct mlx5dv_flow_action_attr actions_attr[])
+{
+	size_t legacy_size = offsetof(struct mlx5dv_flow_action_attr, obj) +
+		sizeof(((struct mlx5dv_flow_action_attr *)0)->obj);
+
+	struct mlx5_dv_context_ops *dvops = mlx5_get_dv_ops(flow_matcher->context);
+
+	if (!dvops || !dvops->create_flow) {
+		errno = EOPNOTSUPP;
+		return NULL;
+	}
+
+	return dvops->create_flow(flow_matcher,
+				  match_value,
+				  num_actions,
+				  actions_attr, legacy_size);
 }
 
 static struct mlx5dv_steering_anchor *
@@ -8186,7 +8223,7 @@
 	ops->create_flow_action_packet_reformat = _mlx5dv_create_flow_action_packet_reformat;
 	ops->create_flow_matcher = _mlx5dv_create_flow_matcher;
 	ops->destroy_flow_matcher = _mlx5dv_destroy_flow_matcher;
-	ops->create_flow = _mlx5dv_create_flow;
+	ops->create_flow = ___mlx5dv_create_flow;
 
 	ops->map_ah_to_qp = _mlx5dv_map_ah_to_qp;
 	ops->query_port = __mlx5dv_query_port;