octeontx2-af: Start/Stop traffic in CGX along with NPC
authorSubbaraya Sundeep <sbhatta@marvell.com>
Thu, 14 Nov 2019 05:26:33 +0000 (10:56 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Nov 2019 02:09:16 +0000 (18:09 -0800)
Traffic for a CGX mapped NIXLF can be stopped by disabling entries
in NPC MCAM or by configuring CGX and mailbox messages exist for the
two options. If traffic is stopped at CGX then VFs of that PF are
also effected hence CGX traffic should be started/stopped by
tracking all the users of it. This patch implements that CGX users
tracking. CGX is also configured along with NPC if required.

Also removed a check which mandates even number of LBK VFs.

Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c

index 3985053..5c190c3 100644 (file)
@@ -2364,18 +2364,6 @@ static int rvu_enable_sriov(struct rvu *rvu)
        if (vfs > chans)
                vfs = chans;
 
-       /* AF's VFs work in pairs and talk over consecutive loopback channels.
-        * Thus we want to enable maximum even number of VFs. In case
-        * odd number of VFs are available then the last VF on the list
-        * remains disabled.
-        */
-       if (vfs & 0x1) {
-               dev_warn(&pdev->dev,
-                        "Number of VFs should be even. Enabling %d out of %d.\n",
-                        vfs - 1, vfs);
-               vfs--;
-       }
-
        if (!vfs)
                return 0;
 
index 7370864..b252d86 100644 (file)
@@ -179,6 +179,9 @@ struct rvu_pfvf {
        struct mcam_entry entry;
        int rxvlan_index;
        bool rxvlan;
+
+       bool    cgx_in_use; /* this PF/VF using CGX? */
+       int     cgx_users;  /* number of cgx users - used only by PFs */
 };
 
 struct nix_txsch {
@@ -306,6 +309,7 @@ struct rvu {
        struct                  workqueue_struct *cgx_evh_wq;
        spinlock_t              cgx_evq_lock; /* cgx event queue lock */
        struct list_head        cgx_evq_head; /* cgx event queue head */
+       struct mutex            cgx_cfg_lock; /* serialize cgx configuration */
 
        char mkex_pfl_name[MKEX_NAME_LEN]; /* Configured MKEX profile name */
 
@@ -410,6 +414,7 @@ int rvu_cgx_exit(struct rvu *rvu);
 void *rvu_cgx_pdata(u8 cgx_id, struct rvu *rvu);
 int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start);
 void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable);
+int rvu_cgx_start_stop_io(struct rvu *rvu, u16 pcifunc, bool start);
 int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id, int index,
                           int rxtxflag, u64 *stat);
 /* NPA APIs */
index 7e110b7..0bbb2eb 100644 (file)
@@ -308,6 +308,8 @@ int rvu_cgx_init(struct rvu *rvu)
        if (err)
                return err;
 
+       mutex_init(&rvu->cgx_cfg_lock);
+
        /* Ensure event handler registration is completed, before
         * we turn on the links
         */
@@ -638,3 +640,50 @@ int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id,
 
        return 0;
 }
+
+int rvu_cgx_start_stop_io(struct rvu *rvu, u16 pcifunc, bool start)
+{
+       struct rvu_pfvf *parent_pf, *pfvf;
+       int cgx_users, err = 0;
+
+       if (!is_pf_cgxmapped(rvu, rvu_get_pf(pcifunc)))
+               return 0;
+
+       parent_pf = &rvu->pf[rvu_get_pf(pcifunc)];
+       pfvf = rvu_get_pfvf(rvu, pcifunc);
+
+       mutex_lock(&rvu->cgx_cfg_lock);
+
+       if (start && pfvf->cgx_in_use)
+               goto exit;  /* CGX is already started hence nothing to do */
+       if (!start && !pfvf->cgx_in_use)
+               goto exit; /* CGX is already stopped hence nothing to do */
+
+       if (start) {
+               cgx_users = parent_pf->cgx_users;
+               parent_pf->cgx_users++;
+       } else {
+               parent_pf->cgx_users--;
+               cgx_users = parent_pf->cgx_users;
+       }
+
+       /* Start CGX when first of all NIXLFs is started.
+        * Stop CGX when last of all NIXLFs is stopped.
+        */
+       if (!cgx_users) {
+               err = rvu_cgx_config_rxtx(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK,
+                                         start);
+               if (err) {
+                       dev_err(rvu->dev, "Unable to %s CGX\n",
+                               start ? "start" : "stop");
+                       /* Revert the usage count in case of error */
+                       parent_pf->cgx_users = start ? parent_pf->cgx_users  - 1
+                                              : parent_pf->cgx_users  + 1;
+                       goto exit;
+               }
+       }
+       pfvf->cgx_in_use = start;
+exit:
+       mutex_unlock(&rvu->cgx_cfg_lock);
+       return err;
+}
index 63190b8..8a59f7d 100644 (file)
@@ -194,6 +194,11 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf)
                break;
        case NIX_INTF_TYPE_LBK:
                vf = (pcifunc & RVU_PFVF_FUNC_MASK) - 1;
+
+               /* Note that AF's VFs work in pairs and talk over consecutive
+                * loopback channels.Therefore if odd number of AF VFs are
+                * enabled then the last VF remains with no pair.
+                */
                pfvf->rx_chan_base = NIX_CHAN_LBK_CHX(0, vf);
                pfvf->tx_chan_base = vf & 0x1 ? NIX_CHAN_LBK_CHX(0, vf - 1) :
                                                NIX_CHAN_LBK_CHX(0, vf + 1);
@@ -3120,7 +3125,8 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req,
                return err;
 
        rvu_npc_enable_default_entries(rvu, pcifunc, nixlf);
-       return 0;
+
+       return rvu_cgx_start_stop_io(rvu, pcifunc, true);
 }
 
 int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
@@ -3134,7 +3140,8 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req,
                return err;
 
        rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
-       return 0;
+
+       return rvu_cgx_start_stop_io(rvu, pcifunc, false);
 }
 
 void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
@@ -3150,6 +3157,8 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf)
        nix_rx_sync(rvu, blkaddr);
        nix_txschq_free(rvu, pcifunc);
 
+       rvu_cgx_start_stop_io(rvu, pcifunc, false);
+
        if (pfvf->sq_ctx) {
                ctx_req.ctype = NIX_AQ_CTYPE_SQ;
                err = nix_lf_hwctx_disable(rvu, &ctx_req);