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