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