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