File Index
Files and directories
Sign in
FILE

macsec.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c C
   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
  18enum mlx5_macsec_aso_event_arm {
  19	MLX5E_ASO_EPN_ARM = BIT(0),
  20};
  21
  22enum {
  23	MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET,
  24};
  25
  26struct mlx5e_macsec_handle {
  27	struct mlx5e_macsec *macsec;
  28	u32 obj_id;
  29	u8 idx;
  30};
  31
  32enum {
  33	MLX5_MACSEC_EPN,
  34};
  35
  36struct mlx5e_macsec_aso_out {
  37	u8 event_arm;
  38	u32 mode_param;
  39};
  40
  41struct mlx5e_macsec_aso_in {
  42	u8 mode;
  43	u32 obj_id;
  44};
  45
  46struct mlx5e_macsec_epn_state {
  47	u32 epn_msb;
  48	u8 epn_enabled;
  49	u8 overlap;
  50};
  51
  52struct 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
  59struct 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
  74struct mlx5e_macsec_rx_sc;
  75struct mlx5e_macsec_rx_sc_xarray_element {
  76	u32 fs_id;
  77	struct mlx5e_macsec_rx_sc *rx_sc;
  78};
  79
  80struct 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
  90struct 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
  96struct 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
 107struct 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
 115struct 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
 132struct 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
 145struct 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
 161static 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(sizeof(*umr), GFP_KERNEL);
 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
 194out_mkey:
 195	dma_unmap_single(dma_device, dma_addr, sizeof(umr->ctx), DMA_BIDIRECTIONAL);
 196out_dma:
 197	kfree(umr);
 198	return err;
 199}
 200
 201static 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
 210static 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
 239static 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
 302static 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
 314static 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
 329static 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
 337static 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
 365static 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
 402destroy_macsec_object:
 403	mlx5e_macsec_destroy_object(mdev, sa->macsec_obj_id);
 404
 405	return err;
 406}
 407
 408static struct mlx5e_macsec_rx_sc *
 409mlx5e_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
 421static 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
 445static 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
 476static struct mlx5e_macsec_device *
 477mlx5e_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
 492static 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
 504static 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(sizeof(*tx_sa), GFP_KERNEL);
 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
 566destroy_encryption_key:
 567	macsec_device->tx_sa[assoc_num] = NULL;
 568	mlx5_destroy_encryption_key(mdev, tx_sa->enc_key_id);
 569destroy_sa:
 570	kfree(tx_sa);
 571out:
 572	mutex_unlock(&macsec->lock);
 573
 574	return err;
 575}
 576
 577static 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	}
 633out:
 634	mutex_unlock(&macsec->lock);
 635
 636	return err;
 637}
 638
 639static 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
 669out:
 670	mutex_unlock(&macsec->lock);
 671
 672	return err;
 673}
 674
 675static 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(sizeof(*rx_sc), GFP_KERNEL);
 705	if (!rx_sc) {
 706		err = -ENOMEM;
 707		goto out;
 708	}
 709
 710	sc_xarray_element = kzalloc(sizeof(*sc_xarray_element), GFP_KERNEL);
 711	if (!sc_xarray_element) {
 712		err = -ENOMEM;
 713		goto destroy_rx_sc;
 714	}
 715
 716	sc_xarray_element->rx_sc = rx_sc;
 717	err = xa_alloc(&macsec->sc_xarray, &sc_xarray_element->fs_id, sc_xarray_element,
 718		       XA_LIMIT(1, MLX5_MACEC_RX_FS_ID_MAX), GFP_KERNEL);
 719	if (err) {
 720		if (err == -EBUSY)
 721			netdev_err(ctx->netdev,
 722				   "MACsec offload: unable to create entry for RX SC (%d Rx SCs already allocated)\n",
 723				   MLX5_MACEC_RX_FS_ID_MAX);
 724		goto destroy_sc_xarray_elemenet;
 725	}
 726
 727	rx_sc->md_dst = metadata_dst_alloc(0, METADATA_MACSEC, GFP_KERNEL);
 728	if (!rx_sc->md_dst) {
 729		err = -ENOMEM;
 730		goto erase_xa_alloc;
 731	}
 732
 733	rx_sc->sci = ctx_rx_sc->sci;
 734	rx_sc->active = ctx_rx_sc->active;
 735	list_add_rcu(&rx_sc->rx_sc_list_element, rx_sc_list);
 736
 737	rx_sc->sc_xarray_element = sc_xarray_element;
 738	rx_sc->md_dst->u.macsec_info.sci = rx_sc->sci;
 739	mutex_unlock(&macsec->lock);
 740
 741	return 0;
 742
 743erase_xa_alloc:
 744	xa_erase(&macsec->sc_xarray, sc_xarray_element->fs_id);
 745destroy_sc_xarray_elemenet:
 746	kfree(sc_xarray_element);
 747destroy_rx_sc:
 748	kfree(rx_sc);
 749
 750out:
 751	mutex_unlock(&macsec->lock);
 752
 753	return err;
 754}
 755
 756static int mlx5e_macsec_upd_rxsc(struct macsec_context *ctx)
 757{
 758	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
 759	const struct macsec_rx_sc *ctx_rx_sc = ctx->rx_sc;
 760	struct mlx5e_macsec_device *macsec_device;
 761	struct mlx5e_macsec_rx_sc *rx_sc;
 762	struct mlx5e_macsec_sa *rx_sa;
 763	struct mlx5e_macsec *macsec;
 764	struct list_head *list;
 765	int i;
 766	int err = 0;
 767
 768	mutex_lock(&priv->macsec->lock);
 769
 770	macsec = priv->macsec;
 771	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
 772	if (!macsec_device) {
 773		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
 774		err = -EINVAL;
 775		goto out;
 776	}
 777
 778	list = &macsec_device->macsec_rx_sc_list_head;
 779	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx_rx_sc->sci);
 780	if (!rx_sc) {
 781		err = -EINVAL;
 782		goto out;
 783	}
 784
 785	if (rx_sc->active == ctx_rx_sc->active)
 786		goto out;
 787
 788	rx_sc->active = ctx_rx_sc->active;
 789	for (i = 0; i < MACSEC_NUM_AN; ++i) {
 790		rx_sa = rx_sc->rx_sa[i];
 791		if (!rx_sa)
 792			continue;
 793
 794		err = macsec_rx_sa_active_update(ctx, rx_sa, rx_sa->active && ctx_rx_sc->active,
 795						 &rx_sc->sc_xarray_element->fs_id);
 796		if (err)
 797			goto out;
 798	}
 799
 800out:
 801	mutex_unlock(&macsec->lock);
 802
 803	return err;
 804}
 805
 806static void macsec_del_rxsc_ctx(struct mlx5e_macsec *macsec, struct mlx5e_macsec_rx_sc *rx_sc,
 807				struct net_device *netdev)
 808{
 809	struct mlx5e_macsec_sa *rx_sa;
 810	int i;
 811
 812	for (i = 0; i < MACSEC_NUM_AN; ++i) {
 813		rx_sa = rx_sc->rx_sa[i];
 814		if (!rx_sa)
 815			continue;
 816
 817		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, netdev,
 818					rx_sc->sc_xarray_element->fs_id);
 819		mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
 820
 821		kfree(rx_sa);
 822		rx_sc->rx_sa[i] = NULL;
 823	}
 824
 825	/* At this point the relevant MACsec offload Rx rule already removed at
 826	 * mlx5e_macsec_cleanup_sa need to wait for datapath to finish current
 827	 * Rx related data propagating using xa_erase which uses rcu to sync,
 828	 * once fs_id is erased then this rx_sc is hidden from datapath.
 829	 */
 830	list_del_rcu(&rx_sc->rx_sc_list_element);
 831	xa_erase(&macsec->sc_xarray, rx_sc->sc_xarray_element->fs_id);
 832	metadata_dst_free(rx_sc->md_dst);
 833	kfree(rx_sc->sc_xarray_element);
 834	kfree_rcu_mightsleep(rx_sc);
 835}
 836
 837static int mlx5e_macsec_del_rxsc(struct macsec_context *ctx)
 838{
 839	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
 840	struct mlx5e_macsec_device *macsec_device;
 841	struct mlx5e_macsec_rx_sc *rx_sc;
 842	struct mlx5e_macsec *macsec;
 843	struct list_head *list;
 844	int err = 0;
 845
 846	mutex_lock(&priv->macsec->lock);
 847
 848	macsec = priv->macsec;
 849	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
 850	if (!macsec_device) {
 851		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
 852		err = -EINVAL;
 853		goto out;
 854	}
 855
 856	list = &macsec_device->macsec_rx_sc_list_head;
 857	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, ctx->rx_sc->sci);
 858	if (!rx_sc) {
 859		netdev_err(ctx->netdev,
 860			   "MACsec offload rx_sc sci %lld doesn't exist\n",
 861			   ctx->sa.rx_sa->sc->sci);
 862		err = -EINVAL;
 863		goto out;
 864	}
 865
 866	macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
 867out:
 868	mutex_unlock(&macsec->lock);
 869
 870	return err;
 871}
 872
 873static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
 874{
 875	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
 876	const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
 877	struct mlx5e_macsec_device *macsec_device;
 878	struct mlx5_core_dev *mdev = priv->mdev;
 879	u8 assoc_num = ctx->sa.assoc_num;
 880	struct mlx5e_macsec_rx_sc *rx_sc;
 881	sci_t sci = ctx_rx_sa->sc->sci;
 882	struct mlx5e_macsec_sa *rx_sa;
 883	struct mlx5e_macsec *macsec;
 884	struct list_head *list;
 885	int err = 0;
 886
 887	mutex_lock(&priv->macsec->lock);
 888
 889	macsec = priv->macsec;
 890	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
 891	if (!macsec_device) {
 892		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
 893		err = -EINVAL;
 894		goto out;
 895	}
 896
 897	list = &macsec_device->macsec_rx_sc_list_head;
 898	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
 899	if (!rx_sc) {
 900		netdev_err(ctx->netdev,
 901			   "MACsec offload rx_sc sci %lld doesn't exist\n",
 902			   ctx->sa.rx_sa->sc->sci);
 903		err = -EINVAL;
 904		goto out;
 905	}
 906
 907	if (rx_sc->rx_sa[assoc_num]) {
 908		netdev_err(ctx->netdev,
 909			   "MACsec offload rx_sc sci %lld rx_sa %d already exist\n",
 910			   sci, assoc_num);
 911		err = -EEXIST;
 912		goto out;
 913	}
 914
 915	rx_sa = kzalloc(sizeof(*rx_sa), GFP_KERNEL);
 916	if (!rx_sa) {
 917		err = -ENOMEM;
 918		goto out;
 919	}
 920
 921	rx_sa->active = ctx_rx_sa->active;
 922	rx_sa->next_pn = ctx_rx_sa->next_pn;
 923	rx_sa->sci = sci;
 924	rx_sa->assoc_num = assoc_num;
 925
 926	if (ctx->secy->xpn)
 927		update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves,
 928				  ctx_rx_sa->ssci);
 929
 930	err = mlx5_create_encryption_key(mdev, ctx->sa.key, ctx->secy->key_len,
 931					 MLX5_ACCEL_OBJ_MACSEC_KEY,
 932					 &rx_sa->enc_key_id);
 933	if (err)
 934		goto destroy_sa;
 935
 936	rx_sc->rx_sa[assoc_num] = rx_sa;
 937	if (!rx_sa->active)
 938		goto out;
 939
 940	//TODO - add support for both authentication and encryption flows
 941	err = mlx5e_macsec_init_sa(ctx, rx_sa, true, false, &rx_sc->sc_xarray_element->fs_id);
 942	if (err)
 943		goto destroy_encryption_key;
 944
 945	goto out;
 946
 947destroy_encryption_key:
 948	rx_sc->rx_sa[assoc_num] = NULL;
 949	mlx5_destroy_encryption_key(mdev, rx_sa->enc_key_id);
 950destroy_sa:
 951	kfree(rx_sa);
 952out:
 953	mutex_unlock(&macsec->lock);
 954
 955	return err;
 956}
 957
 958static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx)
 959{
 960	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
 961	const struct macsec_rx_sa *ctx_rx_sa = ctx->sa.rx_sa;
 962	struct mlx5e_macsec_device *macsec_device;
 963	u8 assoc_num = ctx->sa.assoc_num;
 964	struct mlx5e_macsec_rx_sc *rx_sc;
 965	sci_t sci = ctx_rx_sa->sc->sci;
 966	struct mlx5e_macsec_sa *rx_sa;
 967	struct mlx5e_macsec *macsec;
 968	struct list_head *list;
 969	int err = 0;
 970
 971	mutex_lock(&priv->macsec->lock);
 972
 973	macsec = priv->macsec;
 974	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
 975	if (!macsec_device) {
 976		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
 977		err = -EINVAL;
 978		goto out;
 979	}
 980
 981	list = &macsec_device->macsec_rx_sc_list_head;
 982	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
 983	if (!rx_sc) {
 984		netdev_err(ctx->netdev,
 985			   "MACsec offload rx_sc sci %lld doesn't exist\n",
 986			   ctx->sa.rx_sa->sc->sci);
 987		err = -EINVAL;
 988		goto out;
 989	}
 990
 991	rx_sa = rx_sc->rx_sa[assoc_num];
 992	if (!rx_sa) {
 993		netdev_err(ctx->netdev,
 994			   "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n",
 995			   sci, assoc_num);
 996		err = -EINVAL;
 997		goto out;
 998	}
 999
1000	if (ctx->sa.update_pn) {
1001		netdev_err(ctx->netdev,
1002			   "MACsec offload update RX sa %d PN isn't supported\n",
1003			   assoc_num);
1004		err = -EINVAL;
1005		goto out;
1006	}
1007
1008	err = macsec_rx_sa_active_update(ctx, rx_sa, ctx_rx_sa->active,
1009					 &rx_sc->sc_xarray_element->fs_id);
1010out:
1011	mutex_unlock(&macsec->lock);
1012
1013	return err;
1014}
1015
1016static int mlx5e_macsec_del_rxsa(struct macsec_context *ctx)
1017{
1018	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1019	struct mlx5e_macsec_device *macsec_device;
1020	sci_t sci = ctx->sa.rx_sa->sc->sci;
1021	struct mlx5e_macsec_rx_sc *rx_sc;
1022	u8 assoc_num = ctx->sa.assoc_num;
1023	struct mlx5e_macsec_sa *rx_sa;
1024	struct mlx5e_macsec *macsec;
1025	struct list_head *list;
1026	int err = 0;
1027
1028	mutex_lock(&priv->macsec->lock);
1029
1030	macsec = priv->macsec;
1031	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1032	if (!macsec_device) {
1033		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1034		err = -EINVAL;
1035		goto out;
1036	}
1037
1038	list = &macsec_device->macsec_rx_sc_list_head;
1039	rx_sc = mlx5e_macsec_get_rx_sc_from_sc_list(list, sci);
1040	if (!rx_sc) {
1041		netdev_err(ctx->netdev,
1042			   "MACsec offload rx_sc sci %lld doesn't exist\n",
1043			   ctx->sa.rx_sa->sc->sci);
1044		err = -EINVAL;
1045		goto out;
1046	}
1047
1048	rx_sa = rx_sc->rx_sa[assoc_num];
1049	if (!rx_sa) {
1050		netdev_err(ctx->netdev,
1051			   "MACsec offload rx_sc sci %lld rx_sa %d doesn't exist\n",
1052			   sci, assoc_num);
1053		err = -EINVAL;
1054		goto out;
1055	}
1056
1057	if (rx_sa->active)
1058		mlx5e_macsec_cleanup_sa(macsec, rx_sa, false, ctx->secy->netdev,
1059					rx_sc->sc_xarray_element->fs_id);
1060	mlx5_destroy_encryption_key(macsec->mdev, rx_sa->enc_key_id);
1061	kfree(rx_sa);
1062	rx_sc->rx_sa[assoc_num] = NULL;
1063
1064out:
1065	mutex_unlock(&macsec->lock);
1066
1067	return err;
1068}
1069
1070static int mlx5e_macsec_add_secy(struct macsec_context *ctx)
1071{
1072	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1073	const struct net_device *dev = ctx->secy->netdev;
1074	const struct net_device *netdev = ctx->netdev;
1075	struct mlx5e_macsec_device *macsec_device;
1076	struct mlx5e_macsec *macsec;
1077	int err = 0;
1078
1079	if (!mlx5e_macsec_secy_features_validate(ctx))
1080		return -EINVAL;
1081
1082	mutex_lock(&priv->macsec->lock);
1083	macsec = priv->macsec;
1084	if (mlx5e_macsec_get_macsec_device_context(macsec, ctx)) {
1085		netdev_err(netdev, "MACsec offload: MACsec net_device already exist\n");
1086		goto out;
1087	}
1088
1089	if (macsec->num_of_devices >= MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES) {
1090		netdev_err(netdev, "Currently, only %d MACsec offload devices can be set\n",
1091			   MLX5_MACSEC_NUM_OF_SUPPORTED_INTERFACES);
1092		err = -EBUSY;
1093		goto out;
1094	}
1095
1096	macsec_device = kzalloc(sizeof(*macsec_device), GFP_KERNEL);
1097	if (!macsec_device) {
1098		err = -ENOMEM;
1099		goto out;
1100	}
1101
1102	macsec_device->dev_addr = kmemdup(dev->dev_addr, dev->addr_len, GFP_KERNEL);
1103	if (!macsec_device->dev_addr) {
1104		kfree(macsec_device);
1105		err = -ENOMEM;
1106		goto out;
1107	}
1108
1109	macsec_device->netdev = dev;
1110
1111	INIT_LIST_HEAD_RCU(&macsec_device->macsec_rx_sc_list_head);
1112	list_add_rcu(&macsec_device->macsec_device_list_element, &macsec->macsec_device_list_head);
1113
1114	++macsec->num_of_devices;
1115out:
1116	mutex_unlock(&macsec->lock);
1117
1118	return err;
1119}
1120
1121static int macsec_upd_secy_hw_address(struct macsec_context *ctx,
1122				      struct mlx5e_macsec_device *macsec_device)
1123{
1124	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1125	const struct net_device *dev = ctx->secy->netdev;
1126	struct mlx5e_macsec *macsec = priv->macsec;
1127	struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
1128	struct mlx5e_macsec_sa *rx_sa;
1129	struct list_head *list;
1130	int i, err = 0;
1131
1132
1133	list = &macsec_device->macsec_rx_sc_list_head;
1134	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) {
1135		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1136			rx_sa = rx_sc->rx_sa[i];
1137			if (!rx_sa || !rx_sa->macsec_rule)
1138				continue;
1139
1140			mlx5e_macsec_cleanup_sa_fs(macsec, rx_sa, false, ctx->secy->netdev,
1141						   rx_sc->sc_xarray_element->fs_id);
1142		}
1143	}
1144
1145	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element) {
1146		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1147			rx_sa = rx_sc->rx_sa[i];
1148			if (!rx_sa)
1149				continue;
1150
1151			if (rx_sa->active) {
1152				err = mlx5e_macsec_init_sa_fs(ctx, rx_sa, true, false,
1153							      &rx_sc->sc_xarray_element->fs_id);
1154				if (err)
1155					goto out;
1156			}
1157		}
1158	}
1159
1160	memcpy(macsec_device->dev_addr, dev->dev_addr, dev->addr_len);
1161out:
1162	return err;
1163}
1164
1165/* this function is called from 2 macsec ops functions:
1166 *  macsec_set_mac_address – MAC address was changed, therefore we need to destroy
1167 *  and create new Tx contexts(macsec object + steering).
1168 *  macsec_changelink – in this case the tx SC or SecY may be changed, therefore need to
1169 *  destroy Tx and Rx contexts(macsec object + steering)
1170 */
1171static int mlx5e_macsec_upd_secy(struct macsec_context *ctx)
1172{
1173	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1174	const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
1175	const struct net_device *dev = ctx->secy->netdev;
1176	struct mlx5e_macsec_device *macsec_device;
1177	struct mlx5e_macsec_sa *tx_sa;
1178	struct mlx5e_macsec *macsec;
1179	int i, err = 0;
1180
1181	if (!mlx5e_macsec_secy_features_validate(ctx))
1182		return -EINVAL;
1183
1184	mutex_lock(&priv->macsec->lock);
1185
1186	macsec = priv->macsec;
1187	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1188	if (!macsec_device) {
1189		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1190		err = -EINVAL;
1191		goto out;
1192	}
1193
1194	/* if the dev_addr hasn't change, it mean the callback is from macsec_changelink */
1195	if (!memcmp(macsec_device->dev_addr, dev->dev_addr, dev->addr_len)) {
1196		err = macsec_upd_secy_hw_address(ctx, macsec_device);
1197		if (err)
1198			goto out;
1199	}
1200
1201	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1202		tx_sa = macsec_device->tx_sa[i];
1203		if (!tx_sa)
1204			continue;
1205
1206		mlx5e_macsec_cleanup_sa_fs(macsec, tx_sa, true, ctx->secy->netdev, 0);
1207	}
1208
1209	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1210		tx_sa = macsec_device->tx_sa[i];
1211		if (!tx_sa)
1212			continue;
1213
1214		if (tx_sa->assoc_num == tx_sc->encoding_sa && tx_sa->active) {
1215			err = mlx5e_macsec_init_sa_fs(ctx, tx_sa, tx_sc->encrypt, true, NULL);
1216			if (err)
1217				goto out;
1218		}
1219	}
1220
1221out:
1222	mutex_unlock(&macsec->lock);
1223
1224	return err;
1225}
1226
1227static int mlx5e_macsec_del_secy(struct macsec_context *ctx)
1228{
1229	struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
1230	struct mlx5e_macsec_device *macsec_device;
1231	struct mlx5e_macsec_rx_sc *rx_sc, *tmp;
1232	struct mlx5e_macsec_sa *tx_sa;
1233	struct mlx5e_macsec *macsec;
1234	struct list_head *list;
1235	int err = 0;
1236	int i;
1237
1238	mutex_lock(&priv->macsec->lock);
1239	macsec = priv->macsec;
1240	macsec_device = mlx5e_macsec_get_macsec_device_context(macsec, ctx);
1241	if (!macsec_device) {
1242		netdev_err(ctx->netdev, "MACsec offload: Failed to find device context\n");
1243		err = -EINVAL;
1244
1245		goto out;
1246	}
1247
1248	for (i = 0; i < MACSEC_NUM_AN; ++i) {
1249		tx_sa = macsec_device->tx_sa[i];
1250		if (!tx_sa)
1251			continue;
1252
1253		mlx5e_macsec_cleanup_sa(macsec, tx_sa, true, ctx->secy->netdev, 0);
1254		mlx5_destroy_encryption_key(macsec->mdev, tx_sa->enc_key_id);
1255		kfree(tx_sa);
1256		macsec_device->tx_sa[i] = NULL;
1257	}
1258
1259	list = &macsec_device->macsec_rx_sc_list_head;
1260	list_for_each_entry_safe(rx_sc, tmp, list, rx_sc_list_element)
1261		macsec_del_rxsc_ctx(macsec, rx_sc, ctx->secy->netdev);
1262
1263	kfree(macsec_device->dev_addr);
1264	macsec_device->dev_addr = NULL;
1265
1266	list_del_rcu(&macsec_device->macsec_device_list_element);
1267	--macsec->num_of_devices;
1268	kfree(macsec_device);
1269
1270out:
1271	mutex_unlock(&macsec->lock);
1272
1273	return err;
1274}
1275
1276static void macsec_build_accel_attrs(struct mlx5e_macsec_sa *sa,
1277				     struct mlx5_macsec_obj_attrs *attrs)
1278{
1279	attrs->epn_state.epn_msb = sa->epn_state.epn_msb;
1280	attrs->epn_state.overlap = sa->epn_state.overlap;
1281}
1282
1283static void macsec_aso_build_wqe_ctrl_seg(struct mlx5e_macsec_aso *macsec_aso,
1284					  struct mlx5_wqe_aso_ctrl_seg *aso_ctrl,
1285					  struct mlx5_aso_ctrl_param *param)
1286{
1287	struct mlx5e_macsec_umr *umr = macsec_aso->umr;
1288
1289	memset(aso_ctrl, 0, sizeof(*aso_ctrl));
1290	aso_ctrl->va_l = cpu_to_be32(umr->dma_addr | ASO_CTRL_READ_EN);
1291	aso_ctrl->va_h = cpu_to_be32((u64)umr->dma_addr >> 32);
1292	aso_ctrl->l_key = cpu_to_be32(umr->mkey);
1293
1294	if (!param)
1295		return;
1296
1297	aso_ctrl->data_mask_mode = param->data_mask_mode << 6;
1298	aso_ctrl->condition_1_0_operand = param->condition_1_operand |
1299						param->condition_0_operand << 4;
1300	aso_ctrl->condition_1_0_offset = param->condition_1_offset |
1301						param->condition_0_offset << 4;
1302	aso_ctrl->data_offset_condition_operand = param->data_offset |
1303						param->condition_operand << 6;
1304	aso_ctrl->condition_0_data = cpu_to_be32(param->condition_0_data);
1305	aso_ctrl->condition_0_mask = cpu_to_be32(param->condition_0_mask);
1306	aso_ctrl->condition_1_data = cpu_to_be32(param->condition_1_data);
1307	aso_ctrl->condition_1_mask = cpu_to_be32(param->condition_1_mask);
1308	aso_ctrl->bitwise_data = cpu_to_be64(param->bitwise_data);
1309	aso_ctrl->data_mask = cpu_to_be64(param->data_mask);
1310}
1311
1312static int mlx5e_macsec_modify_obj(struct mlx5_core_dev *mdev, struct mlx5_macsec_obj_attrs *attrs,
1313				   u32 macsec_id)
1314{
1315	u32 in[MLX5_ST_SZ_DW(modify_macsec_obj_in)] = {};
1316	u32 out[MLX5_ST_SZ_DW(query_macsec_obj_out)];
1317	u64 modify_field_select = 0;
1318	void *obj;
1319	int err;
1320
1321	/* General object fields set */
1322	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_QUERY_GENERAL_OBJECT);
1323	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_GENERAL_OBJECT_TYPES_MACSEC);
1324	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, macsec_id);
1325	err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1326	if (err) {
1327		mlx5_core_err(mdev, "Query MACsec object failed (Object id %d), err = %d\n",
1328			      macsec_id, err);
1329		return err;
1330	}
1331
1332	obj = MLX5_ADDR_OF(query_macsec_obj_out, out, macsec_object);
1333	modify_field_select = MLX5_GET64(macsec_offload_obj, obj, modify_field_select);
1334
1335	/* EPN */
1336	if (!(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP) ||
1337	    !(modify_field_select & MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB)) {
1338		mlx5_core_dbg(mdev, "MACsec object field is not modifiable (Object id %d)\n",
1339			      macsec_id);
1340		return -EOPNOTSUPP;
1341	}
1342
1343	obj = MLX5_ADDR_OF(modify_macsec_obj_in, in, macsec_object);
1344	MLX5_SET64(macsec_offload_obj, obj, modify_field_select,
1345		   MLX5_MODIFY_MACSEC_BITMASK_EPN_OVERLAP | MLX5_MODIFY_MACSEC_BITMASK_EPN_MSB);
1346	MLX5_SET(macsec_offload_obj, obj, epn_msb, attrs->epn_state.epn_msb);
1347	MLX5_SET(macsec_offload_obj, obj, epn_overlap, attrs->epn_state.overlap);
1348
1349	/* General object fields set */
1350	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_MODIFY_GENERAL_OBJECT);
1351
1352	return mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
1353}
1354
1355static void macsec_aso_build_ctrl(struct mlx5e_macsec_aso *aso,
1356				  struct mlx5_wqe_aso_ctrl_seg *aso_ctrl,
1357				  struct mlx5e_macsec_aso_in *in)
1358{
1359	struct mlx5_aso_ctrl_param param = {};
1360
1361	param.data_mask_mode = MLX5_ASO_DATA_MASK_MODE_BITWISE_64BIT;
1362	param.condition_0_operand = MLX5_ASO_ALWAYS_TRUE;
1363	param.condition_1_operand = MLX5_ASO_ALWAYS_TRUE;
1364	if (in->mode == MLX5_MACSEC_EPN) {
1365		param.data_offset = MLX5_MACSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET;
1366		param.bitwise_data = BIT_ULL(54);
1367		param.data_mask = param.bitwise_data;
1368	}
1369	macsec_aso_build_wqe_ctrl_seg(aso, aso_ctrl, &param);
1370}
1371
1372static int macsec_aso_set_arm_event(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec,
1373				    struct mlx5e_macsec_aso_in *in)
1374{
1375	struct mlx5e_macsec_aso *aso;
1376	struct mlx5_aso_wqe *aso_wqe;
1377	struct mlx5_aso *maso;
1378	int err;
1379
1380	aso = &macsec->aso;
1381	maso = aso->maso;
1382
1383	mutex_lock(&aso->aso_lock);
1384	aso_wqe = mlx5_aso_get_wqe(maso);
1385	mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id,
1386			   MLX5_ACCESS_ASO_OPC_MOD_MACSEC);
1387	macsec_aso_build_ctrl(aso, &aso_wqe->aso_ctrl, in);
1388	mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
1389	read_poll_timeout(mlx5_aso_poll_cq, err, !err, 10, 10 * USEC_PER_MSEC,
1390			  false, maso, false);
1391	mutex_unlock(&aso->aso_lock);
1392
1393	return err;
1394}
1395
1396static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macsec,
1397			    struct mlx5e_macsec_aso_in *in, struct mlx5e_macsec_aso_out *out)
1398{
1399	struct mlx5e_macsec_aso *aso;
1400	struct mlx5_aso_wqe *aso_wqe;
1401	struct mlx5_aso *maso;
1402	int err;
1403
1404	aso = &macsec->aso;
1405	maso = aso->maso;
1406
1407	mutex_lock(&aso->aso_lock);
1408
1409	aso_wqe = mlx5_aso_get_wqe(maso);
1410	mlx5_aso_build_wqe(maso, MLX5_MACSEC_ASO_DS_CNT, aso_wqe, in->obj_id,
1411			   MLX5_ACCESS_ASO_OPC_MOD_MACSEC);
1412	macsec_aso_build_wqe_ctrl_seg(aso, &aso_wqe->aso_ctrl, NULL);
1413
1414	mlx5_aso_post_wqe(maso, false, &aso_wqe->ctrl);
1415	read_poll_timeout(mlx5_aso_poll_cq, err, !err, 10, 10 * USEC_PER_MSEC,
1416			  false, maso, false);
1417
1418	if (err)
1419		goto err_out;
1420
1421	if (MLX5_GET(macsec_aso, aso->umr->ctx, epn_event_arm))
1422		out->event_arm |= MLX5E_ASO_EPN_ARM;
1423
1424	out->mode_param = MLX5_GET(macsec_aso, aso->umr->ctx, mode_parameter);
1425
1426err_out:
1427	mutex_unlock(&aso->aso_lock);
1428	return err;
1429}
1430
1431static struct mlx5e_macsec_sa *get_macsec_tx_sa_from_obj_id(const struct mlx5e_macsec *macsec,
1432							    const u32 obj_id)
1433{
1434	const struct list_head *device_list;
1435	struct mlx5e_macsec_sa *macsec_sa;
1436	struct mlx5e_macsec_device *iter;
1437	int i;
1438
1439	device_list = &macsec->macsec_device_list_head;
1440
1441	list_for_each_entry(iter, device_list, macsec_device_list_element) {
1442		for (i = 0; i < MACSEC_NUM_AN; ++i) {
1443			macsec_sa = iter->tx_sa[i];
1444			if (!macsec_sa || !macsec_sa->active)
1445				continue;
1446			if (macsec_sa->macsec_obj_id == obj_id)
1447				return macsec_sa;
1448		}
1449	}
1450
1451	return NULL;
1452}
1453
1454static struct mlx5e_macsec_sa *get_macsec_rx_sa_from_obj_id(const struct mlx5e_macsec *macsec,
1455							    const u32 obj_id)
1456{
1457	const struct list_head *device_list, *sc_list;
1458	struct mlx5e_macsec_rx_sc *mlx5e_rx_sc;
1459	struct mlx5e_macsec_sa *macsec_sa;
1460	struct mlx5e_macsec_device *iter;
1461	int i;
1462
1463	device_list = &macsec->macsec_device_list_head;
1464
1465	list_for_each_entry(iter, device_list, macsec_device_list_element) {
1466		sc_list = &iter->macsec_rx_sc_list_head;
1467		list_for_each_entry(mlx5e_rx_sc, sc_list, rx_sc_list_element) {
1468			for (i = 0; i < MACSEC_NUM_AN; ++i) {
1469				macsec_sa = mlx5e_rx_sc->rx_sa[i];
1470				if (!macsec_sa || !macsec_sa->active)
1471					continue;
1472				if (macsec_sa->macsec_obj_id == obj_id)
1473					return macsec_sa;
1474			}
1475		}
1476	}
1477
1478	return NULL;
1479}
1480
1481static void macsec_epn_update(struct mlx5e_macsec *macsec, struct mlx5_core_dev *mdev,
1482			      struct mlx5e_macsec_sa *sa, u32 obj_id, u32 mode_param)
1483{
1484	struct mlx5_macsec_obj_attrs attrs = {};
1485	struct mlx5e_macsec_aso_in in = {};
1486
1487	/* When the bottom of the replay protection window (mode_param) crosses 2^31 (half sequence
1488	 * number wraparound) hence mode_param > MLX5_MACSEC_EPN_SCOPE_MID the SW should update the
1489	 * esn_overlap to OLD (1).
1490	 * When the bottom of the replay protection window (mode_param) crosses 2^32 (full sequence
1491	 * number wraparound) hence mode_param < MLX5_MACSEC_EPN_SCOPE_MID since it did a
1492	 * wraparound, the SW should update the esn_overlap to NEW (0), and increment the esn_msb.
1493	 */
1494
1495	if (mode_param < MLX5_MACSEC_EPN_SCOPE_MID) {
1496		sa->epn_state.epn_msb++;
1497		sa->epn_state.overlap = 0;
1498	} else {
1499		sa->epn_state.overlap = 1;
1500	}
1501
1502	macsec_build_accel_attrs(sa, &attrs);
1503	mlx5e_macsec_modify_obj(mdev, &attrs, obj_id);
1504
1505	/* Re-set EPN arm event */
1506	in.obj_id = obj_id;
1507	in.mode = MLX5_MACSEC_EPN;
1508	macsec_aso_set_arm_event(mdev, macsec, &in);
1509}
1510
1511static void macsec_async_event(struct work_struct *work)
1512{
1513	struct mlx5e_macsec_async_work *async_work;
1514	struct mlx5e_macsec_aso_out out = {};
1515	struct mlx5e_macsec_aso_in in = {};
1516	struct mlx5e_macsec_sa *macsec_sa;
1517	struct mlx5e_macsec *macsec;
1518	struct mlx5_core_dev *mdev;
1519	u32 obj_id;
1520
1521	async_work = container_of(work, struct mlx5e_macsec_async_work, work);
1522	macsec = async_work->macsec;
1523	mutex_lock(&macsec->lock);
1524
1525	mdev = async_work->mdev;
1526	obj_id = async_work->obj_id;
1527	macsec_sa = get_macsec_tx_sa_from_obj_id(macsec, obj_id);
1528	if (!macsec_sa) {
1529		macsec_sa = get_macsec_rx_sa_from_obj_id(macsec, obj_id);
1530		if (!macsec_sa) {
1531			mlx5_core_dbg(mdev, "MACsec SA is not found (SA object id %d)\n", obj_id);
1532			goto out_async_work;
1533		}
1534	}
1535
1536	/* Query MACsec ASO context */
1537	in.obj_id = obj_id;
1538	macsec_aso_query(mdev, macsec, &in, &out);
1539
1540	/* EPN case */
1541	if (macsec_sa->epn_state.epn_enabled && !(out.event_arm & MLX5E_ASO_EPN_ARM))
1542		macsec_epn_update(macsec, mdev, macsec_sa, obj_id, out.mode_param);
1543
1544out_async_work:
1545	kfree(async_work);
1546	mutex_unlock(&macsec->lock);
1547}
1548
1549static int macsec_obj_change_event(struct notifier_block *nb, unsigned long event, void *data)
1550{
1551	struct mlx5e_macsec *macsec = container_of(nb, struct mlx5e_macsec, nb);
1552	struct mlx5e_macsec_async_work *async_work;
1553	struct mlx5_eqe_obj_change *obj_change;
1554	struct mlx5_eqe *eqe = data;
1555	u16 obj_type;
1556	u32 obj_id;
1557
1558	if (event != MLX5_EVENT_TYPE_OBJECT_CHANGE)
1559		return NOTIFY_DONE;
1560
1561	obj_change = &eqe->data.obj_change;
1562	obj_type = be16_to_cpu(obj_change->obj_type);
1563	obj_id = be32_to_cpu(obj_change->obj_id);
1564
1565	if (obj_type != MLX5_GENERAL_OBJECT_TYPES_MACSEC)
1566		return NOTIFY_DONE;
1567
1568	async_work = kzalloc(sizeof(*async_work), GFP_ATOMIC);
1569	if (!async_work)
1570		return NOTIFY_DONE;
1571
1572	async_work->macsec = macsec;
1573	async_work->mdev = macsec->mdev;
1574	async_work->obj_id = obj_id;
1575
1576	INIT_WORK(&async_work->work, macsec_async_event);
1577
1578	WARN_ON(!queue_work(macsec->wq, &async_work->work));
1579
1580	return NOTIFY_OK;
1581}
1582
1583static int mlx5e_macsec_aso_init(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev)
1584{
1585	struct mlx5_aso *maso;
1586	int err;
1587
1588	err = mlx5_core_alloc_pd(mdev, &aso->pdn);
1589	if (err) {
1590		mlx5_core_err(mdev,
1591			      "MACsec offload: Failed to alloc pd for MACsec ASO, err=%d\n",
1592			      err);
1593		return err;
1594	}
1595
1596	maso = mlx5_aso_create(mdev, aso->pdn);
1597	if (IS_ERR(maso)) {
1598		err = PTR_ERR(maso);
1599		goto err_aso;
1600	}
1601
1602	err = mlx5e_macsec_aso_reg_mr(mdev, aso);
1603	if (err)
1604		goto err_aso_reg;
1605
1606	mutex_init(&aso->aso_lock);
1607
1608	aso->maso = maso;
1609
1610	return 0;
1611
1612err_aso_reg:
1613	mlx5_aso_destroy(maso);
1614err_aso:
1615	mlx5_core_dealloc_pd(mdev, aso->pdn);
1616	return err;
1617}
1618
1619static void mlx5e_macsec_aso_cleanup(struct mlx5e_macsec_aso *aso, struct mlx5_core_dev *mdev)
1620{
1621	if (!aso)
1622		return;
1623
1624	mlx5e_macsec_aso_dereg_mr(mdev, aso);
1625
1626	mlx5_aso_destroy(aso->maso);
1627
1628	mlx5_core_dealloc_pd(mdev, aso->pdn);
1629}
1630
1631static const struct macsec_ops macsec_offload_ops = {
1632	.mdo_add_txsa = mlx5e_macsec_add_txsa,
1633	.mdo_upd_txsa = mlx5e_macsec_upd_txsa,
1634	.mdo_del_txsa = mlx5e_macsec_del_txsa,
1635	.mdo_add_rxsc = mlx5e_macsec_add_rxsc,
1636	.mdo_upd_rxsc = mlx5e_macsec_upd_rxsc,
1637	.mdo_del_rxsc = mlx5e_macsec_del_rxsc,
1638	.mdo_add_rxsa = mlx5e_macsec_add_rxsa,
1639	.mdo_upd_rxsa = mlx5e_macsec_upd_rxsa,
1640	.mdo_del_rxsa = mlx5e_macsec_del_rxsa,
1641	.mdo_add_secy = mlx5e_macsec_add_secy,
1642	.mdo_upd_secy = mlx5e_macsec_upd_secy,
1643	.mdo_del_secy = mlx5e_macsec_del_secy,
1644	.rx_uses_md_dst = true,
1645};
1646
1647bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
1648{
1649	struct metadata_dst *md_dst = skb_metadata_dst(skb);
1650	u32 fs_id;
1651
1652	fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
1653							&md_dst->u.macsec_info.sci);
1654	if (!fs_id)
1655		goto err_out;
1656
1657	return true;
1658
1659err_out:
1660	dev_kfree_skb_any(skb);
1661	return false;
1662}
1663
1664void mlx5e_macsec_tx_build_eseg(struct mlx5e_macsec *macsec,
1665				struct sk_buff *skb,
1666				struct mlx5_wqe_eth_seg *eseg)
1667{
1668	struct metadata_dst *md_dst = skb_metadata_dst(skb);
1669	u32 fs_id;
1670
1671	fs_id = mlx5_macsec_fs_get_fs_id_from_hashtable(macsec->mdev->macsec_fs,
1672							&md_dst->u.macsec_info.sci);
1673	if (!fs_id)
1674		return;
1675
1676	eseg->flow_table_metadata = cpu_to_be32(MLX5_MACSEC_TX_METADATA(fs_id));
1677}
1678
1679void mlx5e_macsec_offload_handle_rx_skb(struct net_device *netdev,
1680					struct sk_buff *skb,
1681					struct mlx5_cqe64 *cqe)
1682{
1683	struct mlx5e_macsec_rx_sc_xarray_element *sc_xarray_element;
1684	u32 macsec_meta_data = be32_to_cpu(cqe->ft_metadata);
1685	struct mlx5e_priv *priv = macsec_netdev_priv(netdev);
1686	struct mlx5e_macsec_rx_sc *rx_sc;
1687	struct mlx5e_macsec *macsec;
1688	u32  fs_id;
1689
1690	macsec = priv->macsec;
1691	if (!macsec)
1692		return;
1693
1694	fs_id = MLX5_MACSEC_RX_METADAT_HANDLE(macsec_meta_data);
1695
1696	rcu_read_lock();
1697	sc_xarray_element = xa_load(&macsec->sc_xarray, fs_id);
1698	rx_sc = sc_xarray_element->rx_sc;
1699	if (rx_sc) {
1700		dst_hold(&rx_sc->md_dst->dst);
1701		skb_dst_set(skb, &rx_sc->md_dst->dst);
1702	}
1703
1704	rcu_read_unlock();
1705}
1706
1707void mlx5e_macsec_build_netdev(struct mlx5e_priv *priv)
1708{
1709	struct net_device *netdev = priv->netdev;
1710
1711	if (!mlx5e_is_macsec_device(priv->mdev))
1712		return;
1713
1714	/* Enable MACsec */
1715	mlx5_core_dbg(priv->mdev, "mlx5e: MACsec acceleration enabled\n");
1716	netdev->macsec_ops = &macsec_offload_ops;
1717	netdev->features |= NETIF_F_HW_MACSEC;
1718	netif_keep_dst(netdev);
1719}
1720
1721int mlx5e_macsec_init(struct mlx5e_priv *priv)
1722{
1723	struct mlx5_core_dev *mdev = priv->mdev;
1724	struct mlx5e_macsec *macsec = NULL;
1725	struct mlx5_macsec_fs *macsec_fs;
1726	int err;
1727
1728	if (!mlx5e_is_macsec_device(priv->mdev)) {
1729		mlx5_core_dbg(mdev, "Not a MACsec offload device\n");
1730		return 0;
1731	}
1732
1733	macsec = kzalloc(sizeof(*macsec), GFP_KERNEL);
1734	if (!macsec)
1735		return -ENOMEM;
1736
1737	INIT_LIST_HEAD(&macsec->macsec_device_list_head);
1738	mutex_init(&macsec->lock);
1739
1740	err = mlx5e_macsec_aso_init(&macsec->aso, priv->mdev);
1741	if (err) {
1742		mlx5_core_err(mdev, "MACsec offload: Failed to init aso, err=%d\n", err);
1743		goto err_aso;
1744	}
1745
1746	macsec->wq = alloc_ordered_workqueue("mlx5e_macsec_%s", 0, priv->netdev->name);
1747	if (!macsec->wq) {
1748		err = -ENOMEM;
1749		goto err_wq;
1750	}
1751
1752	xa_init_flags(&macsec->sc_xarray, XA_FLAGS_ALLOC1);
1753
1754	priv->macsec = macsec;
1755
1756	macsec->mdev = mdev;
1757
1758	macsec_fs = mlx5_macsec_fs_init(mdev);
1759	if (!macsec_fs) {
1760		err = -ENOMEM;
1761		goto err_out;
1762	}
1763
1764	mdev->macsec_fs = macsec_fs;
1765
1766	macsec->nb.notifier_call = macsec_obj_change_event;
1767	mlx5_notifier_register(mdev, &macsec->nb);
1768
1769	mlx5_core_dbg(mdev, "MACsec attached to netdevice\n");
1770
1771	return 0;
1772
1773err_out:
1774	destroy_workqueue(macsec->wq);
1775err_wq:
1776	mlx5e_macsec_aso_cleanup(&macsec->aso, priv->mdev);
1777err_aso:
1778	kfree(macsec);
1779	priv->macsec = NULL;
1780	return err;
1781}
1782
1783void mlx5e_macsec_cleanup(struct mlx5e_priv *priv)
1784{
1785	struct mlx5e_macsec *macsec = priv->macsec;
1786	struct mlx5_core_dev *mdev = priv->mdev;
1787
1788	if (!macsec)
1789		return;
1790
1791	mlx5_notifier_unregister(mdev, &macsec->nb);
1792	mlx5_macsec_fs_cleanup(mdev->macsec_fs);
1793	destroy_workqueue(macsec->wq);
1794	mlx5e_macsec_aso_cleanup(&macsec->aso, mdev);
1795	mutex_destroy(&macsec->lock);
1796	kfree(macsec);
1797}
~/ Read-only file preview.