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