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