octeontx2-pf: Support to enable/disable pause frames via ethtool
authorGeetha sowjanya <gakula@marvell.com>
Mon, 2 Mar 2020 07:19:24 +0000 (12:49 +0530)
committerDavid S. Miller <davem@davemloft.net>
Mon, 2 Mar 2020 19:08:51 +0000 (11:08 -0800)
Added mailbox requests to retrieve backpressure IDs from AF and Aura,
CQ contexts are configured with these BPIDs. So that when resource
levels reach configured thresholds they assert backpressure on the
interface which is also mapped to same BPID.

Also added support to enable/disable pause frames generation via ethtool.

Signed-off-by: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index b945bd3..af4437d 100644 (file)
@@ -220,6 +220,25 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu)
        return err;
 }
 
+int otx2_config_pause_frm(struct otx2_nic *pfvf)
+{
+       struct cgx_pause_frm_cfg *req;
+       int err;
+
+       otx2_mbox_lock(&pfvf->mbox);
+       req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox);
+       if (!req)
+               return -ENOMEM;
+
+       req->rx_pause = !!(pfvf->flags & OTX2_FLAG_RX_PAUSE_ENABLED);
+       req->tx_pause = !!(pfvf->flags & OTX2_FLAG_TX_PAUSE_ENABLED);
+       req->set = 1;
+
+       err = otx2_sync_mbox_msg(&pfvf->mbox);
+       otx2_mbox_unlock(&pfvf->mbox);
+       return err;
+}
+
 int otx2_set_flowkey_cfg(struct otx2_nic *pfvf)
 {
        struct otx2_rss_info *rss = &pfvf->hw.rss_info;
@@ -580,6 +599,7 @@ void otx2_sqb_flush(struct otx2_nic *pfvf)
  * RED accepts pkts if free pointers > 102 & <= 205.
  * Drops pkts if free pointers < 102.
  */
+#define RQ_BP_LVL_AURA   (255 - ((85 * 256) / 100)) /* BP when 85% is full */
 #define RQ_PASS_LVL_AURA (255 - ((95 * 256) / 100)) /* RED when 95% is full */
 #define RQ_DROP_LVL_AURA (255 - ((99 * 256) / 100)) /* Drop when 99% is full */
 
@@ -741,6 +761,13 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
        if (qidx < pfvf->hw.rx_queues) {
                aq->cq.drop = RQ_DROP_LVL_CQ(pfvf->hw.rq_skid, cq->cqe_cnt);
                aq->cq.drop_ena = 1;
+
+               /* Enable receive CQ backpressure */
+               aq->cq.bp_ena = 1;
+               aq->cq.bpid = pfvf->bpid[0];
+
+               /* Set backpressure level is same as cq pass level */
+               aq->cq.bp = RQ_PASS_LVL_CQ(pfvf->hw.rq_skid, qset->rqe_cnt);
        }
 
        /* Fill AQ info */
@@ -996,6 +1023,14 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
        aq->aura.fc_addr = pool->fc_addr->iova;
        aq->aura.fc_hyst_bits = 0; /* Store count on all updates */
 
+       /* Enable backpressure for RQ aura */
+       if (aura_id < pfvf->hw.rqpool_cnt) {
+               aq->aura.bp_ena = 0;
+               aq->aura.nix0_bpid = pfvf->bpid[0];
+               /* Set backpressure level for RQ's Aura */
+               aq->aura.bp = RQ_BP_LVL_AURA;
+       }
+
        /* Fill AQ info */
        aq->ctype = NPA_AQ_CTYPE_AURA;
        aq->op = NPA_AQ_INSTOP_INIT;
@@ -1307,6 +1342,25 @@ void otx2_ctx_disable(struct mbox *mbox, int type, bool npa)
        otx2_mbox_unlock(mbox);
 }
 
+int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable)
+{
+       struct nix_bp_cfg_req *req;
+
+       if (enable)
+               req = otx2_mbox_alloc_msg_nix_bp_enable(&pfvf->mbox);
+       else
+               req = otx2_mbox_alloc_msg_nix_bp_disable(&pfvf->mbox);
+
+       if (!req)
+               return -ENOMEM;
+
+       req->chan_base = 0;
+       req->chan_cnt = 1;
+       req->bpid_per_chan = 0;
+
+       return otx2_sync_mbox_msg(&pfvf->mbox);
+}
+
 /* Mbox message handlers */
 void mbox_handler_cgx_stats(struct otx2_nic *pfvf,
                            struct cgx_stats_rsp *rsp)
@@ -1355,6 +1409,17 @@ void mbox_handler_msix_offset(struct otx2_nic *pfvf,
        pfvf->hw.nix_msixoff = rsp->nix_msixoff;
 }
 
+void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf,
+                               struct nix_bp_cfg_rsp *rsp)
+{
+       int chan, chan_id;
+
+       for (chan = 0; chan < rsp->chan_cnt; chan++) {
+               chan_id = ((rsp->chan_bpid[chan] >> 10) & 0x7F);
+               pfvf->bpid[chan_id] = rsp->chan_bpid[chan] & 0x3FF;
+       }
+}
+
 void otx2_free_cints(struct otx2_nic *pfvf, int n)
 {
        struct otx2_qset *qset = &pfvf->qset;
index 320f3b7..885c3dc 100644 (file)
@@ -204,6 +204,8 @@ struct otx2_nic {
        u16                     rbsize; /* Receive buffer size */
 
 #define OTX2_FLAG_INTF_DOWN                    BIT_ULL(2)
+#define OTX2_FLAG_RX_PAUSE_ENABLED             BIT_ULL(9)
+#define OTX2_FLAG_TX_PAUSE_ENABLED             BIT_ULL(10)
        u64                     flags;
 
        struct otx2_qset        qset;
@@ -216,6 +218,7 @@ struct otx2_nic {
        struct workqueue_struct *mbox_wq;
 
        u16                     pcifunc; /* RVU PF_FUNC */
+       u16                     bpid[NIX_MAX_BPID_CHAN];
        struct cgx_link_user_info linfo;
 
        u64                     reset_count;
@@ -558,6 +561,7 @@ int otx2_hw_set_mtu(struct otx2_nic *pfvf, int mtu);
 void otx2_tx_timeout(struct net_device *netdev, unsigned int txq);
 void otx2_get_mac_from_af(struct net_device *netdev);
 void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx);
+int otx2_config_pause_frm(struct otx2_nic *pfvf);
 
 /* RVU block related APIs */
 int otx2_attach_npa_nix(struct otx2_nic *pfvf);
@@ -578,6 +582,7 @@ dma_addr_t otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
                           gfp_t gfp);
 int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
 void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
+int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
 void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
 void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
 
@@ -598,6 +603,8 @@ void mbox_handler_nix_txsch_alloc(struct otx2_nic *pf,
                                  struct nix_txsch_alloc_rsp *rsp);
 void mbox_handler_cgx_stats(struct otx2_nic *pfvf,
                            struct cgx_stats_rsp *rsp);
+void mbox_handler_nix_bp_enable(struct otx2_nic *pfvf,
+                               struct nix_bp_cfg_rsp *rsp);
 
 /* Device stats APIs */
 void otx2_get_dev_stats(struct otx2_nic *pfvf);
index 60fcf82..f450111 100644 (file)
@@ -253,6 +253,45 @@ fail:
        return err;
 }
 
+static void otx2_get_pauseparam(struct net_device *netdev,
+                               struct ethtool_pauseparam *pause)
+{
+       struct otx2_nic *pfvf = netdev_priv(netdev);
+       struct cgx_pause_frm_cfg *req, *rsp;
+
+       req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox);
+       if (!req)
+               return;
+
+       if (!otx2_sync_mbox_msg(&pfvf->mbox)) {
+               rsp = (struct cgx_pause_frm_cfg *)
+                      otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+               pause->rx_pause = rsp->rx_pause;
+               pause->tx_pause = rsp->tx_pause;
+       }
+}
+
+static int otx2_set_pauseparam(struct net_device *netdev,
+                              struct ethtool_pauseparam *pause)
+{
+       struct otx2_nic *pfvf = netdev_priv(netdev);
+
+       if (pause->autoneg)
+               return -EOPNOTSUPP;
+
+       if (pause->rx_pause)
+               pfvf->flags |= OTX2_FLAG_RX_PAUSE_ENABLED;
+       else
+               pfvf->flags &= ~OTX2_FLAG_RX_PAUSE_ENABLED;
+
+       if (pause->tx_pause)
+               pfvf->flags |= OTX2_FLAG_TX_PAUSE_ENABLED;
+       else
+               pfvf->flags &= ~OTX2_FLAG_TX_PAUSE_ENABLED;
+
+       return otx2_config_pause_frm(pfvf);
+}
+
 static void otx2_get_ringparam(struct net_device *netdev,
                               struct ethtool_ringparam *ring)
 {
@@ -654,6 +693,8 @@ static const struct ethtool_ops otx2_ethtool_ops = {
        .set_rxfh               = otx2_set_rxfh,
        .get_msglevel           = otx2_get_msglevel,
        .set_msglevel           = otx2_set_msglevel,
+       .get_pauseparam         = otx2_get_pauseparam,
+       .set_pauseparam         = otx2_set_pauseparam,
 };
 
 void otx2_set_ethtool_ops(struct net_device *netdev)
index 85f9b9b..22f9a32 100644 (file)
@@ -148,6 +148,9 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
                mbox_handler_nix_txsch_alloc(pf,
                                             (struct nix_txsch_alloc_rsp *)msg);
                break;
+       case MBOX_MSG_NIX_BP_ENABLE:
+               mbox_handler_nix_bp_enable(pf, (struct nix_bp_cfg_rsp *)msg);
+               break;
        case MBOX_MSG_CGX_STATS:
                mbox_handler_cgx_stats(pf, (struct cgx_stats_rsp *)msg);
                break;
@@ -654,6 +657,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
        if (err)
                goto err_free_npa_lf;
 
+       /* Enable backpressure */
+       otx2_nix_config_bp(pf, true);
+
        /* Init Auras and pools used by NIX RQ, for free buffer ptrs */
        err = otx2_rq_aura_pool_init(pf);
        if (err) {
@@ -737,6 +743,12 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
        if (err)
                dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
 
+       otx2_mbox_lock(mbox);
+       /* Disable backpressure */
+       if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
+               otx2_nix_config_bp(pf, false);
+       otx2_mbox_unlock(mbox);
+
        /* Disable RQs */
        otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);