octeontx2-vf: Link event notification support
authorTomasz Duszynski <tduszynski@marvell.com>
Fri, 20 Mar 2020 18:57:23 +0000 (00:27 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 24 Mar 2020 04:11:43 +0000 (21:11 -0700)
VF shares physical link with PF. Admin function (AF) sends
notification to PF whenever a link change event happens. PF
has to forward the same notification to each of the enabled VF.

PF traps START/STOP_RX messages sent by VF to AF to keep track of
VF's enabled/disabled state.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index 701bdfa..f51a29c 100644 (file)
@@ -193,6 +193,12 @@ struct otx2_hw {
        u64                     cgx_tx_stats[CGX_TX_STATS_COUNT];
 };
 
+struct otx2_vf_config {
+       struct otx2_nic *pf;
+       struct delayed_work link_event_work;
+       bool intf_down; /* interface was either configured or not */
+};
+
 struct flr_work {
        struct work_struct work;
        struct otx2_nic *pf;
@@ -229,6 +235,7 @@ struct otx2_nic {
        u8                      total_vfs;
        u16                     pcifunc; /* RVU PF_FUNC */
        u16                     bpid[NIX_MAX_BPID_CHAN];
+       struct otx2_vf_config   *vf_configs;
        struct cgx_link_user_info linfo;
 
        u64                     reset_count;
index bc421f1..d491819 100644 (file)
@@ -715,6 +715,8 @@ static int otx2_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs)
 static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
                                       struct mbox_msghdr *msg)
 {
+       int devid;
+
        if (msg->id >= MBOX_MSG_MAX) {
                dev_err(pf->dev,
                        "Mbox msg with unknown ID 0x%x\n", msg->id);
@@ -728,6 +730,26 @@ static void otx2_process_pfaf_mbox_msg(struct otx2_nic *pf,
                return;
        }
 
+       /* message response heading VF */
+       devid = msg->pcifunc & RVU_PFVF_FUNC_MASK;
+       if (devid) {
+               struct otx2_vf_config *config = &pf->vf_configs[devid - 1];
+               struct delayed_work *dwork;
+
+               switch (msg->id) {
+               case MBOX_MSG_NIX_LF_START_RX:
+                       config->intf_down = false;
+                       dwork = &config->link_event_work;
+                       schedule_delayed_work(dwork, msecs_to_jiffies(100));
+                       break;
+               case MBOX_MSG_NIX_LF_STOP_RX:
+                       config->intf_down = true;
+                       break;
+               }
+
+               return;
+       }
+
        switch (msg->id) {
        case MBOX_MSG_READY:
                pf->pcifunc = msg->pcifunc;
@@ -809,9 +831,22 @@ int otx2_mbox_up_handler_cgx_link_event(struct otx2_nic *pf,
                                        struct cgx_link_info_msg *msg,
                                        struct msg_rsp *rsp)
 {
+       int i;
+
        /* Copy the link info sent by AF */
        pf->linfo = msg->link_info;
 
+       /* notify VFs about link event */
+       for (i = 0; i < pci_num_vf(pf->pdev); i++) {
+               struct otx2_vf_config *config = &pf->vf_configs[i];
+               struct delayed_work *dwork = &config->link_event_work;
+
+               if (config->intf_down)
+                       continue;
+
+               schedule_delayed_work(dwork, msecs_to_jiffies(100));
+       }
+
        /* interface has not been fully configured yet */
        if (pf->flags & OTX2_FLAG_INTF_DOWN)
                return 0;
@@ -1925,11 +1960,39 @@ err_release_regions:
        return err;
 }
 
+static void otx2_vf_link_event_task(struct work_struct *work)
+{
+       struct otx2_vf_config *config;
+       struct cgx_link_info_msg *req;
+       struct mbox_msghdr *msghdr;
+       struct otx2_nic *pf;
+       int vf_idx;
+
+       config = container_of(work, struct otx2_vf_config,
+                             link_event_work.work);
+       vf_idx = config - config->pf->vf_configs;
+       pf = config->pf;
+
+       msghdr = otx2_mbox_alloc_msg_rsp(&pf->mbox_pfvf[0].mbox_up, vf_idx,
+                                        sizeof(*req), sizeof(struct msg_rsp));
+       if (!msghdr) {
+               dev_err(pf->dev, "Failed to create VF%d link event\n", vf_idx);
+               return;
+       }
+
+       req = (struct cgx_link_info_msg *)msghdr;
+       req->hdr.id = MBOX_MSG_CGX_LINK_EVENT;
+       req->hdr.sig = OTX2_MBOX_REQ_SIG;
+       memcpy(&req->link_info, &pf->linfo, sizeof(req->link_info));
+
+       otx2_sync_mbox_up_msg(&pf->mbox_pfvf[0], vf_idx);
+}
+
 static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct otx2_nic *pf = netdev_priv(netdev);
-       int ret;
+       int ret, i;
 
        /* Init PF <=> VF mailbox stuff */
        ret = otx2_pfvf_mbox_init(pf, numvfs);
@@ -1940,9 +2003,23 @@ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
        if (ret)
                goto free_mbox;
 
+       pf->vf_configs = kcalloc(numvfs, sizeof(struct otx2_vf_config),
+                                GFP_KERNEL);
+       if (!pf->vf_configs) {
+               ret = -ENOMEM;
+               goto free_intr;
+       }
+
+       for (i = 0; i < numvfs; i++) {
+               pf->vf_configs[i].pf = pf;
+               pf->vf_configs[i].intf_down = true;
+               INIT_DELAYED_WORK(&pf->vf_configs[i].link_event_work,
+                                 otx2_vf_link_event_task);
+       }
+
        ret = otx2_pf_flr_init(pf, numvfs);
        if (ret)
-               goto free_intr;
+               goto free_configs;
 
        ret = otx2_register_flr_me_intr(pf, numvfs);
        if (ret)
@@ -1957,6 +2034,8 @@ free_flr_intr:
        otx2_disable_flr_me_intr(pf);
 free_flr:
        otx2_flr_wq_destroy(pf);
+free_configs:
+       kfree(pf->vf_configs);
 free_intr:
        otx2_disable_pfvf_mbox_intr(pf, numvfs);
 free_mbox:
@@ -1969,12 +2048,17 @@ static int otx2_sriov_disable(struct pci_dev *pdev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct otx2_nic *pf = netdev_priv(netdev);
        int numvfs = pci_num_vf(pdev);
+       int i;
 
        if (!numvfs)
                return 0;
 
        pci_disable_sriov(pdev);
 
+       for (i = 0; i < pci_num_vf(pdev); i++)
+               cancel_delayed_work_sync(&pf->vf_configs[i].link_event_work);
+       kfree(pf->vf_configs);
+
        otx2_disable_flr_me_intr(pf);
        otx2_flr_wq_destroy(pf);
        otx2_disable_pfvf_mbox_intr(pf, numvfs);