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