Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Mar 24-27, 2025, special US time zones
Register
Loading...
Note: File does not exist in v5.4.
   1// SPDX-License-Identifier: GPL-2.0
   2/* Marvell MACSEC hardware offload driver
   3 *
   4 * Copyright (C) 2022 Marvell.
   5 */
   6
   7#include <crypto/skcipher.h>
   8#include <linux/rtnetlink.h>
   9#include <linux/bitfield.h>
  10#include "otx2_common.h"
  11
  12#define MCS_TCAM0_MAC_DA_MASK		GENMASK_ULL(47, 0)
  13#define MCS_TCAM0_MAC_SA_MASK		GENMASK_ULL(63, 48)
  14#define MCS_TCAM1_MAC_SA_MASK		GENMASK_ULL(31, 0)
  15#define MCS_TCAM1_ETYPE_MASK		GENMASK_ULL(47, 32)
  16
  17#define MCS_SA_MAP_MEM_SA_USE		BIT_ULL(9)
  18
  19#define MCS_RX_SECY_PLCY_RW_MASK	GENMASK_ULL(49, 18)
  20#define MCS_RX_SECY_PLCY_RP		BIT_ULL(17)
  21#define MCS_RX_SECY_PLCY_AUTH_ENA	BIT_ULL(16)
  22#define MCS_RX_SECY_PLCY_CIP		GENMASK_ULL(8, 5)
  23#define MCS_RX_SECY_PLCY_VAL		GENMASK_ULL(2, 1)
  24#define MCS_RX_SECY_PLCY_ENA		BIT_ULL(0)
  25
  26#define MCS_TX_SECY_PLCY_MTU		GENMASK_ULL(43, 28)
  27#define MCS_TX_SECY_PLCY_ST_TCI		GENMASK_ULL(27, 22)
  28#define MCS_TX_SECY_PLCY_ST_OFFSET	GENMASK_ULL(21, 15)
  29#define MCS_TX_SECY_PLCY_INS_MODE	BIT_ULL(14)
  30#define MCS_TX_SECY_PLCY_AUTH_ENA	BIT_ULL(13)
  31#define MCS_TX_SECY_PLCY_CIP		GENMASK_ULL(5, 2)
  32#define MCS_TX_SECY_PLCY_PROTECT	BIT_ULL(1)
  33#define MCS_TX_SECY_PLCY_ENA		BIT_ULL(0)
  34
  35#define MCS_GCM_AES_128			0
  36#define MCS_GCM_AES_256			1
  37#define MCS_GCM_AES_XPN_128		2
  38#define MCS_GCM_AES_XPN_256		3
  39
  40#define MCS_TCI_ES			0x40 /* end station */
  41#define MCS_TCI_SC			0x20 /* SCI present */
  42#define MCS_TCI_SCB			0x10 /* epon */
  43#define MCS_TCI_E			0x08 /* encryption */
  44#define MCS_TCI_C			0x04 /* changed text */
  45
  46#define CN10K_MAX_HASH_LEN		16
  47#define CN10K_MAX_SAK_LEN		32
  48
  49static int cn10k_ecb_aes_encrypt(struct otx2_nic *pfvf, u8 *sak,
  50				 u16 sak_len, u8 *hash)
  51{
  52	u8 data[CN10K_MAX_HASH_LEN] = { 0 };
  53	struct skcipher_request *req = NULL;
  54	struct scatterlist sg_src, sg_dst;
  55	struct crypto_skcipher *tfm;
  56	DECLARE_CRYPTO_WAIT(wait);
  57	int err;
  58
  59	tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
  60	if (IS_ERR(tfm)) {
  61		dev_err(pfvf->dev, "failed to allocate transform for ecb-aes\n");
  62		return PTR_ERR(tfm);
  63	}
  64
  65	req = skcipher_request_alloc(tfm, GFP_KERNEL);
  66	if (!req) {
  67		dev_err(pfvf->dev, "failed to allocate request for skcipher\n");
  68		err = -ENOMEM;
  69		goto free_tfm;
  70	}
  71
  72	err = crypto_skcipher_setkey(tfm, sak, sak_len);
  73	if (err) {
  74		dev_err(pfvf->dev, "failed to set key for skcipher\n");
  75		goto free_req;
  76	}
  77
  78	/* build sg list */
  79	sg_init_one(&sg_src, data, CN10K_MAX_HASH_LEN);
  80	sg_init_one(&sg_dst, hash, CN10K_MAX_HASH_LEN);
  81
  82	skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
  83	skcipher_request_set_crypt(req, &sg_src, &sg_dst,
  84				   CN10K_MAX_HASH_LEN, NULL);
  85
  86	err = crypto_skcipher_encrypt(req);
  87	err = crypto_wait_req(err, &wait);
  88
  89free_req:
  90	skcipher_request_free(req);
  91free_tfm:
  92	crypto_free_skcipher(tfm);
  93	return err;
  94}
  95
  96static struct cn10k_mcs_txsc *cn10k_mcs_get_txsc(struct cn10k_mcs_cfg *cfg,
  97						 struct macsec_secy *secy)
  98{
  99	struct cn10k_mcs_txsc *txsc;
 100
 101	list_for_each_entry(txsc, &cfg->txsc_list, entry) {
 102		if (txsc->sw_secy == secy)
 103			return txsc;
 104	}
 105
 106	return NULL;
 107}
 108
 109static struct cn10k_mcs_rxsc *cn10k_mcs_get_rxsc(struct cn10k_mcs_cfg *cfg,
 110						 struct macsec_secy *secy,
 111						 struct macsec_rx_sc *rx_sc)
 112{
 113	struct cn10k_mcs_rxsc *rxsc;
 114
 115	list_for_each_entry(rxsc, &cfg->rxsc_list, entry) {
 116		if (rxsc->sw_rxsc == rx_sc && rxsc->sw_secy == secy)
 117			return rxsc;
 118	}
 119
 120	return NULL;
 121}
 122
 123static const char *rsrc_name(enum mcs_rsrc_type rsrc_type)
 124{
 125	switch (rsrc_type) {
 126	case MCS_RSRC_TYPE_FLOWID:
 127		return "FLOW";
 128	case MCS_RSRC_TYPE_SC:
 129		return "SC";
 130	case MCS_RSRC_TYPE_SECY:
 131		return "SECY";
 132	case MCS_RSRC_TYPE_SA:
 133		return "SA";
 134	default:
 135		return "Unknown";
 136	};
 137
 138	return "Unknown";
 139}
 140
 141static int cn10k_mcs_alloc_rsrc(struct otx2_nic *pfvf, enum mcs_direction dir,
 142				enum mcs_rsrc_type type, u16 *rsrc_id)
 143{
 144	struct mbox *mbox = &pfvf->mbox;
 145	struct mcs_alloc_rsrc_req *req;
 146	struct mcs_alloc_rsrc_rsp *rsp;
 147	int ret = -ENOMEM;
 148
 149	mutex_lock(&mbox->lock);
 150
 151	req = otx2_mbox_alloc_msg_mcs_alloc_resources(mbox);
 152	if (!req)
 153		goto fail;
 154
 155	req->rsrc_type = type;
 156	req->rsrc_cnt  = 1;
 157	req->dir = dir;
 158
 159	ret = otx2_sync_mbox_msg(mbox);
 160	if (ret)
 161		goto fail;
 162
 163	rsp = (struct mcs_alloc_rsrc_rsp *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
 164							     0, &req->hdr);
 165	if (IS_ERR(rsp) || req->rsrc_cnt != rsp->rsrc_cnt ||
 166	    req->rsrc_type != rsp->rsrc_type || req->dir != rsp->dir) {
 167		ret = -EINVAL;
 168		goto fail;
 169	}
 170
 171	switch (rsp->rsrc_type) {
 172	case MCS_RSRC_TYPE_FLOWID:
 173		*rsrc_id = rsp->flow_ids[0];
 174		break;
 175	case MCS_RSRC_TYPE_SC:
 176		*rsrc_id = rsp->sc_ids[0];
 177		break;
 178	case MCS_RSRC_TYPE_SECY:
 179		*rsrc_id = rsp->secy_ids[0];
 180		break;
 181	case MCS_RSRC_TYPE_SA:
 182		*rsrc_id = rsp->sa_ids[0];
 183		break;
 184	default:
 185		ret = -EINVAL;
 186		goto fail;
 187	}
 188
 189	mutex_unlock(&mbox->lock);
 190
 191	return 0;
 192fail:
 193	dev_err(pfvf->dev, "Failed to allocate %s %s resource\n",
 194		dir == MCS_TX ? "TX" : "RX", rsrc_name(type));
 195	mutex_unlock(&mbox->lock);
 196	return ret;
 197}
 198
 199static void cn10k_mcs_free_rsrc(struct otx2_nic *pfvf, enum mcs_direction dir,
 200				enum mcs_rsrc_type type, u16 hw_rsrc_id,
 201				bool all)
 202{
 203	struct mcs_clear_stats *clear_req;
 204	struct mbox *mbox = &pfvf->mbox;
 205	struct mcs_free_rsrc_req *req;
 206
 207	mutex_lock(&mbox->lock);
 208
 209	clear_req = otx2_mbox_alloc_msg_mcs_clear_stats(mbox);
 210	if (!clear_req)
 211		goto fail;
 212
 213	clear_req->id = hw_rsrc_id;
 214	clear_req->type = type;
 215	clear_req->dir = dir;
 216
 217	req = otx2_mbox_alloc_msg_mcs_free_resources(mbox);
 218	if (!req)
 219		goto fail;
 220
 221	req->rsrc_id = hw_rsrc_id;
 222	req->rsrc_type = type;
 223	req->dir = dir;
 224	if (all)
 225		req->all = 1;
 226
 227	if (otx2_sync_mbox_msg(&pfvf->mbox))
 228		goto fail;
 229
 230	mutex_unlock(&mbox->lock);
 231
 232	return;
 233fail:
 234	dev_err(pfvf->dev, "Failed to free %s %s resource\n",
 235		dir == MCS_TX ? "TX" : "RX", rsrc_name(type));
 236	mutex_unlock(&mbox->lock);
 237}
 238
 239static int cn10k_mcs_alloc_txsa(struct otx2_nic *pfvf, u16 *hw_sa_id)
 240{
 241	return cn10k_mcs_alloc_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SA, hw_sa_id);
 242}
 243
 244static int cn10k_mcs_alloc_rxsa(struct otx2_nic *pfvf, u16 *hw_sa_id)
 245{
 246	return cn10k_mcs_alloc_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SA, hw_sa_id);
 247}
 248
 249static void cn10k_mcs_free_txsa(struct otx2_nic *pfvf, u16 hw_sa_id)
 250{
 251	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SA, hw_sa_id, false);
 252}
 253
 254static void cn10k_mcs_free_rxsa(struct otx2_nic *pfvf, u16 hw_sa_id)
 255{
 256	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SA, hw_sa_id, false);
 257}
 258
 259static int cn10k_mcs_write_rx_secy(struct otx2_nic *pfvf,
 260				   struct macsec_secy *secy, u8 hw_secy_id)
 261{
 262	struct mcs_secy_plcy_write_req *req;
 263	struct mbox *mbox = &pfvf->mbox;
 264	u64 policy;
 265	u8 cipher;
 266	int ret;
 267
 268	mutex_lock(&mbox->lock);
 269
 270	req = otx2_mbox_alloc_msg_mcs_secy_plcy_write(mbox);
 271	if (!req) {
 272		ret = -ENOMEM;
 273		goto fail;
 274	}
 275
 276	policy = FIELD_PREP(MCS_RX_SECY_PLCY_RW_MASK, secy->replay_window);
 277	if (secy->replay_protect)
 278		policy |= MCS_RX_SECY_PLCY_RP;
 279
 280	policy |= MCS_RX_SECY_PLCY_AUTH_ENA;
 281
 282	switch (secy->key_len) {
 283	case 16:
 284		cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
 285		break;
 286	case 32:
 287		cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
 288		break;
 289	default:
 290		cipher = MCS_GCM_AES_128;
 291		dev_warn(pfvf->dev, "Unsupported key length\n");
 292		break;
 293	}
 294
 295	policy |= FIELD_PREP(MCS_RX_SECY_PLCY_CIP, cipher);
 296	policy |= FIELD_PREP(MCS_RX_SECY_PLCY_VAL, secy->validate_frames);
 297
 298	policy |= MCS_RX_SECY_PLCY_ENA;
 299
 300	req->plcy = policy;
 301	req->secy_id = hw_secy_id;
 302	req->dir = MCS_RX;
 303
 304	ret = otx2_sync_mbox_msg(mbox);
 305
 306fail:
 307	mutex_unlock(&mbox->lock);
 308	return ret;
 309}
 310
 311static int cn10k_mcs_write_rx_flowid(struct otx2_nic *pfvf,
 312				     struct cn10k_mcs_rxsc *rxsc, u8 hw_secy_id)
 313{
 314	struct macsec_rx_sc *sw_rx_sc = rxsc->sw_rxsc;
 315	struct macsec_secy *secy = rxsc->sw_secy;
 316	struct mcs_flowid_entry_write_req *req;
 317	struct mbox *mbox = &pfvf->mbox;
 318	u64 mac_da;
 319	int ret;
 320
 321	mutex_lock(&mbox->lock);
 322
 323	req = otx2_mbox_alloc_msg_mcs_flowid_entry_write(mbox);
 324	if (!req) {
 325		ret = -ENOMEM;
 326		goto fail;
 327	}
 328
 329	mac_da = ether_addr_to_u64(secy->netdev->dev_addr);
 330
 331	req->data[0] = FIELD_PREP(MCS_TCAM0_MAC_DA_MASK, mac_da);
 332	req->mask[0] = ~0ULL;
 333	req->mask[0] = ~MCS_TCAM0_MAC_DA_MASK;
 334
 335	req->data[1] = FIELD_PREP(MCS_TCAM1_ETYPE_MASK, ETH_P_MACSEC);
 336	req->mask[1] = ~0ULL;
 337	req->mask[1] &= ~MCS_TCAM1_ETYPE_MASK;
 338
 339	req->mask[2] = ~0ULL;
 340	req->mask[3] = ~0ULL;
 341
 342	req->flow_id = rxsc->hw_flow_id;
 343	req->secy_id = hw_secy_id;
 344	req->sc_id = rxsc->hw_sc_id;
 345	req->dir = MCS_RX;
 346
 347	if (sw_rx_sc->active)
 348		req->ena = 1;
 349
 350	ret = otx2_sync_mbox_msg(mbox);
 351
 352fail:
 353	mutex_unlock(&mbox->lock);
 354	return ret;
 355}
 356
 357static int cn10k_mcs_write_sc_cam(struct otx2_nic *pfvf,
 358				  struct cn10k_mcs_rxsc *rxsc, u8 hw_secy_id)
 359{
 360	struct macsec_rx_sc *sw_rx_sc = rxsc->sw_rxsc;
 361	struct mcs_rx_sc_cam_write_req *sc_req;
 362	struct mbox *mbox = &pfvf->mbox;
 363	int ret;
 364
 365	mutex_lock(&mbox->lock);
 366
 367	sc_req = otx2_mbox_alloc_msg_mcs_rx_sc_cam_write(mbox);
 368	if (!sc_req) {
 369		ret = -ENOMEM;
 370		goto fail;
 371	}
 372
 373	sc_req->sci = (__force u64)cpu_to_be64((__force u64)sw_rx_sc->sci);
 374	sc_req->sc_id = rxsc->hw_sc_id;
 375	sc_req->secy_id = hw_secy_id;
 376
 377	ret = otx2_sync_mbox_msg(mbox);
 378
 379fail:
 380	mutex_unlock(&mbox->lock);
 381	return ret;
 382}
 383
 384static int cn10k_mcs_write_keys(struct otx2_nic *pfvf,
 385				struct macsec_secy *secy,
 386				struct mcs_sa_plcy_write_req *req,
 387				u8 *sak, u8 *salt, ssci_t ssci)
 388{
 389	u8 hash_rev[CN10K_MAX_HASH_LEN];
 390	u8 sak_rev[CN10K_MAX_SAK_LEN];
 391	u8 salt_rev[MACSEC_SALT_LEN];
 392	u8 hash[CN10K_MAX_HASH_LEN];
 393	u32 ssci_63_32;
 394	int err, i;
 395
 396	err = cn10k_ecb_aes_encrypt(pfvf, sak, secy->key_len, hash);
 397	if (err) {
 398		dev_err(pfvf->dev, "Generating hash using ECB(AES) failed\n");
 399		return err;
 400	}
 401
 402	for (i = 0; i < secy->key_len; i++)
 403		sak_rev[i] = sak[secy->key_len - 1 - i];
 404
 405	for (i = 0; i < CN10K_MAX_HASH_LEN; i++)
 406		hash_rev[i] = hash[CN10K_MAX_HASH_LEN - 1 - i];
 407
 408	for (i = 0; i < MACSEC_SALT_LEN; i++)
 409		salt_rev[i] = salt[MACSEC_SALT_LEN - 1 - i];
 410
 411	ssci_63_32 = (__force u32)cpu_to_be32((__force u32)ssci);
 412
 413	memcpy(&req->plcy[0][0], sak_rev, secy->key_len);
 414	memcpy(&req->plcy[0][4], hash_rev, CN10K_MAX_HASH_LEN);
 415	memcpy(&req->plcy[0][6], salt_rev, MACSEC_SALT_LEN);
 416	req->plcy[0][7] |= (u64)ssci_63_32 << 32;
 417
 418	return 0;
 419}
 420
 421static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
 422				      struct macsec_secy *secy,
 423				      struct cn10k_mcs_rxsc *rxsc,
 424				      u8 assoc_num, bool sa_in_use)
 425{
 426	struct mcs_sa_plcy_write_req *plcy_req;
 427	u8 *sak = rxsc->sa_key[assoc_num];
 428	u8 *salt = rxsc->salt[assoc_num];
 429	struct mcs_rx_sc_sa_map *map_req;
 430	struct mbox *mbox = &pfvf->mbox;
 431	int ret;
 432
 433	mutex_lock(&mbox->lock);
 434
 435	plcy_req = otx2_mbox_alloc_msg_mcs_sa_plcy_write(mbox);
 436	if (!plcy_req) {
 437		ret = -ENOMEM;
 438		goto fail;
 439	}
 440
 441	map_req = otx2_mbox_alloc_msg_mcs_rx_sc_sa_map_write(mbox);
 442	if (!map_req) {
 443		otx2_mbox_reset(&mbox->mbox, 0);
 444		ret = -ENOMEM;
 445		goto fail;
 446	}
 447
 448	ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
 449				   salt, rxsc->ssci[assoc_num]);
 450	if (ret)
 451		goto fail;
 452
 453	plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num];
 454	plcy_req->sa_cnt = 1;
 455	plcy_req->dir = MCS_RX;
 456
 457	map_req->sa_index = rxsc->hw_sa_id[assoc_num];
 458	map_req->sa_in_use = sa_in_use;
 459	map_req->sc_id = rxsc->hw_sc_id;
 460	map_req->an = assoc_num;
 461
 462	/* Send two messages together */
 463	ret = otx2_sync_mbox_msg(mbox);
 464
 465fail:
 466	mutex_unlock(&mbox->lock);
 467	return ret;
 468}
 469
 470static int cn10k_mcs_write_rx_sa_pn(struct otx2_nic *pfvf,
 471				    struct cn10k_mcs_rxsc *rxsc,
 472				    u8 assoc_num, u64 next_pn)
 473{
 474	struct mcs_pn_table_write_req *req;
 475	struct mbox *mbox = &pfvf->mbox;
 476	int ret;
 477
 478	mutex_lock(&mbox->lock);
 479
 480	req = otx2_mbox_alloc_msg_mcs_pn_table_write(mbox);
 481	if (!req) {
 482		ret = -ENOMEM;
 483		goto fail;
 484	}
 485
 486	req->pn_id = rxsc->hw_sa_id[assoc_num];
 487	req->next_pn = next_pn;
 488	req->dir = MCS_RX;
 489
 490	ret = otx2_sync_mbox_msg(mbox);
 491
 492fail:
 493	mutex_unlock(&mbox->lock);
 494	return ret;
 495}
 496
 497static int cn10k_mcs_write_tx_secy(struct otx2_nic *pfvf,
 498				   struct macsec_secy *secy,
 499				   struct cn10k_mcs_txsc *txsc)
 500{
 501	struct mcs_secy_plcy_write_req *req;
 502	struct mbox *mbox = &pfvf->mbox;
 503	struct macsec_tx_sc *sw_tx_sc;
 504	u8 sectag_tci = 0;
 505	u8 tag_offset;
 506	u64 policy;
 507	u8 cipher;
 508	int ret;
 509
 510	/* Insert SecTag after 12 bytes (DA+SA) or 16 bytes
 511	 * if VLAN tag needs to be sent in clear text.
 512	 */
 513	tag_offset = txsc->vlan_dev ? 16 : 12;
 514	sw_tx_sc = &secy->tx_sc;
 515
 516	mutex_lock(&mbox->lock);
 517
 518	req = otx2_mbox_alloc_msg_mcs_secy_plcy_write(mbox);
 519	if (!req) {
 520		ret = -ENOMEM;
 521		goto fail;
 522	}
 523
 524	if (sw_tx_sc->send_sci) {
 525		sectag_tci |= MCS_TCI_SC;
 526	} else {
 527		if (sw_tx_sc->end_station)
 528			sectag_tci |= MCS_TCI_ES;
 529		if (sw_tx_sc->scb)
 530			sectag_tci |= MCS_TCI_SCB;
 531	}
 532
 533	if (sw_tx_sc->encrypt)
 534		sectag_tci |= (MCS_TCI_E | MCS_TCI_C);
 535
 536	policy = FIELD_PREP(MCS_TX_SECY_PLCY_MTU, secy->netdev->mtu);
 537	/* Write SecTag excluding AN bits(1..0) */
 538	policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_TCI, sectag_tci >> 2);
 539	policy |= FIELD_PREP(MCS_TX_SECY_PLCY_ST_OFFSET, tag_offset);
 540	policy |= MCS_TX_SECY_PLCY_INS_MODE;
 541	policy |= MCS_TX_SECY_PLCY_AUTH_ENA;
 542
 543	switch (secy->key_len) {
 544	case 16:
 545		cipher = secy->xpn ? MCS_GCM_AES_XPN_128 : MCS_GCM_AES_128;
 546		break;
 547	case 32:
 548		cipher = secy->xpn ? MCS_GCM_AES_XPN_256 : MCS_GCM_AES_256;
 549		break;
 550	default:
 551		cipher = MCS_GCM_AES_128;
 552		dev_warn(pfvf->dev, "Unsupported key length\n");
 553		break;
 554	}
 555
 556	policy |= FIELD_PREP(MCS_TX_SECY_PLCY_CIP, cipher);
 557
 558	if (secy->protect_frames)
 559		policy |= MCS_TX_SECY_PLCY_PROTECT;
 560
 561	/* If the encodingsa does not exist/active and protect is
 562	 * not set then frames can be sent out as it is. Hence enable
 563	 * the policy irrespective of secy operational when !protect.
 564	 */
 565	if (!secy->protect_frames || secy->operational)
 566		policy |= MCS_TX_SECY_PLCY_ENA;
 567
 568	req->plcy = policy;
 569	req->secy_id = txsc->hw_secy_id_tx;
 570	req->dir = MCS_TX;
 571
 572	ret = otx2_sync_mbox_msg(mbox);
 573
 574fail:
 575	mutex_unlock(&mbox->lock);
 576	return ret;
 577}
 578
 579static int cn10k_mcs_write_tx_flowid(struct otx2_nic *pfvf,
 580				     struct macsec_secy *secy,
 581				     struct cn10k_mcs_txsc *txsc)
 582{
 583	struct mcs_flowid_entry_write_req *req;
 584	struct mbox *mbox = &pfvf->mbox;
 585	u64 mac_sa;
 586	int ret;
 587
 588	mutex_lock(&mbox->lock);
 589
 590	req = otx2_mbox_alloc_msg_mcs_flowid_entry_write(mbox);
 591	if (!req) {
 592		ret = -ENOMEM;
 593		goto fail;
 594	}
 595
 596	mac_sa = ether_addr_to_u64(secy->netdev->dev_addr);
 597
 598	req->data[0] = FIELD_PREP(MCS_TCAM0_MAC_SA_MASK, mac_sa);
 599	req->data[1] = FIELD_PREP(MCS_TCAM1_MAC_SA_MASK, mac_sa >> 16);
 600
 601	req->mask[0] = ~0ULL;
 602	req->mask[0] &= ~MCS_TCAM0_MAC_SA_MASK;
 603
 604	req->mask[1] = ~0ULL;
 605	req->mask[1] &= ~MCS_TCAM1_MAC_SA_MASK;
 606
 607	req->mask[2] = ~0ULL;
 608	req->mask[3] = ~0ULL;
 609
 610	req->flow_id = txsc->hw_flow_id;
 611	req->secy_id = txsc->hw_secy_id_tx;
 612	req->sc_id = txsc->hw_sc_id;
 613	req->sci = (__force u64)cpu_to_be64((__force u64)secy->sci);
 614	req->dir = MCS_TX;
 615	/* This can be enabled since stack xmits packets only when interface is up */
 616	req->ena = 1;
 617
 618	ret = otx2_sync_mbox_msg(mbox);
 619
 620fail:
 621	mutex_unlock(&mbox->lock);
 622	return ret;
 623}
 624
 625static int cn10k_mcs_link_tx_sa2sc(struct otx2_nic *pfvf,
 626				   struct macsec_secy *secy,
 627				   struct cn10k_mcs_txsc *txsc,
 628				   u8 sa_num, bool sa_active)
 629{
 630	struct mcs_tx_sc_sa_map *map_req;
 631	struct mbox *mbox = &pfvf->mbox;
 632	int ret;
 633
 634	/* Link the encoding_sa only to SC out of all SAs */
 635	if (txsc->encoding_sa != sa_num)
 636		return 0;
 637
 638	mutex_lock(&mbox->lock);
 639
 640	map_req = otx2_mbox_alloc_msg_mcs_tx_sc_sa_map_write(mbox);
 641	if (!map_req) {
 642		otx2_mbox_reset(&mbox->mbox, 0);
 643		ret = -ENOMEM;
 644		goto fail;
 645	}
 646
 647	map_req->sa_index0 = txsc->hw_sa_id[sa_num];
 648	map_req->sa_index0_vld = sa_active;
 649	map_req->sectag_sci = (__force u64)cpu_to_be64((__force u64)secy->sci);
 650	map_req->sc_id = txsc->hw_sc_id;
 651
 652	ret = otx2_sync_mbox_msg(mbox);
 653
 654fail:
 655	mutex_unlock(&mbox->lock);
 656	return ret;
 657}
 658
 659static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
 660				      struct macsec_secy *secy,
 661				      struct cn10k_mcs_txsc *txsc,
 662				      u8 assoc_num)
 663{
 664	struct mcs_sa_plcy_write_req *plcy_req;
 665	u8 *sak = txsc->sa_key[assoc_num];
 666	u8 *salt = txsc->salt[assoc_num];
 667	struct mbox *mbox = &pfvf->mbox;
 668	int ret;
 669
 670	mutex_lock(&mbox->lock);
 671
 672	plcy_req = otx2_mbox_alloc_msg_mcs_sa_plcy_write(mbox);
 673	if (!plcy_req) {
 674		ret = -ENOMEM;
 675		goto fail;
 676	}
 677
 678	ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
 679				   salt, txsc->ssci[assoc_num]);
 680	if (ret)
 681		goto fail;
 682
 683	plcy_req->plcy[0][8] = assoc_num;
 684	plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num];
 685	plcy_req->sa_cnt = 1;
 686	plcy_req->dir = MCS_TX;
 687
 688	ret = otx2_sync_mbox_msg(mbox);
 689
 690fail:
 691	mutex_unlock(&mbox->lock);
 692	return ret;
 693}
 694
 695static int cn10k_write_tx_sa_pn(struct otx2_nic *pfvf,
 696				struct cn10k_mcs_txsc *txsc,
 697				u8 assoc_num, u64 next_pn)
 698{
 699	struct mcs_pn_table_write_req *req;
 700	struct mbox *mbox = &pfvf->mbox;
 701	int ret;
 702
 703	mutex_lock(&mbox->lock);
 704
 705	req = otx2_mbox_alloc_msg_mcs_pn_table_write(mbox);
 706	if (!req) {
 707		ret = -ENOMEM;
 708		goto fail;
 709	}
 710
 711	req->pn_id = txsc->hw_sa_id[assoc_num];
 712	req->next_pn = next_pn;
 713	req->dir = MCS_TX;
 714
 715	ret = otx2_sync_mbox_msg(mbox);
 716
 717fail:
 718	mutex_unlock(&mbox->lock);
 719	return ret;
 720}
 721
 722static int cn10k_mcs_ena_dis_flowid(struct otx2_nic *pfvf, u16 hw_flow_id,
 723				    bool enable, enum mcs_direction dir)
 724{
 725	struct mcs_flowid_ena_dis_entry *req;
 726	struct mbox *mbox = &pfvf->mbox;
 727	int ret;
 728
 729	mutex_lock(&mbox->lock);
 730
 731	req = otx2_mbox_alloc_msg_mcs_flowid_ena_entry(mbox);
 732	if (!req) {
 733		ret = -ENOMEM;
 734		goto fail;
 735	}
 736
 737	req->flow_id = hw_flow_id;
 738	req->ena = enable;
 739	req->dir = dir;
 740
 741	ret = otx2_sync_mbox_msg(mbox);
 742
 743fail:
 744	mutex_unlock(&mbox->lock);
 745	return ret;
 746}
 747
 748static int cn10k_mcs_sa_stats(struct otx2_nic *pfvf, u8 hw_sa_id,
 749			      struct mcs_sa_stats *rsp_p,
 750			      enum mcs_direction dir, bool clear)
 751{
 752	struct mcs_clear_stats *clear_req;
 753	struct mbox *mbox = &pfvf->mbox;
 754	struct mcs_stats_req *req;
 755	struct mcs_sa_stats *rsp;
 756	int ret;
 757
 758	mutex_lock(&mbox->lock);
 759
 760	req = otx2_mbox_alloc_msg_mcs_get_sa_stats(mbox);
 761	if (!req) {
 762		ret = -ENOMEM;
 763		goto fail;
 764	}
 765
 766	req->id = hw_sa_id;
 767	req->dir = dir;
 768
 769	if (!clear)
 770		goto send_msg;
 771
 772	clear_req = otx2_mbox_alloc_msg_mcs_clear_stats(mbox);
 773	if (!clear_req) {
 774		ret = -ENOMEM;
 775		goto fail;
 776	}
 777	clear_req->id = hw_sa_id;
 778	clear_req->dir = dir;
 779	clear_req->type = MCS_RSRC_TYPE_SA;
 780
 781send_msg:
 782	ret = otx2_sync_mbox_msg(mbox);
 783	if (ret)
 784		goto fail;
 785
 786	rsp = (struct mcs_sa_stats *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
 787						       0, &req->hdr);
 788	if (IS_ERR(rsp)) {
 789		ret = PTR_ERR(rsp);
 790		goto fail;
 791	}
 792
 793	memcpy(rsp_p, rsp, sizeof(*rsp_p));
 794
 795	mutex_unlock(&mbox->lock);
 796
 797	return 0;
 798fail:
 799	mutex_unlock(&mbox->lock);
 800	return ret;
 801}
 802
 803static int cn10k_mcs_sc_stats(struct otx2_nic *pfvf, u8 hw_sc_id,
 804			      struct mcs_sc_stats *rsp_p,
 805			      enum mcs_direction dir, bool clear)
 806{
 807	struct mcs_clear_stats *clear_req;
 808	struct mbox *mbox = &pfvf->mbox;
 809	struct mcs_stats_req *req;
 810	struct mcs_sc_stats *rsp;
 811	int ret;
 812
 813	mutex_lock(&mbox->lock);
 814
 815	req = otx2_mbox_alloc_msg_mcs_get_sc_stats(mbox);
 816	if (!req) {
 817		ret = -ENOMEM;
 818		goto fail;
 819	}
 820
 821	req->id = hw_sc_id;
 822	req->dir = dir;
 823
 824	if (!clear)
 825		goto send_msg;
 826
 827	clear_req = otx2_mbox_alloc_msg_mcs_clear_stats(mbox);
 828	if (!clear_req) {
 829		ret = -ENOMEM;
 830		goto fail;
 831	}
 832	clear_req->id = hw_sc_id;
 833	clear_req->dir = dir;
 834	clear_req->type = MCS_RSRC_TYPE_SC;
 835
 836send_msg:
 837	ret = otx2_sync_mbox_msg(mbox);
 838	if (ret)
 839		goto fail;
 840
 841	rsp = (struct mcs_sc_stats *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
 842						       0, &req->hdr);
 843	if (IS_ERR(rsp)) {
 844		ret = PTR_ERR(rsp);
 845		goto fail;
 846	}
 847
 848	memcpy(rsp_p, rsp, sizeof(*rsp_p));
 849
 850	mutex_unlock(&mbox->lock);
 851
 852	return 0;
 853fail:
 854	mutex_unlock(&mbox->lock);
 855	return ret;
 856}
 857
 858static int cn10k_mcs_secy_stats(struct otx2_nic *pfvf, u8 hw_secy_id,
 859				struct mcs_secy_stats *rsp_p,
 860				enum mcs_direction dir, bool clear)
 861{
 862	struct mcs_clear_stats *clear_req;
 863	struct mbox *mbox = &pfvf->mbox;
 864	struct mcs_secy_stats *rsp;
 865	struct mcs_stats_req *req;
 866	int ret;
 867
 868	mutex_lock(&mbox->lock);
 869
 870	req = otx2_mbox_alloc_msg_mcs_get_secy_stats(mbox);
 871	if (!req) {
 872		ret = -ENOMEM;
 873		goto fail;
 874	}
 875
 876	req->id = hw_secy_id;
 877	req->dir = dir;
 878
 879	if (!clear)
 880		goto send_msg;
 881
 882	clear_req = otx2_mbox_alloc_msg_mcs_clear_stats(mbox);
 883	if (!clear_req) {
 884		ret = -ENOMEM;
 885		goto fail;
 886	}
 887	clear_req->id = hw_secy_id;
 888	clear_req->dir = dir;
 889	clear_req->type = MCS_RSRC_TYPE_SECY;
 890
 891send_msg:
 892	ret = otx2_sync_mbox_msg(mbox);
 893	if (ret)
 894		goto fail;
 895
 896	rsp = (struct mcs_secy_stats *)otx2_mbox_get_rsp(&pfvf->mbox.mbox,
 897							 0, &req->hdr);
 898	if (IS_ERR(rsp)) {
 899		ret = PTR_ERR(rsp);
 900		goto fail;
 901	}
 902
 903	memcpy(rsp_p, rsp, sizeof(*rsp_p));
 904
 905	mutex_unlock(&mbox->lock);
 906
 907	return 0;
 908fail:
 909	mutex_unlock(&mbox->lock);
 910	return ret;
 911}
 912
 913static struct cn10k_mcs_txsc *cn10k_mcs_create_txsc(struct otx2_nic *pfvf)
 914{
 915	struct cn10k_mcs_txsc *txsc;
 916	int ret;
 917
 918	txsc = kzalloc(sizeof(*txsc), GFP_KERNEL);
 919	if (!txsc)
 920		return ERR_PTR(-ENOMEM);
 921
 922	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_FLOWID,
 923				   &txsc->hw_flow_id);
 924	if (ret)
 925		goto fail;
 926
 927	/* For a SecY, one TX secy and one RX secy HW resources are needed */
 928	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY,
 929				   &txsc->hw_secy_id_tx);
 930	if (ret)
 931		goto free_flowid;
 932
 933	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY,
 934				   &txsc->hw_secy_id_rx);
 935	if (ret)
 936		goto free_tx_secy;
 937
 938	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SC,
 939				   &txsc->hw_sc_id);
 940	if (ret)
 941		goto free_rx_secy;
 942
 943	return txsc;
 944free_rx_secy:
 945	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY,
 946			    txsc->hw_secy_id_rx, false);
 947free_tx_secy:
 948	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY,
 949			    txsc->hw_secy_id_tx, false);
 950free_flowid:
 951	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_FLOWID,
 952			    txsc->hw_flow_id, false);
 953fail:
 954	kfree(txsc);
 955	return ERR_PTR(ret);
 956}
 957
 958/* Free Tx SC and its SAs(if any) resources to AF
 959 */
 960static void cn10k_mcs_delete_txsc(struct otx2_nic *pfvf,
 961				  struct cn10k_mcs_txsc *txsc)
 962{
 963	u8 sa_bmap = txsc->sa_bmap;
 964	u8 sa_num = 0;
 965
 966	while (sa_bmap) {
 967		if (sa_bmap & 1) {
 968			cn10k_mcs_write_tx_sa_plcy(pfvf, txsc->sw_secy,
 969						   txsc, sa_num);
 970			cn10k_mcs_free_txsa(pfvf, txsc->hw_sa_id[sa_num]);
 971		}
 972		sa_num++;
 973		sa_bmap >>= 1;
 974	}
 975
 976	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SC,
 977			    txsc->hw_sc_id, false);
 978	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY,
 979			    txsc->hw_secy_id_rx, false);
 980	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY,
 981			    txsc->hw_secy_id_tx, false);
 982	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_FLOWID,
 983			    txsc->hw_flow_id, false);
 984}
 985
 986static struct cn10k_mcs_rxsc *cn10k_mcs_create_rxsc(struct otx2_nic *pfvf)
 987{
 988	struct cn10k_mcs_rxsc *rxsc;
 989	int ret;
 990
 991	rxsc = kzalloc(sizeof(*rxsc), GFP_KERNEL);
 992	if (!rxsc)
 993		return ERR_PTR(-ENOMEM);
 994
 995	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_FLOWID,
 996				   &rxsc->hw_flow_id);
 997	if (ret)
 998		goto fail;
 999
1000	ret = cn10k_mcs_alloc_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SC,
1001				   &rxsc->hw_sc_id);
1002	if (ret)
1003		goto free_flowid;
1004
1005	return rxsc;
1006free_flowid:
1007	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_FLOWID,
1008			    rxsc->hw_flow_id, false);
1009fail:
1010	kfree(rxsc);
1011	return ERR_PTR(ret);
1012}
1013
1014/* Free Rx SC and its SAs(if any) resources to AF
1015 */
1016static void cn10k_mcs_delete_rxsc(struct otx2_nic *pfvf,
1017				  struct cn10k_mcs_rxsc *rxsc)
1018{
1019	u8 sa_bmap = rxsc->sa_bmap;
1020	u8 sa_num = 0;
1021
1022	while (sa_bmap) {
1023		if (sa_bmap & 1) {
1024			cn10k_mcs_write_rx_sa_plcy(pfvf, rxsc->sw_secy, rxsc,
1025						   sa_num, false);
1026			cn10k_mcs_free_rxsa(pfvf, rxsc->hw_sa_id[sa_num]);
1027		}
1028		sa_num++;
1029		sa_bmap >>= 1;
1030	}
1031
1032	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SC,
1033			    rxsc->hw_sc_id, false);
1034	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_FLOWID,
1035			    rxsc->hw_flow_id, false);
1036}
1037
1038static int cn10k_mcs_secy_tx_cfg(struct otx2_nic *pfvf, struct macsec_secy *secy,
1039				 struct cn10k_mcs_txsc *txsc,
1040				 struct macsec_tx_sa *sw_tx_sa, u8 sa_num)
1041{
1042	if (sw_tx_sa) {
1043		cn10k_mcs_write_tx_sa_plcy(pfvf, secy, txsc, sa_num);
1044		cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, sw_tx_sa->next_pn);
1045		cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, sa_num,
1046					sw_tx_sa->active);
1047	}
1048
1049	cn10k_mcs_write_tx_secy(pfvf, secy, txsc);
1050	cn10k_mcs_write_tx_flowid(pfvf, secy, txsc);
1051	/* When updating secy, change RX secy also */
1052	cn10k_mcs_write_rx_secy(pfvf, secy, txsc->hw_secy_id_rx);
1053
1054	return 0;
1055}
1056
1057static int cn10k_mcs_secy_rx_cfg(struct otx2_nic *pfvf,
1058				 struct macsec_secy *secy, u8 hw_secy_id)
1059{
1060	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1061	struct cn10k_mcs_rxsc *mcs_rx_sc;
1062	struct macsec_rx_sc *sw_rx_sc;
1063	struct macsec_rx_sa *sw_rx_sa;
1064	u8 sa_num;
1065
1066	for (sw_rx_sc = rcu_dereference_bh(secy->rx_sc); sw_rx_sc && sw_rx_sc->active;
1067	     sw_rx_sc = rcu_dereference_bh(sw_rx_sc->next)) {
1068		mcs_rx_sc = cn10k_mcs_get_rxsc(cfg, secy, sw_rx_sc);
1069		if (unlikely(!mcs_rx_sc))
1070			continue;
1071
1072		for (sa_num = 0; sa_num < CN10K_MCS_SA_PER_SC; sa_num++) {
1073			sw_rx_sa = rcu_dereference_bh(sw_rx_sc->sa[sa_num]);
1074			if (!sw_rx_sa)
1075				continue;
1076
1077			cn10k_mcs_write_rx_sa_plcy(pfvf, secy, mcs_rx_sc,
1078						   sa_num, sw_rx_sa->active);
1079			cn10k_mcs_write_rx_sa_pn(pfvf, mcs_rx_sc, sa_num,
1080						 sw_rx_sa->next_pn);
1081		}
1082
1083		cn10k_mcs_write_rx_flowid(pfvf, mcs_rx_sc, hw_secy_id);
1084		cn10k_mcs_write_sc_cam(pfvf, mcs_rx_sc, hw_secy_id);
1085	}
1086
1087	return 0;
1088}
1089
1090static int cn10k_mcs_disable_rxscs(struct otx2_nic *pfvf,
1091				   struct macsec_secy *secy,
1092				   bool delete)
1093{
1094	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1095	struct cn10k_mcs_rxsc *mcs_rx_sc;
1096	struct macsec_rx_sc *sw_rx_sc;
1097	int ret;
1098
1099	for (sw_rx_sc = rcu_dereference_bh(secy->rx_sc); sw_rx_sc && sw_rx_sc->active;
1100	     sw_rx_sc = rcu_dereference_bh(sw_rx_sc->next)) {
1101		mcs_rx_sc = cn10k_mcs_get_rxsc(cfg, secy, sw_rx_sc);
1102		if (unlikely(!mcs_rx_sc))
1103			continue;
1104
1105		ret = cn10k_mcs_ena_dis_flowid(pfvf, mcs_rx_sc->hw_flow_id,
1106					       false, MCS_RX);
1107		if (ret)
1108			dev_err(pfvf->dev, "Failed to disable TCAM for SC %d\n",
1109				mcs_rx_sc->hw_sc_id);
1110		if (delete) {
1111			cn10k_mcs_delete_rxsc(pfvf, mcs_rx_sc);
1112			list_del(&mcs_rx_sc->entry);
1113			kfree(mcs_rx_sc);
1114		}
1115	}
1116
1117	return 0;
1118}
1119
1120static void cn10k_mcs_sync_stats(struct otx2_nic *pfvf, struct macsec_secy *secy,
1121				 struct cn10k_mcs_txsc *txsc)
1122{
1123	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1124	struct mcs_secy_stats rx_rsp = { 0 };
1125	struct mcs_sc_stats sc_rsp = { 0 };
1126	struct cn10k_mcs_rxsc *rxsc;
1127
1128	/* Because of shared counters for some stats in the hardware, when
1129	 * updating secy policy take a snapshot of current stats and reset them.
1130	 * Below are the effected stats because of shared counters.
1131	 */
1132
1133	/* Check if sync is really needed */
1134	if (secy->validate_frames == txsc->last_validate_frames &&
1135	    secy->replay_protect == txsc->last_replay_protect)
1136		return;
1137
1138	cn10k_mcs_secy_stats(pfvf, txsc->hw_secy_id_rx, &rx_rsp, MCS_RX, true);
1139
1140	txsc->stats.InPktsBadTag += rx_rsp.pkt_badtag_cnt;
1141	txsc->stats.InPktsUnknownSCI += rx_rsp.pkt_nosa_cnt;
1142	txsc->stats.InPktsNoSCI += rx_rsp.pkt_nosaerror_cnt;
1143	if (txsc->last_validate_frames == MACSEC_VALIDATE_STRICT)
1144		txsc->stats.InPktsNoTag += rx_rsp.pkt_untaged_cnt;
1145	else
1146		txsc->stats.InPktsUntagged += rx_rsp.pkt_untaged_cnt;
1147
1148	list_for_each_entry(rxsc, &cfg->rxsc_list, entry) {
1149		cn10k_mcs_sc_stats(pfvf, rxsc->hw_sc_id, &sc_rsp, MCS_RX, true);
1150
1151		rxsc->stats.InOctetsValidated += sc_rsp.octet_validate_cnt;
1152		rxsc->stats.InOctetsDecrypted += sc_rsp.octet_decrypt_cnt;
1153
1154		rxsc->stats.InPktsInvalid += sc_rsp.pkt_invalid_cnt;
1155		rxsc->stats.InPktsNotValid += sc_rsp.pkt_notvalid_cnt;
1156
1157		if (txsc->last_replay_protect)
1158			rxsc->stats.InPktsLate += sc_rsp.pkt_late_cnt;
1159		else
1160			rxsc->stats.InPktsDelayed += sc_rsp.pkt_late_cnt;
1161
1162		if (txsc->last_validate_frames == MACSEC_VALIDATE_DISABLED)
1163			rxsc->stats.InPktsUnchecked += sc_rsp.pkt_unchecked_cnt;
1164		else
1165			rxsc->stats.InPktsOK += sc_rsp.pkt_unchecked_cnt;
1166	}
1167
1168	txsc->last_validate_frames = secy->validate_frames;
1169	txsc->last_replay_protect = secy->replay_protect;
1170}
1171
1172static int cn10k_mdo_open(struct macsec_context *ctx)
1173{
1174	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1175	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1176	struct macsec_secy *secy = ctx->secy;
1177	struct macsec_tx_sa *sw_tx_sa;
1178	struct cn10k_mcs_txsc *txsc;
1179	u8 sa_num;
1180	int err;
1181
1182	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1183	if (!txsc)
1184		return -ENOENT;
1185
1186	sa_num = txsc->encoding_sa;
1187	sw_tx_sa = rcu_dereference_bh(secy->tx_sc.sa[sa_num]);
1188
1189	err = cn10k_mcs_secy_tx_cfg(pfvf, secy, txsc, sw_tx_sa, sa_num);
1190	if (err)
1191		return err;
1192
1193	return cn10k_mcs_secy_rx_cfg(pfvf, secy, txsc->hw_secy_id_rx);
1194}
1195
1196static int cn10k_mdo_stop(struct macsec_context *ctx)
1197{
1198	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1199	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1200	struct cn10k_mcs_txsc *txsc;
1201	int err;
1202
1203	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1204	if (!txsc)
1205		return -ENOENT;
1206
1207	err = cn10k_mcs_ena_dis_flowid(pfvf, txsc->hw_flow_id, false, MCS_TX);
1208	if (err)
1209		return err;
1210
1211	return cn10k_mcs_disable_rxscs(pfvf, ctx->secy, false);
1212}
1213
1214static int cn10k_mdo_add_secy(struct macsec_context *ctx)
1215{
1216	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1217	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1218	struct macsec_secy *secy = ctx->secy;
1219	struct cn10k_mcs_txsc *txsc;
1220
1221	if (secy->icv_len != MACSEC_DEFAULT_ICV_LEN)
1222		return -EOPNOTSUPP;
1223
1224	txsc = cn10k_mcs_create_txsc(pfvf);
1225	if (IS_ERR(txsc))
1226		return -ENOSPC;
1227
1228	txsc->sw_secy = secy;
1229	txsc->encoding_sa = secy->tx_sc.encoding_sa;
1230	txsc->last_validate_frames = secy->validate_frames;
1231	txsc->last_replay_protect = secy->replay_protect;
1232	txsc->vlan_dev = is_vlan_dev(ctx->netdev);
1233
1234	list_add(&txsc->entry, &cfg->txsc_list);
1235
1236	if (netif_running(secy->netdev))
1237		return cn10k_mcs_secy_tx_cfg(pfvf, secy, txsc, NULL, 0);
1238
1239	return 0;
1240}
1241
1242static int cn10k_mdo_upd_secy(struct macsec_context *ctx)
1243{
1244	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1245	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1246	struct macsec_secy *secy = ctx->secy;
1247	struct macsec_tx_sa *sw_tx_sa;
1248	struct cn10k_mcs_txsc *txsc;
1249	bool active;
1250	u8 sa_num;
1251	int err;
1252
1253	txsc = cn10k_mcs_get_txsc(cfg, secy);
1254	if (!txsc)
1255		return -ENOENT;
1256
1257	/* Encoding SA got changed */
1258	if (txsc->encoding_sa != secy->tx_sc.encoding_sa) {
1259		txsc->encoding_sa = secy->tx_sc.encoding_sa;
1260		sa_num = txsc->encoding_sa;
1261		sw_tx_sa = rcu_dereference_bh(secy->tx_sc.sa[sa_num]);
1262		active = sw_tx_sa ? sw_tx_sa->active : false;
1263		cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, sa_num, active);
1264	}
1265
1266	if (netif_running(secy->netdev)) {
1267		cn10k_mcs_sync_stats(pfvf, secy, txsc);
1268
1269		err = cn10k_mcs_secy_tx_cfg(pfvf, secy, txsc, NULL, 0);
1270		if (err)
1271			return err;
1272	}
1273
1274	return 0;
1275}
1276
1277static int cn10k_mdo_del_secy(struct macsec_context *ctx)
1278{
1279	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1280	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1281	struct cn10k_mcs_txsc *txsc;
1282
1283	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1284	if (!txsc)
1285		return -ENOENT;
1286
1287	cn10k_mcs_ena_dis_flowid(pfvf, txsc->hw_flow_id, false, MCS_TX);
1288	cn10k_mcs_disable_rxscs(pfvf, ctx->secy, true);
1289	cn10k_mcs_delete_txsc(pfvf, txsc);
1290	list_del(&txsc->entry);
1291	kfree(txsc);
1292
1293	return 0;
1294}
1295
1296static int cn10k_mdo_add_txsa(struct macsec_context *ctx)
1297{
1298	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1299	struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
1300	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1301	struct macsec_secy *secy = ctx->secy;
1302	u8 sa_num = ctx->sa.assoc_num;
1303	struct cn10k_mcs_txsc *txsc;
1304	int err;
1305
1306	txsc = cn10k_mcs_get_txsc(cfg, secy);
1307	if (!txsc)
1308		return -ENOENT;
1309
1310	if (sa_num >= CN10K_MCS_SA_PER_SC)
1311		return -EOPNOTSUPP;
1312
1313	if (cn10k_mcs_alloc_txsa(pfvf, &txsc->hw_sa_id[sa_num]))
1314		return -ENOSPC;
1315
1316	memcpy(&txsc->sa_key[sa_num], ctx->sa.key, secy->key_len);
1317	memcpy(&txsc->salt[sa_num], sw_tx_sa->key.salt.bytes, MACSEC_SALT_LEN);
1318	txsc->ssci[sa_num] = sw_tx_sa->ssci;
1319
1320	txsc->sa_bmap |= 1 << sa_num;
1321
1322	if (netif_running(secy->netdev)) {
1323		err = cn10k_mcs_write_tx_sa_plcy(pfvf, secy, txsc, sa_num);
1324		if (err)
1325			return err;
1326
1327		err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
1328					   sw_tx_sa->next_pn);
1329		if (err)
1330			return err;
1331
1332		err = cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc,
1333					      sa_num, sw_tx_sa->active);
1334		if (err)
1335			return err;
1336	}
1337
1338	return 0;
1339}
1340
1341static int cn10k_mdo_upd_txsa(struct macsec_context *ctx)
1342{
1343	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1344	struct macsec_tx_sa *sw_tx_sa = ctx->sa.tx_sa;
1345	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1346	struct macsec_secy *secy = ctx->secy;
1347	u8 sa_num = ctx->sa.assoc_num;
1348	struct cn10k_mcs_txsc *txsc;
1349	int err;
1350
1351	txsc = cn10k_mcs_get_txsc(cfg, secy);
1352	if (!txsc)
1353		return -ENOENT;
1354
1355	if (sa_num >= CN10K_MCS_SA_PER_SC)
1356		return -EOPNOTSUPP;
1357
1358	if (netif_running(secy->netdev)) {
1359		/* Keys cannot be changed after creation */
1360		if (ctx->sa.update_pn) {
1361			err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num,
1362						   sw_tx_sa->next_pn);
1363			if (err)
1364				return err;
1365		}
1366
1367		err = cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc,
1368					      sa_num, sw_tx_sa->active);
1369		if (err)
1370			return err;
1371	}
1372
1373	return 0;
1374}
1375
1376static int cn10k_mdo_del_txsa(struct macsec_context *ctx)
1377{
1378	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1379	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1380	u8 sa_num = ctx->sa.assoc_num;
1381	struct cn10k_mcs_txsc *txsc;
1382
1383	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1384	if (!txsc)
1385		return -ENOENT;
1386
1387	if (sa_num >= CN10K_MCS_SA_PER_SC)
1388		return -EOPNOTSUPP;
1389
1390	cn10k_mcs_free_txsa(pfvf, txsc->hw_sa_id[sa_num]);
1391	txsc->sa_bmap &= ~(1 << sa_num);
1392
1393	return 0;
1394}
1395
1396static int cn10k_mdo_add_rxsc(struct macsec_context *ctx)
1397{
1398	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1399	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1400	struct macsec_secy *secy = ctx->secy;
1401	struct cn10k_mcs_rxsc *rxsc;
1402	struct cn10k_mcs_txsc *txsc;
1403	int err;
1404
1405	txsc = cn10k_mcs_get_txsc(cfg, secy);
1406	if (!txsc)
1407		return -ENOENT;
1408
1409	rxsc = cn10k_mcs_create_rxsc(pfvf);
1410	if (IS_ERR(rxsc))
1411		return -ENOSPC;
1412
1413	rxsc->sw_secy = ctx->secy;
1414	rxsc->sw_rxsc = ctx->rx_sc;
1415	list_add(&rxsc->entry, &cfg->rxsc_list);
1416
1417	if (netif_running(secy->netdev)) {
1418		err = cn10k_mcs_write_rx_flowid(pfvf, rxsc, txsc->hw_secy_id_rx);
1419		if (err)
1420			return err;
1421
1422		err = cn10k_mcs_write_sc_cam(pfvf, rxsc, txsc->hw_secy_id_rx);
1423		if (err)
1424			return err;
1425	}
1426
1427	return 0;
1428}
1429
1430static int cn10k_mdo_upd_rxsc(struct macsec_context *ctx)
1431{
1432	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1433	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1434	struct macsec_secy *secy = ctx->secy;
1435	bool enable = ctx->rx_sc->active;
1436	struct cn10k_mcs_rxsc *rxsc;
1437
1438	rxsc = cn10k_mcs_get_rxsc(cfg, secy, ctx->rx_sc);
1439	if (!rxsc)
1440		return -ENOENT;
1441
1442	if (netif_running(secy->netdev))
1443		return cn10k_mcs_ena_dis_flowid(pfvf, rxsc->hw_flow_id,
1444						enable, MCS_RX);
1445
1446	return 0;
1447}
1448
1449static int cn10k_mdo_del_rxsc(struct macsec_context *ctx)
1450{
1451	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1452	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1453	struct cn10k_mcs_rxsc *rxsc;
1454
1455	rxsc = cn10k_mcs_get_rxsc(cfg, ctx->secy, ctx->rx_sc);
1456	if (!rxsc)
1457		return -ENOENT;
1458
1459	cn10k_mcs_ena_dis_flowid(pfvf, rxsc->hw_flow_id, false, MCS_RX);
1460	cn10k_mcs_delete_rxsc(pfvf, rxsc);
1461	list_del(&rxsc->entry);
1462	kfree(rxsc);
1463
1464	return 0;
1465}
1466
1467static int cn10k_mdo_add_rxsa(struct macsec_context *ctx)
1468{
1469	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1470	struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
1471	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1472	struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
1473	struct macsec_secy *secy = ctx->secy;
1474	bool sa_in_use = rx_sa->active;
1475	u8 sa_num = ctx->sa.assoc_num;
1476	struct cn10k_mcs_rxsc *rxsc;
1477	int err;
1478
1479	rxsc = cn10k_mcs_get_rxsc(cfg, secy, sw_rx_sc);
1480	if (!rxsc)
1481		return -ENOENT;
1482
1483	if (sa_num >= CN10K_MCS_SA_PER_SC)
1484		return -EOPNOTSUPP;
1485
1486	if (cn10k_mcs_alloc_rxsa(pfvf, &rxsc->hw_sa_id[sa_num]))
1487		return -ENOSPC;
1488
1489	memcpy(&rxsc->sa_key[sa_num], ctx->sa.key, ctx->secy->key_len);
1490	memcpy(&rxsc->salt[sa_num], rx_sa->key.salt.bytes, MACSEC_SALT_LEN);
1491	rxsc->ssci[sa_num] = rx_sa->ssci;
1492
1493	rxsc->sa_bmap |= 1 << sa_num;
1494
1495	if (netif_running(secy->netdev)) {
1496		err = cn10k_mcs_write_rx_sa_plcy(pfvf, secy, rxsc,
1497						 sa_num, sa_in_use);
1498		if (err)
1499			return err;
1500
1501		err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
1502					       rx_sa->next_pn);
1503		if (err)
1504			return err;
1505	}
1506
1507	return 0;
1508}
1509
1510static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx)
1511{
1512	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1513	struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
1514	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1515	struct macsec_rx_sa *rx_sa = ctx->sa.rx_sa;
1516	struct macsec_secy *secy = ctx->secy;
1517	bool sa_in_use = rx_sa->active;
1518	u8 sa_num = ctx->sa.assoc_num;
1519	struct cn10k_mcs_rxsc *rxsc;
1520	int err;
1521
1522	rxsc = cn10k_mcs_get_rxsc(cfg, secy, sw_rx_sc);
1523	if (!rxsc)
1524		return -ENOENT;
1525
1526	if (sa_num >= CN10K_MCS_SA_PER_SC)
1527		return -EOPNOTSUPP;
1528
1529	if (netif_running(secy->netdev)) {
1530		err = cn10k_mcs_write_rx_sa_plcy(pfvf, secy, rxsc, sa_num, sa_in_use);
1531		if (err)
1532			return err;
1533
1534		if (!ctx->sa.update_pn)
1535			return 0;
1536
1537		err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num,
1538					       rx_sa->next_pn);
1539		if (err)
1540			return err;
1541	}
1542
1543	return 0;
1544}
1545
1546static int cn10k_mdo_del_rxsa(struct macsec_context *ctx)
1547{
1548	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1549	struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
1550	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1551	u8 sa_num = ctx->sa.assoc_num;
1552	struct cn10k_mcs_rxsc *rxsc;
1553
1554	rxsc = cn10k_mcs_get_rxsc(cfg, ctx->secy, sw_rx_sc);
1555	if (!rxsc)
1556		return -ENOENT;
1557
1558	if (sa_num >= CN10K_MCS_SA_PER_SC)
1559		return -EOPNOTSUPP;
1560
1561	cn10k_mcs_write_rx_sa_plcy(pfvf, ctx->secy, rxsc, sa_num, false);
1562	cn10k_mcs_free_rxsa(pfvf, rxsc->hw_sa_id[sa_num]);
1563
1564	rxsc->sa_bmap &= ~(1 << sa_num);
1565
1566	return 0;
1567}
1568
1569static int cn10k_mdo_get_dev_stats(struct macsec_context *ctx)
1570{
1571	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1572	struct mcs_secy_stats tx_rsp = { 0 }, rx_rsp = { 0 };
1573	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1574	struct macsec_secy *secy = ctx->secy;
1575	struct cn10k_mcs_txsc *txsc;
1576
1577	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1578	if (!txsc)
1579		return -ENOENT;
1580
1581	cn10k_mcs_secy_stats(pfvf, txsc->hw_secy_id_tx, &tx_rsp, MCS_TX, false);
1582	ctx->stats.dev_stats->OutPktsUntagged = tx_rsp.pkt_untagged_cnt;
1583	ctx->stats.dev_stats->OutPktsTooLong = tx_rsp.pkt_toolong_cnt;
1584
1585	cn10k_mcs_secy_stats(pfvf, txsc->hw_secy_id_rx, &rx_rsp, MCS_RX, true);
1586	txsc->stats.InPktsBadTag += rx_rsp.pkt_badtag_cnt;
1587	txsc->stats.InPktsUnknownSCI += rx_rsp.pkt_nosa_cnt;
1588	txsc->stats.InPktsNoSCI += rx_rsp.pkt_nosaerror_cnt;
1589	if (secy->validate_frames == MACSEC_VALIDATE_STRICT)
1590		txsc->stats.InPktsNoTag += rx_rsp.pkt_untaged_cnt;
1591	else
1592		txsc->stats.InPktsUntagged += rx_rsp.pkt_untaged_cnt;
1593	txsc->stats.InPktsOverrun = 0;
1594
1595	ctx->stats.dev_stats->InPktsNoTag = txsc->stats.InPktsNoTag;
1596	ctx->stats.dev_stats->InPktsUntagged = txsc->stats.InPktsUntagged;
1597	ctx->stats.dev_stats->InPktsBadTag = txsc->stats.InPktsBadTag;
1598	ctx->stats.dev_stats->InPktsUnknownSCI = txsc->stats.InPktsUnknownSCI;
1599	ctx->stats.dev_stats->InPktsNoSCI = txsc->stats.InPktsNoSCI;
1600	ctx->stats.dev_stats->InPktsOverrun = txsc->stats.InPktsOverrun;
1601
1602	return 0;
1603}
1604
1605static int cn10k_mdo_get_tx_sc_stats(struct macsec_context *ctx)
1606{
1607	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1608	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1609	struct mcs_sc_stats rsp = { 0 };
1610	struct cn10k_mcs_txsc *txsc;
1611
1612	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1613	if (!txsc)
1614		return -ENOENT;
1615
1616	cn10k_mcs_sc_stats(pfvf, txsc->hw_sc_id, &rsp, MCS_TX, false);
1617
1618	ctx->stats.tx_sc_stats->OutPktsProtected = rsp.pkt_protected_cnt;
1619	ctx->stats.tx_sc_stats->OutPktsEncrypted = rsp.pkt_encrypt_cnt;
1620	ctx->stats.tx_sc_stats->OutOctetsProtected = rsp.octet_protected_cnt;
1621	ctx->stats.tx_sc_stats->OutOctetsEncrypted = rsp.octet_encrypt_cnt;
1622
1623	return 0;
1624}
1625
1626static int cn10k_mdo_get_tx_sa_stats(struct macsec_context *ctx)
1627{
1628	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1629	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1630	struct mcs_sa_stats rsp = { 0 };
1631	u8 sa_num = ctx->sa.assoc_num;
1632	struct cn10k_mcs_txsc *txsc;
1633
1634	txsc = cn10k_mcs_get_txsc(cfg, ctx->secy);
1635	if (!txsc)
1636		return -ENOENT;
1637
1638	if (sa_num >= CN10K_MCS_SA_PER_SC)
1639		return -EOPNOTSUPP;
1640
1641	cn10k_mcs_sa_stats(pfvf, txsc->hw_sa_id[sa_num], &rsp, MCS_TX, false);
1642
1643	ctx->stats.tx_sa_stats->OutPktsProtected = rsp.pkt_protected_cnt;
1644	ctx->stats.tx_sa_stats->OutPktsEncrypted = rsp.pkt_encrypt_cnt;
1645
1646	return 0;
1647}
1648
1649static int cn10k_mdo_get_rx_sc_stats(struct macsec_context *ctx)
1650{
1651	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1652	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1653	struct macsec_secy *secy = ctx->secy;
1654	struct mcs_sc_stats rsp = { 0 };
1655	struct cn10k_mcs_rxsc *rxsc;
1656
1657	rxsc = cn10k_mcs_get_rxsc(cfg, secy, ctx->rx_sc);
1658	if (!rxsc)
1659		return -ENOENT;
1660
1661	cn10k_mcs_sc_stats(pfvf, rxsc->hw_sc_id, &rsp, MCS_RX, true);
1662
1663	rxsc->stats.InOctetsValidated += rsp.octet_validate_cnt;
1664	rxsc->stats.InOctetsDecrypted += rsp.octet_decrypt_cnt;
1665
1666	rxsc->stats.InPktsInvalid += rsp.pkt_invalid_cnt;
1667	rxsc->stats.InPktsNotValid += rsp.pkt_notvalid_cnt;
1668
1669	if (secy->replay_protect)
1670		rxsc->stats.InPktsLate += rsp.pkt_late_cnt;
1671	else
1672		rxsc->stats.InPktsDelayed += rsp.pkt_late_cnt;
1673
1674	if (secy->validate_frames == MACSEC_VALIDATE_DISABLED)
1675		rxsc->stats.InPktsUnchecked += rsp.pkt_unchecked_cnt;
1676	else
1677		rxsc->stats.InPktsOK += rsp.pkt_unchecked_cnt;
1678
1679	ctx->stats.rx_sc_stats->InOctetsValidated = rxsc->stats.InOctetsValidated;
1680	ctx->stats.rx_sc_stats->InOctetsDecrypted = rxsc->stats.InOctetsDecrypted;
1681	ctx->stats.rx_sc_stats->InPktsInvalid = rxsc->stats.InPktsInvalid;
1682	ctx->stats.rx_sc_stats->InPktsNotValid = rxsc->stats.InPktsNotValid;
1683	ctx->stats.rx_sc_stats->InPktsLate = rxsc->stats.InPktsLate;
1684	ctx->stats.rx_sc_stats->InPktsDelayed = rxsc->stats.InPktsDelayed;
1685	ctx->stats.rx_sc_stats->InPktsUnchecked = rxsc->stats.InPktsUnchecked;
1686	ctx->stats.rx_sc_stats->InPktsOK = rxsc->stats.InPktsOK;
1687
1688	return 0;
1689}
1690
1691static int cn10k_mdo_get_rx_sa_stats(struct macsec_context *ctx)
1692{
1693	struct otx2_nic *pfvf = macsec_netdev_priv(ctx->netdev);
1694	struct macsec_rx_sc *sw_rx_sc = ctx->sa.rx_sa->sc;
1695	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1696	struct mcs_sa_stats rsp = { 0 };
1697	u8 sa_num = ctx->sa.assoc_num;
1698	struct cn10k_mcs_rxsc *rxsc;
1699
1700	rxsc = cn10k_mcs_get_rxsc(cfg, ctx->secy, sw_rx_sc);
1701	if (!rxsc)
1702		return -ENOENT;
1703
1704	if (sa_num >= CN10K_MCS_SA_PER_SC)
1705		return -EOPNOTSUPP;
1706
1707	cn10k_mcs_sa_stats(pfvf, rxsc->hw_sa_id[sa_num], &rsp, MCS_RX, false);
1708
1709	ctx->stats.rx_sa_stats->InPktsOK = rsp.pkt_ok_cnt;
1710	ctx->stats.rx_sa_stats->InPktsInvalid = rsp.pkt_invalid_cnt;
1711	ctx->stats.rx_sa_stats->InPktsNotValid = rsp.pkt_notvalid_cnt;
1712	ctx->stats.rx_sa_stats->InPktsNotUsingSA = rsp.pkt_nosaerror_cnt;
1713	ctx->stats.rx_sa_stats->InPktsUnusedSA = rsp.pkt_nosa_cnt;
1714
1715	return 0;
1716}
1717
1718static const struct macsec_ops cn10k_mcs_ops = {
1719	.mdo_dev_open = cn10k_mdo_open,
1720	.mdo_dev_stop = cn10k_mdo_stop,
1721	.mdo_add_secy = cn10k_mdo_add_secy,
1722	.mdo_upd_secy = cn10k_mdo_upd_secy,
1723	.mdo_del_secy = cn10k_mdo_del_secy,
1724	.mdo_add_rxsc = cn10k_mdo_add_rxsc,
1725	.mdo_upd_rxsc = cn10k_mdo_upd_rxsc,
1726	.mdo_del_rxsc = cn10k_mdo_del_rxsc,
1727	.mdo_add_rxsa = cn10k_mdo_add_rxsa,
1728	.mdo_upd_rxsa = cn10k_mdo_upd_rxsa,
1729	.mdo_del_rxsa = cn10k_mdo_del_rxsa,
1730	.mdo_add_txsa = cn10k_mdo_add_txsa,
1731	.mdo_upd_txsa = cn10k_mdo_upd_txsa,
1732	.mdo_del_txsa = cn10k_mdo_del_txsa,
1733	.mdo_get_dev_stats = cn10k_mdo_get_dev_stats,
1734	.mdo_get_tx_sc_stats = cn10k_mdo_get_tx_sc_stats,
1735	.mdo_get_tx_sa_stats = cn10k_mdo_get_tx_sa_stats,
1736	.mdo_get_rx_sc_stats = cn10k_mdo_get_rx_sc_stats,
1737	.mdo_get_rx_sa_stats = cn10k_mdo_get_rx_sa_stats,
1738};
1739
1740void cn10k_handle_mcs_event(struct otx2_nic *pfvf, struct mcs_intr_info *event)
1741{
1742	struct cn10k_mcs_cfg *cfg = pfvf->macsec_cfg;
1743	struct macsec_tx_sa *sw_tx_sa = NULL;
1744	struct macsec_secy *secy = NULL;
1745	struct cn10k_mcs_txsc *txsc;
1746	u8 an;
1747
1748	if (!test_bit(CN10K_HW_MACSEC, &pfvf->hw.cap_flag))
1749		return;
1750
1751	if (!(event->intr_mask & MCS_CPM_TX_PACKET_XPN_EQ0_INT))
1752		return;
1753
1754	/* Find the SecY to which the expired hardware SA is mapped */
1755	list_for_each_entry(txsc, &cfg->txsc_list, entry) {
1756		for (an = 0; an < CN10K_MCS_SA_PER_SC; an++)
1757			if (txsc->hw_sa_id[an] == event->sa_id) {
1758				secy = txsc->sw_secy;
1759				sw_tx_sa = rcu_dereference_bh(secy->tx_sc.sa[an]);
1760			}
1761	}
1762
1763	if (secy && sw_tx_sa)
1764		macsec_pn_wrapped(secy, sw_tx_sa);
1765}
1766
1767int cn10k_mcs_init(struct otx2_nic *pfvf)
1768{
1769	struct mbox *mbox = &pfvf->mbox;
1770	struct cn10k_mcs_cfg *cfg;
1771	struct mcs_intr_cfg *req;
1772
1773	if (!test_bit(CN10K_HW_MACSEC, &pfvf->hw.cap_flag))
1774		return 0;
1775
1776	cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
1777	if (!cfg)
1778		return -ENOMEM;
1779
1780	INIT_LIST_HEAD(&cfg->txsc_list);
1781	INIT_LIST_HEAD(&cfg->rxsc_list);
1782	pfvf->macsec_cfg = cfg;
1783
1784	pfvf->netdev->features |= NETIF_F_HW_MACSEC;
1785	pfvf->netdev->macsec_ops = &cn10k_mcs_ops;
1786
1787	mutex_lock(&mbox->lock);
1788
1789	req = otx2_mbox_alloc_msg_mcs_intr_cfg(mbox);
1790	if (!req)
1791		goto fail;
1792
1793	req->intr_mask = MCS_CPM_TX_PACKET_XPN_EQ0_INT;
1794
1795	if (otx2_sync_mbox_msg(mbox))
1796		goto fail;
1797
1798	mutex_unlock(&mbox->lock);
1799
1800	return 0;
1801fail:
1802	dev_err(pfvf->dev, "Cannot notify PN wrapped event\n");
1803	mutex_unlock(&mbox->lock);
1804	return 0;
1805}
1806
1807void cn10k_mcs_free(struct otx2_nic *pfvf)
1808{
1809	if (!test_bit(CN10K_HW_MACSEC, &pfvf->hw.cap_flag))
1810		return;
1811
1812	cn10k_mcs_free_rsrc(pfvf, MCS_TX, MCS_RSRC_TYPE_SECY, 0, true);
1813	cn10k_mcs_free_rsrc(pfvf, MCS_RX, MCS_RSRC_TYPE_SECY, 0, true);
1814	kfree(pfvf->macsec_cfg);
1815	pfvf->macsec_cfg = NULL;
1816}