1*1339678fSYevgeny Kliteynik // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2*1339678fSYevgeny Kliteynik // Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3*1339678fSYevgeny Kliteynik 
4*1339678fSYevgeny Kliteynik #include "dr_types.h"
5*1339678fSYevgeny Kliteynik #include "dr_ste.h"
6*1339678fSYevgeny Kliteynik 
7*1339678fSYevgeny Kliteynik struct dr_definer_object {
8*1339678fSYevgeny Kliteynik 	u32 id;
9*1339678fSYevgeny Kliteynik 	u16 format_id;
10*1339678fSYevgeny Kliteynik 	u8 dw_selectors[MLX5_IFC_DEFINER_DW_SELECTORS_NUM];
11*1339678fSYevgeny Kliteynik 	u8 byte_selectors[MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM];
12*1339678fSYevgeny Kliteynik 	u8 match_mask[DR_STE_SIZE_MATCH_TAG];
13*1339678fSYevgeny Kliteynik 	refcount_t refcount;
14*1339678fSYevgeny Kliteynik };
15*1339678fSYevgeny Kliteynik 
dr_definer_compare(struct dr_definer_object * definer,u16 format_id,u8 * dw_selectors,u8 * byte_selectors,u8 * match_mask)16*1339678fSYevgeny Kliteynik static bool dr_definer_compare(struct dr_definer_object *definer,
17*1339678fSYevgeny Kliteynik 			       u16 format_id, u8 *dw_selectors,
18*1339678fSYevgeny Kliteynik 			       u8 *byte_selectors, u8 *match_mask)
19*1339678fSYevgeny Kliteynik {
20*1339678fSYevgeny Kliteynik 	int i;
21*1339678fSYevgeny Kliteynik 
22*1339678fSYevgeny Kliteynik 	if (definer->format_id != format_id)
23*1339678fSYevgeny Kliteynik 		return false;
24*1339678fSYevgeny Kliteynik 
25*1339678fSYevgeny Kliteynik 	for (i = 0; i < MLX5_IFC_DEFINER_DW_SELECTORS_NUM; i++)
26*1339678fSYevgeny Kliteynik 		if (definer->dw_selectors[i] != dw_selectors[i])
27*1339678fSYevgeny Kliteynik 			return false;
28*1339678fSYevgeny Kliteynik 
29*1339678fSYevgeny Kliteynik 	for (i = 0; i < MLX5_IFC_DEFINER_BYTE_SELECTORS_NUM; i++)
30*1339678fSYevgeny Kliteynik 		if (definer->byte_selectors[i] != byte_selectors[i])
31*1339678fSYevgeny Kliteynik 			return false;
32*1339678fSYevgeny Kliteynik 
33*1339678fSYevgeny Kliteynik 	if (memcmp(definer->match_mask, match_mask, DR_STE_SIZE_MATCH_TAG))
34*1339678fSYevgeny Kliteynik 		return false;
35*1339678fSYevgeny Kliteynik 
36*1339678fSYevgeny Kliteynik 	return true;
37*1339678fSYevgeny Kliteynik }
38*1339678fSYevgeny Kliteynik 
39*1339678fSYevgeny Kliteynik static struct dr_definer_object *
dr_definer_find_obj(struct mlx5dr_domain * dmn,u16 format_id,u8 * dw_selectors,u8 * byte_selectors,u8 * match_mask)40*1339678fSYevgeny Kliteynik dr_definer_find_obj(struct mlx5dr_domain *dmn, u16 format_id,
41*1339678fSYevgeny Kliteynik 		    u8 *dw_selectors, u8 *byte_selectors, u8 *match_mask)
42*1339678fSYevgeny Kliteynik {
43*1339678fSYevgeny Kliteynik 	struct dr_definer_object *definer_obj;
44*1339678fSYevgeny Kliteynik 	unsigned long id;
45*1339678fSYevgeny Kliteynik 
46*1339678fSYevgeny Kliteynik 	xa_for_each(&dmn->definers_xa, id, definer_obj) {
47*1339678fSYevgeny Kliteynik 		if (dr_definer_compare(definer_obj, format_id,
48*1339678fSYevgeny Kliteynik 				       dw_selectors, byte_selectors,
49*1339678fSYevgeny Kliteynik 				       match_mask))
50*1339678fSYevgeny Kliteynik 			return definer_obj;
51*1339678fSYevgeny Kliteynik 	}
52*1339678fSYevgeny Kliteynik 
53*1339678fSYevgeny Kliteynik 	return NULL;
54*1339678fSYevgeny Kliteynik }
55*1339678fSYevgeny Kliteynik 
56*1339678fSYevgeny Kliteynik static struct dr_definer_object *
dr_definer_create_obj(struct mlx5dr_domain * dmn,u16 format_id,u8 * dw_selectors,u8 * byte_selectors,u8 * match_mask)57*1339678fSYevgeny Kliteynik dr_definer_create_obj(struct mlx5dr_domain *dmn, u16 format_id,
58*1339678fSYevgeny Kliteynik 		      u8 *dw_selectors, u8 *byte_selectors, u8 *match_mask)
59*1339678fSYevgeny Kliteynik {
60*1339678fSYevgeny Kliteynik 	struct dr_definer_object *definer_obj;
61*1339678fSYevgeny Kliteynik 	int ret = 0;
62*1339678fSYevgeny Kliteynik 
63*1339678fSYevgeny Kliteynik 	definer_obj = kzalloc(sizeof(*definer_obj), GFP_KERNEL);
64*1339678fSYevgeny Kliteynik 	if (!definer_obj)
65*1339678fSYevgeny Kliteynik 		return NULL;
66*1339678fSYevgeny Kliteynik 
67*1339678fSYevgeny Kliteynik 	ret = mlx5dr_cmd_create_definer(dmn->mdev,
68*1339678fSYevgeny Kliteynik 					format_id,
69*1339678fSYevgeny Kliteynik 					dw_selectors,
70*1339678fSYevgeny Kliteynik 					byte_selectors,
71*1339678fSYevgeny Kliteynik 					match_mask,
72*1339678fSYevgeny Kliteynik 					&definer_obj->id);
73*1339678fSYevgeny Kliteynik 	if (ret)
74*1339678fSYevgeny Kliteynik 		goto err_free_definer_obj;
75*1339678fSYevgeny Kliteynik 
76*1339678fSYevgeny Kliteynik 	/* Definer ID can have 32 bits, but STE format
77*1339678fSYevgeny Kliteynik 	 * supports only definers with 8 bit IDs.
78*1339678fSYevgeny Kliteynik 	 */
79*1339678fSYevgeny Kliteynik 	if (definer_obj->id > 0xff) {
80*1339678fSYevgeny Kliteynik 		mlx5dr_err(dmn, "Unsupported definer ID (%d)\n", definer_obj->id);
81*1339678fSYevgeny Kliteynik 		goto err_destroy_definer;
82*1339678fSYevgeny Kliteynik 	}
83*1339678fSYevgeny Kliteynik 
84*1339678fSYevgeny Kliteynik 	definer_obj->format_id = format_id;
85*1339678fSYevgeny Kliteynik 	memcpy(definer_obj->dw_selectors, dw_selectors, sizeof(definer_obj->dw_selectors));
86*1339678fSYevgeny Kliteynik 	memcpy(definer_obj->byte_selectors, byte_selectors, sizeof(definer_obj->byte_selectors));
87*1339678fSYevgeny Kliteynik 	memcpy(definer_obj->match_mask, match_mask, sizeof(definer_obj->match_mask));
88*1339678fSYevgeny Kliteynik 
89*1339678fSYevgeny Kliteynik 	refcount_set(&definer_obj->refcount, 1);
90*1339678fSYevgeny Kliteynik 
91*1339678fSYevgeny Kliteynik 	ret = xa_insert(&dmn->definers_xa, definer_obj->id, definer_obj, GFP_KERNEL);
92*1339678fSYevgeny Kliteynik 	if (ret) {
93*1339678fSYevgeny Kliteynik 		mlx5dr_dbg(dmn, "Couldn't insert new definer into xarray (%d)\n", ret);
94*1339678fSYevgeny Kliteynik 		goto err_destroy_definer;
95*1339678fSYevgeny Kliteynik 	}
96*1339678fSYevgeny Kliteynik 
97*1339678fSYevgeny Kliteynik 	return definer_obj;
98*1339678fSYevgeny Kliteynik 
99*1339678fSYevgeny Kliteynik err_destroy_definer:
100*1339678fSYevgeny Kliteynik 	mlx5dr_cmd_destroy_definer(dmn->mdev, definer_obj->id);
101*1339678fSYevgeny Kliteynik err_free_definer_obj:
102*1339678fSYevgeny Kliteynik 	kfree(definer_obj);
103*1339678fSYevgeny Kliteynik 
104*1339678fSYevgeny Kliteynik 	return NULL;
105*1339678fSYevgeny Kliteynik }
106*1339678fSYevgeny Kliteynik 
dr_definer_destroy_obj(struct mlx5dr_domain * dmn,struct dr_definer_object * definer_obj)107*1339678fSYevgeny Kliteynik static void dr_definer_destroy_obj(struct mlx5dr_domain *dmn,
108*1339678fSYevgeny Kliteynik 				   struct dr_definer_object *definer_obj)
109*1339678fSYevgeny Kliteynik {
110*1339678fSYevgeny Kliteynik 	mlx5dr_cmd_destroy_definer(dmn->mdev, definer_obj->id);
111*1339678fSYevgeny Kliteynik 	xa_erase(&dmn->definers_xa, definer_obj->id);
112*1339678fSYevgeny Kliteynik 	kfree(definer_obj);
113*1339678fSYevgeny Kliteynik }
114*1339678fSYevgeny Kliteynik 
mlx5dr_definer_get(struct mlx5dr_domain * dmn,u16 format_id,u8 * dw_selectors,u8 * byte_selectors,u8 * match_mask,u32 * definer_id)115*1339678fSYevgeny Kliteynik int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
116*1339678fSYevgeny Kliteynik 		       u8 *dw_selectors, u8 *byte_selectors,
117*1339678fSYevgeny Kliteynik 		       u8 *match_mask, u32 *definer_id)
118*1339678fSYevgeny Kliteynik {
119*1339678fSYevgeny Kliteynik 	struct dr_definer_object *definer_obj;
120*1339678fSYevgeny Kliteynik 	int ret = 0;
121*1339678fSYevgeny Kliteynik 
122*1339678fSYevgeny Kliteynik 	definer_obj = dr_definer_find_obj(dmn, format_id, dw_selectors,
123*1339678fSYevgeny Kliteynik 					  byte_selectors, match_mask);
124*1339678fSYevgeny Kliteynik 	if (!definer_obj) {
125*1339678fSYevgeny Kliteynik 		definer_obj = dr_definer_create_obj(dmn, format_id,
126*1339678fSYevgeny Kliteynik 						    dw_selectors, byte_selectors,
127*1339678fSYevgeny Kliteynik 						    match_mask);
128*1339678fSYevgeny Kliteynik 		if (!definer_obj)
129*1339678fSYevgeny Kliteynik 			return -ENOMEM;
130*1339678fSYevgeny Kliteynik 	} else {
131*1339678fSYevgeny Kliteynik 		refcount_inc(&definer_obj->refcount);
132*1339678fSYevgeny Kliteynik 	}
133*1339678fSYevgeny Kliteynik 
134*1339678fSYevgeny Kliteynik 	*definer_id = definer_obj->id;
135*1339678fSYevgeny Kliteynik 
136*1339678fSYevgeny Kliteynik 	return ret;
137*1339678fSYevgeny Kliteynik }
138*1339678fSYevgeny Kliteynik 
mlx5dr_definer_put(struct mlx5dr_domain * dmn,u32 definer_id)139*1339678fSYevgeny Kliteynik void mlx5dr_definer_put(struct mlx5dr_domain *dmn, u32 definer_id)
140*1339678fSYevgeny Kliteynik {
141*1339678fSYevgeny Kliteynik 	struct dr_definer_object *definer_obj;
142*1339678fSYevgeny Kliteynik 
143*1339678fSYevgeny Kliteynik 	definer_obj = xa_load(&dmn->definers_xa, definer_id);
144*1339678fSYevgeny Kliteynik 	if (!definer_obj) {
145*1339678fSYevgeny Kliteynik 		mlx5dr_err(dmn, "Definer ID %d not found\n", definer_id);
146*1339678fSYevgeny Kliteynik 		return;
147*1339678fSYevgeny Kliteynik 	}
148*1339678fSYevgeny Kliteynik 
149*1339678fSYevgeny Kliteynik 	if (refcount_dec_and_test(&definer_obj->refcount))
150*1339678fSYevgeny Kliteynik 		dr_definer_destroy_obj(dmn, definer_obj);
151*1339678fSYevgeny Kliteynik }
152