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