From 465ed9c1fc3b8f091c978b8a80ada5953a15b45c Mon Sep 17 00:00:00 2001 From: Sunil Goutham Date: Mon, 19 Nov 2018 16:17:41 +0530 Subject: [PATCH] octeontx2-af: Add FLR handling support for AF's VFs Added support to handle FLR for AF's VFs (i.e LBK VFs). Just the FLR interrupt enable/disable, handler registration etc, actual HW resource cleanup or LFs teardown logic is already there. Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/af/rvu.c | 129 +++++++++++++++--- 1 file changed, 110 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 34e87e66c259..6154f675d47b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -1788,6 +1788,23 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc) mutex_unlock(&rvu->flr_lock); } +static void rvu_afvf_flr_handler(struct rvu *rvu, int vf) +{ + int reg = 0; + + /* pcifunc = 0(PF0) | (vf + 1) */ + __rvu_flr_handler(rvu, vf + 1); + + if (vf >= 64) { + reg = 1; + vf = vf - 64; + } + + /* Signal FLR finish and enable IRQ */ + rvupf_write64(rvu, RVU_PF_VFTRPENDX(reg), BIT_ULL(vf)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(reg), BIT_ULL(vf)); +} + static void rvu_flr_handler(struct work_struct *work) { struct rvu_work *flrwork = container_of(work, struct rvu_work, work); @@ -1797,6 +1814,10 @@ static void rvu_flr_handler(struct work_struct *work) int pf; pf = flrwork - rvu->flr_wrk; + if (pf >= rvu->hw->total_pfs) { + rvu_afvf_flr_handler(rvu, pf - rvu->hw->total_pfs); + return; + } cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); numvfs = (cfg >> 12) & 0xFF; @@ -1814,6 +1835,29 @@ static void rvu_flr_handler(struct work_struct *work) rvu_write64(rvu, BLKADDR_RVUM, RVU_AF_PFFLR_INT_ENA_W1S, BIT_ULL(pf)); } +static void rvu_afvf_queue_flr_work(struct rvu *rvu, int start_vf, int numvfs) +{ + int dev, vf, reg = 0; + u64 intr; + + if (start_vf >= 64) + reg = 1; + + intr = rvupf_read64(rvu, RVU_PF_VFFLR_INTX(reg)); + if (!intr) + return; + + for (vf = 0; vf < numvfs; vf++) { + if (!(intr & BIT_ULL(vf))) + continue; + dev = vf + start_vf + rvu->hw->total_pfs; + queue_work(rvu->flr_wq, &rvu->flr_wrk[dev].work); + /* Clear and disable the interrupt */ + rvupf_write64(rvu, RVU_PF_VFFLR_INTX(reg), BIT_ULL(vf)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(reg), BIT_ULL(vf)); + } +} + static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq) { struct rvu *rvu = (struct rvu *)rvu_irq; @@ -1821,6 +1865,8 @@ static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq) u8 pf; intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFFLR_INT); + if (!intr) + goto afvf_flr; for (pf = 0; pf < rvu->hw->total_pfs; pf++) { if (intr & (1ULL << pf)) { @@ -1834,6 +1880,12 @@ static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq) BIT_ULL(pf)); } } + +afvf_flr: + rvu_afvf_queue_flr_work(rvu, 0, 64); + if (rvu->vfs > 64) + rvu_afvf_queue_flr_work(rvu, 64, rvu->vfs - 64); + return IRQ_HANDLED; } @@ -1876,7 +1928,7 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu) static int rvu_register_interrupts(struct rvu *rvu) { - int ret, offset; + int ret, offset, pf_vec_start; rvu->num_vec = pci_msix_vec_count(rvu->pdev); @@ -1941,10 +1993,11 @@ static int rvu_register_interrupts(struct rvu *rvu) return 0; /* Get PF MSIX vectors offset. */ - offset = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_INT_CFG(0)) & 0x3ff; + pf_vec_start = rvu_read64(rvu, BLKADDR_RVUM, + RVU_PRIV_PFX_INT_CFG(0)) & 0x3ff; /* Register MBOX0 interrupt. */ - offset += RVU_PF_INT_VEC_VFPF_MBOX0; + offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX0; sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox0"); ret = request_irq(pci_irq_vector(rvu->pdev, offset), rvu_mbox_intr_handler, 0, @@ -1959,7 +2012,7 @@ static int rvu_register_interrupts(struct rvu *rvu) /* Register MBOX1 interrupt. MBOX1 IRQ number follows MBOX0 so * simply increment current offset by 1. */ - offset += 1; + offset = pf_vec_start + RVU_PF_INT_VEC_VFPF_MBOX1; sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox1"); ret = request_irq(pci_irq_vector(rvu->pdev, offset), rvu_mbox_intr_handler, 0, @@ -1971,10 +2024,35 @@ static int rvu_register_interrupts(struct rvu *rvu) rvu->irq_allocated[offset] = true; + /* Register FLR interrupt handler for AF's VFs */ + offset = pf_vec_start + RVU_PF_INT_VEC_VFFLR0; + sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF FLR0"); + ret = request_irq(pci_irq_vector(rvu->pdev, offset), + rvu_flr_intr_handler, 0, + &rvu->irq_name[offset * NAME_SIZE], rvu); + if (ret) { + dev_err(rvu->dev, + "RVUAF: IRQ registration failed for RVUAFVF FLR0\n"); + goto fail; + } + rvu->irq_allocated[offset] = true; + + offset = pf_vec_start + RVU_PF_INT_VEC_VFFLR1; + sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF FLR1"); + ret = request_irq(pci_irq_vector(rvu->pdev, offset), + rvu_flr_intr_handler, 0, + &rvu->irq_name[offset * NAME_SIZE], rvu); + if (ret) { + dev_err(rvu->dev, + "RVUAF: IRQ registration failed for RVUAFVF FLR1\n"); + goto fail; + } + rvu->irq_allocated[offset] = true; + return 0; fail: - pci_free_irq_vectors(rvu->pdev); + rvu_unregister_interrupts(rvu); return ret; } @@ -1985,16 +2063,16 @@ static void rvu_flr_wq_destroy(struct rvu *rvu) destroy_workqueue(rvu->flr_wq); rvu->flr_wq = NULL; } - kfree(rvu->flr_wrk); } static int rvu_flr_init(struct rvu *rvu) { + int dev, num_devs; u64 cfg; int pf; /* Enable FLR for all PFs*/ - for (pf = 1; pf < rvu->hw->total_pfs; pf++) { + for (pf = 0; pf < rvu->hw->total_pfs; pf++) { cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf)); rvu_write64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf), cfg | BIT_ULL(22)); @@ -2006,16 +2084,17 @@ static int rvu_flr_init(struct rvu *rvu) if (!rvu->flr_wq) return -ENOMEM; - rvu->flr_wrk = devm_kcalloc(rvu->dev, rvu->hw->total_pfs, + num_devs = rvu->hw->total_pfs + pci_sriov_get_totalvfs(rvu->pdev); + rvu->flr_wrk = devm_kcalloc(rvu->dev, num_devs, sizeof(struct rvu_work), GFP_KERNEL); if (!rvu->flr_wrk) { destroy_workqueue(rvu->flr_wq); return -ENOMEM; } - for (pf = 0; pf < rvu->hw->total_pfs; pf++) { - rvu->flr_wrk[pf].rvu = rvu; - INIT_WORK(&rvu->flr_wrk[pf].work, rvu_flr_handler); + for (dev = 0; dev < num_devs; dev++) { + rvu->flr_wrk[dev].rvu = rvu; + INIT_WORK(&rvu->flr_wrk[dev].work, rvu_flr_handler); } mutex_init(&rvu->flr_lock); @@ -2023,26 +2102,35 @@ static int rvu_flr_init(struct rvu *rvu) return 0; } -static void rvu_disable_afvf_mbox_intr(struct rvu *rvu) +static void rvu_disable_afvf_intr(struct rvu *rvu) { int vfs = rvu->vfs; rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), INTR_MASK(vfs)); - if (vfs > 64) - rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(1), - INTR_MASK(vfs - 64)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(0), INTR_MASK(vfs)); + if (vfs <= 64) + return; + + rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(1), + INTR_MASK(vfs - 64)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1CX(1), INTR_MASK(vfs - 64)); } -static void rvu_enable_afvf_mbox_intr(struct rvu *rvu) +static void rvu_enable_afvf_intr(struct rvu *rvu) { int vfs = rvu->vfs; /* Clear any pending interrupts and enable AF VF interrupts for * the first 64 VFs. */ + /* Mbox */ rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(0), INTR_MASK(vfs)); rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1SX(0), INTR_MASK(vfs)); + /* FLR */ + rvupf_write64(rvu, RVU_PF_VFFLR_INTX(0), INTR_MASK(vfs)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(0), INTR_MASK(vfs)); + /* Same for remaining VFs, if any. */ if (vfs <= 64) return; @@ -2050,6 +2138,9 @@ static void rvu_enable_afvf_mbox_intr(struct rvu *rvu) rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(1), INTR_MASK(vfs - 64)); rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1SX(1), INTR_MASK(vfs - 64)); + + rvupf_write64(rvu, RVU_PF_VFFLR_INTX(1), INTR_MASK(vfs - 64)); + rvupf_write64(rvu, RVU_PF_VFFLR_INT_ENA_W1SX(1), INTR_MASK(vfs - 64)); } #define PCI_DEVID_OCTEONTX2_LBK 0xA061 @@ -2125,13 +2216,13 @@ static int rvu_enable_sriov(struct rvu *rvu) if (err) return err; - rvu_enable_afvf_mbox_intr(rvu); + rvu_enable_afvf_intr(rvu); /* Make sure IRQs are enabled before SRIOV. */ mb(); err = pci_enable_sriov(pdev, vfs); if (err) { - rvu_disable_afvf_mbox_intr(rvu); + rvu_disable_afvf_intr(rvu); rvu_mbox_destroy(&rvu->afvf_wq_info); return err; } @@ -2141,7 +2232,7 @@ static int rvu_enable_sriov(struct rvu *rvu) static void rvu_disable_sriov(struct rvu *rvu) { - rvu_disable_afvf_mbox_intr(rvu); + rvu_disable_afvf_intr(rvu); rvu_mbox_destroy(&rvu->afvf_wq_info); pci_disable_sriov(rvu->pdev); } -- 2.30.2