1222a4eeaSGeetha sowjanya // SPDX-License-Identifier: GPL-2.0 2222a4eeaSGeetha sowjanya /* Marvell RVU Admin Function driver 3222a4eeaSGeetha sowjanya * 4222a4eeaSGeetha sowjanya * Copyright (C) 2024 Marvell. 5222a4eeaSGeetha sowjanya * 6222a4eeaSGeetha sowjanya */ 7222a4eeaSGeetha sowjanya 8222a4eeaSGeetha sowjanya #include <linux/bitfield.h> 9222a4eeaSGeetha sowjanya #include <linux/types.h> 10222a4eeaSGeetha sowjanya #include <linux/device.h> 11222a4eeaSGeetha sowjanya #include <linux/module.h> 12222a4eeaSGeetha sowjanya #include <linux/pci.h> 13222a4eeaSGeetha sowjanya 14222a4eeaSGeetha sowjanya #include "rvu.h" 15222a4eeaSGeetha sowjanya #include "rvu_reg.h" 16222a4eeaSGeetha sowjanya 17b8fea84aSGeetha sowjanya #define M(_name, _id, _fn_name, _req_type, _rsp_type) \ 18b8fea84aSGeetha sowjanya static struct _req_type __maybe_unused \ 19b8fea84aSGeetha sowjanya *otx2_mbox_alloc_msg_ ## _fn_name(struct rvu *rvu, int devid) \ 20b8fea84aSGeetha sowjanya { \ 21b8fea84aSGeetha sowjanya struct _req_type *req; \ 22b8fea84aSGeetha sowjanya \ 23b8fea84aSGeetha sowjanya req = (struct _req_type *)otx2_mbox_alloc_msg_rsp( \ 24b8fea84aSGeetha sowjanya &rvu->afpf_wq_info.mbox_up, devid, sizeof(struct _req_type), \ 25b8fea84aSGeetha sowjanya sizeof(struct _rsp_type)); \ 26b8fea84aSGeetha sowjanya if (!req) \ 27b8fea84aSGeetha sowjanya return NULL; \ 28b8fea84aSGeetha sowjanya req->hdr.sig = OTX2_MBOX_REQ_SIG; \ 29b8fea84aSGeetha sowjanya req->hdr.id = _id; \ 30b8fea84aSGeetha sowjanya return req; \ 31b8fea84aSGeetha sowjanya } 32b8fea84aSGeetha sowjanya 33b8fea84aSGeetha sowjanya MBOX_UP_REP_MESSAGES 34b8fea84aSGeetha sowjanya #undef M 35b8fea84aSGeetha sowjanya 36b8fea84aSGeetha sowjanya static int rvu_rep_up_notify(struct rvu *rvu, struct rep_event *event) 37b8fea84aSGeetha sowjanya { 389ed0343fSGeetha sowjanya struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, event->pcifunc); 39b8fea84aSGeetha sowjanya struct rep_event *msg; 40b8fea84aSGeetha sowjanya int pf; 41b8fea84aSGeetha sowjanya 42b8fea84aSGeetha sowjanya pf = rvu_get_pf(event->pcifunc); 43b8fea84aSGeetha sowjanya 449ed0343fSGeetha sowjanya if (event->event & RVU_EVENT_MAC_ADDR_CHANGE) 459ed0343fSGeetha sowjanya ether_addr_copy(pfvf->mac_addr, event->evt_data.mac); 469ed0343fSGeetha sowjanya 47b8fea84aSGeetha sowjanya mutex_lock(&rvu->mbox_lock); 48b8fea84aSGeetha sowjanya msg = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf); 49b8fea84aSGeetha sowjanya if (!msg) { 50b8fea84aSGeetha sowjanya mutex_unlock(&rvu->mbox_lock); 51b8fea84aSGeetha sowjanya return -ENOMEM; 52b8fea84aSGeetha sowjanya } 53b8fea84aSGeetha sowjanya 54b8fea84aSGeetha sowjanya msg->hdr.pcifunc = event->pcifunc; 55b8fea84aSGeetha sowjanya msg->event = event->event; 56b8fea84aSGeetha sowjanya 57b8fea84aSGeetha sowjanya memcpy(&msg->evt_data, &event->evt_data, sizeof(struct rep_evt_data)); 58b8fea84aSGeetha sowjanya 59b8fea84aSGeetha sowjanya otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf); 60b8fea84aSGeetha sowjanya 61b8fea84aSGeetha sowjanya otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf); 62b8fea84aSGeetha sowjanya 63b8fea84aSGeetha sowjanya mutex_unlock(&rvu->mbox_lock); 64b8fea84aSGeetha sowjanya return 0; 65b8fea84aSGeetha sowjanya } 66b8fea84aSGeetha sowjanya 67b8fea84aSGeetha sowjanya static void rvu_rep_wq_handler(struct work_struct *work) 68b8fea84aSGeetha sowjanya { 69b8fea84aSGeetha sowjanya struct rvu *rvu = container_of(work, struct rvu, rep_evt_work); 70b8fea84aSGeetha sowjanya struct rep_evtq_ent *qentry; 71b8fea84aSGeetha sowjanya struct rep_event *event; 72b8fea84aSGeetha sowjanya unsigned long flags; 73b8fea84aSGeetha sowjanya 74b8fea84aSGeetha sowjanya do { 75b8fea84aSGeetha sowjanya spin_lock_irqsave(&rvu->rep_evtq_lock, flags); 76b8fea84aSGeetha sowjanya qentry = list_first_entry_or_null(&rvu->rep_evtq_head, 77b8fea84aSGeetha sowjanya struct rep_evtq_ent, 78b8fea84aSGeetha sowjanya node); 79b8fea84aSGeetha sowjanya if (qentry) 80b8fea84aSGeetha sowjanya list_del(&qentry->node); 81b8fea84aSGeetha sowjanya 82b8fea84aSGeetha sowjanya spin_unlock_irqrestore(&rvu->rep_evtq_lock, flags); 83b8fea84aSGeetha sowjanya if (!qentry) 84b8fea84aSGeetha sowjanya break; /* nothing more to process */ 85b8fea84aSGeetha sowjanya 86b8fea84aSGeetha sowjanya event = &qentry->event; 87b8fea84aSGeetha sowjanya 88b8fea84aSGeetha sowjanya rvu_rep_up_notify(rvu, event); 89b8fea84aSGeetha sowjanya kfree(qentry); 90b8fea84aSGeetha sowjanya } while (1); 91b8fea84aSGeetha sowjanya } 92b8fea84aSGeetha sowjanya 93b8fea84aSGeetha sowjanya int rvu_mbox_handler_rep_event_notify(struct rvu *rvu, struct rep_event *req, 94b8fea84aSGeetha sowjanya struct msg_rsp *rsp) 95b8fea84aSGeetha sowjanya { 96b8fea84aSGeetha sowjanya struct rep_evtq_ent *qentry; 97b8fea84aSGeetha sowjanya 98b8fea84aSGeetha sowjanya qentry = kmalloc(sizeof(*qentry), GFP_ATOMIC); 99b8fea84aSGeetha sowjanya if (!qentry) 100b8fea84aSGeetha sowjanya return -ENOMEM; 101b8fea84aSGeetha sowjanya 102b8fea84aSGeetha sowjanya qentry->event = *req; 103b8fea84aSGeetha sowjanya spin_lock(&rvu->rep_evtq_lock); 104b8fea84aSGeetha sowjanya list_add_tail(&qentry->node, &rvu->rep_evtq_head); 105b8fea84aSGeetha sowjanya spin_unlock(&rvu->rep_evtq_lock); 106b8fea84aSGeetha sowjanya queue_work(rvu->rep_evt_wq, &rvu->rep_evt_work); 107b8fea84aSGeetha sowjanya return 0; 108b8fea84aSGeetha sowjanya } 109b8fea84aSGeetha sowjanya 110b8fea84aSGeetha sowjanya int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable) 111b8fea84aSGeetha sowjanya { 112b8fea84aSGeetha sowjanya struct rep_event *req; 113b8fea84aSGeetha sowjanya int pf; 114b8fea84aSGeetha sowjanya 115b8fea84aSGeetha sowjanya if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc))) 116b8fea84aSGeetha sowjanya return 0; 117b8fea84aSGeetha sowjanya 118b8fea84aSGeetha sowjanya pf = rvu_get_pf(rvu->rep_pcifunc); 119b8fea84aSGeetha sowjanya 120b8fea84aSGeetha sowjanya mutex_lock(&rvu->mbox_lock); 121b8fea84aSGeetha sowjanya req = otx2_mbox_alloc_msg_rep_event_up_notify(rvu, pf); 122b8fea84aSGeetha sowjanya if (!req) { 123b8fea84aSGeetha sowjanya mutex_unlock(&rvu->mbox_lock); 124b8fea84aSGeetha sowjanya return -ENOMEM; 125b8fea84aSGeetha sowjanya } 126b8fea84aSGeetha sowjanya 127b8fea84aSGeetha sowjanya req->hdr.pcifunc = rvu->rep_pcifunc; 128b8fea84aSGeetha sowjanya req->event |= RVU_EVENT_PFVF_STATE; 129b8fea84aSGeetha sowjanya req->pcifunc = pcifunc; 130b8fea84aSGeetha sowjanya req->evt_data.vf_state = enable; 131b8fea84aSGeetha sowjanya 132b8fea84aSGeetha sowjanya otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf); 133b8fea84aSGeetha sowjanya otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf); 134b8fea84aSGeetha sowjanya 135b8fea84aSGeetha sowjanya mutex_unlock(&rvu->mbox_lock); 136b8fea84aSGeetha sowjanya return 0; 137b8fea84aSGeetha sowjanya } 138b8fea84aSGeetha sowjanya 139940754a2SGeetha sowjanya #define RVU_LF_RX_STATS(reg) \ 140940754a2SGeetha sowjanya rvu_read64(rvu, blkaddr, NIX_AF_LFX_RX_STATX(nixlf, reg)) 141940754a2SGeetha sowjanya 142940754a2SGeetha sowjanya #define RVU_LF_TX_STATS(reg) \ 143940754a2SGeetha sowjanya rvu_read64(rvu, blkaddr, NIX_AF_LFX_TX_STATX(nixlf, reg)) 144940754a2SGeetha sowjanya 145940754a2SGeetha sowjanya int rvu_mbox_handler_nix_lf_stats(struct rvu *rvu, 146940754a2SGeetha sowjanya struct nix_stats_req *req, 147940754a2SGeetha sowjanya struct nix_stats_rsp *rsp) 148940754a2SGeetha sowjanya { 149940754a2SGeetha sowjanya u16 pcifunc = req->pcifunc; 150940754a2SGeetha sowjanya int nixlf, blkaddr, err; 151940754a2SGeetha sowjanya struct msg_req rst_req; 152940754a2SGeetha sowjanya struct msg_rsp rst_rsp; 153940754a2SGeetha sowjanya 154940754a2SGeetha sowjanya err = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr); 155940754a2SGeetha sowjanya if (err) 156940754a2SGeetha sowjanya return 0; 157940754a2SGeetha sowjanya 158940754a2SGeetha sowjanya if (req->reset) { 159940754a2SGeetha sowjanya rst_req.hdr.pcifunc = pcifunc; 160940754a2SGeetha sowjanya return rvu_mbox_handler_nix_stats_rst(rvu, &rst_req, &rst_rsp); 161940754a2SGeetha sowjanya } 162940754a2SGeetha sowjanya rsp->rx.octs = RVU_LF_RX_STATS(RX_OCTS); 163940754a2SGeetha sowjanya rsp->rx.ucast = RVU_LF_RX_STATS(RX_UCAST); 164940754a2SGeetha sowjanya rsp->rx.bcast = RVU_LF_RX_STATS(RX_BCAST); 165940754a2SGeetha sowjanya rsp->rx.mcast = RVU_LF_RX_STATS(RX_MCAST); 166940754a2SGeetha sowjanya rsp->rx.drop = RVU_LF_RX_STATS(RX_DROP); 167940754a2SGeetha sowjanya rsp->rx.err = RVU_LF_RX_STATS(RX_ERR); 168940754a2SGeetha sowjanya rsp->rx.drop_octs = RVU_LF_RX_STATS(RX_DROP_OCTS); 169940754a2SGeetha sowjanya rsp->rx.drop_mcast = RVU_LF_RX_STATS(RX_DRP_MCAST); 170940754a2SGeetha sowjanya rsp->rx.drop_bcast = RVU_LF_RX_STATS(RX_DRP_BCAST); 171940754a2SGeetha sowjanya 172940754a2SGeetha sowjanya rsp->tx.octs = RVU_LF_TX_STATS(TX_OCTS); 173940754a2SGeetha sowjanya rsp->tx.ucast = RVU_LF_TX_STATS(TX_UCAST); 174940754a2SGeetha sowjanya rsp->tx.bcast = RVU_LF_TX_STATS(TX_BCAST); 175940754a2SGeetha sowjanya rsp->tx.mcast = RVU_LF_TX_STATS(TX_MCAST); 176940754a2SGeetha sowjanya rsp->tx.drop = RVU_LF_TX_STATS(TX_DROP); 177940754a2SGeetha sowjanya 178940754a2SGeetha sowjanya rsp->pcifunc = req->pcifunc; 179940754a2SGeetha sowjanya return 0; 180940754a2SGeetha sowjanya } 181940754a2SGeetha sowjanya 182683645a2SGeetha sowjanya static u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc) 183683645a2SGeetha sowjanya { 184683645a2SGeetha sowjanya int id; 185683645a2SGeetha sowjanya 186683645a2SGeetha sowjanya for (id = 0; id < rvu->rep_cnt; id++) 187683645a2SGeetha sowjanya if (rvu->rep2pfvf_map[id] == pcifunc) 188683645a2SGeetha sowjanya return id; 189683645a2SGeetha sowjanya return 0; 190683645a2SGeetha sowjanya } 191683645a2SGeetha sowjanya 192683645a2SGeetha sowjanya static int rvu_rep_tx_vlan_cfg(struct rvu *rvu, u16 pcifunc, 193683645a2SGeetha sowjanya u16 vlan_tci, int *vidx) 194683645a2SGeetha sowjanya { 195683645a2SGeetha sowjanya struct nix_vtag_config_rsp rsp = {}; 196683645a2SGeetha sowjanya struct nix_vtag_config req = {}; 197683645a2SGeetha sowjanya u64 etype = ETH_P_8021Q; 198683645a2SGeetha sowjanya int err; 199683645a2SGeetha sowjanya 200683645a2SGeetha sowjanya /* Insert vlan tag */ 201683645a2SGeetha sowjanya req.hdr.pcifunc = pcifunc; 202683645a2SGeetha sowjanya req.vtag_size = VTAGSIZE_T4; 203683645a2SGeetha sowjanya req.cfg_type = 0; /* tx vlan cfg */ 204683645a2SGeetha sowjanya req.tx.cfg_vtag0 = true; 205683645a2SGeetha sowjanya req.tx.vtag0 = FIELD_PREP(NIX_VLAN_ETYPE_MASK, etype) | vlan_tci; 206683645a2SGeetha sowjanya 207683645a2SGeetha sowjanya err = rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp); 208683645a2SGeetha sowjanya if (err) { 209683645a2SGeetha sowjanya dev_err(rvu->dev, "Tx vlan config failed\n"); 210683645a2SGeetha sowjanya return err; 211683645a2SGeetha sowjanya } 212683645a2SGeetha sowjanya *vidx = rsp.vtag0_idx; 213683645a2SGeetha sowjanya return 0; 214683645a2SGeetha sowjanya } 215683645a2SGeetha sowjanya 216683645a2SGeetha sowjanya static int rvu_rep_rx_vlan_cfg(struct rvu *rvu, u16 pcifunc) 217683645a2SGeetha sowjanya { 218683645a2SGeetha sowjanya struct nix_vtag_config req = {}; 219683645a2SGeetha sowjanya struct nix_vtag_config_rsp rsp; 220683645a2SGeetha sowjanya 221683645a2SGeetha sowjanya /* config strip, capture and size */ 222683645a2SGeetha sowjanya req.hdr.pcifunc = pcifunc; 223683645a2SGeetha sowjanya req.vtag_size = VTAGSIZE_T4; 224683645a2SGeetha sowjanya req.cfg_type = 1; /* rx vlan cfg */ 225683645a2SGeetha sowjanya req.rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0; 226683645a2SGeetha sowjanya req.rx.strip_vtag = true; 227683645a2SGeetha sowjanya req.rx.capture_vtag = false; 228683645a2SGeetha sowjanya 229683645a2SGeetha sowjanya return rvu_mbox_handler_nix_vtag_cfg(rvu, &req, &rsp); 230683645a2SGeetha sowjanya } 231683645a2SGeetha sowjanya 232683645a2SGeetha sowjanya static int rvu_rep_install_rx_rule(struct rvu *rvu, u16 pcifunc, 233683645a2SGeetha sowjanya u16 entry, bool rte) 234683645a2SGeetha sowjanya { 235683645a2SGeetha sowjanya struct npc_install_flow_req req = {}; 236683645a2SGeetha sowjanya struct npc_install_flow_rsp rsp = {}; 237683645a2SGeetha sowjanya struct rvu_pfvf *pfvf; 238683645a2SGeetha sowjanya u16 vlan_tci, rep_id; 239683645a2SGeetha sowjanya 240683645a2SGeetha sowjanya pfvf = rvu_get_pfvf(rvu, pcifunc); 241683645a2SGeetha sowjanya 242683645a2SGeetha sowjanya /* To steer the traffic from Representee to Representor */ 243683645a2SGeetha sowjanya rep_id = rvu_rep_get_vlan_id(rvu, pcifunc); 244683645a2SGeetha sowjanya if (rte) { 245683645a2SGeetha sowjanya vlan_tci = rep_id | BIT_ULL(8); 246683645a2SGeetha sowjanya req.vf = rvu->rep_pcifunc; 247683645a2SGeetha sowjanya req.op = NIX_RX_ACTIONOP_UCAST; 248683645a2SGeetha sowjanya req.index = rep_id; 249683645a2SGeetha sowjanya } else { 250683645a2SGeetha sowjanya vlan_tci = rep_id; 251683645a2SGeetha sowjanya req.vf = pcifunc; 252683645a2SGeetha sowjanya req.op = NIX_RX_ACTION_DEFAULT; 253683645a2SGeetha sowjanya } 254683645a2SGeetha sowjanya 255683645a2SGeetha sowjanya rvu_rep_rx_vlan_cfg(rvu, req.vf); 256683645a2SGeetha sowjanya req.entry = entry; 257683645a2SGeetha sowjanya req.hdr.pcifunc = 0; /* AF is requester */ 258683645a2SGeetha sowjanya req.features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_VLAN_ETYPE_CTAG); 259683645a2SGeetha sowjanya req.vtag0_valid = true; 260683645a2SGeetha sowjanya req.vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0; 261683645a2SGeetha sowjanya req.packet.vlan_etype = cpu_to_be16(ETH_P_8021Q); 262683645a2SGeetha sowjanya req.mask.vlan_etype = cpu_to_be16(ETH_P_8021Q); 263683645a2SGeetha sowjanya req.packet.vlan_tci = cpu_to_be16(vlan_tci); 264683645a2SGeetha sowjanya req.mask.vlan_tci = cpu_to_be16(0xffff); 265683645a2SGeetha sowjanya 266683645a2SGeetha sowjanya req.channel = RVU_SWITCH_LBK_CHAN; 267683645a2SGeetha sowjanya req.chan_mask = 0xffff; 268683645a2SGeetha sowjanya req.intf = pfvf->nix_rx_intf; 269683645a2SGeetha sowjanya 270683645a2SGeetha sowjanya return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 271683645a2SGeetha sowjanya } 272683645a2SGeetha sowjanya 273683645a2SGeetha sowjanya static int rvu_rep_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry, 274683645a2SGeetha sowjanya bool rte) 275683645a2SGeetha sowjanya { 276683645a2SGeetha sowjanya struct npc_install_flow_req req = {}; 277683645a2SGeetha sowjanya struct npc_install_flow_rsp rsp = {}; 278683645a2SGeetha sowjanya struct rvu_pfvf *pfvf; 279683645a2SGeetha sowjanya int vidx, err; 280683645a2SGeetha sowjanya u16 vlan_tci; 281683645a2SGeetha sowjanya u8 lbkid; 282683645a2SGeetha sowjanya 283683645a2SGeetha sowjanya pfvf = rvu_get_pfvf(rvu, pcifunc); 284683645a2SGeetha sowjanya vlan_tci = rvu_rep_get_vlan_id(rvu, pcifunc); 285683645a2SGeetha sowjanya if (rte) 286683645a2SGeetha sowjanya vlan_tci |= BIT_ULL(8); 287683645a2SGeetha sowjanya 288683645a2SGeetha sowjanya err = rvu_rep_tx_vlan_cfg(rvu, pcifunc, vlan_tci, &vidx); 289683645a2SGeetha sowjanya if (err) 290683645a2SGeetha sowjanya return err; 291683645a2SGeetha sowjanya 292683645a2SGeetha sowjanya lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1; 293683645a2SGeetha sowjanya req.hdr.pcifunc = 0; /* AF is requester */ 294683645a2SGeetha sowjanya if (rte) { 295683645a2SGeetha sowjanya req.vf = pcifunc; 296683645a2SGeetha sowjanya } else { 297683645a2SGeetha sowjanya req.vf = rvu->rep_pcifunc; 298683645a2SGeetha sowjanya req.packet.sq_id = vlan_tci; 299683645a2SGeetha sowjanya req.mask.sq_id = 0xffff; 300683645a2SGeetha sowjanya } 301683645a2SGeetha sowjanya 302683645a2SGeetha sowjanya req.entry = entry; 303683645a2SGeetha sowjanya req.intf = pfvf->nix_tx_intf; 304683645a2SGeetha sowjanya req.op = NIX_TX_ACTIONOP_UCAST_CHAN; 305683645a2SGeetha sowjanya req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN; 306683645a2SGeetha sowjanya req.set_cntr = 1; 307683645a2SGeetha sowjanya req.vtag0_def = vidx; 308683645a2SGeetha sowjanya req.vtag0_op = 1; 309683645a2SGeetha sowjanya return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 310683645a2SGeetha sowjanya } 311683645a2SGeetha sowjanya 312683645a2SGeetha sowjanya int rvu_rep_install_mcam_rules(struct rvu *rvu) 313683645a2SGeetha sowjanya { 314683645a2SGeetha sowjanya struct rvu_switch *rswitch = &rvu->rswitch; 315683645a2SGeetha sowjanya u16 start = rswitch->start_entry; 316683645a2SGeetha sowjanya struct rvu_hwinfo *hw = rvu->hw; 317683645a2SGeetha sowjanya u16 pcifunc, entry = 0; 318683645a2SGeetha sowjanya int pf, vf, numvfs; 319683645a2SGeetha sowjanya int err, nixlf, i; 320683645a2SGeetha sowjanya u8 rep; 321683645a2SGeetha sowjanya 322683645a2SGeetha sowjanya for (pf = 1; pf < hw->total_pfs; pf++) { 323683645a2SGeetha sowjanya if (!is_pf_cgxmapped(rvu, pf)) 324683645a2SGeetha sowjanya continue; 325683645a2SGeetha sowjanya 326683645a2SGeetha sowjanya pcifunc = pf << RVU_PFVF_PF_SHIFT; 327683645a2SGeetha sowjanya rvu_get_nix_blkaddr(rvu, pcifunc); 328683645a2SGeetha sowjanya rep = true; 329683645a2SGeetha sowjanya for (i = 0; i < 2; i++) { 330683645a2SGeetha sowjanya err = rvu_rep_install_rx_rule(rvu, pcifunc, 331683645a2SGeetha sowjanya start + entry, rep); 332683645a2SGeetha sowjanya if (err) 333683645a2SGeetha sowjanya return err; 334683645a2SGeetha sowjanya rswitch->entry2pcifunc[entry++] = pcifunc; 335683645a2SGeetha sowjanya 336683645a2SGeetha sowjanya err = rvu_rep_install_tx_rule(rvu, pcifunc, 337683645a2SGeetha sowjanya start + entry, rep); 338683645a2SGeetha sowjanya if (err) 339683645a2SGeetha sowjanya return err; 340683645a2SGeetha sowjanya rswitch->entry2pcifunc[entry++] = pcifunc; 341683645a2SGeetha sowjanya rep = false; 342683645a2SGeetha sowjanya } 343683645a2SGeetha sowjanya 344683645a2SGeetha sowjanya rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); 345683645a2SGeetha sowjanya for (vf = 0; vf < numvfs; vf++) { 346683645a2SGeetha sowjanya pcifunc = pf << RVU_PFVF_PF_SHIFT | 347683645a2SGeetha sowjanya ((vf + 1) & RVU_PFVF_FUNC_MASK); 348683645a2SGeetha sowjanya rvu_get_nix_blkaddr(rvu, pcifunc); 349683645a2SGeetha sowjanya 350683645a2SGeetha sowjanya /* Skip installimg rules if nixlf is not attached */ 351683645a2SGeetha sowjanya err = nix_get_nixlf(rvu, pcifunc, &nixlf, NULL); 352683645a2SGeetha sowjanya if (err) 353683645a2SGeetha sowjanya continue; 354683645a2SGeetha sowjanya rep = true; 355683645a2SGeetha sowjanya for (i = 0; i < 2; i++) { 356683645a2SGeetha sowjanya err = rvu_rep_install_rx_rule(rvu, pcifunc, 357683645a2SGeetha sowjanya start + entry, 358683645a2SGeetha sowjanya rep); 359683645a2SGeetha sowjanya if (err) 360683645a2SGeetha sowjanya return err; 361683645a2SGeetha sowjanya rswitch->entry2pcifunc[entry++] = pcifunc; 362683645a2SGeetha sowjanya 363683645a2SGeetha sowjanya err = rvu_rep_install_tx_rule(rvu, pcifunc, 364683645a2SGeetha sowjanya start + entry, 365683645a2SGeetha sowjanya rep); 366683645a2SGeetha sowjanya if (err) 367683645a2SGeetha sowjanya return err; 368683645a2SGeetha sowjanya rswitch->entry2pcifunc[entry++] = pcifunc; 369683645a2SGeetha sowjanya rep = false; 370683645a2SGeetha sowjanya } 371683645a2SGeetha sowjanya } 372683645a2SGeetha sowjanya } 373b8fea84aSGeetha sowjanya 374b8fea84aSGeetha sowjanya /* Initialize the wq for handling REP events */ 375b8fea84aSGeetha sowjanya spin_lock_init(&rvu->rep_evtq_lock); 376b8fea84aSGeetha sowjanya INIT_LIST_HEAD(&rvu->rep_evtq_head); 377b8fea84aSGeetha sowjanya INIT_WORK(&rvu->rep_evt_work, rvu_rep_wq_handler); 378b8fea84aSGeetha sowjanya rvu->rep_evt_wq = alloc_workqueue("rep_evt_wq", 0, 0); 379b8fea84aSGeetha sowjanya if (!rvu->rep_evt_wq) { 380b8fea84aSGeetha sowjanya dev_err(rvu->dev, "REP workqueue allocation failed\n"); 381b8fea84aSGeetha sowjanya return -ENOMEM; 382b8fea84aSGeetha sowjanya } 383683645a2SGeetha sowjanya return 0; 384683645a2SGeetha sowjanya } 385683645a2SGeetha sowjanya 386683645a2SGeetha sowjanya void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena) 387683645a2SGeetha sowjanya { 388683645a2SGeetha sowjanya struct rvu_switch *rswitch = &rvu->rswitch; 389683645a2SGeetha sowjanya struct npc_mcam *mcam = &rvu->hw->mcam; 390683645a2SGeetha sowjanya u32 max = rswitch->used_entries; 391683645a2SGeetha sowjanya int blkaddr; 392683645a2SGeetha sowjanya u16 entry; 393683645a2SGeetha sowjanya 394683645a2SGeetha sowjanya if (!rswitch->used_entries) 395683645a2SGeetha sowjanya return; 396683645a2SGeetha sowjanya 397683645a2SGeetha sowjanya blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); 398683645a2SGeetha sowjanya 399683645a2SGeetha sowjanya if (blkaddr < 0) 400683645a2SGeetha sowjanya return; 401683645a2SGeetha sowjanya 402683645a2SGeetha sowjanya rvu_switch_enable_lbk_link(rvu, pcifunc, ena); 403683645a2SGeetha sowjanya mutex_lock(&mcam->lock); 404683645a2SGeetha sowjanya for (entry = 0; entry < max; entry++) { 405683645a2SGeetha sowjanya if (rswitch->entry2pcifunc[entry] == pcifunc) 406683645a2SGeetha sowjanya npc_enable_mcam_entry(rvu, mcam, blkaddr, entry, ena); 407683645a2SGeetha sowjanya } 408683645a2SGeetha sowjanya mutex_unlock(&mcam->lock); 409683645a2SGeetha sowjanya } 410683645a2SGeetha sowjanya 411683645a2SGeetha sowjanya int rvu_rep_pf_init(struct rvu *rvu) 412683645a2SGeetha sowjanya { 413683645a2SGeetha sowjanya u16 pcifunc = rvu->rep_pcifunc; 414683645a2SGeetha sowjanya struct rvu_pfvf *pfvf; 415683645a2SGeetha sowjanya 416683645a2SGeetha sowjanya pfvf = rvu_get_pfvf(rvu, pcifunc); 417683645a2SGeetha sowjanya set_bit(NIXLF_INITIALIZED, &pfvf->flags); 418683645a2SGeetha sowjanya rvu_switch_enable_lbk_link(rvu, pcifunc, true); 419683645a2SGeetha sowjanya rvu_rep_rx_vlan_cfg(rvu, pcifunc); 420683645a2SGeetha sowjanya return 0; 421683645a2SGeetha sowjanya } 422683645a2SGeetha sowjanya 423683645a2SGeetha sowjanya int rvu_mbox_handler_esw_cfg(struct rvu *rvu, struct esw_cfg_req *req, 424683645a2SGeetha sowjanya struct msg_rsp *rsp) 425683645a2SGeetha sowjanya { 426683645a2SGeetha sowjanya if (req->hdr.pcifunc != rvu->rep_pcifunc) 427683645a2SGeetha sowjanya return 0; 428683645a2SGeetha sowjanya 429683645a2SGeetha sowjanya rvu->rep_mode = req->ena; 430*6c40ca95SGeetha sowjanya 431*6c40ca95SGeetha sowjanya if (!rvu->rep_mode) 432*6c40ca95SGeetha sowjanya rvu_npc_free_mcam_entries(rvu, req->hdr.pcifunc, -1); 433*6c40ca95SGeetha sowjanya 434683645a2SGeetha sowjanya return 0; 435683645a2SGeetha sowjanya } 436683645a2SGeetha sowjanya 437222a4eeaSGeetha sowjanya int rvu_mbox_handler_get_rep_cnt(struct rvu *rvu, struct msg_req *req, 438222a4eeaSGeetha sowjanya struct get_rep_cnt_rsp *rsp) 439222a4eeaSGeetha sowjanya { 440222a4eeaSGeetha sowjanya int pf, vf, numvfs, hwvf, rep = 0; 441222a4eeaSGeetha sowjanya u16 pcifunc; 442222a4eeaSGeetha sowjanya 443222a4eeaSGeetha sowjanya rvu->rep_pcifunc = req->hdr.pcifunc; 444222a4eeaSGeetha sowjanya rsp->rep_cnt = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs; 445222a4eeaSGeetha sowjanya rvu->rep_cnt = rsp->rep_cnt; 446222a4eeaSGeetha sowjanya 447222a4eeaSGeetha sowjanya rvu->rep2pfvf_map = devm_kzalloc(rvu->dev, rvu->rep_cnt * 448222a4eeaSGeetha sowjanya sizeof(u16), GFP_KERNEL); 449222a4eeaSGeetha sowjanya if (!rvu->rep2pfvf_map) 450222a4eeaSGeetha sowjanya return -ENOMEM; 451222a4eeaSGeetha sowjanya 452222a4eeaSGeetha sowjanya for (pf = 0; pf < rvu->hw->total_pfs; pf++) { 453222a4eeaSGeetha sowjanya if (!is_pf_cgxmapped(rvu, pf)) 454222a4eeaSGeetha sowjanya continue; 455222a4eeaSGeetha sowjanya pcifunc = pf << RVU_PFVF_PF_SHIFT; 456222a4eeaSGeetha sowjanya rvu->rep2pfvf_map[rep] = pcifunc; 457222a4eeaSGeetha sowjanya rsp->rep_pf_map[rep] = pcifunc; 458222a4eeaSGeetha sowjanya rep++; 459222a4eeaSGeetha sowjanya rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvf); 460222a4eeaSGeetha sowjanya for (vf = 0; vf < numvfs; vf++) { 461222a4eeaSGeetha sowjanya rvu->rep2pfvf_map[rep] = pcifunc | 462222a4eeaSGeetha sowjanya ((vf + 1) & RVU_PFVF_FUNC_MASK); 463222a4eeaSGeetha sowjanya rsp->rep_pf_map[rep] = rvu->rep2pfvf_map[rep]; 464222a4eeaSGeetha sowjanya rep++; 465222a4eeaSGeetha sowjanya } 466222a4eeaSGeetha sowjanya } 467222a4eeaSGeetha sowjanya return 0; 468222a4eeaSGeetha sowjanya } 469