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