[PATCH net-next v2] octeontx2-pf: Add NIXLF error and poison interrupt handlers
From: <hidden>
Date: 2026-08-31 06:46:41
Also in:
lkml
Subsystem:
marvell octeontx2 physical function driver, networking drivers, the rest · Maintainers:
Sunil Goutham, Geetha sowjanya, Ratheesh Kannoth, Subbaraya Sundeep, Bharat Bhushan, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
From: Naveen Mamindlapalli <redacted> Register and handle the NIX LF error (NIX_LF_ERR_INT) and poison/RAS (NIX_LF_RAS) interrupt vectors, The handlers acknowledge the interrupt and log the status (ratelimited) to help debug NIX LF faults. Signed-off-by: Nitin Shetty J <redacted> Signed-off-by: Naveen Mamindlapalli <redacted> --- Changes in v2: - Clamp VF qcount to OTX2_MAX_CQ_CNT to fix MSIX vector budget underflow on >64 CPU systems. - Skip ERR/POISON vector allocation for representors that don't register those handlers. - Fix stale comment and typo in otx2_realloc_msix_vectors(). --- .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 88 ++++++++++++++++++- .../ethernet/marvell/octeontx2/nic/otx2_reg.h | 2 + .../ethernet/marvell/octeontx2/nic/otx2_vf.c | 4 +- 3 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index c995f2900859..1f8cb78c1919 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c@@ -1524,6 +1524,34 @@ irqreturn_t otx2_cq_intr_handler(int irq, void *cq_irq) } EXPORT_SYMBOL(otx2_cq_intr_handler); +static irqreturn_t otx2_nixlf_err_intr_handler(int irq, void *data) +{ + struct otx2_nic *pf = data; + u64 regval; + + /* Clear interrupt */ + regval = otx2_read64(pf, NIX_LF_ERR_INT); + otx2_write64(pf, NIX_LF_ERR_INT, regval); + + dev_err_ratelimited(pf->dev, "NIXLF Error Interrupt: 0x%llx\n", regval); + + return IRQ_HANDLED; +} + +static irqreturn_t otx2_nixlf_poison_intr_handler(int irq, void *data) +{ + struct otx2_nic *pf = data; + u64 regval; + + /* Clear interrupt */ + regval = otx2_read64(pf, NIX_LF_RAS); + otx2_write64(pf, NIX_LF_RAS, regval); + + dev_err_ratelimited(pf->dev, "NIXLF Poison Interrupt: 0x%llx\n", regval); + + return IRQ_HANDLED; +} + void otx2_disable_napi(struct otx2_nic *pf) { struct otx2_qset *qset = &pf->qset;
@@ -2080,6 +2108,34 @@ int otx2_open(struct net_device *netdev) otx2_set_cints_affinity(pf); + /* Register NIXLF error IRQ handler */ + vec = pf->hw.nix_msixoff + NIX_LF_ERR_VEC; + irq_name = &pf->hw.irq_name[vec * NAME_SIZE]; + snprintf(irq_name, NAME_SIZE, "%s-nixlf-err", pf->netdev->name); + err = request_irq(pci_irq_vector(pf->pdev, vec), + otx2_nixlf_err_intr_handler, 0, irq_name, pf); + if (err) { + dev_err(pf->dev, + "RVUPF%d: IRQ registration failed for NIXLF ERR vector\n", + rvu_get_pf(pf->pdev, pf->pcifunc)); + goto err_free_cints; + } + otx2_write64(pf, NIX_LF_ERR_INT_ENA_W1S, NIX_LF_ERR_INT_MASK); + + /* Register NIXLF POISON interrupt handler */ + vec = pf->hw.nix_msixoff + NIX_LF_POISON_VEC; + irq_name = &pf->hw.irq_name[vec * NAME_SIZE]; + snprintf(irq_name, NAME_SIZE, "%s-nixlf-poison", pf->netdev->name); + err = request_irq(pci_irq_vector(pf->pdev, vec), + otx2_nixlf_poison_intr_handler, 0, irq_name, pf); + if (err) { + dev_err(pf->dev, + "RVUPF%d: IRQ registration failed for NIXLF POISON vector\n", + rvu_get_pf(pf->pdev, pf->pcifunc)); + goto err_free_errint; + } + otx2_write64(pf, NIX_LF_RAS_ENA_W1S, NIX_LF_RAS_MASK); + if (pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT) otx2_enable_rxvlan(pf, true);
@@ -2132,6 +2188,16 @@ int otx2_open(struct net_device *netdev) netif_tx_stop_all_queues(netdev); netif_carrier_off(netdev); pf->flags |= OTX2_FLAG_INTF_DOWN; + /* free NIXLF POISON irq */ + vec = pci_irq_vector(pf->pdev, + pf->hw.nix_msixoff + NIX_LF_POISON_VEC); + otx2_write64(pf, NIX_LF_RAS_ENA_W1C, NIX_LF_RAS_MASK); + free_irq(vec, pf); +err_free_errint: + vec = pci_irq_vector(pf->pdev, + pf->hw.nix_msixoff + NIX_LF_ERR_VEC); + otx2_write64(pf, NIX_LF_ERR_INT_ENA_W1C, NIX_LF_ERR_INT_MASK); + free_irq(vec, pf); err_free_cints: otx2_free_cints(pf, qidx); vec = pci_irq_vector(pf->pdev,
@@ -2171,6 +2237,18 @@ int otx2_stop(struct net_device *netdev) /* Clear RSS enable flag */ pf->hw.rss_info.enable = false; + /* Cleanup NIXLF Poison IRQ */ + vec = pci_irq_vector(pf->pdev, + pf->hw.nix_msixoff + NIX_LF_POISON_VEC); + otx2_write64(pf, NIX_LF_RAS_ENA_W1C, NIX_LF_RAS_MASK); + free_irq(vec, pf); + + /* Cleanup NIXLF Error IRQ */ + vec = pci_irq_vector(pf->pdev, + pf->hw.nix_msixoff + NIX_LF_ERR_VEC); + otx2_write64(pf, NIX_LF_ERR_INT_ENA_W1C, NIX_LF_ERR_INT_MASK); + free_irq(vec, pf); + /* Cleanup Queue IRQ */ vec = pci_irq_vector(pf->pdev, pf->hw.nix_msixoff + NIX_LF_QINT_VEC_START);
@@ -3006,11 +3084,15 @@ int otx2_realloc_msix_vectors(struct otx2_nic *pf) struct otx2_hw *hw = &pf->hw; int num_vec, err; - /* NPA interrupts are inot registered, so alloc only - * upto NIX vector offset. + /* Skip NPA vectors. Representors only use CINT vectors, so limit + * the budget to that range. For PF/VF, allocate the full NIX LF + * interrupt range (QINT, CINT, GINT, ERR and POISON vectors). */ num_vec = hw->nix_msixoff; - num_vec += NIX_LF_CINT_VEC_START + hw->max_queues; + if (pf->flags & OTX2_FLAG_REP_MODE_ENABLED) + num_vec += NIX_LF_CINT_VEC_START + hw->max_queues; + else + num_vec += NIX_LF_POISON_VEC + 1; otx2_disable_mbox_intr(pf); pci_free_irq_vectors(hw->pdev);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
index 1cd576fd09c5..c144fd2bbe51 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_reg.h@@ -121,10 +121,12 @@ #define NIX_LF_ERR_INT_W1S (NIX_LFBASE | 0x228) #define NIX_LF_ERR_INT_ENA_W1C (NIX_LFBASE | 0x230) #define NIX_LF_ERR_INT_ENA_W1S (NIX_LFBASE | 0x238) +#define NIX_LF_ERR_INT_MASK GENMASK_ULL(31, 0) #define NIX_LF_RAS (NIX_LFBASE | 0x240) #define NIX_LF_RAS_W1S (NIX_LFBASE | 0x248) #define NIX_LF_RAS_ENA_W1C (NIX_LFBASE | 0x250) #define NIX_LF_RAS_ENA_W1S (NIX_LFBASE | 0x258) +#define NIX_LF_RAS_MASK GENMASK_ULL(10, 0) #define NIX_LF_SQ_OP_ERR_DBG (NIX_LFBASE | 0x260) #define NIX_LF_MNQ_ERR_DBG (NIX_LFBASE | 0x270) #define NIX_LF_SEND_ERR_DBG (NIX_LFBASE | 0x280)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index b022f52c6845..eda4ed52a8d8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c@@ -554,7 +554,7 @@ static int otx2vf_realloc_msix_vectors(struct otx2_nic *vf) int num_vec, err; num_vec = hw->nix_msixoff; - num_vec += NIX_LF_CINT_VEC_START + hw->max_queues; + num_vec += NIX_LF_POISON_VEC + 1; otx2vf_disable_mbox_intr(vf); pci_free_irq_vectors(hw->pdev);
@@ -597,7 +597,7 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); - qcount = num_online_cpus(); + qcount = min_t(int, num_online_cpus(), OTX2_MAX_CQ_CNT); qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES); netdev = alloc_etherdev_mqs(sizeof(*vf), qcount + qos_txqs, qcount); if (!netdev)
--
2.48.1