Skip to content

Commit 3fc44ca

Browse files
kliteynkuba-moo
authored andcommitted
net/mlx5: HWS, update flow - support through bigger action RTC
This patch is the second part of update flow implementation. Instead of using two action RTCs, we use the same RTC which is twice the size of what was required before the update flow support. This way we always allocate STEs from the same RTC (same pool), which means that update is done similar to how create is done. The bigger size allows us to allocate and write new STEs, and later free the old (pre-update) STEs. Similar to rule creation, STEs are written in reverse order: - write action STEs, while match STE is still pointing to the old action STEs - overwrite the match STE with the new one, which now is pointing to the new action STEs Old action STEs can be freed only once we got completion on the writing of the new match STE. To implement this we added new rule states: UPDATING/UPDATED. Rule is moved to UPDATING state in the beginning of the update flow. Once all completions are received, rule is moved to UPDATED state. At this point old action STEs are freed and rule goes back to CREATED state. Signed-off-by: Yevgeny Kliteynik <[email protected]> Signed-off-by: Vlad Dogaru <[email protected]> Reviewed-by: Mark Bloch <[email protected]> Signed-off-by: Tariq Toukan <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ab6912f commit 3fc44ca

File tree

4 files changed

+80
-53
lines changed

4 files changed

+80
-53
lines changed

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,13 @@ static int hws_matcher_create_rtc(struct mlx5hws_matcher *matcher,
283283
rtc_1_id = &action_ste->rtc_1_id;
284284
ste_pool = action_ste->pool;
285285
ste = &action_ste->ste;
286+
/* Action RTC size calculation:
287+
* log((max number of rules in matcher) *
288+
* (max number of action STEs per rule) *
289+
* (2 to support writing new STEs for update rule))
290+
*/
286291
ste->order = ilog2(roundup_pow_of_two(action_ste->max_stes)) +
287-
attr->table.sz_row_log;
292+
attr->table.sz_row_log + 1;
288293
rtc_attr.log_size = ste->order;
289294
rtc_attr.log_depth = 0;
290295
rtc_attr.update_index_mode = MLX5_IFC_RTC_STE_UPDATE_MODE_BY_OFFSET;
@@ -554,8 +559,9 @@ static int hws_matcher_bind_at(struct mlx5hws_matcher *matcher)
554559
pool_attr.table_type = tbl->type;
555560
pool_attr.pool_type = MLX5HWS_POOL_TYPE_STE;
556561
pool_attr.flags = MLX5HWS_POOL_FLAGS_FOR_STE_ACTION_POOL;
562+
/* Pool size is similar to action RTC size */
557563
pool_attr.alloc_log_sz = ilog2(roundup_pow_of_two(action_ste->max_stes)) +
558-
matcher->attr.table.sz_row_log;
564+
matcher->attr.table.sz_row_log + 1;
559565
hws_matcher_set_pool_attr(&pool_attr, matcher);
560566
action_ste->pool = mlx5hws_pool_create(ctx, &pool_attr);
561567
if (!action_ste->pool) {

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -129,22 +129,18 @@ static void hws_rule_gen_comp(struct mlx5hws_send_engine *queue,
129129

130130
static void
131131
hws_rule_save_resize_info(struct mlx5hws_rule *rule,
132-
struct mlx5hws_send_ste_attr *ste_attr,
133-
bool is_update)
132+
struct mlx5hws_send_ste_attr *ste_attr)
134133
{
135134
if (!mlx5hws_matcher_is_resizable(rule->matcher))
136135
return;
137136

138-
if (likely(!is_update)) {
137+
/* resize_info might already exist (if we're in update flow) */
138+
if (likely(!rule->resize_info)) {
139139
rule->resize_info = kzalloc(sizeof(*rule->resize_info), GFP_KERNEL);
140140
if (unlikely(!rule->resize_info)) {
141141
pr_warn("HWS: resize info isn't allocated for rule\n");
142142
return;
143143
}
144-
145-
rule->resize_info->max_stes = rule->matcher->action_ste.max_stes;
146-
rule->resize_info->action_ste_pool = rule->matcher->action_ste.max_stes ?
147-
rule->matcher->action_ste.pool : NULL;
148144
}
149145

150146
memcpy(rule->resize_info->ctrl_seg, ste_attr->wqe_ctrl,
@@ -199,8 +195,7 @@ hws_rule_load_delete_info(struct mlx5hws_rule *rule,
199195
}
200196
}
201197

202-
static int hws_rule_alloc_action_ste(struct mlx5hws_rule *rule,
203-
struct mlx5hws_rule_attr *attr)
198+
static int hws_rule_alloc_action_ste(struct mlx5hws_rule *rule)
204199
{
205200
struct mlx5hws_matcher *matcher = rule->matcher;
206201
struct mlx5hws_matcher_action_ste *action_ste;
@@ -215,32 +210,29 @@ static int hws_rule_alloc_action_ste(struct mlx5hws_rule *rule,
215210
"Failed to allocate STE for rule actions");
216211
return ret;
217212
}
218-
rule->action_ste_idx = ste.offset;
213+
214+
rule->action_ste.pool = matcher->action_ste.pool;
215+
rule->action_ste.num_stes = matcher->action_ste.max_stes;
216+
rule->action_ste.index = ste.offset;
219217

220218
return 0;
221219
}
222220

223-
void mlx5hws_rule_free_action_ste(struct mlx5hws_rule *rule)
221+
void mlx5hws_rule_free_action_ste(struct mlx5hws_rule_action_ste_info *action_ste)
224222
{
225-
struct mlx5hws_matcher *matcher = rule->matcher;
226223
struct mlx5hws_pool_chunk ste = {0};
227-
struct mlx5hws_pool *pool;
228-
u8 max_stes;
229224

230-
if (mlx5hws_matcher_is_resizable(matcher)) {
231-
/* Free the original action pool if rule was resized */
232-
max_stes = rule->resize_info->max_stes;
233-
pool = rule->resize_info->action_ste_pool;
234-
} else {
235-
max_stes = matcher->action_ste.max_stes;
236-
pool = matcher->action_ste.pool;
237-
}
225+
if (!action_ste->num_stes)
226+
return;
238227

239-
/* This release is safe only when the rule match part was deleted */
240-
ste.order = ilog2(roundup_pow_of_two(max_stes));
241-
ste.offset = rule->action_ste_idx;
228+
ste.order = ilog2(roundup_pow_of_two(action_ste->num_stes));
229+
ste.offset = action_ste->index;
242230

243-
mlx5hws_pool_chunk_free(pool, &ste);
231+
/* This release is safe only when the rule match STE was deleted
232+
* (when the rule is being deleted) or replaced with the new STE that
233+
* isn't pointing to old action STEs (when the rule is being updated).
234+
*/
235+
mlx5hws_pool_chunk_free(action_ste->pool, &ste);
244236
}
245237

246238
static void hws_rule_create_init(struct mlx5hws_rule *rule,
@@ -257,11 +249,24 @@ static void hws_rule_create_init(struct mlx5hws_rule *rule,
257249
/* In update we use these rtc's */
258250
rule->rtc_0 = 0;
259251
rule->rtc_1 = 0;
252+
253+
rule->action_ste.pool = NULL;
254+
rule->action_ste.num_stes = 0;
255+
rule->action_ste.index = -1;
256+
257+
rule->status = MLX5HWS_RULE_STATUS_CREATING;
258+
} else {
259+
rule->status = MLX5HWS_RULE_STATUS_UPDATING;
260260
}
261261

262+
/* Initialize the old action STE info - shallow-copy action_ste.
263+
* In create flow this will set old_action_ste fields to initial values.
264+
* In update flow this will save the existing action STE info,
265+
* so that we will later use it to free old STEs.
266+
*/
267+
rule->old_action_ste = rule->action_ste;
268+
262269
rule->pending_wqes = 0;
263-
rule->action_ste_idx = -1;
264-
rule->status = MLX5HWS_RULE_STATUS_CREATING;
265270

266271
/* Init default send STE attributes */
267272
ste_attr->gta_opcode = MLX5HWS_WQE_GTA_OP_ACTIVATE;
@@ -288,7 +293,6 @@ static void hws_rule_move_init(struct mlx5hws_rule *rule,
288293
rule->rtc_1 = 0;
289294

290295
rule->pending_wqes = 0;
291-
rule->action_ste_idx = -1;
292296
rule->status = MLX5HWS_RULE_STATUS_CREATING;
293297
rule->resize_info->state = MLX5HWS_RULE_RESIZE_STATE_WRITING;
294298
}
@@ -349,19 +353,17 @@ static int hws_rule_create_hws(struct mlx5hws_rule *rule,
349353

350354
if (action_stes) {
351355
/* Allocate action STEs for rules that need more than match STE */
352-
if (!is_update) {
353-
ret = hws_rule_alloc_action_ste(rule, attr);
354-
if (ret) {
355-
mlx5hws_err(ctx, "Failed to allocate action memory %d", ret);
356-
mlx5hws_send_abort_new_dep_wqe(queue);
357-
return ret;
358-
}
356+
ret = hws_rule_alloc_action_ste(rule);
357+
if (ret) {
358+
mlx5hws_err(ctx, "Failed to allocate action memory %d", ret);
359+
mlx5hws_send_abort_new_dep_wqe(queue);
360+
return ret;
359361
}
360362
/* Skip RX/TX based on the dep_wqe init */
361363
ste_attr.rtc_0 = dep_wqe->rtc_0 ? matcher->action_ste.rtc_0_id : 0;
362364
ste_attr.rtc_1 = dep_wqe->rtc_1 ? matcher->action_ste.rtc_1_id : 0;
363365
/* Action STEs are written to a specific index last to first */
364-
ste_attr.direct_index = rule->action_ste_idx + action_stes;
366+
ste_attr.direct_index = rule->action_ste.index + action_stes;
365367
apply.next_direct_idx = ste_attr.direct_index;
366368
} else {
367369
apply.next_direct_idx = 0;
@@ -412,7 +414,7 @@ static int hws_rule_create_hws(struct mlx5hws_rule *rule,
412414
if (!is_update)
413415
hws_rule_save_delete_info(rule, &ste_attr);
414416

415-
hws_rule_save_resize_info(rule, &ste_attr, is_update);
417+
hws_rule_save_resize_info(rule, &ste_attr);
416418
mlx5hws_send_engine_inc_rule(queue);
417419

418420
if (!attr->burst)
@@ -433,7 +435,10 @@ static void hws_rule_destroy_failed_hws(struct mlx5hws_rule *rule,
433435
attr->user_data, MLX5HWS_RULE_STATUS_DELETED);
434436

435437
/* Rule failed now we can safely release action STEs */
436-
mlx5hws_rule_free_action_ste(rule);
438+
mlx5hws_rule_free_action_ste(&rule->action_ste);
439+
440+
/* Perhaps the rule failed updating - release old action STEs as well */
441+
mlx5hws_rule_free_action_ste(&rule->old_action_ste);
437442

438443
/* Clear complex tag */
439444
hws_rule_clear_delete_info(rule);
@@ -470,7 +475,8 @@ static int hws_rule_destroy_hws(struct mlx5hws_rule *rule,
470475
}
471476

472477
/* Rule is not completed yet */
473-
if (rule->status == MLX5HWS_RULE_STATUS_CREATING)
478+
if (rule->status == MLX5HWS_RULE_STATUS_CREATING ||
479+
rule->status == MLX5HWS_RULE_STATUS_UPDATING)
474480
return -EBUSY;
475481

476482
/* Rule failed and doesn't require cleanup */
@@ -487,7 +493,7 @@ static int hws_rule_destroy_hws(struct mlx5hws_rule *rule,
487493
hws_rule_gen_comp(queue, rule, false,
488494
attr->user_data, MLX5HWS_RULE_STATUS_DELETED);
489495

490-
mlx5hws_rule_free_action_ste(rule);
496+
mlx5hws_rule_free_action_ste(&rule->action_ste);
491497
mlx5hws_rule_clear_resize_info(rule);
492498
return 0;
493499
}

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ enum mlx5hws_rule_status {
1515
MLX5HWS_RULE_STATUS_UNKNOWN,
1616
MLX5HWS_RULE_STATUS_CREATING,
1717
MLX5HWS_RULE_STATUS_CREATED,
18+
MLX5HWS_RULE_STATUS_UPDATING,
19+
MLX5HWS_RULE_STATUS_UPDATED,
1820
MLX5HWS_RULE_STATUS_DELETING,
1921
MLX5HWS_RULE_STATUS_DELETED,
2022
MLX5HWS_RULE_STATUS_FAILING,
@@ -41,13 +43,17 @@ struct mlx5hws_rule_match_tag {
4143
};
4244
};
4345

46+
struct mlx5hws_rule_action_ste_info {
47+
struct mlx5hws_pool *pool;
48+
int index; /* STE array index */
49+
u8 num_stes;
50+
};
51+
4452
struct mlx5hws_rule_resize_info {
45-
struct mlx5hws_pool *action_ste_pool;
4653
u32 rtc_0;
4754
u32 rtc_1;
4855
u32 rule_idx;
4956
u8 state;
50-
u8 max_stes;
5157
u8 ctrl_seg[MLX5HWS_WQE_SZ_GTA_CTRL]; /* Ctrl segment of STE: 48 bytes */
5258
u8 data_seg[MLX5HWS_WQE_SZ_GTA_DATA]; /* Data segment of STE: 64 bytes */
5359
};
@@ -58,17 +64,18 @@ struct mlx5hws_rule {
5864
struct mlx5hws_rule_match_tag tag;
5965
struct mlx5hws_rule_resize_info *resize_info;
6066
};
67+
struct mlx5hws_rule_action_ste_info action_ste;
68+
struct mlx5hws_rule_action_ste_info old_action_ste;
6169
u32 rtc_0; /* The RTC into which the STE was inserted */
6270
u32 rtc_1; /* The RTC into which the STE was inserted */
63-
int action_ste_idx; /* STE array index */
6471
u8 status; /* enum mlx5hws_rule_status */
6572
u8 pending_wqes;
6673
bool skip_delete; /* For complex rules - another rule with same tag
6774
* still exists, so don't actually delete this rule.
6875
*/
6976
};
7077

71-
void mlx5hws_rule_free_action_ste(struct mlx5hws_rule *rule);
78+
void mlx5hws_rule_free_action_ste(struct mlx5hws_rule_action_ste_info *action_ste);
7279

7380
int mlx5hws_rule_move_hws_remove(struct mlx5hws_rule *rule,
7481
void *queue, void *user_data);

drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,17 +377,25 @@ static void hws_send_engine_update_rule(struct mlx5hws_send_engine *queue,
377377

378378
*status = MLX5HWS_FLOW_OP_ERROR;
379379
} else {
380-
/* Increase the status, this only works on good flow as the enum
381-
* is arrange it away creating -> created -> deleting -> deleted
380+
/* Increase the status, this only works on good flow as
381+
* the enum is arranged this way:
382+
* - creating -> created
383+
* - updating -> updated
384+
* - deleting -> deleted
382385
*/
383386
priv->rule->status++;
384387
*status = MLX5HWS_FLOW_OP_SUCCESS;
385-
/* Rule was deleted now we can safely release action STEs
386-
* and clear resize info
387-
*/
388388
if (priv->rule->status == MLX5HWS_RULE_STATUS_DELETED) {
389-
mlx5hws_rule_free_action_ste(priv->rule);
389+
/* Rule was deleted, now we can safely release
390+
* action STEs and clear resize info
391+
*/
392+
mlx5hws_rule_free_action_ste(&priv->rule->action_ste);
390393
mlx5hws_rule_clear_resize_info(priv->rule);
394+
} else if (priv->rule->status == MLX5HWS_RULE_STATUS_UPDATED) {
395+
/* Rule was updated, free the old action STEs */
396+
mlx5hws_rule_free_action_ste(&priv->rule->old_action_ste);
397+
/* Update completed - move the rule back to "created" */
398+
priv->rule->status = MLX5HWS_RULE_STATUS_CREATED;
391399
}
392400
}
393401
}

0 commit comments

Comments
 (0)