Commit 465ed9c1 authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

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: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8bb991c5
...@@ -1788,6 +1788,23 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc) ...@@ -1788,6 +1788,23 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
mutex_unlock(&rvu->flr_lock); 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) static void rvu_flr_handler(struct work_struct *work)
{ {
struct rvu_work *flrwork = container_of(work, struct rvu_work, 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) ...@@ -1797,6 +1814,10 @@ static void rvu_flr_handler(struct work_struct *work)
int pf; int pf;
pf = flrwork - rvu->flr_wrk; 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)); cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf));
numvfs = (cfg >> 12) & 0xFF; numvfs = (cfg >> 12) & 0xFF;
...@@ -1814,6 +1835,29 @@ static void rvu_flr_handler(struct work_struct *work) ...@@ -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)); 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) static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq)
{ {
struct rvu *rvu = (struct rvu *)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) ...@@ -1821,6 +1865,8 @@ static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq)
u8 pf; u8 pf;
intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFFLR_INT); intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFFLR_INT);
if (!intr)
goto afvf_flr;
for (pf = 0; pf < rvu->hw->total_pfs; pf++) { for (pf = 0; pf < rvu->hw->total_pfs; pf++) {
if (intr & (1ULL << pf)) { if (intr & (1ULL << pf)) {
...@@ -1834,6 +1880,12 @@ static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq) ...@@ -1834,6 +1880,12 @@ static irqreturn_t rvu_flr_intr_handler(int irq, void *rvu_irq)
BIT_ULL(pf)); 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; return IRQ_HANDLED;
} }
...@@ -1876,7 +1928,7 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu) ...@@ -1876,7 +1928,7 @@ static int rvu_afvf_msix_vectors_num_ok(struct rvu *rvu)
static int rvu_register_interrupts(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); rvu->num_vec = pci_msix_vec_count(rvu->pdev);
...@@ -1941,10 +1993,11 @@ static int rvu_register_interrupts(struct rvu *rvu) ...@@ -1941,10 +1993,11 @@ static int rvu_register_interrupts(struct rvu *rvu)
return 0; return 0;
/* Get PF MSIX vectors offset. */ /* 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. */ /* 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"); sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox0");
ret = request_irq(pci_irq_vector(rvu->pdev, offset), ret = request_irq(pci_irq_vector(rvu->pdev, offset),
rvu_mbox_intr_handler, 0, rvu_mbox_intr_handler, 0,
...@@ -1959,7 +2012,7 @@ static int rvu_register_interrupts(struct rvu *rvu) ...@@ -1959,7 +2012,7 @@ static int rvu_register_interrupts(struct rvu *rvu)
/* Register MBOX1 interrupt. MBOX1 IRQ number follows MBOX0 so /* Register MBOX1 interrupt. MBOX1 IRQ number follows MBOX0 so
* simply increment current offset by 1. * 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"); sprintf(&rvu->irq_name[offset * NAME_SIZE], "RVUAFVF Mbox1");
ret = request_irq(pci_irq_vector(rvu->pdev, offset), ret = request_irq(pci_irq_vector(rvu->pdev, offset),
rvu_mbox_intr_handler, 0, rvu_mbox_intr_handler, 0,
...@@ -1971,10 +2024,35 @@ static int rvu_register_interrupts(struct rvu *rvu) ...@@ -1971,10 +2024,35 @@ static int rvu_register_interrupts(struct rvu *rvu)
rvu->irq_allocated[offset] = true; 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; return 0;
fail: fail:
pci_free_irq_vectors(rvu->pdev); rvu_unregister_interrupts(rvu);
return ret; return ret;
} }
...@@ -1985,16 +2063,16 @@ static void rvu_flr_wq_destroy(struct rvu *rvu) ...@@ -1985,16 +2063,16 @@ static void rvu_flr_wq_destroy(struct rvu *rvu)
destroy_workqueue(rvu->flr_wq); destroy_workqueue(rvu->flr_wq);
rvu->flr_wq = NULL; rvu->flr_wq = NULL;
} }
kfree(rvu->flr_wrk);
} }
static int rvu_flr_init(struct rvu *rvu) static int rvu_flr_init(struct rvu *rvu)
{ {
int dev, num_devs;
u64 cfg; u64 cfg;
int pf; int pf;
/* Enable FLR for all PFs*/ /* 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)); cfg = rvu_read64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf));
rvu_write64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf), rvu_write64(rvu, BLKADDR_RVUM, RVU_PRIV_PFX_CFG(pf),
cfg | BIT_ULL(22)); cfg | BIT_ULL(22));
...@@ -2006,16 +2084,17 @@ static int rvu_flr_init(struct rvu *rvu) ...@@ -2006,16 +2084,17 @@ static int rvu_flr_init(struct rvu *rvu)
if (!rvu->flr_wq) if (!rvu->flr_wq)
return -ENOMEM; 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); sizeof(struct rvu_work), GFP_KERNEL);
if (!rvu->flr_wrk) { if (!rvu->flr_wrk) {
destroy_workqueue(rvu->flr_wq); destroy_workqueue(rvu->flr_wq);
return -ENOMEM; return -ENOMEM;
} }
for (pf = 0; pf < rvu->hw->total_pfs; pf++) { for (dev = 0; dev < num_devs; dev++) {
rvu->flr_wrk[pf].rvu = rvu; rvu->flr_wrk[dev].rvu = rvu;
INIT_WORK(&rvu->flr_wrk[pf].work, rvu_flr_handler); INIT_WORK(&rvu->flr_wrk[dev].work, rvu_flr_handler);
} }
mutex_init(&rvu->flr_lock); mutex_init(&rvu->flr_lock);
...@@ -2023,26 +2102,35 @@ static int rvu_flr_init(struct rvu *rvu) ...@@ -2023,26 +2102,35 @@ static int rvu_flr_init(struct rvu *rvu)
return 0; 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; int vfs = rvu->vfs;
rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), INTR_MASK(vfs)); rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(0), INTR_MASK(vfs));
if (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), rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1CX(1),
INTR_MASK(vfs - 64)); 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; int vfs = rvu->vfs;
/* Clear any pending interrupts and enable AF VF interrupts for /* Clear any pending interrupts and enable AF VF interrupts for
* the first 64 VFs. * the first 64 VFs.
*/ */
/* Mbox */
rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(0), INTR_MASK(vfs)); 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)); 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. */ /* Same for remaining VFs, if any. */
if (vfs <= 64) if (vfs <= 64)
return; return;
...@@ -2050,6 +2138,9 @@ static void rvu_enable_afvf_mbox_intr(struct rvu *rvu) ...@@ -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_INTX(1), INTR_MASK(vfs - 64));
rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1SX(1), rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INT_ENA_W1SX(1),
INTR_MASK(vfs - 64)); 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 #define PCI_DEVID_OCTEONTX2_LBK 0xA061
...@@ -2125,13 +2216,13 @@ static int rvu_enable_sriov(struct rvu *rvu) ...@@ -2125,13 +2216,13 @@ static int rvu_enable_sriov(struct rvu *rvu)
if (err) if (err)
return err; return err;
rvu_enable_afvf_mbox_intr(rvu); rvu_enable_afvf_intr(rvu);
/* Make sure IRQs are enabled before SRIOV. */ /* Make sure IRQs are enabled before SRIOV. */
mb(); mb();
err = pci_enable_sriov(pdev, vfs); err = pci_enable_sriov(pdev, vfs);
if (err) { if (err) {
rvu_disable_afvf_mbox_intr(rvu); rvu_disable_afvf_intr(rvu);
rvu_mbox_destroy(&rvu->afvf_wq_info); rvu_mbox_destroy(&rvu->afvf_wq_info);
return err; return err;
} }
...@@ -2141,7 +2232,7 @@ static int rvu_enable_sriov(struct rvu *rvu) ...@@ -2141,7 +2232,7 @@ static int rvu_enable_sriov(struct rvu *rvu)
static void rvu_disable_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); rvu_mbox_destroy(&rvu->afvf_wq_info);
pci_disable_sriov(rvu->pdev); pci_disable_sriov(rvu->pdev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment