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