rvu_switch.c (6960B)
1// SPDX-License-Identifier: GPL-2.0 2/* Marvell RVU Admin Function driver 3 * 4 * Copyright (C) 2021 Marvell. 5 * 6 */ 7 8#include <linux/bitfield.h> 9#include "rvu.h" 10 11static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc, 12 u16 chan_mask) 13{ 14 struct npc_install_flow_req req = { 0 }; 15 struct npc_install_flow_rsp rsp = { 0 }; 16 struct rvu_pfvf *pfvf; 17 18 pfvf = rvu_get_pfvf(rvu, pcifunc); 19 /* If the pcifunc is not initialized then nothing to do. 20 * This same function will be called again via rvu_switch_update_rules 21 * after pcifunc is initialized. 22 */ 23 if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags)) 24 return 0; 25 26 ether_addr_copy(req.packet.dmac, pfvf->mac_addr); 27 eth_broadcast_addr((u8 *)&req.mask.dmac); 28 req.hdr.pcifunc = 0; /* AF is requester */ 29 req.vf = pcifunc; 30 req.features = BIT_ULL(NPC_DMAC); 31 req.channel = pfvf->rx_chan_base; 32 req.chan_mask = chan_mask; 33 req.intf = pfvf->nix_rx_intf; 34 req.op = NIX_RX_ACTION_DEFAULT; 35 req.default_rule = 1; 36 37 return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 38} 39 40static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry) 41{ 42 struct npc_install_flow_req req = { 0 }; 43 struct npc_install_flow_rsp rsp = { 0 }; 44 struct rvu_pfvf *pfvf; 45 u8 lbkid; 46 47 pfvf = rvu_get_pfvf(rvu, pcifunc); 48 /* If the pcifunc is not initialized then nothing to do. 49 * This same function will be called again via rvu_switch_update_rules 50 * after pcifunc is initialized. 51 */ 52 if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags)) 53 return 0; 54 55 lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1; 56 ether_addr_copy(req.packet.dmac, pfvf->mac_addr); 57 eth_broadcast_addr((u8 *)&req.mask.dmac); 58 req.hdr.pcifunc = 0; /* AF is requester */ 59 req.vf = pcifunc; 60 req.entry = entry; 61 req.features = BIT_ULL(NPC_DMAC); 62 req.intf = pfvf->nix_tx_intf; 63 req.op = NIX_TX_ACTIONOP_UCAST_CHAN; 64 req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN; 65 req.set_cntr = 1; 66 67 return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp); 68} 69 70static int rvu_switch_install_rules(struct rvu *rvu) 71{ 72 struct rvu_switch *rswitch = &rvu->rswitch; 73 u16 start = rswitch->start_entry; 74 struct rvu_hwinfo *hw = rvu->hw; 75 u16 pcifunc, entry = 0; 76 int pf, vf, numvfs; 77 int err; 78 79 for (pf = 1; pf < hw->total_pfs; pf++) { 80 if (!is_pf_cgxmapped(rvu, pf)) 81 continue; 82 83 pcifunc = pf << 10; 84 /* rvu_get_nix_blkaddr sets up the corresponding NIX block 85 * address and NIX RX and TX interfaces for a pcifunc. 86 * Generally it is called during attach call of a pcifunc but it 87 * is called here since we are pre-installing rules before 88 * nixlfs are attached 89 */ 90 rvu_get_nix_blkaddr(rvu, pcifunc); 91 92 /* MCAM RX rule for a PF/VF already exists as default unicast 93 * rules installed by AF. Hence change the channel in those 94 * rules to ignore channel so that packets with the required 95 * DMAC received from LBK(by other PF/VFs in system) or from 96 * external world (from wire) are accepted. 97 */ 98 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0); 99 if (err) { 100 dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n", 101 pf, err); 102 return err; 103 } 104 105 err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry); 106 if (err) { 107 dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n", 108 pf, err); 109 return err; 110 } 111 112 rswitch->entry2pcifunc[entry++] = pcifunc; 113 114 rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); 115 for (vf = 0; vf < numvfs; vf++) { 116 pcifunc = pf << 10 | ((vf + 1) & 0x3FF); 117 rvu_get_nix_blkaddr(rvu, pcifunc); 118 119 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0); 120 if (err) { 121 dev_err(rvu->dev, 122 "RX rule for PF%dVF%d failed(%d)\n", 123 pf, vf, err); 124 return err; 125 } 126 127 err = rvu_switch_install_tx_rule(rvu, pcifunc, 128 start + entry); 129 if (err) { 130 dev_err(rvu->dev, 131 "TX rule for PF%dVF%d failed(%d)\n", 132 pf, vf, err); 133 return err; 134 } 135 136 rswitch->entry2pcifunc[entry++] = pcifunc; 137 } 138 } 139 140 return 0; 141} 142 143void rvu_switch_enable(struct rvu *rvu) 144{ 145 struct npc_mcam_alloc_entry_req alloc_req = { 0 }; 146 struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 }; 147 struct npc_delete_flow_req uninstall_req = { 0 }; 148 struct npc_mcam_free_entry_req free_req = { 0 }; 149 struct rvu_switch *rswitch = &rvu->rswitch; 150 struct msg_rsp rsp; 151 int ret; 152 153 alloc_req.contig = true; 154 alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs; 155 ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req, 156 &alloc_rsp); 157 if (ret) { 158 dev_err(rvu->dev, 159 "Unable to allocate MCAM entries\n"); 160 goto exit; 161 } 162 163 if (alloc_rsp.count != alloc_req.count) { 164 dev_err(rvu->dev, 165 "Unable to allocate %d MCAM entries, got %d\n", 166 alloc_req.count, alloc_rsp.count); 167 goto free_entries; 168 } 169 170 rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16), 171 GFP_KERNEL); 172 if (!rswitch->entry2pcifunc) 173 goto free_entries; 174 175 rswitch->used_entries = alloc_rsp.count; 176 rswitch->start_entry = alloc_rsp.entry; 177 178 ret = rvu_switch_install_rules(rvu); 179 if (ret) 180 goto uninstall_rules; 181 182 return; 183 184uninstall_rules: 185 uninstall_req.start = rswitch->start_entry; 186 uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1; 187 rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp); 188 kfree(rswitch->entry2pcifunc); 189free_entries: 190 free_req.all = 1; 191 rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); 192exit: 193 return; 194} 195 196void rvu_switch_disable(struct rvu *rvu) 197{ 198 struct npc_delete_flow_req uninstall_req = { 0 }; 199 struct npc_mcam_free_entry_req free_req = { 0 }; 200 struct rvu_switch *rswitch = &rvu->rswitch; 201 struct rvu_hwinfo *hw = rvu->hw; 202 int pf, vf, numvfs; 203 struct msg_rsp rsp; 204 u16 pcifunc; 205 int err; 206 207 if (!rswitch->used_entries) 208 return; 209 210 for (pf = 1; pf < hw->total_pfs; pf++) { 211 if (!is_pf_cgxmapped(rvu, pf)) 212 continue; 213 214 pcifunc = pf << 10; 215 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); 216 if (err) 217 dev_err(rvu->dev, 218 "Reverting RX rule for PF%d failed(%d)\n", 219 pf, err); 220 221 rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); 222 for (vf = 0; vf < numvfs; vf++) { 223 pcifunc = pf << 10 | ((vf + 1) & 0x3FF); 224 err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF); 225 if (err) 226 dev_err(rvu->dev, 227 "Reverting RX rule for PF%dVF%d failed(%d)\n", 228 pf, vf, err); 229 } 230 } 231 232 uninstall_req.start = rswitch->start_entry; 233 uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1; 234 free_req.all = 1; 235 rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp); 236 rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp); 237 rswitch->used_entries = 0; 238 kfree(rswitch->entry2pcifunc); 239} 240 241void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc) 242{ 243 struct rvu_switch *rswitch = &rvu->rswitch; 244 u32 max = rswitch->used_entries; 245 u16 entry; 246 247 if (!rswitch->used_entries) 248 return; 249 250 for (entry = 0; entry < max; entry++) { 251 if (rswitch->entry2pcifunc[entry] == pcifunc) 252 break; 253 } 254 255 if (entry >= max) 256 return; 257 258 rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry); 259 rvu_switch_install_rx_rule(rvu, pcifunc, 0x0); 260}