Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Marvell RVU Admin Function driver
0003  *
0004  * Copyright (C) 2021 Marvell.
0005  *
0006  */
0007 
0008 #include <linux/bitfield.h>
0009 #include "rvu.h"
0010 
0011 static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc,
0012                       u16 chan_mask)
0013 {
0014     struct npc_install_flow_req req = { 0 };
0015     struct npc_install_flow_rsp rsp = { 0 };
0016     struct rvu_pfvf *pfvf;
0017 
0018     pfvf = rvu_get_pfvf(rvu, pcifunc);
0019     /* If the pcifunc is not initialized then nothing to do.
0020      * This same function will be called again via rvu_switch_update_rules
0021      * after pcifunc is initialized.
0022      */
0023     if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
0024         return 0;
0025 
0026     ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
0027     eth_broadcast_addr((u8 *)&req.mask.dmac);
0028     req.hdr.pcifunc = 0; /* AF is requester */
0029     req.vf = pcifunc;
0030     req.features = BIT_ULL(NPC_DMAC);
0031     req.channel = pfvf->rx_chan_base;
0032     req.chan_mask = chan_mask;
0033     req.intf = pfvf->nix_rx_intf;
0034     req.op = NIX_RX_ACTION_DEFAULT;
0035     req.default_rule = 1;
0036 
0037     return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
0038 }
0039 
0040 static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry)
0041 {
0042     struct npc_install_flow_req req = { 0 };
0043     struct npc_install_flow_rsp rsp = { 0 };
0044     struct rvu_pfvf *pfvf;
0045     u8 lbkid;
0046 
0047     pfvf = rvu_get_pfvf(rvu, pcifunc);
0048     /* If the pcifunc is not initialized then nothing to do.
0049      * This same function will be called again via rvu_switch_update_rules
0050      * after pcifunc is initialized.
0051      */
0052     if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags))
0053         return 0;
0054 
0055     lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1;
0056     ether_addr_copy(req.packet.dmac, pfvf->mac_addr);
0057     eth_broadcast_addr((u8 *)&req.mask.dmac);
0058     req.hdr.pcifunc = 0; /* AF is requester */
0059     req.vf = pcifunc;
0060     req.entry = entry;
0061     req.features = BIT_ULL(NPC_DMAC);
0062     req.intf = pfvf->nix_tx_intf;
0063     req.op = NIX_TX_ACTIONOP_UCAST_CHAN;
0064     req.index = (lbkid << 8) | RVU_SWITCH_LBK_CHAN;
0065     req.set_cntr = 1;
0066 
0067     return rvu_mbox_handler_npc_install_flow(rvu, &req, &rsp);
0068 }
0069 
0070 static int rvu_switch_install_rules(struct rvu *rvu)
0071 {
0072     struct rvu_switch *rswitch = &rvu->rswitch;
0073     u16 start = rswitch->start_entry;
0074     struct rvu_hwinfo *hw = rvu->hw;
0075     u16 pcifunc, entry = 0;
0076     int pf, vf, numvfs;
0077     int err;
0078 
0079     for (pf = 1; pf < hw->total_pfs; pf++) {
0080         if (!is_pf_cgxmapped(rvu, pf))
0081             continue;
0082 
0083         pcifunc = pf << 10;
0084         /* rvu_get_nix_blkaddr sets up the corresponding NIX block
0085          * address and NIX RX and TX interfaces for a pcifunc.
0086          * Generally it is called during attach call of a pcifunc but it
0087          * is called here since we are pre-installing rules before
0088          * nixlfs are attached
0089          */
0090         rvu_get_nix_blkaddr(rvu, pcifunc);
0091 
0092         /* MCAM RX rule for a PF/VF already exists as default unicast
0093          * rules installed by AF. Hence change the channel in those
0094          * rules to ignore channel so that packets with the required
0095          * DMAC received from LBK(by other PF/VFs in system) or from
0096          * external world (from wire) are accepted.
0097          */
0098         err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
0099         if (err) {
0100             dev_err(rvu->dev, "RX rule for PF%d failed(%d)\n",
0101                 pf, err);
0102             return err;
0103         }
0104 
0105         err = rvu_switch_install_tx_rule(rvu, pcifunc, start + entry);
0106         if (err) {
0107             dev_err(rvu->dev, "TX rule for PF%d failed(%d)\n",
0108                 pf, err);
0109             return err;
0110         }
0111 
0112         rswitch->entry2pcifunc[entry++] = pcifunc;
0113 
0114         rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
0115         for (vf = 0; vf < numvfs; vf++) {
0116             pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
0117             rvu_get_nix_blkaddr(rvu, pcifunc);
0118 
0119             err = rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
0120             if (err) {
0121                 dev_err(rvu->dev,
0122                     "RX rule for PF%dVF%d failed(%d)\n",
0123                     pf, vf, err);
0124                 return err;
0125             }
0126 
0127             err = rvu_switch_install_tx_rule(rvu, pcifunc,
0128                              start + entry);
0129             if (err) {
0130                 dev_err(rvu->dev,
0131                     "TX rule for PF%dVF%d failed(%d)\n",
0132                     pf, vf, err);
0133                 return err;
0134             }
0135 
0136             rswitch->entry2pcifunc[entry++] = pcifunc;
0137         }
0138     }
0139 
0140     return 0;
0141 }
0142 
0143 void rvu_switch_enable(struct rvu *rvu)
0144 {
0145     struct npc_mcam_alloc_entry_req alloc_req = { 0 };
0146     struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
0147     struct npc_delete_flow_req uninstall_req = { 0 };
0148     struct npc_mcam_free_entry_req free_req = { 0 };
0149     struct rvu_switch *rswitch = &rvu->rswitch;
0150     struct msg_rsp rsp;
0151     int ret;
0152 
0153     alloc_req.contig = true;
0154     alloc_req.count = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs;
0155     ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &alloc_req,
0156                             &alloc_rsp);
0157     if (ret) {
0158         dev_err(rvu->dev,
0159             "Unable to allocate MCAM entries\n");
0160         goto exit;
0161     }
0162 
0163     if (alloc_rsp.count != alloc_req.count) {
0164         dev_err(rvu->dev,
0165             "Unable to allocate %d MCAM entries, got %d\n",
0166             alloc_req.count, alloc_rsp.count);
0167         goto free_entries;
0168     }
0169 
0170     rswitch->entry2pcifunc = kcalloc(alloc_req.count, sizeof(u16),
0171                      GFP_KERNEL);
0172     if (!rswitch->entry2pcifunc)
0173         goto free_entries;
0174 
0175     rswitch->used_entries = alloc_rsp.count;
0176     rswitch->start_entry = alloc_rsp.entry;
0177 
0178     ret = rvu_switch_install_rules(rvu);
0179     if (ret)
0180         goto uninstall_rules;
0181 
0182     return;
0183 
0184 uninstall_rules:
0185     uninstall_req.start = rswitch->start_entry;
0186     uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
0187     rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
0188     kfree(rswitch->entry2pcifunc);
0189 free_entries:
0190     free_req.all = 1;
0191     rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
0192 exit:
0193     return;
0194 }
0195 
0196 void rvu_switch_disable(struct rvu *rvu)
0197 {
0198     struct npc_delete_flow_req uninstall_req = { 0 };
0199     struct npc_mcam_free_entry_req free_req = { 0 };
0200     struct rvu_switch *rswitch = &rvu->rswitch;
0201     struct rvu_hwinfo *hw = rvu->hw;
0202     int pf, vf, numvfs;
0203     struct msg_rsp rsp;
0204     u16 pcifunc;
0205     int err;
0206 
0207     if (!rswitch->used_entries)
0208         return;
0209 
0210     for (pf = 1; pf < hw->total_pfs; pf++) {
0211         if (!is_pf_cgxmapped(rvu, pf))
0212             continue;
0213 
0214         pcifunc = pf << 10;
0215         err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
0216         if (err)
0217             dev_err(rvu->dev,
0218                 "Reverting RX rule for PF%d failed(%d)\n",
0219                 pf, err);
0220 
0221         rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL);
0222         for (vf = 0; vf < numvfs; vf++) {
0223             pcifunc = pf << 10 | ((vf + 1) & 0x3FF);
0224             err = rvu_switch_install_rx_rule(rvu, pcifunc, 0xFFF);
0225             if (err)
0226                 dev_err(rvu->dev,
0227                     "Reverting RX rule for PF%dVF%d failed(%d)\n",
0228                     pf, vf, err);
0229         }
0230     }
0231 
0232     uninstall_req.start = rswitch->start_entry;
0233     uninstall_req.end =  rswitch->start_entry + rswitch->used_entries - 1;
0234     free_req.all = 1;
0235     rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
0236     rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
0237     rswitch->used_entries = 0;
0238     kfree(rswitch->entry2pcifunc);
0239 }
0240 
0241 void rvu_switch_update_rules(struct rvu *rvu, u16 pcifunc)
0242 {
0243     struct rvu_switch *rswitch = &rvu->rswitch;
0244     u32 max = rswitch->used_entries;
0245     u16 entry;
0246 
0247     if (!rswitch->used_entries)
0248         return;
0249 
0250     for (entry = 0; entry < max; entry++) {
0251         if (rswitch->entry2pcifunc[entry] == pcifunc)
0252             break;
0253     }
0254 
0255     if (entry >= max)
0256         return;
0257 
0258     rvu_switch_install_tx_rule(rvu, pcifunc, rswitch->start_entry + entry);
0259     rvu_switch_install_rx_rule(rvu, pcifunc, 0x0);
0260 }