xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c (revision 87320be9f0d24fce67631b7eef919f0b79c3e45c)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3 
4 #include <linux/mlx5/device.h>
5 #include <linux/mlx5/mlx5_ifc.h>
6 #include <linux/xarray.h>
7 #include <linux/if_vlan.h>
8 #include <linux/iopoll.h>
9 
10 #include "en.h"
11 #include "lib/aso.h"
12 #include "lib/crypto.h"
13 #include "en_accel/macsec.h"
14 
15 #define MLX5_MACSEC_EPN_SCOPE_MID 0x80000000L
16 #define MLX5E_MACSEC_ASO_CTX_SZ MLX5_ST_SZ_BYTES(macsec_aso)
17 
18 enum mlx5_macsec_aso_event_arm {
19 	MLX5E_ASO_EPN_ARM = BIT(0),
20 };
21 
22 enum {
23 	MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET,
24 };
25 
26 struct mlx5e_macsec_handle {
27 	struct mlx5e_macsec *macsec;
28 	u32 obj_id;
29 	u8 idx;
30 };
31 
32 enum {
33 	MLX5_MACSEC_EPN,
34 };
35 
36 struct mlx5e_macsec_aso_out {
37 	u8 event_arm;
38 	u32 mode_param;
39 };
40 
41 struct mlx5e_macsec_aso_in {
42 	u8 mode;
43 	u32 obj_id;
44 };
45 
46 struct mlx5e_macsec_epn_state {
47 	u32 epn_msb;
48 	u8 epn_enabled;
49 	u8 overlap;
50 };
51 
52 struct mlx5e_macsec_async_work {
53 	struct mlx5e_macsec *macsec;
54 	struct mlx5_core_dev *mdev;
55 	struct work_struct work;
56 	u32 obj_id;
57 };
58 
59 struct mlx5e_macsec_sa {
60 	bool active;
61 	u8  assoc_num;
62 	u32 macsec_obj_id;
63 	u32 enc_key_id;
64 	u32 next_pn;
65 	sci_t sci;
66 	ssci_t ssci;
67 	salt_t salt;
68 
69 	union mlx5_macsec_rule *macsec_rule;
70 	struct rcu_head rcu_head;
71 	struct mlx5e_macsec_epn_state epn_state;
72 };
73 
74 struct mlx5e_macsec_rx_sc;
75 struct mlx5e_macsec_rx_sc_xarray_element {
76 	u32 fs_id;
77 	struct mlx5e_macsec_rx_sc *rx_sc;
78 };
79 
80 struct mlx5e_macsec_rx_sc {
81 	bool active;
82 	sci_t sci;
83 	struct mlx5e_macsec_sa *rx_sa[MACSEC_NUM_AN];
84 	struct list_head rx_sc_list_element;
85 	struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
86 	struct metadata_dst *md_dst;
87 	struct rcu_head rcu_head;
88 };
89 
90 struct mlx5e_macsec_umr {
91 	u8 __aligned(64) ctx[MLX5_ST_SZ_BYTES(macsec_aso)];
92 	dma_addr_t dma_addr;
93 	u32 mkey;
94 };
95 
96 struct mlx5e_macsec_aso {
97 	/* ASO */
98 	struct mlx5_aso *maso;
99 	/* Protects macsec ASO */
100 	struct mutex aso_lock;
101 	/* UMR */
102 	struct mlx5e_macsec_umr *umr;
103 
104 	u32 pdn;
105 };
106 
107 struct mlx5e_macsec_device {
108 	const struct net_device *netdev;
109 	struct mlx5e_macsec_sa *tx_sa[MACSEC_NUM_AN];
110 	struct list_head macsec_rx_sc_list_head;
111 	unsigned char *dev_addr;
112 	struct list_head macsec_device_list_element;
113 };
114 
115 struct mlx5e_macsec {
116 	struct list_head macsec_device_list_head;
117 	int num_of_devices;
118 	struct mutex lock; /* Protects mlx5e_macsec internal contexts */
119 
120 	/* Rx fs_id -> rx_sc mapping */
121 	struct xarray sc_xarray;
122 
123 	struct mlx5_core_dev *mdev;
124 
125 	/* ASO */
126 	struct mlx5e_macsec_aso aso;
127 
128 	struct notifier_block nb;
129 	struct workqueue_struct *wq;
130 };
131 
132 struct mlx5_macsec_obj_attrs {
133 	u32 aso_pdn;
134 	u32 next_pn;
135 	__be64 sci;
136 	u32 enc_key_id;
137 	bool encrypt;
138 	struct mlx5e_macsec_epn_state epn_state;
139 	salt_t salt;
140 	__be32 ssci;
141 	bool replay_protect;
142 	u32 replay_window;
143 };
144 
145 struct mlx5_aso_ctrl_param {
146 	u8   data_mask_mode;
147 	u8   condition_0_operand;
148 	u8   condition_1_operand;
149 	u8   condition_0_offset;
150 	u8   condition_1_offset;
151 	u8   data_offset;
152 	u8   condition_operand;
153 	u32  condition_0_data;
154 	u32  condition_0_mask;
155 	u32  condition_1_data;
156 	u32  condition_1_mask;
157 	u64  bitwise_data;
158 	u64  data_mask;
159 };
160 
mlx5e_macsec_aso_reg_mr(struct mlx5_core_dev * mdev,struct mlx5e_macsec_aso * aso)161 static int mlx5e_macsec_aso_reg_mr(struct mlx5_core_dev *mdev, struct mlx5e_macsec_aso *aso)
162 {
163 	struct mlx5e_macsec_umr *umr;
164 	struct device *dma_device;
165 	dma_addr_t dma_addr;
166 	int err;
167 
168 	umr = kzalloc_obj(*umr);
169 	if (!umr) {
170 		err = -ENOMEM;
171 		return err;
172 	}
173 
174 	dma_device = mlx5_core_dma_dev(mdev);
175 	dma_addr = dma_map_single(dma_device, umr->ctx, sizeof(umr->ctx), DMA_BIDIRECTIONAL);
176 	err = dma_mapping_error(dma_device, dma_addr);
177 	if (err) {
178 		mlx5_core_err(mdev, "Can't map dma device, err=%d\n", err);
179 		goto out_dma;
180 	}
181 
182 	err = mlx5e_create_mkey(mdev, aso->pdn, &umr->mkey);
183 	if (err) {
184 		mlx5_core_err(mdev, "Can't create mkey, err=%d\n", err);
185 		goto out_mkey;
186 	}
187 
188 	umr->dma_addr = dma_addr;
189 
190 	aso->umr = umr;
191 
192 	return 0;
193 
194 out_mkey:
195 	dma_unmap_single(dma_device, dma_addr, sizeof(umr->ctx), DMA_BIDIRECTIONAL);
196 out_dma:
197 	kfree(umr);
198 	return err;
199 }
200 
mlx5e_macsec_aso_dereg_mr(struct mlx5_core_dev * mdev,struct mlx5e_macsec_aso * aso)201 static void mlx5e_macsec_aso_dereg_mr(struct mlx5_core_dev *mdev, struct mlx5e_macsec_aso *aso)
202 {
203 	struct mlx5e_macsec_umr *umr = aso->umr;
204 
205 	mlx5_core_destroy_mkey(mdev, umr->mkey);
206 	dma_unmap_single(&mdev->pdev->dev, umr->dma_addr, sizeof(umr->ctx), DMA_BIDIRECTIONAL);
207 	kfree(umr);
208 }
209 
macsec_set_replay_protection(struct mlx5_macsec_obj_attrs * attrs,void * aso_ctx)210 static int macsec_set_replay_protection(struct mlx5_macsec_obj_attrs *attrs, void *aso_ctx)
211 {
212 	u8 window_sz;
213 
214 	if (!attrs->replay_protect)
215 		return 0;
216 
217 	switch (attrs->replay_window) {
218 	case 256:
219 		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_256BIT;
220 		break;
221 	case 128:
222 		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_128BIT;
223 		break;
224 	case 64:
225 		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_64BIT;
226 		break;
227 	case 32:
228 		window_sz = MLX5_MACSEC_ASO_REPLAY_WIN_32BIT;
229 		break;
230 	default:
231 		return -EINVAL;
232 	}
233 	MLX5_SET(macsec_aso, aso_ctx, window_size, window_sz);
234 	MLX5_SET(macsec_aso, aso_ctx, mode, MLX5_MACSEC_ASO_REPLAY_PROTECTION);
235 
236 	return 0;
237 }
238 
mlx5e_macsec_create_object(struct mlx5_core_dev * mdev,struct mlx5_macsec_obj_attrs * attrs,bool is_tx,u32 * macsec_obj_id)239 static int mlx5e_macsec_create_object(struct mlx5_core_dev *mdev,
240 				      struct mlx5_macsec_obj_attrs *attrs,
241 				      bool is_tx,
242 				      u32 *macsec_obj_id)
243 {
244 	u32 in[MLX5_ST_SZ_DW(create_macsec_obj_in)] = {};
245 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
246 	void *aso_ctx;
247 	void *obj;
248 	int err;
249 
250 	obj = MLX5_ADDR_OF(create_macsec_obj_in, in, macsec_object);
251 	aso_ctx = MLX5_ADDR_OF(macsec_offload_obj, obj, macsec_aso);
252 
253 	MLX5_SET(macsec_offload_obj, obj, confidentiality_en, attrs->encrypt);
254 	MLX5_SET(macsec_offload_obj, obj, dekn, attrs->enc_key_id);
255 	MLX5_SET(macsec_offload_obj, obj, aso_return_reg, MLX5_MACSEC_ASO_REG_C_4_5);
256 	MLX5_SET(macsec_offload_obj, obj, macsec_aso_access_pd, attrs->aso_pdn);
257 	MLX5_SET(macsec_aso, aso_ctx, mode_parameter, attrs->next_pn);
258 
259 	/* Epn */
260 	if (attrs->epn_state.epn_enabled) {
261 		void *salt_p;
262 		int i;
263 
264 		MLX5_SET(macsec_aso, aso_ctx, epn_event_arm, 1);
265 		MLX5_SET(macsec_offload_obj, obj, epn_en, 1);
266 		MLX5_SET(macsec_offload_obj, obj, epn_msb, attrs->epn_state.epn_msb);
267 		MLX5_SET(macsec_offload_obj, obj, epn_overlap, attrs->epn_state.overlap);
268 		MLX5_SET64(macsec_offload_obj, obj, sci, (__force u64)attrs->ssci);
269 		salt_p = MLX5_ADDR_OF(macsec_offload_obj, obj, salt);
270 		for (i = 0; i < 3 ; i++)
271 			memcpy((u32 *)salt_p + i, &attrs->salt.bytes[4 * (2 - i)], 4);
272 	} else {
273 		MLX5_SET64(macsec_offload_obj, obj, sci, (__force u64)(attrs->sci));
274 	}
275 
276 	MLX5_SET(macsec_aso, aso_ctx, valid, 0x1);
277 	if (is_tx) {
278 		MLX5_SET(macsec_aso, aso_ctx, mode, MLX5_MACSEC_ASO_INC_SN);
279 	} else {
280 		err = macsec_set_replay_protection(attrs, aso_ctx);
281 		if (err)
282 			return err;
283 	}
284 
285 	/* general object fields set */
286 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
287 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC);
288 
289 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
290 	if (err) {
291 		mlx5_core_err(mdev,
292 			      "MACsec offload: Failed to create MACsec object (err = %d)\n",
293 			      err);
294 		return err;
295 	}
296 
297 	*macsec_obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
298 
299 	return err;
300 }
301 
mlx5e_macsec_destroy_object(struct mlx5_core_dev * mdev,u32 macsec_obj_id)302 static void mlx5e_macsec_destroy_object(struct mlx5_core_dev *mdev, u32 macsec_obj_id)
303 {
304 	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {};
305 	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
306 
307 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
308 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC);
309 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, macsec_obj_id);
310 
311 	mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
312 }
313 
mlx5e_macsec_cleanup_sa_fs(struct mlx5e_macsec * macsec,struct mlx5e_macsec_sa * sa,bool is_tx,struct net_device * netdev,u32 fs_id)314 static void mlx5e_macsec_cleanup_sa_fs(struct mlx5e_macsec *macsec,
315 				       struct mlx5e_macsec_sa *sa, bool is_tx,
316 				       struct net_device *netdev, u32 fs_id)
317 {
318 	int action =  (is_tx) ?  MLX5_ACCEL_MACSEC_ACTION_ENCRYPT :
319 				 MLX5_ACCEL_MACSEC_ACTION_DECRYPT;
320 
321 	if (!sa->macsec_rule)
322 		return;
323 
324 	mlx5_macsec_fs_del_rule(macsec->mdev->macsec_fs, sa->macsec_rule, action, netdev,
325 				fs_id);
326 	sa->macsec_rule = NULL;
327 }
328 
mlx5e_macsec_cleanup_sa(struct mlx5e_macsec * macsec,struct mlx5e_macsec_sa * sa,bool is_tx,struct net_device * netdev,u32 fs_id)329 static void mlx5e_macsec_cleanup_sa(struct mlx5e_macsec *macsec,
330 				    struct mlx5e_macsec_sa *sa, bool is_tx,
331 				    struct net_device *netdev, u32 fs_id)
332 {
333 	mlx5e_macsec_cleanup_sa_fs(macsec, sa, is_tx, netdev, fs_id);
334 	mlx5e_macsec_destroy_object(macsec->mdev, sa->macsec_obj_id);
335 }
336 
mlx5e_macsec_init_sa_fs(struct macsec_context * ctx,struct mlx5e_macsec_sa * sa,bool encrypt,bool is_tx,u32 * fs_id)337 static int mlx5e_macsec_init_sa_fs(struct macsec_context *ctx,
338 				   struct mlx5e_macsec_sa *sa, bool encrypt,
339 				   bool is_tx, u32 *fs_id)
340 {
341 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
342 	struct mlx5_macsec_fs *macsec_fs = priv->mdev->macsec_fs;
343 	const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
344 	struct mlx5_macsec_rule_attrs rule_attrs;
345 	union mlx5_macsec_rule *macsec_rule;
346 
347 	if (is_tx && tx_sc->encoding_sa != sa->assoc_num)
348 		return 0;
349 
350 	rule_attrs.macsec_obj_id = sa->macsec_obj_id;
351 	rule_attrs.sci = sa->sci;
352 	rule_attrs.assoc_num = sa->assoc_num;
353 	rule_attrs.action = (is_tx) ? MLX5_ACCEL_MACSEC_ACTION_ENCRYPT :
354 				      MLX5_ACCEL_MACSEC_ACTION_DECRYPT;
355 
356 	macsec_rule = mlx5_macsec_fs_add_rule(macsec_fs, ctx, &rule_attrs, fs_id);
357 	if (!macsec_rule)
358 		return -ENOMEM;
359 
360 	sa->macsec_rule = macsec_rule;
361 
362 	return 0;
363 }
364 
mlx5e_macsec_init_sa(struct macsec_context * ctx,struct mlx5e_macsec_sa * sa,bool encrypt,bool is_tx,u32 * fs_id)365 static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
366 				struct mlx5e_macsec_sa *sa,
367 				bool encrypt, bool is_tx, u32 *fs_id)
368 {
369 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
370 	struct mlx5e_macsec *macsec = priv->macsec;
371 	struct mlx5_core_dev *mdev = priv->mdev;
372 	struct mlx5_macsec_obj_attrs obj_attrs;
373 	int err;
374 
375 	obj_attrs.next_pn = sa->next_pn;
376 	obj_attrs.sci = cpu_to_be64((__force u64)sa->sci);
377 	obj_attrs.enc_key_id = sa->enc_key_id;
378 	obj_attrs.encrypt = encrypt;
379 	obj_attrs.aso_pdn = macsec->aso.pdn;
380 	obj_attrs.epn_state = sa->epn_state;
381 
382 	if (sa->epn_state.epn_enabled) {
383 		obj_attrs.ssci = cpu_to_be32((__force u32)sa->ssci);
384 		memcpy(&obj_attrs.salt, &sa->salt, sizeof(sa->salt));
385 	}
386 
387 	obj_attrs.replay_window = ctx->secy->replay_window;
388 	obj_attrs.replay_protect = ctx->secy->replay_protect;
389 
390 	err = mlx5e_macsec_create_object(mdev, &obj_attrs, is_tx, &sa->macsec_obj_id);
391 	if (err)
392 		return err;
393 
394 	if (sa->active) {
395 		err = mlx5e_macsec_init_sa_fs(ctx, sa, encrypt, is_tx, fs_id);
396 		if (err)
397 			goto destroy_macsec_object;
398 	}
399 
400 	return 0;
401 
402 destroy_macsec_object:
403 	mlx5e_macsec_destroy_object(mdev, sa->macsec_obj_id);
404 
405 	return err;
406 }
407 
408 static struct mlx5e_macsec_rx_sc *
mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head * list,sci_t sci)409 mlx5e_macsec_get_rx_sc_from_sc_list(const struct list_head *list, sci_t sci)
410 {
411 	struct mlx5e_macsec_rx_sc *iter;
412 
413 	list_for_each_entry_rcu(iter, list, rx_sc_list_element) {
414 		if (iter->sci == sci)
415 			return iter;
416 	}
417 
418 	return NULL;
419 }
420 
macsec_rx_sa_active_update(struct macsec_context * ctx,struct mlx5e_macsec_sa * rx_sa,bool active,u32 * fs_id)421 static int macsec_rx_sa_active_update(struct macsec_context *ctx,
422 				      struct mlx5e_macsec_sa *rx_sa,
423 				      bool active, u32 *fs_id)
424 {
425 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
426 	struct mlx5e_macsec *macsec = priv->macsec;
427 	int err = 0;
428 
429 	if (rx_sa->active == active)
430 		return 0;
431 
432 	rx_sa->active = active;
433 	if (!active) {
434 		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev, *fs_id);
435 		return 0;
436 	}
437 
438 	err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, fs_id);
439 	if (err)
440 		rx_sa->active = false;
441 
442 	return err;
443 }
444 
mlx5e_macsec_secy_features_validate(struct macsec_context * ctx)445 static bool mlx5e_macsec_secy_features_validate(struct macsec_context *ctx)
446 {
447 	const struct net_device *netdev = ctx->netdev;
448 	const struct macsec_secy *secy = ctx->secy;
449 
450 	if (secy->validate_frames != MACSEC_VALIDATE_STRICT) {
451 		netdev_err(netdev,
452 			   "MACsec offload is supported only when validate_frame is in strict mode\n");
453 		return false;
454 	}
455 
456 	if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN) {
457 		netdev_err(netdev, "MACsec offload is supported only when icv_len is %d\n",
458 			   MACSEC_DEFAULT_ICV_LEN);
459 		return false;
460 	}
461 
462 	if (!secy->protect_frames) {
463 		netdev_err(netdev,
464 			   "MACsec offload is supported only when protect_frames is set\n");
465 		return false;
466 	}
467 
468 	if (!ctx->secy->tx_sc.encrypt) {
469 		netdev_err(netdev, "MACsec offload: encrypt off isn't supported\n");
470 		return false;
471 	}
472 
473 	return true;
474 }
475 
476 static struct mlx5e_macsec_device *
mlx5e_macsec_get_macsec_device_context(const struct mlx5e_macsec * macsec,const struct macsec_context * ctx)477 mlx5e_macsec_get_macsec_device_context(const struct mlx5e_macsec *macsec,
478 				       const struct macsec_context *ctx)
479 {
480 	struct mlx5e_macsec_device *iter;
481 	const struct list_head *list;
482 
483 	list = &macsec->macsec_device_list_head;
484 	list_for_each_entry_rcu(iter, list, macsec_device_list_element) {
485 		if (iter->netdev == ctx->secy->netdev)
486 			return iter;
487 	}
488 
489 	return NULL;
490 }
491 
update_macsec_epn(struct mlx5e_macsec_sa * sa,const struct macsec_key * key,const pn_t * next_pn_halves,ssci_t ssci)492 static void update_macsec_epn(struct mlx5e_macsec_sa *sa, const struct macsec_key *key,
493 			      const pn_t *next_pn_halves, ssci_t ssci)
494 {
495 	struct mlx5e_macsec_epn_state *epn_state = &sa->epn_state;
496 
497 	sa->ssci = ssci;
498 	sa->salt = key->salt;
499 	epn_state->epn_enabled = 1;
500 	epn_state->epn_msb = next_pn_halves->upper;
501 	epn_state->overlap = next_pn_halves->lower < MLX5_MACSEC_EPN_SCOPE_MID ? 0 : 1;
502 }
503 
mlx5e_macsec_add_txsa(struct macsec_context * ctx)504 static int mlx5e_macsec_add_txsa(struct macsec_context *ctx)
505 {
506 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
507 	const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
508 	const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa;
509 	const struct macsec_secy *secy = ctx->secy;
510 	struct mlx5e_macsec_device *macsec_device;
511 	struct mlx5_core_dev *mdev = priv->mdev;
512 	u8 assoc_num = ctx->sa.assoc_num;
513 	struct mlx5e_macsec_sa *tx_sa;
514 	struct mlx5e_macsec *macsec;
515 	int err = 0;
516 
517 	mutex_lock(&priv->macsec->lock);
518 
519 	macsec = priv->macsec;
520 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
521 	if (!macsec_device) {
522 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
523 		err = -EEXIST;
524 		goto out;
525 	}
526 
527 	if (macsec_device->tx_sa[assoc_num]) {
528 		netdev_err(ctx->netdev, "MACsec offload tx_sa: %d already exist\n", assoc_num);
529 		err = -EEXIST;
530 		goto out;
531 	}
532 
533 	tx_sa = kzalloc_obj(*tx_sa);
534 	if (!tx_sa) {
535 		err = -ENOMEM;
536 		goto out;
537 	}
538 
539 	tx_sa->active = ctx_tx_sa->active;
540 	tx_sa->next_pn = ctx_tx_sa->next_pn_halves.lower;
541 	tx_sa->sci = secy->sci;
542 	tx_sa->assoc_num = assoc_num;
543 
544 	if (secy->xpn)
545 		update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves,
546 				  ctx_tx_sa->ssci);
547 
548 	err = mlx5_create_encryption_key(mdev, ctx->sa.key, secy->key_len,
549 					 MLX5_ACCEL_OBJ_MACSEC_KEY,
550 					 &tx_sa->enc_key_id);
551 	if (err)
552 		goto destroy_sa;
553 
554 	macsec_device->tx_sa[assoc_num] = tx_sa;
555 	if (!secy->operational)
556 		goto out;
557 
558 	err = mlx5e_macsec_init_sa(ctx, tx_sa, tx_sc->encrypt, true, NULL);
559 	if (err)
560 		goto destroy_encryption_key;
561 
562 	mutex_unlock(&macsec->lock);
563 
564 	return 0;
565 
566 destroy_encryption_key:
567 	macsec_device->tx_sa[assoc_num] = NULL;
568 	mlx5_destroy_encryption_key(mdev, tx_sa->enc_key_id);
569 destroy_sa:
570 	kfree(tx_sa);
571 out:
572 	mutex_unlock(&macsec->lock);
573 
574 	return err;
575 }
576 
mlx5e_macsec_upd_txsa(struct macsec_context * ctx)577 static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx)
578 {
579 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
580 	const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
581 	const struct macsec_tx_sa *ctx_tx_sa = ctx->sa.tx_sa;
582 	struct mlx5e_macsec_device *macsec_device;
583 	u8 assoc_num = ctx->sa.assoc_num;
584 	struct mlx5e_macsec_sa *tx_sa;
585 	struct mlx5e_macsec *macsec;
586 	struct net_device *netdev;
587 	int err = 0;
588 
589 	mutex_lock(&priv->macsec->lock);
590 
591 	macsec = priv->macsec;
592 	netdev = ctx->netdev;
593 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
594 	if (!macsec_device) {
595 		netdev_err(netdev, "MACsec offload: Failed to find device context\n");
596 		err = -EINVAL;
597 		goto out;
598 	}
599 
600 	tx_sa = macsec_device->tx_sa[assoc_num];
601 	if (!tx_sa) {
602 		netdev_err(netdev, "MACsec offload: TX sa 0x%x doesn't exist\n", assoc_num);
603 		err = -EEXIST;
604 		goto out;
605 	}
606 
607 	if (ctx->sa.update_pn) {
608 		netdev_err(netdev, "MACsec offload: update TX sa %d PN isn't supported\n",
609 			   assoc_num);
610 		err = -EINVAL;
611 		goto out;
612 	}
613 
614 	if (tx_sa->active == ctx_tx_sa->active)
615 		goto out;
616 
617 	tx_sa->active = ctx_tx_sa->active;
618 	if (tx_sa->assoc_num != tx_sc->encoding_sa)
619 		goto out;
620 
621 	if (ctx_tx_sa->active) {
622 		err = mlx5e_macsec_init_sa_fs(ctx, tx_sa, tx_sc->encrypt, true, NULL);
623 		if (err)
624 			goto out;
625 	} else {
626 		if (!tx_sa->macsec_rule) {
627 			err = -EINVAL;
628 			goto out;
629 		}
630 
631 		mlx5e_macsec_cleanup_sa_fs(macsec, tx_sa, true, ctx->secy->netdev, 0);
632 	}
633 out:
634 	mutex_unlock(&macsec->lock);
635 
636 	return err;
637 }
638 
mlx5e_macsec_del_txsa(struct macsec_context * ctx)639 static int mlx5e_macsec_del_txsa(struct macsec_context *ctx)
640 {
641 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
642 	struct mlx5e_macsec_device *macsec_device;
643 	u8 assoc_num = ctx->sa.assoc_num;
644 	struct mlx5e_macsec_sa *tx_sa;
645 	struct mlx5e_macsec *macsec;
646 	int err = 0;
647 
648 	mutex_lock(&priv->macsec->lock);
649 	macsec = priv->macsec;
650 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
651 	if (!macsec_device) {
652 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
653 		err = -EINVAL;
654 		goto out;
655 	}
656 
657 	tx_sa = macsec_device->tx_sa[assoc_num];
658 	if (!tx_sa) {
659 		netdev_err(ctx->netdev, "MACsec offload: TX sa 0x%x doesn't exist\n", assoc_num);
660 		err = -EEXIST;
661 		goto out;
662 	}
663 
664 	mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
665 	mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
666 	kfree_rcu_mightsleep(tx_sa);
667 	macsec_device->tx_sa[assoc_num] = NULL;
668 
669 out:
670 	mutex_unlock(&macsec->lock);
671 
672 	return err;
673 }
674 
mlx5e_macsec_add_rxsc(struct macsec_context * ctx)675 static int mlx5e_macsec_add_rxsc(struct macsec_context *ctx)
676 {
677 	struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
678 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
679 	const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc;
680 	struct mlx5e_macsec_device *macsec_device;
681 	struct mlx5e_macsec_rx_sc *rx_sc;
682 	struct list_head *rx_sc_list;
683 	struct mlx5e_macsec *macsec;
684 	int err = 0;
685 
686 	mutex_lock(&priv->macsec->lock);
687 	macsec = priv->macsec;
688 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
689 	if (!macsec_device) {
690 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
691 		err = -EINVAL;
692 		goto out;
693 	}
694 
695 	rx_sc_list = &macsec_device->macsec_rx_sc_list_head;
696 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(rx_sc_list, ctx_rx_sc->sci);
697 	if (rx_sc) {
698 		netdev_err(ctx->netdev, "MACsec offload: rx_sc (sci %lld) already exists\n",
699 			   ctx_rx_sc->sci);
700 		err = -EEXIST;
701 		goto out;
702 	}
703 
704 	rx_sc = kzalloc_obj(*rx_sc);
705 	if (!rx_sc) {
706 		err = -ENOMEM;
707 		goto out;
708 	}
709 
710 	sc_xarray_element = kzalloc_obj(*sc_xarray_element);
711 	if (!sc_xarray_element) {
712 		err = -ENOMEM;
713 		goto destroy_rx_sc;
714 	}
715 
716 	sc_xarray_element->rx_sc = rx_sc;
717 
718 	rx_sc->md_dst = metadata_dst_alloc(0, METADATA_MACSEC, GFP_KERNEL);
719 	if (!rx_sc->md_dst) {
720 		err = -ENOMEM;
721 		goto destroy_sc_xarray_elemenet;
722 	}
723 
724 	rx_sc->sci = ctx_rx_sc->sci;
725 	rx_sc->active = ctx_rx_sc->active;
726 	rx_sc->sc_xarray_element = sc_xarray_element;
727 	rx_sc->md_dst->u.macsec_info.sci = rx_sc->sci;
728 
729 	/*
730 	 * Publish the fully-initialised SC last: xa_alloc() makes
731 	 * sc_xarray_element->rx_sc (and rx_sc->md_dst) reachable from the RX
732 	 * datapath via xa_load().  Doing it only after md_dst is allocated and
733 	 * initialised pairs with the rcu_read_lock()/xa_load() in
734 	 * mlx5e_macsec_offload_handle_rx_skb(), so a reader can never observe
735 	 * a non-NULL md_dst with uninitialised contents.
736 	 */
737 	err = xa_alloc(&macsec->sc_xarray, &sc_xarray_element->fs_id, sc_xarray_element,
738 		       XA_LIMIT(1, MLX5_MACEC_RX_FS_ID_MAX), GFP_KERNEL);
739 	if (err) {
740 		if (err == -EBUSY)
741 			netdev_err(ctx->netdev,
742 				   "MACsec offload: unable to create entry for RX SC (%d Rx SCs already allocated)\n",
743 				   MLX5_MACEC_RX_FS_ID_MAX);
744 		goto destroy_md_dst;
745 	}
746 
747 	list_add_rcu(&rx_sc->rx_sc_list_element, rx_sc_list);
748 	mutex_unlock(&macsec->lock);
749 
750 	return 0;
751 
752 destroy_md_dst:
753 	dst_release(&rx_sc->md_dst->dst);
754 destroy_sc_xarray_elemenet:
755 	kfree(sc_xarray_element);
756 destroy_rx_sc:
757 	kfree(rx_sc);
758 
759 out:
760 	mutex_unlock(&macsec->lock);
761 
762 	return err;
763 }
764 
mlx5e_macsec_upd_rxsc(struct macsec_context * ctx)765 static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
766 {
767 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
768 	const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc;
769 	struct mlx5e_macsec_device *macsec_device;
770 	struct mlx5e_macsec_rx_sc *rx_sc;
771 	struct mlx5e_macsec_sa *rx_sa;
772 	struct mlx5e_macsec *macsec;
773 	struct list_head *list;
774 	int i;
775 	int err = 0;
776 
777 	mutex_lock(&priv->macsec->lock);
778 
779 	macsec = priv->macsec;
780 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
781 	if (!macsec_device) {
782 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
783 		err = -EINVAL;
784 		goto out;
785 	}
786 
787 	list = &macsec_device->macsec_rx_sc_list_head;
788 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx_rx_sc->sci);
789 	if (!rx_sc) {
790 		err = -EINVAL;
791 		goto out;
792 	}
793 
794 	if (rx_sc->active == ctx_rx_sc->active)
795 		goto out;
796 
797 	rx_sc->active = ctx_rx_sc->active;
798 	for (i = 0; i < MACSEC_NUM_AN; ++i) {
799 		rx_sa = rx_sc->rx_sa[i];
800 		if (!rx_sa)
801 			continue;
802 
803 		err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active,
804 						 &rx_sc->sc_xarray_element->fs_id);
805 		if (err)
806 			goto out;
807 	}
808 
809 out:
810 	mutex_unlock(&macsec->lock);
811 
812 	return err;
813 }
814 
macsec_del_rxsc_ctx(struct mlx5e_macsec * macsec,struct mlx5e_macsec_rx_sc * rx_sc,struct net_device * netdev)815 static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc,
816 				struct net_device *netdev)
817 {
818 	struct mlx5e_macsec_sa *rx_sa;
819 	int i;
820 
821 	for (i = 0; i < MACSEC_NUM_AN; ++i) {
822 		rx_sa = rx_sc->rx_sa[i];
823 		if (!rx_sa)
824 			continue;
825 
826 		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, netdev,
827 					rx_sc->sc_xarray_element->fs_id);
828 		mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
829 
830 		kfree(rx_sa);
831 		rx_sc->rx_sa[i] = NULL;
832 	}
833 
834 	/* At this point the relevant MACsec offload Rx rule already removed at
835 	 * mlx5e_macsec_cleanup_sa need to wait for datapath to finish current
836 	 * Rx related data propagating using xa_erase which uses rcu to sync,
837 	 * once fs_id is erased then this rx_sc is hidden from datapath.
838 	 */
839 	list_del_rcu(&rx_sc->rx_sc_list_element);
840 	xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id);
841 	dst_release(&rx_sc->md_dst->dst);
842 	kfree(rx_sc->sc_xarray_element);
843 	kfree_rcu_mightsleep(rx_sc);
844 }
845 
mlx5e_macsec_del_rxsc(struct macsec_context * ctx)846 static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
847 {
848 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
849 	struct mlx5e_macsec_device *macsec_device;
850 	struct mlx5e_macsec_rx_sc *rx_sc;
851 	struct mlx5e_macsec *macsec;
852 	struct list_head *list;
853 	int err = 0;
854 
855 	mutex_lock(&priv->macsec->lock);
856 
857 	macsec = priv->macsec;
858 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
859 	if (!macsec_device) {
860 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
861 		err = -EINVAL;
862 		goto out;
863 	}
864 
865 	list = &macsec_device->macsec_rx_sc_list_head;
866 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx->rx_sc->sci);
867 	if (!rx_sc) {
868 		netdev_err(ctx->netdev,
869 			   "MACsec offload rx_sc sci %lld doesn't exist\n",
870 			   ctx->sa.rx_sa->sc->sci);
871 		err = -EINVAL;
872 		goto out;
873 	}
874 
875 	macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
876 out:
877 	mutex_unlock(&macsec->lock);
878 
879 	return err;
880 }
881 
mlx5e_macsec_add_rxsa(struct macsec_context * ctx)882 static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
883 {
884 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
885 	const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
886 	struct mlx5e_macsec_device *macsec_device;
887 	struct mlx5_core_dev *mdev = priv->mdev;
888 	u8 assoc_num = ctx->sa.assoc_num;
889 	struct mlx5e_macsec_rx_sc *rx_sc;
890 	sci_t sci = ctx_rx_sa->sc->sci;
891 	struct mlx5e_macsec_sa *rx_sa;
892 	struct mlx5e_macsec *macsec;
893 	struct list_head *list;
894 	int err = 0;
895 
896 	mutex_lock(&priv->macsec->lock);
897 
898 	macsec = priv->macsec;
899 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
900 	if (!macsec_device) {
901 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
902 		err = -EINVAL;
903 		goto out;
904 	}
905 
906 	list = &macsec_device->macsec_rx_sc_list_head;
907 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
908 	if (!rx_sc) {
909 		netdev_err(ctx->netdev,
910 			   "MACsec offload rx_sc sci %lld doesn't exist\n",
911 			   ctx->sa.rx_sa->sc->sci);
912 		err = -EINVAL;
913 		goto out;
914 	}
915 
916 	if (rx_sc->rx_sa[assoc_num]) {
917 		netdev_err(ctx->netdev,
918 			   "MACsec offload rx_sc sci %lld rx_sa %d already exist\n",
919 			   sci, assoc_num);
920 		err = -EEXIST;
921 		goto out;
922 	}
923 
924 	rx_sa = kzalloc_obj(*rx_sa);
925 	if (!rx_sa) {
926 		err = -ENOMEM;
927 		goto out;
928 	}
929 
930 	rx_sa->active = ctx_rx_sa->active;
931 	rx_sa->next_pn = ctx_rx_sa->next_pn;
932 	rx_sa->sci = sci;
933 	rx_sa->assoc_num = assoc_num;
934 
935 	if (ctx->secy->xpn)
936 		update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves,
937 				  ctx_rx_sa->ssci);
938 
939 	err = mlx5_create_encryption_key(mdev, ctx->sa.key, ctx->secy->key_len,
940 					 MLX5_ACCEL_OBJ_MACSEC_KEY,
941 					 &rx_sa->enc_key_id);
942 	if (err)
943 		goto destroy_sa;
944 
945 	rx_sc->rx_sa[assoc_num] = rx_sa;
946 	if (!rx_sa->active)
947 		goto out;
948 
949 	//TODO - add support for both authentication and encryption flows
950 	err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, &rx_sc->sc_xarray_element->fs_id);
951 	if (err)
952 		goto destroy_encryption_key;
953 
954 	goto out;
955 
956 destroy_encryption_key:
957 	rx_sc->rx_sa[assoc_num] = NULL;
958 	mlx5_destroy_encryption_key(mdev, rx_sa->enc_key_id);
959 destroy_sa:
960 	kfree(rx_sa);
961 out:
962 	mutex_unlock(&macsec->lock);
963 
964 	return err;
965 }
966 
mlx5e_macsec_upd_rxsa(struct macsec_context * ctx)967 static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
968 {
969 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
970 	const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
971 	struct mlx5e_macsec_device *macsec_device;
972 	u8 assoc_num = ctx->sa.assoc_num;
973 	struct mlx5e_macsec_rx_sc *rx_sc;
974 	sci_t sci = ctx_rx_sa->sc->sci;
975 	struct mlx5e_macsec_sa *rx_sa;
976 	struct mlx5e_macsec *macsec;
977 	struct list_head *list;
978 	int err = 0;
979 
980 	mutex_lock(&priv->macsec->lock);
981 
982 	macsec = priv->macsec;
983 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
984 	if (!macsec_device) {
985 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
986 		err = -EINVAL;
987 		goto out;
988 	}
989 
990 	list = &macsec_device->macsec_rx_sc_list_head;
991 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
992 	if (!rx_sc) {
993 		netdev_err(ctx->netdev,
994 			   "MACsec offload rx_sc sci %lld doesn't exist\n",
995 			   ctx->sa.rx_sa->sc->sci);
996 		err = -EINVAL;
997 		goto out;
998 	}
999 
1000 	rx_sa = rx_sc->rx_sa[assoc_num];
1001 	if (!rx_sa) {
1002 		netdev_err(ctx->netdev,
1003 			   "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n",
1004 			   sci, assoc_num);
1005 		err = -EINVAL;
1006 		goto out;
1007 	}
1008 
1009 	if (ctx->sa.update_pn) {
1010 		netdev_err(ctx->netdev,
1011 			   "MACsec offload update RX sa %d PN isn't supported\n",
1012 			   assoc_num);
1013 		err = -EINVAL;
1014 		goto out;
1015 	}
1016 
1017 	err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active,
1018 					 &rx_sc->sc_xarray_element->fs_id);
1019 out:
1020 	mutex_unlock(&macsec->lock);
1021 
1022 	return err;
1023 }
1024 
mlx5e_macsec_del_rxsa(struct macsec_context * ctx)1025 static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx)
1026 {
1027 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1028 	struct mlx5e_macsec_device *macsec_device;
1029 	sci_t sci = ctx->sa.rx_sa->sc->sci;
1030 	struct mlx5e_macsec_rx_sc *rx_sc;
1031 	u8 assoc_num = ctx->sa.assoc_num;
1032 	struct mlx5e_macsec_sa *rx_sa;
1033 	struct mlx5e_macsec *macsec;
1034 	struct list_head *list;
1035 	int err = 0;
1036 
1037 	mutex_lock(&priv->macsec->lock);
1038 
1039 	macsec = priv->macsec;
1040 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1041 	if (!macsec_device) {
1042 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1043 		err = -EINVAL;
1044 		goto out;
1045 	}
1046 
1047 	list = &macsec_device->macsec_rx_sc_list_head;
1048 	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
1049 	if (!rx_sc) {
1050 		netdev_err(ctx->netdev,
1051 			   "MACsec offload rx_sc sci %lld doesn't exist\n",
1052 			   ctx->sa.rx_sa->sc->sci);
1053 		err = -EINVAL;
1054 		goto out;
1055 	}
1056 
1057 	rx_sa = rx_sc->rx_sa[assoc_num];
1058 	if (!rx_sa) {
1059 		netdev_err(ctx->netdev,
1060 			   "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n",
1061 			   sci, assoc_num);
1062 		err = -EINVAL;
1063 		goto out;
1064 	}
1065 
1066 	if (rx_sa->active)
1067 		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev,
1068 					rx_sc->sc_xarray_element->fs_id);
1069 	mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
1070 	kfree(rx_sa);
1071 	rx_sc->rx_sa[assoc_num] = NULL;
1072 
1073 out:
1074 	mutex_unlock(&macsec->lock);
1075 
1076 	return err;
1077 }
1078 
mlx5e_macsec_add_secy(struct macsec_context * ctx)1079 static int mlx5e_macsec_add_secy(struct macsec_context *ctx)
1080 {
1081 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1082 	const struct net_device *dev = ctx->secy->netdev;
1083 	const struct net_device *netdev = ctx->netdev;
1084 	struct mlx5e_macsec_device *macsec_device;
1085 	struct mlx5e_macsec *macsec;
1086 	int err = 0;
1087 
1088 	if (!mlx5e_macsec_secy_features_validate(ctx))
1089 		return -EINVAL;
1090 
1091 	mutex_lock(&priv->macsec->lock);
1092 	macsec = priv->macsec;
1093 	if (mlx5e_macsec_get_macsec_device_context(macsec, ctx)) {
1094 		netdev_err(netdev, "MACsec offload: MACsec net_device already exist\n");
1095 		goto out;
1096 	}
1097 
1098 	if (macsec->num_of_devices >= MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES) {
1099 		netdev_err(netdev, "Currently, only %d MACsec offload devices can be set\n",
1100 			   MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES);
1101 		err = -EBUSY;
1102 		goto out;
1103 	}
1104 
1105 	macsec_device = kzalloc_obj(*macsec_device);
1106 	if (!macsec_device) {
1107 		err = -ENOMEM;
1108 		goto out;
1109 	}
1110 
1111 	macsec_device->dev_addr = kmemdup(dev->dev_addr, dev->addr_len, GFP_KERNEL);
1112 	if (!macsec_device->dev_addr) {
1113 		kfree(macsec_device);
1114 		err = -ENOMEM;
1115 		goto out;
1116 	}
1117 
1118 	macsec_device->netdev = dev;
1119 
1120 	INIT_LIST_HEAD_RCU(&macsec_device->macsec_rx_sc_list_head);
1121 	list_add_rcu(&macsec_device->macsec_device_list_element, &macsec->macsec_device_list_head);
1122 
1123 	++macsec->num_of_devices;
1124 out:
1125 	mutex_unlock(&macsec->lock);
1126 
1127 	return err;
1128 }
1129 
macsec_upd_secy_hw_address(struct macsec_context * ctx,struct mlx5e_macsec_device * macsec_device)1130 static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
1131 				      struct mlx5e_macsec_device *macsec_device)
1132 {
1133 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1134 	const struct net_device *dev = ctx->secy->netdev;
1135 	struct mlx5e_macsec *macsec = priv->macsec;
1136 	struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
1137 	struct mlx5e_macsec_sa *rx_sa;
1138 	struct list_head *list;
1139 	int i, err = 0;
1140 
1141 
1142 	list = &macsec_device->macsec_rx_sc_list_head;
1143 	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) {
1144 		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1145 			rx_sa = rx_sc->rx_sa[i];
1146 			if (!rx_sa || !rx_sa->macsec_rule)
1147 				continue;
1148 
1149 			mlx5e_macsec_cleanup_sa_fs(macsec, rx_sa, false, ctx->secy->netdev,
1150 						   rx_sc->sc_xarray_element->fs_id);
1151 		}
1152 	}
1153 
1154 	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) {
1155 		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1156 			rx_sa = rx_sc->rx_sa[i];
1157 			if (!rx_sa)
1158 				continue;
1159 
1160 			if (rx_sa->active) {
1161 				err = mlx5e_macsec_init_sa_fs(ctx, rx_sa, true, false,
1162 							      &rx_sc->sc_xarray_element->fs_id);
1163 				if (err)
1164 					goto out;
1165 			}
1166 		}
1167 	}
1168 
1169 	memcpy(macsec_device->dev_addr, dev->dev_addr, dev->addr_len);
1170 out:
1171 	return err;
1172 }
1173 
1174 /* this function is called from 2 macsec ops functions:
1175  *  macsec_set_mac_address – MAC address was changed, therefore we need to destroy
1176  *  and create new Tx contexts(macsec object + steering).
1177  *  macsec_changelink – in this case the tx SC or SecY may be changed, therefore need to
1178  *  destroy Tx and Rx contexts(macsec object + steering)
1179  */
mlx5e_macsec_upd_secy(struct macsec_context * ctx)1180 static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
1181 {
1182 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1183 	const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
1184 	const struct net_device *dev = ctx->secy->netdev;
1185 	struct mlx5e_macsec_device *macsec_device;
1186 	struct mlx5e_macsec_sa *tx_sa;
1187 	struct mlx5e_macsec *macsec;
1188 	int i, err = 0;
1189 
1190 	if (!mlx5e_macsec_secy_features_validate(ctx))
1191 		return -EINVAL;
1192 
1193 	mutex_lock(&priv->macsec->lock);
1194 
1195 	macsec = priv->macsec;
1196 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1197 	if (!macsec_device) {
1198 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1199 		err = -EINVAL;
1200 		goto out;
1201 	}
1202 
1203 	/* if the dev_addr hasn't change, it mean the callback is from macsec_changelink */
1204 	if (!memcmp(macsec_device->dev_addr, dev->dev_addr, dev->addr_len)) {
1205 		err = macsec_upd_secy_hw_address(ctx, macsec_device);
1206 		if (err)
1207 			goto out;
1208 	}
1209 
1210 	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1211 		tx_sa = macsec_device->tx_sa[i];
1212 		if (!tx_sa)
1213 			continue;
1214 
1215 		mlx5e_macsec_cleanup_sa_fs(macsec, tx_sa, true, ctx->secy->netdev, 0);
1216 	}
1217 
1218 	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1219 		tx_sa = macsec_device->tx_sa[i];
1220 		if (!tx_sa)
1221 			continue;
1222 
1223 		if (tx_sa->assoc_num == tx_sc->encoding_sa && tx_sa->active) {
1224 			err = mlx5e_macsec_init_sa_fs(ctx, tx_sa, tx_sc->encrypt, true, NULL);
1225 			if (err)
1226 				goto out;
1227 		}
1228 	}
1229 
1230 out:
1231 	mutex_unlock(&macsec->lock);
1232 
1233 	return err;
1234 }
1235 
mlx5e_macsec_del_secy(struct macsec_context * ctx)1236 static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
1237 {
1238 	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1239 	struct mlx5e_macsec_device *macsec_device;
1240 	struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
1241 	struct mlx5e_macsec_sa *tx_sa;
1242 	struct mlx5e_macsec *macsec;
1243 	struct list_head *list;
1244 	int err = 0;
1245 	int i;
1246 
1247 	mutex_lock(&priv->macsec->lock);
1248 	macsec = priv->macsec;
1249 	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1250 	if (!macsec_device) {
1251 		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1252 		err = -EINVAL;
1253 
1254 		goto out;
1255 	}
1256 
1257 	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1258 		tx_sa = macsec_device->tx_sa[i];
1259 		if (!tx_sa)
1260 			continue;
1261 
1262 		mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
1263 		mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
1264 		kfree(tx_sa);
1265 		macsec_device->tx_sa[i] = NULL;
1266 	}
1267 
1268 	list = &macsec_device->macsec_rx_sc_list_head;
1269 	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element)
1270 		macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
1271 
1272 	kfree(macsec_device->dev_addr);
1273 	macsec_device->dev_addr = NULL;
1274 
1275 	list_del_rcu(&macsec_device->macsec_device_list_element);
1276 	--macsec->num_of_devices;
1277 	kfree(macsec_device);
1278 
1279 out:
1280 	mutex_unlock(&macsec->lock);
1281 
1282 	return err;
1283 }
1284 
macsec_build_accel_attrs(struct mlx5e_macsec_sa * sa,struct mlx5_macsec_obj_attrs * attrs)1285 static void macsec_build_accel_attrs(struct mlx5e_macsec_sa *sa,
1286 				     struct mlx5_macsec_obj_attrs *attrs)
1287 {
1288 	attrs->epn_state.epn_msb = sa->epn_state.epn_msb;
1289 	attrs->epn_state.overlap = sa->epn_state.overlap;
1290 }
1291 
macsec_aso_build_wqe_ctrl_seg(struct mlx5e_macsec_aso * macsec_aso,struct mlx5_wqe_aso_ctrl_seg * aso_ctrl,struct mlx5_aso_ctrl_param * param)1292 static void macsec_aso_build_wqe_ctrl_seg(struct mlx5e_macsec_aso *macsec_aso,
1293 					  struct mlx5_wqe_aso_ctrl_seg *aso_ctrl,
1294 					  struct mlx5_aso_ctrl_param *param)
1295 {
1296 	struct mlx5e_macsec_umr *umr = macsec_aso->umr;
1297 
1298 	memset(aso_ctrl, 0, sizeof(*aso_ctrl));
1299 	aso_ctrl->va_l = cpu_to_be32(umr->dma_addr | ASO_CTRL_READ_EN);
1300 	aso_ctrl->va_h = cpu_to_be32((u64)umr->dma_addr >> 32);
1301 	aso_ctrl->l_key = cpu_to_be32(umr->mkey);
1302 
1303 	if (!param)
1304 		return;
1305 
1306 	aso_ctrl->data_mask_mode = param->data_mask_mode << 6;
1307 	aso_ctrl->condition_1_0_operand = param->condition_1_operand |
1308 						param->condition_0_operand << 4;
1309 	aso_ctrl->condition_1_0_offset = param->condition_1_offset |
1310 						param->condition_0_offset << 4;
1311 	aso_ctrl->data_offset_condition_operand = param->data_offset |
1312 						param->condition_operand << 6;
1313 	aso_ctrl->condition_0_data = cpu_to_be32(param->condition_0_data);
1314 	aso_ctrl->condition_0_mask = cpu_to_be32(param->condition_0_mask);
1315 	aso_ctrl->condition_1_data = cpu_to_be32(param->condition_1_data);
1316 	aso_ctrl->condition_1_mask = cpu_to_be32(param->condition_1_mask);
1317 	aso_ctrl->bitwise_data = cpu_to_be64(param->bitwise_data);
1318 	aso_ctrl->data_mask = cpu_to_be64(param->data_mask);
1319 }
1320 
mlx5e_macsec_modify_obj(struct mlx5_core_dev * mdev,struct mlx5_macsec_obj_attrs * attrs,u32 macsec_id)1321 static int mlx5e_macsec_modify_obj(struct mlx5_core_dev *mdev, struct mlx5_macsec_obj_attrs *attrs,
1322 				   u32 macsec_id)
1323 {
1324 	u32 in[MLX5_ST_SZ_DW(modify_macsec_obj_in)] = {};
1325 	u32 out[MLX5_ST_SZ_DW(query_macsec_obj_out)];
1326 	u64 modify_field_select = 0;
1327 	void *obj;
1328 	int err;
1329 
1330 	/* General object fields set */
1331 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
1332 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC);
1333 	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, macsec_id);
1334 	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1335 	if (err) {
1336 		mlx5_core_err(mdev, "Query MACsec object failed (Object id %d), err = %d\n",
1337 			      macsec_id, err);
1338 		return err;
1339 	}
1340 
1341 	obj = MLX5_ADDR_OF(query_macsec_obj_out, out, macsec_object);
1342 	modify_field_select = MLX5_GET64(macsec_offload_obj, obj, modify_field_select);
1343 
1344 	/* EPN */
1345 	if (!(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP) ||
1346 	    !(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB)) {
1347 		mlx5_core_dbg(mdev, "MACsec object field is not modifiable (Object id %d)\n",
1348 			      macsec_id);
1349 		return -EOPNOTSUPP;
1350 	}
1351 
1352 	obj = MLX5_ADDR_OF(modify_macsec_obj_in, in, macsec_object);
1353 	MLX5_SET64(macsec_offload_obj, obj, modify_field_select,
1354 		   MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP | MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB);
1355 	MLX5_SET(macsec_offload_obj, obj, epn_msb, attrs->epn_state.epn_msb);
1356 	MLX5_SET(macsec_offload_obj, obj, epn_overlap, attrs->epn_state.overlap);
1357 
1358 	/* General object fields set */
1359 	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
1360 
1361 	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1362 }
1363 
macsec_aso_build_ctrl(struct mlx5e_macsec_aso * aso,struct mlx5_wqe_aso_ctrl_seg * aso_ctrl,struct mlx5e_macsec_aso_in * in)1364 static void macsec_aso_build_ctrl(struct mlx5e_macsec_aso *aso,
1365 				  struct mlx5_wqe_aso_ctrl_seg *aso_ctrl,
1366 				  struct mlx5e_macsec_aso_in *in)
1367 {
1368 	struct mlx5_aso_ctrl_param param = {};
1369 
1370 	param.data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BITWISE_64BIT;
1371 	param.condition_0_operand = MLX5_ASO_ALWAYS_TRUE;
1372 	param.condition_1_operand = MLX5_ASO_ALWAYS_TRUE;
1373 	if (in->mode == MLX5_MACSEC_EPN) {
1374 		param.data_offset = MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET;
1375 		param.bitwise_data = BIT_ULL(54);
1376 		param.data_mask = param.bitwise_data;
1377 	}
1378 	macsec_aso_build_wqe_ctrl_seg(aso, aso_ctrl, &param);
1379 }
1380 
macsec_aso_set_arm_event(struct mlx5_core_dev * mdev,struct mlx5e_macsec * macsec,struct mlx5e_macsec_aso_in * in)1381 static int macsec_aso_set_arm_event(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec,
1382 				    struct mlx5e_macsec_aso_in *in)
1383 {
1384 	struct mlx5e_macsec_aso *aso;
1385 	struct mlx5_aso_wqe *aso_wqe;
1386 	struct mlx5_aso *maso;
1387 	int err;
1388 
1389 	aso = &macsec->aso;
1390 	maso = aso->maso;
1391 
1392 	mutex_lock(&aso->aso_lock);
1393 	aso_wqe = mlx5_aso_get_wqe(maso);
1394 	mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id,
1395 			   MLX5_ACCESS_ASO_OPC_MOD_MACSEC);
1396 	macsec_aso_build_ctrl(aso, &aso_wqe->aso_ctrl, in);
1397 	mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
1398 	read_poll_timeout(mlx5_aso_poll_cq, err, !err, 10, 10 * USEC_PER_MSEC,
1399 			  false, maso, false);
1400 	mutex_unlock(&aso->aso_lock);
1401 
1402 	return err;
1403 }
1404 
macsec_aso_query(struct mlx5_core_dev * mdev,struct mlx5e_macsec * macsec,struct mlx5e_macsec_aso_in * in,struct mlx5e_macsec_aso_out * out)1405 static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec,
1406 			    struct mlx5e_macsec_aso_in *in, struct mlx5e_macsec_aso_out *out)
1407 {
1408 	struct mlx5e_macsec_aso *aso;
1409 	struct mlx5_aso_wqe *aso_wqe;
1410 	struct mlx5_aso *maso;
1411 	int err;
1412 
1413 	aso = &macsec->aso;
1414 	maso = aso->maso;
1415 
1416 	mutex_lock(&aso->aso_lock);
1417 
1418 	aso_wqe = mlx5_aso_get_wqe(maso);
1419 	mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id,
1420 			   MLX5_ACCESS_ASO_OPC_MOD_MACSEC);
1421 	macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL);
1422 
1423 	mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
1424 	read_poll_timeout(mlx5_aso_poll_cq, err, !err, 10, 10 * USEC_PER_MSEC,
1425 			  false, maso, false);
1426 
1427 	if (err)
1428 		goto err_out;
1429 
1430 	if (MLX5_GET(macsec_aso, aso->umr->ctx, epn_event_arm))
1431 		out->event_arm |= MLX5E_ASO_EPN_ARM;
1432 
1433 	out->mode_param = MLX5_GET(macsec_aso, aso->umr->ctx, mode_parameter);
1434 
1435 err_out:
1436 	mutex_unlock(&aso->aso_lock);
1437 	return err;
1438 }
1439 
get_macsec_tx_sa_from_obj_id(const struct mlx5e_macsec * macsec,const u32 obj_id)1440 static struct mlx5e_macsec_sa *get_macsec_tx_sa_from_obj_id(const struct mlx5e_macsec *macsec,
1441 							    const u32 obj_id)
1442 {
1443 	const struct list_head *device_list;
1444 	struct mlx5e_macsec_sa *macsec_sa;
1445 	struct mlx5e_macsec_device *iter;
1446 	int i;
1447 
1448 	device_list = &macsec->macsec_device_list_head;
1449 
1450 	list_for_each_entry(iter, device_list, macsec_device_list_element) {
1451 		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1452 			macsec_sa = iter->tx_sa[i];
1453 			if (!macsec_sa || !macsec_sa->active)
1454 				continue;
1455 			if (macsec_sa->macsec_obj_id == obj_id)
1456 				return macsec_sa;
1457 		}
1458 	}
1459 
1460 	return NULL;
1461 }
1462 
get_macsec_rx_sa_from_obj_id(const struct mlx5e_macsec * macsec,const u32 obj_id)1463 static struct mlx5e_macsec_sa *get_macsec_rx_sa_from_obj_id(const struct mlx5e_macsec *macsec,
1464 							    const u32 obj_id)
1465 {
1466 	const struct list_head *device_list, *sc_list;
1467 	struct mlx5e_macsec_rx_sc *mlx5e_rx_sc;
1468 	struct mlx5e_macsec_sa *macsec_sa;
1469 	struct mlx5e_macsec_device *iter;
1470 	int i;
1471 
1472 	device_list = &macsec->macsec_device_list_head;
1473 
1474 	list_for_each_entry(iter, device_list, macsec_device_list_element) {
1475 		sc_list = &iter->macsec_rx_sc_list_head;
1476 		list_for_each_entry(mlx5e_rx_sc, sc_list, rx_sc_list_element) {
1477 			for (i = 0; i < MACSEC_NUM_AN; ++i) {
1478 				macsec_sa = mlx5e_rx_sc->rx_sa[i];
1479 				if (!macsec_sa || !macsec_sa->active)
1480 					continue;
1481 				if (macsec_sa->macsec_obj_id == obj_id)
1482 					return macsec_sa;
1483 			}
1484 		}
1485 	}
1486 
1487 	return NULL;
1488 }
1489 
macsec_epn_update(struct mlx5e_macsec * macsec,struct mlx5_core_dev * mdev,struct mlx5e_macsec_sa * sa,u32 obj_id,u32 mode_param)1490 static void macsec_epn_update(struct mlx5e_macsec *macsec, struct mlx5_core_dev *mdev,
1491 			      struct mlx5e_macsec_sa *sa, u32 obj_id, u32 mode_param)
1492 {
1493 	struct mlx5_macsec_obj_attrs attrs = {};
1494 	struct mlx5e_macsec_aso_in in = {};
1495 
1496 	/* When the bottom of the replay protection window (mode_param) crosses 2^31 (half sequence
1497 	 * number wraparound) hence mode_param > MLX5_MACSEC_EPN_SCOPE_MID the SW should update the
1498 	 * esn_overlap to OLD (1).
1499 	 * When the bottom of the replay protection window (mode_param) crosses 2^32 (full sequence
1500 	 * number wraparound) hence mode_param < MLX5_MACSEC_EPN_SCOPE_MID since it did a
1501 	 * wraparound, the SW should update the esn_overlap to NEW (0), and increment the esn_msb.
1502 	 */
1503 
1504 	if (mode_param < MLX5_MACSEC_EPN_SCOPE_MID) {
1505 		sa->epn_state.epn_msb++;
1506 		sa->epn_state.overlap = 0;
1507 	} else {
1508 		sa->epn_state.overlap = 1;
1509 	}
1510 
1511 	macsec_build_accel_attrs(sa, &attrs);
1512 	mlx5e_macsec_modify_obj(mdev, &attrs, obj_id);
1513 
1514 	/* Re-set EPN arm event */
1515 	in.obj_id = obj_id;
1516 	in.mode = MLX5_MACSEC_EPN;
1517 	macsec_aso_set_arm_event(mdev, macsec, &in);
1518 }
1519 
macsec_async_event(struct work_struct * work)1520 static void macsec_async_event(struct work_struct *work)
1521 {
1522 	struct mlx5e_macsec_async_work *async_work;
1523 	struct mlx5e_macsec_aso_out out = {};
1524 	struct mlx5e_macsec_aso_in in = {};
1525 	struct mlx5e_macsec_sa *macsec_sa;
1526 	struct mlx5e_macsec *macsec;
1527 	struct mlx5_core_dev *mdev;
1528 	u32 obj_id;
1529 
1530 	async_work = container_of(work, struct mlx5e_macsec_async_work, work);
1531 	macsec = async_work->macsec;
1532 	mutex_lock(&macsec->lock);
1533 
1534 	mdev = async_work->mdev;
1535 	obj_id = async_work->obj_id;
1536 	macsec_sa = get_macsec_tx_sa_from_obj_id(macsec, obj_id);
1537 	if (!macsec_sa) {
1538 		macsec_sa = get_macsec_rx_sa_from_obj_id(macsec, obj_id);
1539 		if (!macsec_sa) {
1540 			mlx5_core_dbg(mdev, "MACsec SA is not found (SA object id %d)\n", obj_id);
1541 			goto out_async_work;
1542 		}
1543 	}
1544 
1545 	/* Query MACsec ASO context */
1546 	in.obj_id = obj_id;
1547 	macsec_aso_query(mdev, macsec, &in, &out);
1548 
1549 	/* EPN case */
1550 	if (macsec_sa->epn_state.epn_enabled && !(out.event_arm & MLX5E_ASO_EPN_ARM))
1551 		macsec_epn_update(macsec, mdev, macsec_sa, obj_id, out.mode_param);
1552 
1553 out_async_work:
1554 	kfree(async_work);
1555 	mutex_unlock(&macsec->lock);
1556 }
1557 
macsec_obj_change_event(struct notifier_block * nb,unsigned long event,void * data)1558 static int macsec_obj_change_event(struct notifier_block *nb, unsigned long event, void *data)
1559 {
1560 	struct mlx5e_macsec *macsec = container_of(nb, struct mlx5e_macsec, nb);
1561 	struct mlx5e_macsec_async_work *async_work;
1562 	struct mlx5_eqe_obj_change *obj_change;
1563 	struct mlx5_eqe *eqe = data;
1564 	u16 obj_type;
1565 	u32 obj_id;
1566 
1567 	if (event != MLX5_EVENT_TYPE_OBJECT_CHANGE)
1568 		return NOTIFY_DONE;
1569 
1570 	obj_change = &eqe->data.obj_change;
1571 	obj_type = be16_to_cpu(obj_change->obj_type);
1572 	obj_id = be32_to_cpu(obj_change->obj_id);
1573 
1574 	if (obj_type != MLX5_GENERAL_OBJECT_TYPES_MACSEC)
1575 		return NOTIFY_DONE;
1576 
1577 	async_work = kzalloc_obj(*async_work, GFP_ATOMIC);
1578 	if (!async_work)
1579 		return NOTIFY_DONE;
1580 
1581 	async_work->macsec = macsec;
1582 	async_work->mdev = macsec->mdev;
1583 	async_work->obj_id = obj_id;
1584 
1585 	INIT_WORK(&async_work->work, macsec_async_event);
1586 
1587 	WARN_ON(!queue_work(macsec->wq, &async_work->work));
1588 
1589 	return NOTIFY_OK;
1590 }
1591 
mlx5e_macsec_aso_init(struct mlx5e_macsec_aso * aso,struct mlx5_core_dev * mdev)1592 static int mlx5e_macsec_aso_init(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev)
1593 {
1594 	struct mlx5_aso *maso;
1595 	int err;
1596 
1597 	err = mlx5_core_alloc_pd(mdev, &aso->pdn);
1598 	if (err) {
1599 		mlx5_core_err(mdev,
1600 			      "MACsec offload: Failed to alloc pd for MACsec ASO, err=%d\n",
1601 			      err);
1602 		return err;
1603 	}
1604 
1605 	maso = mlx5_aso_create(mdev, aso->pdn);
1606 	if (IS_ERR(maso)) {
1607 		err = PTR_ERR(maso);
1608 		goto err_aso;
1609 	}
1610 
1611 	err = mlx5e_macsec_aso_reg_mr(mdev, aso);
1612 	if (err)
1613 		goto err_aso_reg;
1614 
1615 	mutex_init(&aso->aso_lock);
1616 
1617 	aso->maso = maso;
1618 
1619 	return 0;
1620 
1621 err_aso_reg:
1622 	mlx5_aso_destroy(maso);
1623 err_aso:
1624 	mlx5_core_dealloc_pd(mdev, aso->pdn);
1625 	return err;
1626 }
1627 
mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso * aso,struct mlx5_core_dev * mdev)1628 static void mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev)
1629 {
1630 	if (!aso)
1631 		return;
1632 
1633 	mlx5e_macsec_aso_dereg_mr(mdev, aso);
1634 
1635 	mlx5_aso_destroy(aso->maso);
1636 
1637 	mlx5_core_dealloc_pd(mdev, aso->pdn);
1638 }
1639 
1640 static const struct macsec_ops macsec_offload_ops = {
1641 	.mdo_add_txsa = mlx5e_macsec_add_txsa,
1642 	.mdo_upd_txsa = mlx5e_macsec_upd_txsa,
1643 	.mdo_del_txsa = mlx5e_macsec_del_txsa,
1644 	.mdo_add_rxsc = mlx5e_macsec_add_rxsc,
1645 	.mdo_upd_rxsc = mlx5e_macsec_upd_rxsc,
1646 	.mdo_del_rxsc = mlx5e_macsec_del_rxsc,
1647 	.mdo_add_rxsa = mlx5e_macsec_add_rxsa,
1648 	.mdo_upd_rxsa = mlx5e_macsec_upd_rxsa,
1649 	.mdo_del_rxsa = mlx5e_macsec_del_rxsa,
1650 	.mdo_add_secy = mlx5e_macsec_add_secy,
1651 	.mdo_upd_secy = mlx5e_macsec_upd_secy,
1652 	.mdo_del_secy = mlx5e_macsec_del_secy,
1653 	.rx_uses_md_dst = true,
1654 };
1655 
mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec * macsec,struct sk_buff * skb)1656 bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
1657 {
1658 	struct metadata_dst *md_dst = skb_metadata_dst(skb);
1659 	u32 fs_id;
1660 
1661 	fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
1662 							&md_dst->u.macsec_info.sci);
1663 	if (!fs_id)
1664 		goto err_out;
1665 
1666 	return true;
1667 
1668 err_out:
1669 	dev_kfree_skb_any(skb);
1670 	return false;
1671 }
1672 
mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec * macsec,struct sk_buff * skb,struct mlx5_wqe_eth_seg * eseg)1673 void mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec *macsec,
1674 				struct sk_buff *skb,
1675 				struct mlx5_wqe_eth_seg *eseg)
1676 {
1677 	struct metadata_dst *md_dst = skb_metadata_dst(skb);
1678 	u32 fs_id;
1679 
1680 	fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
1681 							&md_dst->u.macsec_info.sci);
1682 	if (!fs_id)
1683 		return;
1684 
1685 	eseg->flow_table_metadata = cpu_to_be32(MLX5_MACSEC_TX_METADATA(fs_id));
1686 }
1687 
mlx5e_macsec_offload_handle_rx_skb(struct net_device * netdev,struct sk_buff * skb,struct mlx5_cqe64 * cqe)1688 void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
1689 					struct sk_buff *skb,
1690 					struct mlx5_cqe64 *cqe)
1691 {
1692 	struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
1693 	u32 macsec_meta_data = be32_to_cpu(cqe->ft_metadata);
1694 	struct mlx5e_priv *priv = macsec_netdev_priv(netdev);
1695 	struct mlx5e_macsec_rx_sc *rx_sc;
1696 	struct mlx5e_macsec *macsec;
1697 	u32  fs_id;
1698 
1699 	macsec = priv->macsec;
1700 	if (!macsec)
1701 		return;
1702 
1703 	fs_id = MLX5_MACSEC_RX_METADAT_HANDLE(macsec_meta_data);
1704 
1705 	rcu_read_lock();
1706 	sc_xarray_element = xa_load(&macsec->sc_xarray, fs_id);
1707 	rx_sc = sc_xarray_element ? sc_xarray_element->rx_sc : NULL;
1708 	if (rx_sc && rx_sc->md_dst) {
1709 		if (dst_hold_safe(&rx_sc->md_dst->dst))
1710 			skb_dst_set(skb, &rx_sc->md_dst->dst);
1711 	}
1712 
1713 	rcu_read_unlock();
1714 }
1715 
mlx5e_macsec_build_netdev(struct mlx5e_priv * priv)1716 void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv)
1717 {
1718 	struct net_device *netdev = priv->netdev;
1719 
1720 	if (!mlx5e_is_macsec_device(priv->mdev))
1721 		return;
1722 
1723 	/* Enable MACsec */
1724 	mlx5_core_dbg(priv->mdev, "mlx5e: MACsec acceleration enabled\n");
1725 	netdev->macsec_ops = &macsec_offload_ops;
1726 	netdev->features |= NETIF_F_HW_MACSEC;
1727 	netif_keep_dst(netdev);
1728 }
1729 
mlx5e_macsec_init(struct mlx5e_priv * priv)1730 int mlx5e_macsec_init(struct mlx5e_priv *priv)
1731 {
1732 	struct mlx5_core_dev *mdev = priv->mdev;
1733 	struct mlx5e_macsec *macsec = NULL;
1734 	struct mlx5_macsec_fs *macsec_fs;
1735 	int err;
1736 
1737 	if (!mlx5e_is_macsec_device(priv->mdev)) {
1738 		mlx5_core_dbg(mdev, "Not a MACsec offload device\n");
1739 		return 0;
1740 	}
1741 
1742 	macsec = kzalloc_obj(*macsec);
1743 	if (!macsec)
1744 		return -ENOMEM;
1745 
1746 	INIT_LIST_HEAD(&macsec->macsec_device_list_head);
1747 	mutex_init(&macsec->lock);
1748 
1749 	err = mlx5e_macsec_aso_init(&macsec->aso, priv->mdev);
1750 	if (err) {
1751 		mlx5_core_err(mdev, "MACsec offload: Failed to init aso, err=%d\n", err);
1752 		goto err_aso;
1753 	}
1754 
1755 	macsec->wq = alloc_ordered_workqueue("mlx5e_macsec_%s", 0, priv->netdev->name);
1756 	if (!macsec->wq) {
1757 		err = -ENOMEM;
1758 		goto err_wq;
1759 	}
1760 
1761 	xa_init_flags(&macsec->sc_xarray, XA_FLAGS_ALLOC1);
1762 
1763 	priv->macsec = macsec;
1764 
1765 	macsec->mdev = mdev;
1766 
1767 	macsec_fs = mlx5_macsec_fs_init(mdev);
1768 	if (!macsec_fs) {
1769 		err = -ENOMEM;
1770 		goto err_out;
1771 	}
1772 
1773 	mdev->macsec_fs = macsec_fs;
1774 
1775 	macsec->nb.notifier_call = macsec_obj_change_event;
1776 	mlx5_notifier_register(mdev, &macsec->nb);
1777 
1778 	mlx5_core_dbg(mdev, "MACsec attached to netdevice\n");
1779 
1780 	return 0;
1781 
1782 err_out:
1783 	destroy_workqueue(macsec->wq);
1784 err_wq:
1785 	mlx5e_macsec_aso_cleanup(&macsec->aso, priv->mdev);
1786 err_aso:
1787 	kfree(macsec);
1788 	priv->macsec = NULL;
1789 	return err;
1790 }
1791 
mlx5e_macsec_cleanup(struct mlx5e_priv * priv)1792 void mlx5e_macsec_cleanup(struct mlx5e_priv *priv)
1793 {
1794 	struct mlx5e_macsec *macsec = priv->macsec;
1795 	struct mlx5_core_dev *mdev = priv->mdev;
1796 
1797 	if (!macsec)
1798 		return;
1799 
1800 	mlx5_notifier_unregister(mdev, &macsec->nb);
1801 	mlx5_macsec_fs_cleanup(mdev->macsec_fs);
1802 	destroy_workqueue(macsec->wq);
1803 	mlx5e_macsec_aso_cleanup(&macsec->aso, mdev);
1804 	mutex_destroy(&macsec->lock);
1805 	kfree(macsec);
1806 }
1807