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