net/mlx5e: Protect global IPsec ASO
[linux-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_accel / ipsec_offload.c
CommitLineData
5ec4f0ce 1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
7e4e8491 2/* Copyright (c) 2017, Mellanox Technologies inc. All rights reserved. */
2d64663c
RS
3
4#include "mlx5_core.h"
8518d05b 5#include "en.h"
c6e3b421 6#include "ipsec.h"
2d64663c
RS
7#include "lib/mlx5.h"
8
cee137a6
LR
9enum {
10 MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET,
11};
12
2451da08 13u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
2d64663c 14{
effbe267 15 u32 caps = 0;
2451da08
LR
16
17 if (!MLX5_CAP_GEN(mdev, ipsec_offload))
18 return 0;
19
20 if (!MLX5_CAP_GEN(mdev, log_max_dek))
21 return 0;
22
23 if (!(MLX5_CAP_GEN_64(mdev, general_obj_types) &
24 MLX5_HCA_CAP_GENERAL_OBJECT_TYPES_IPSEC))
25 return 0;
2d64663c 26
5e466345
HN
27 if (!MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ipsec_encrypt) ||
28 !MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ipsec_decrypt))
29 return 0;
30
effbe267
LR
31 if (!MLX5_CAP_IPSEC(mdev, ipsec_crypto_esp_aes_gcm_128_encrypt) ||
32 !MLX5_CAP_IPSEC(mdev, ipsec_crypto_esp_aes_gcm_128_decrypt))
33 return 0;
2451da08 34
effbe267
LR
35 if (MLX5_CAP_IPSEC(mdev, ipsec_crypto_offload) &&
36 MLX5_CAP_ETH(mdev, insert_trailer) && MLX5_CAP_ETH(mdev, swp))
37 caps |= MLX5_IPSEC_CAP_CRYPTO;
38
59592cfd
LR
39 if (MLX5_CAP_IPSEC(mdev, ipsec_full_offload) &&
40 MLX5_CAP_FLOWTABLE_NIC_TX(mdev, reformat_add_esp_trasport) &&
41 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_del_esp_trasport) &&
42 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap))
43 caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD;
44
effbe267
LR
45 if (!caps)
46 return 0;
2d64663c 47
2984287c 48 if (MLX5_CAP_IPSEC(mdev, ipsec_esn))
effbe267 49 caps |= MLX5_IPSEC_CAP_ESN;
2d64663c
RS
50
51 /* We can accommodate up to 2^24 different IPsec objects
52 * because we use up to 24 bit in flow table metadata
53 * to hold the IPsec Object unique handle.
54 */
55 WARN_ON_ONCE(MLX5_CAP_IPSEC(mdev, log_max_ipsec_offload) > 24);
56 return caps;
57}
2451da08 58EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps);
2d64663c 59
8d15f364
LR
60static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
61 struct mlx5_accel_esp_xfrm_attrs *attrs)
62{
63 void *aso_ctx;
64
65 aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso);
66 if (attrs->esn_trigger) {
67 MLX5_SET(ipsec_aso, aso_ctx, esn_event_arm, 1);
68
69 if (attrs->dir == XFRM_DEV_OFFLOAD_IN) {
70 MLX5_SET(ipsec_aso, aso_ctx, window_sz,
71 attrs->replay_window / 64);
72 MLX5_SET(ipsec_aso, aso_ctx, mode,
73 MLX5_IPSEC_ASO_REPLAY_PROTECTION);
74 }
75 }
76
77 /* ASO context */
78 MLX5_SET(ipsec_obj, obj, ipsec_aso_access_pd, pdn);
79 MLX5_SET(ipsec_obj, obj, full_offload, 1);
80 MLX5_SET(ipsec_aso, aso_ctx, valid, 1);
81 /* MLX5_IPSEC_ASO_REG_C_4_5 is type C register that is used
82 * in flow steering to perform matching against. Please be
83 * aware that this register was chosen arbitrary and can't
84 * be used in other places as long as IPsec packet offload
85 * active.
86 */
87 MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5);
88 if (attrs->dir == XFRM_DEV_OFFLOAD_OUT)
89 MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN);
1ed78fc0
LR
90
91 if (attrs->hard_packet_limit != XFRM_INF) {
92 MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt,
93 lower_32_bits(attrs->hard_packet_limit));
94 MLX5_SET(ipsec_aso, aso_ctx, hard_lft_arm, 1);
95 MLX5_SET(ipsec_aso, aso_ctx, remove_flow_enable, 1);
96 }
97
98 if (attrs->soft_packet_limit != XFRM_INF) {
99 MLX5_SET(ipsec_aso, aso_ctx, remove_flow_soft_lft,
100 lower_32_bits(attrs->soft_packet_limit));
101
102 MLX5_SET(ipsec_aso, aso_ctx, soft_lft_arm, 1);
103 }
8d15f364
LR
104}
105
b73e6728 106static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
2d64663c 107{
b73e6728
LR
108 struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs;
109 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
6cd2126a 110 struct aes_gcm_keymat *aes_gcm = &attrs->aes_gcm;
2d64663c
RS
111 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
112 u32 in[MLX5_ST_SZ_DW(create_ipsec_obj_in)] = {};
113 void *obj, *salt_p, *salt_iv_p;
8d15f364 114 struct mlx5e_hw_objs *res;
2d64663c
RS
115 int err;
116
117 obj = MLX5_ADDR_OF(create_ipsec_obj_in, in, ipsec_object);
118
119 /* salt and seq_iv */
120 salt_p = MLX5_ADDR_OF(ipsec_obj, obj, salt);
121 memcpy(salt_p, &aes_gcm->salt, sizeof(aes_gcm->salt));
122
1c4a59b9 123 MLX5_SET(ipsec_obj, obj, icv_length, MLX5_IPSEC_OBJECT_ICV_LEN_16B);
2d64663c
RS
124 salt_iv_p = MLX5_ADDR_OF(ipsec_obj, obj, implicit_iv);
125 memcpy(salt_iv_p, &aes_gcm->seq_iv, sizeof(aes_gcm->seq_iv));
126 /* esn */
e3840530 127 if (attrs->esn_trigger) {
2d64663c 128 MLX5_SET(ipsec_obj, obj, esn_en, 1);
b73e6728 129 MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
e3840530 130 MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
2d64663c
RS
131 }
132
b73e6728 133 MLX5_SET(ipsec_obj, obj, dekn, sa_entry->enc_key_id);
2d64663c
RS
134
135 /* general object fields set */
136 MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
137 MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
138 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
139 MLX5_GENERAL_OBJECT_TYPES_IPSEC);
140
8d15f364
LR
141 res = &mdev->mlx5e_res.hw_objs;
142 if (attrs->type == XFRM_DEV_OFFLOAD_PACKET)
143 mlx5e_ipsec_packet_setup(obj, res->pdn, attrs);
144
2d64663c
RS
145 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
146 if (!err)
b73e6728
LR
147 sa_entry->ipsec_obj_id =
148 MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
2d64663c
RS
149
150 return err;
151}
152
b73e6728 153static void mlx5_destroy_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
2d64663c 154{
b73e6728 155 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
2d64663c
RS
156 u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
157 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
158
159 MLX5_SET(general_obj_in_cmd_hdr, in, opcode,
160 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
161 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type,
162 MLX5_GENERAL_OBJECT_TYPES_IPSEC);
b73e6728 163 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, sa_entry->ipsec_obj_id);
2d64663c
RS
164
165 mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
166}
167
b73e6728 168int mlx5_ipsec_create_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry)
2d64663c 169{
6cd2126a 170 struct aes_gcm_keymat *aes_gcm = &sa_entry->attrs.aes_gcm;
b73e6728 171 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
2d64663c
RS
172 int err;
173
2d64663c
RS
174 /* key */
175 err = mlx5_create_encryption_key(mdev, aes_gcm->aes_key,
176 aes_gcm->key_len / BITS_PER_BYTE,
177 MLX5_ACCEL_OBJ_IPSEC_KEY,
b73e6728 178 &sa_entry->enc_key_id);
2d64663c
RS
179 if (err) {
180 mlx5_core_dbg(mdev, "Failed to create encryption key (err = %d)\n", err);
b73e6728 181 return err;
2d64663c
RS
182 }
183
b73e6728 184 err = mlx5_create_ipsec_obj(sa_entry);
2d64663c
RS
185 if (err) {
186 mlx5_core_dbg(mdev, "Failed to create IPsec object (err = %d)\n", err);
187 goto err_enc_key;
188 }
189
b73e6728 190 return 0;
2d64663c
RS
191
192err_enc_key:
b73e6728
LR
193 mlx5_destroy_encryption_key(mdev, sa_entry->enc_key_id);
194 return err;
2d64663c
RS
195}
196
b73e6728 197void mlx5_ipsec_free_sa_ctx(struct mlx5e_ipsec_sa_entry *sa_entry)
2d64663c 198{
b73e6728 199 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
2d64663c 200
b73e6728
LR
201 mlx5_destroy_ipsec_obj(sa_entry);
202 mlx5_destroy_encryption_key(mdev, sa_entry->enc_key_id);
2d64663c
RS
203}
204
b73e6728
LR
205static int mlx5_modify_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry,
206 const struct mlx5_accel_esp_xfrm_attrs *attrs)
7ed92f97 207{
b73e6728 208 struct mlx5_core_dev *mdev = mlx5e_ipsec_sa2dev(sa_entry);
7ed92f97
RS
209 u32 in[MLX5_ST_SZ_DW(modify_ipsec_obj_in)] = {};
210 u32 out[MLX5_ST_SZ_DW(query_ipsec_obj_out)];
211 u64 modify_field_select = 0;
212 u64 general_obj_types;
213 void *obj;
214 int err;
215
e3840530 216 if (!attrs->esn_trigger)
7ed92f97
RS
217 return 0;
218
219 general_obj_types = MLX5_CAP_GEN_64(mdev, general_obj_types);
220 if (!(general_obj_types & MLX5_HCA_CAP_GENERAL_OBJECT_TYPES_IPSEC))
221 return -EINVAL;
222
223 /* general object fields set */
224 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
225 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_IPSEC);
b73e6728 226 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, sa_entry->ipsec_obj_id);
7ed92f97
RS
227 err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
228 if (err) {
229 mlx5_core_err(mdev, "Query IPsec object failed (Object id %d), err = %d\n",
b73e6728 230 sa_entry->ipsec_obj_id, err);
7ed92f97
RS
231 return err;
232 }
233
234 obj = MLX5_ADDR_OF(query_ipsec_obj_out, out, ipsec_object);
235 modify_field_select = MLX5_GET64(ipsec_obj, obj, modify_field_select);
236
237 /* esn */
238 if (!(modify_field_select & MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP) ||
239 !(modify_field_select & MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB))
240 return -EOPNOTSUPP;
241
242 obj = MLX5_ADDR_OF(modify_ipsec_obj_in, in, ipsec_object);
656d3389
LR
243 MLX5_SET64(ipsec_obj, obj, modify_field_select,
244 MLX5_MODIFY_IPSEC_BITMASK_ESN_OVERLAP |
245 MLX5_MODIFY_IPSEC_BITMASK_ESN_MSB);
b73e6728 246 MLX5_SET(ipsec_obj, obj, esn_msb, attrs->esn);
e3840530 247 MLX5_SET(ipsec_obj, obj, esn_overlap, attrs->esn_overlap);
7ed92f97
RS
248
249 /* general object fields set */
250 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
251
252 return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
253}
254
b73e6728 255void mlx5_accel_esp_modify_xfrm(struct mlx5e_ipsec_sa_entry *sa_entry,
a534e24d 256 const struct mlx5_accel_esp_xfrm_attrs *attrs)
7ed92f97 257{
a534e24d 258 int err;
7ed92f97 259
b73e6728 260 err = mlx5_modify_ipsec_obj(sa_entry, attrs);
a534e24d
LR
261 if (err)
262 return;
263
b73e6728 264 memcpy(&sa_entry->attrs, attrs, sizeof(sa_entry->attrs));
7e4e8491 265}
8518d05b 266
cee137a6
LR
267static void
268mlx5e_ipsec_aso_update_esn(struct mlx5e_ipsec_sa_entry *sa_entry,
269 const struct mlx5_accel_esp_xfrm_attrs *attrs)
270{
271 struct mlx5_wqe_aso_ctrl_seg data = {};
272
273 data.data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BITWISE_64BIT << 6;
274 data.condition_1_0_operand = MLX5_ASO_ALWAYS_TRUE | MLX5_ASO_ALWAYS_TRUE
275 << 4;
276 data.data_offset_condition_operand = MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET;
277 data.bitwise_data = cpu_to_be64(BIT_ULL(54));
278 data.data_mask = data.bitwise_data;
279
280 mlx5e_ipsec_aso_query(sa_entry, &data);
281}
282
283static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry,
284 u32 mode_param)
285{
286 struct mlx5_accel_esp_xfrm_attrs attrs = {};
287
288 if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) {
289 sa_entry->esn_state.esn++;
290 sa_entry->esn_state.overlap = 0;
291 } else {
292 sa_entry->esn_state.overlap = 1;
293 }
294
295 mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs);
296 mlx5_accel_esp_modify_xfrm(sa_entry, &attrs);
297 mlx5e_ipsec_aso_update_esn(sa_entry, &attrs);
298}
299
8c582ddf
LR
300static void mlx5e_ipsec_handle_event(struct work_struct *_work)
301{
302 struct mlx5e_ipsec_work *work =
303 container_of(_work, struct mlx5e_ipsec_work, work);
304 struct mlx5_accel_esp_xfrm_attrs *attrs;
305 struct mlx5e_ipsec_sa_entry *sa_entry;
306 struct mlx5e_ipsec_aso *aso;
307 struct mlx5e_ipsec *ipsec;
308 int ret;
309
310 sa_entry = xa_load(&work->ipsec->sadb, work->id);
311 if (!sa_entry)
312 goto out;
313
314 ipsec = sa_entry->ipsec;
315 aso = ipsec->aso;
316 attrs = &sa_entry->attrs;
317
318 spin_lock(&sa_entry->x->lock);
319 ret = mlx5e_ipsec_aso_query(sa_entry, NULL);
320 if (ret)
321 goto unlock;
322
cee137a6
LR
323 if (attrs->esn_trigger &&
324 !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) {
325 u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter);
326
327 mlx5e_ipsec_update_esn_state(sa_entry, mode_param);
328 }
329
8c582ddf
LR
330 if (attrs->soft_packet_limit != XFRM_INF)
331 if (!MLX5_GET(ipsec_aso, aso->ctx, soft_lft_arm) ||
332 !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm) ||
333 !MLX5_GET(ipsec_aso, aso->ctx, remove_flow_enable))
334 xfrm_state_check_expire(sa_entry->x);
8c582ddf
LR
335
336unlock:
337 spin_unlock(&sa_entry->x->lock);
338out:
339 kfree(work);
340}
341
342static int mlx5e_ipsec_event(struct notifier_block *nb, unsigned long event,
343 void *data)
344{
345 struct mlx5e_ipsec *ipsec = container_of(nb, struct mlx5e_ipsec, nb);
346 struct mlx5_eqe_obj_change *object;
347 struct mlx5e_ipsec_work *work;
348 struct mlx5_eqe *eqe = data;
349 u16 type;
350
351 if (event != MLX5_EVENT_TYPE_OBJECT_CHANGE)
352 return NOTIFY_DONE;
353
354 object = &eqe->data.obj_change;
355 type = be16_to_cpu(object->obj_type);
356
357 if (type != MLX5_GENERAL_OBJECT_TYPES_IPSEC)
358 return NOTIFY_DONE;
359
360 work = kmalloc(sizeof(*work), GFP_ATOMIC);
361 if (!work)
362 return NOTIFY_DONE;
363
364 INIT_WORK(&work->work, mlx5e_ipsec_handle_event);
365 work->ipsec = ipsec;
366 work->id = be32_to_cpu(object->obj_id);
367
368 queue_work(ipsec->wq, &work->work);
369 return NOTIFY_OK;
370}
371
8518d05b
LR
372int mlx5e_ipsec_aso_init(struct mlx5e_ipsec *ipsec)
373{
374 struct mlx5_core_dev *mdev = ipsec->mdev;
375 struct mlx5e_ipsec_aso *aso;
376 struct mlx5e_hw_objs *res;
377 struct device *pdev;
378 int err;
379
380 aso = kzalloc(sizeof(*ipsec->aso), GFP_KERNEL);
381 if (!aso)
382 return -ENOMEM;
383
384 res = &mdev->mlx5e_res.hw_objs;
385
386 pdev = mlx5_core_dma_dev(mdev);
387 aso->dma_addr = dma_map_single(pdev, aso->ctx, sizeof(aso->ctx),
388 DMA_BIDIRECTIONAL);
389 err = dma_mapping_error(pdev, aso->dma_addr);
390 if (err)
391 goto err_dma;
392
393 aso->aso = mlx5_aso_create(mdev, res->pdn);
394 if (IS_ERR(aso->aso)) {
395 err = PTR_ERR(aso->aso);
396 goto err_aso_create;
397 }
398
e4d38c45 399 spin_lock_init(&aso->lock);
8c582ddf
LR
400 ipsec->nb.notifier_call = mlx5e_ipsec_event;
401 mlx5_notifier_register(mdev, &ipsec->nb);
402
8518d05b
LR
403 ipsec->aso = aso;
404 return 0;
405
406err_aso_create:
407 dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx),
408 DMA_BIDIRECTIONAL);
409err_dma:
410 kfree(aso);
411 return err;
412}
413
414void mlx5e_ipsec_aso_cleanup(struct mlx5e_ipsec *ipsec)
415{
416 struct mlx5_core_dev *mdev = ipsec->mdev;
417 struct mlx5e_ipsec_aso *aso;
418 struct device *pdev;
419
420 aso = ipsec->aso;
421 pdev = mlx5_core_dma_dev(mdev);
422
8c582ddf 423 mlx5_notifier_unregister(mdev, &ipsec->nb);
8518d05b
LR
424 mlx5_aso_destroy(aso->aso);
425 dma_unmap_single(pdev, aso->dma_addr, sizeof(aso->ctx),
426 DMA_BIDIRECTIONAL);
427 kfree(aso);
428}
1ed78fc0 429
8c582ddf
LR
430static void mlx5e_ipsec_aso_copy(struct mlx5_wqe_aso_ctrl_seg *ctrl,
431 struct mlx5_wqe_aso_ctrl_seg *data)
432{
433 if (!data)
434 return;
435
436 ctrl->data_mask_mode = data->data_mask_mode;
437 ctrl->condition_1_0_operand = data->condition_1_0_operand;
438 ctrl->condition_1_0_offset = data->condition_1_0_offset;
439 ctrl->data_offset_condition_operand = data->data_offset_condition_operand;
440 ctrl->condition_0_data = data->condition_0_data;
441 ctrl->condition_0_mask = data->condition_0_mask;
442 ctrl->condition_1_data = data->condition_1_data;
443 ctrl->condition_1_mask = data->condition_1_mask;
444 ctrl->bitwise_data = data->bitwise_data;
445 ctrl->data_mask = data->data_mask;
446}
447
448int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry,
449 struct mlx5_wqe_aso_ctrl_seg *data)
1ed78fc0
LR
450{
451 struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
452 struct mlx5e_ipsec_aso *aso = ipsec->aso;
453 struct mlx5_core_dev *mdev = ipsec->mdev;
454 struct mlx5_wqe_aso_ctrl_seg *ctrl;
455 struct mlx5e_hw_objs *res;
456 struct mlx5_aso_wqe *wqe;
457 u8 ds_cnt;
e4d38c45 458 int ret;
1ed78fc0 459
8c582ddf 460 lockdep_assert_held(&sa_entry->x->lock);
1ed78fc0
LR
461 res = &mdev->mlx5e_res.hw_objs;
462
e4d38c45 463 spin_lock_bh(&aso->lock);
1ed78fc0
LR
464 memset(aso->ctx, 0, sizeof(aso->ctx));
465 wqe = mlx5_aso_get_wqe(aso->aso);
466 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS);
467 mlx5_aso_build_wqe(aso->aso, ds_cnt, wqe, sa_entry->ipsec_obj_id,
468 MLX5_ACCESS_ASO_OPC_MOD_IPSEC);
469
470 ctrl = &wqe->aso_ctrl;
471 ctrl->va_l =
472 cpu_to_be32(lower_32_bits(aso->dma_addr) | ASO_CTRL_READ_EN);
473 ctrl->va_h = cpu_to_be32(upper_32_bits(aso->dma_addr));
474 ctrl->l_key = cpu_to_be32(res->mkey);
8c582ddf 475 mlx5e_ipsec_aso_copy(ctrl, data);
1ed78fc0
LR
476
477 mlx5_aso_post_wqe(aso->aso, false, &wqe->ctrl);
e4d38c45
LR
478 ret = mlx5_aso_poll_cq(aso->aso, false);
479 spin_unlock_bh(&aso->lock);
480 return ret;
1ed78fc0
LR
481}
482
483void mlx5e_ipsec_aso_update_curlft(struct mlx5e_ipsec_sa_entry *sa_entry,
484 u64 *packets)
485{
486 struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
487 struct mlx5e_ipsec_aso *aso = ipsec->aso;
488 u64 hard_cnt;
489
490 hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt);
491 /* HW decresases the limit till it reaches zero to fire an avent.
492 * We need to fix the calculations, so the returned count is a total
493 * number of passed packets and not how much left.
494 */
495 *packets = sa_entry->attrs.hard_packet_limit - hard_cnt;
496}