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