]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
octeon_ep: ensure dbell BADDR updation
authorVimlesh Kumar <vimleshk@marvell.com>
Fri, 6 Feb 2026 11:15:07 +0000 (11:15 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 10 Feb 2026 14:57:59 +0000 (15:57 +0100)
Make sure the OUT DBELL base address reflects the
latest values written to it.

Fix:
Add a wait until the OUT DBELL base address register
is updated with the DMA ring descriptor address,
and modify the setup_oq function to properly
handle failures.

Fixes: 0807dc76f3bf5 ("octeon_ep: support Octeon CN10K devices")
Signed-off-by: Sathesh Edara <sedara@marvell.com>
Signed-off-by: Shinas Rasheed <srasheed@marvell.com>
Signed-off-by: Vimlesh Kumar <vimleshk@marvell.com>
Link: https://patch.msgid.link/20260206111510.1045092-3-vimleshk@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/marvell/octeon_ep/octep_cn9k_pf.c
drivers/net/ethernet/marvell/octeon_ep/octep_cnxk_pf.c
drivers/net/ethernet/marvell/octeon_ep/octep_main.h
drivers/net/ethernet/marvell/octeon_ep/octep_rx.c

index f0bcb5f3c1474171f049364d0eeb3802e5783af4..01e82d0b6b2cdd29cc3bfde153601db421277408 100644 (file)
@@ -307,7 +307,7 @@ static void octep_setup_iq_regs_cn93_pf(struct octep_device *oct, int iq_no)
 }
 
 /* Setup registers for a hardware Rx Queue  */
-static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no)
+static int octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no)
 {
        u64 reg_val;
        u64 oq_ctl = 0ULL;
@@ -355,6 +355,7 @@ static void octep_setup_oq_regs_cn93_pf(struct octep_device *oct, int oq_no)
        reg_val = ((u64)time_threshold << 32) |
                  CFG_GET_OQ_INTR_PKT(oct->conf);
        octep_write_csr64(oct, CN93_SDP_R_OUT_INT_LEVELS(oq_no), reg_val);
+       return 0;
 }
 
 /* Setup registers for a PF mailbox */
index 07e00887c6940a349f811724abdb837dbc78f92b..09a3f1d0645b85bb943b736f7a6fc6ae3c539844 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jiffies.h>
 
 #include "octep_config.h"
 #include "octep_main.h"
@@ -327,12 +328,14 @@ static void octep_setup_iq_regs_cnxk_pf(struct octep_device *oct, int iq_no)
 }
 
 /* Setup registers for a hardware Rx Queue  */
-static void octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no)
+static int octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no)
 {
-       u64 reg_val;
-       u64 oq_ctl = 0ULL;
-       u32 time_threshold = 0;
        struct octep_oq *oq = oct->oq[oq_no];
+       unsigned long t_out_jiffies;
+       u32 time_threshold = 0;
+       u64 oq_ctl = 0ULL;
+       u64 reg_ba_val;
+       u64 reg_val;
 
        oq_no += CFG_GET_PORTS_PF_SRN(oct->conf);
        reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no));
@@ -343,6 +346,36 @@ static void octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no)
                        reg_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no));
                } while (!(reg_val & CNXK_R_OUT_CTL_IDLE));
        }
+       octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no),  oq->max_count);
+       /* Wait for WMARK to get applied */
+       usleep_range(10, 15);
+
+       octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no),
+                         oq->desc_ring_dma);
+       octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no),
+                         oq->max_count);
+       reg_ba_val = octep_read_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no));
+
+       if (reg_ba_val != oq->desc_ring_dma) {
+               t_out_jiffies = jiffies + 10 * HZ;
+               do {
+                       if (reg_ba_val == ULLONG_MAX)
+                               return -EFAULT;
+                       octep_write_csr64(oct,
+                                         CNXK_SDP_R_OUT_SLIST_BADDR(oq_no),
+                                         oq->desc_ring_dma);
+                       octep_write_csr64(oct,
+                                         CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no),
+                                         oq->max_count);
+                       reg_ba_val =
+                       octep_read_csr64(oct,
+                                        CNXK_SDP_R_OUT_SLIST_BADDR(oq_no));
+               } while ((reg_ba_val != oq->desc_ring_dma) &&
+                         time_before(jiffies, t_out_jiffies));
+
+               if (reg_ba_val != oq->desc_ring_dma)
+                       return -EAGAIN;
+       }
 
        reg_val &= ~(CNXK_R_OUT_CTL_IMODE);
        reg_val &= ~(CNXK_R_OUT_CTL_ROR_P);
@@ -356,10 +389,6 @@ static void octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no)
        reg_val |= (CNXK_R_OUT_CTL_ES_P);
 
        octep_write_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no), reg_val);
-       octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_BADDR(oq_no),
-                         oq->desc_ring_dma);
-       octep_write_csr64(oct, CNXK_SDP_R_OUT_SLIST_RSIZE(oq_no),
-                         oq->max_count);
 
        oq_ctl = octep_read_csr64(oct, CNXK_SDP_R_OUT_CONTROL(oq_no));
 
@@ -385,6 +414,7 @@ static void octep_setup_oq_regs_cnxk_pf(struct octep_device *oct, int oq_no)
        reg_val &= ~0xFFFFFFFFULL;
        reg_val |= CFG_GET_OQ_WMARK(oct->conf);
        octep_write_csr64(oct, CNXK_SDP_R_OUT_WMARK(oq_no), reg_val);
+       return 0;
 }
 
 /* Setup registers for a PF mailbox */
index 81ac4267811c81493467694327847153b2db2ac2..35d0ff289a70df831936256f45ee5d6df7985e98 100644 (file)
@@ -77,7 +77,7 @@ struct octep_pci_win_regs {
 
 struct octep_hw_ops {
        void (*setup_iq_regs)(struct octep_device *oct, int q);
-       void (*setup_oq_regs)(struct octep_device *oct, int q);
+       int (*setup_oq_regs)(struct octep_device *oct, int q);
        void (*setup_mbox_regs)(struct octep_device *oct, int mbox);
 
        irqreturn_t (*mbox_intr_handler)(void *ioq_vector);
index 82b6b19e76b47abda14f8ffb9f47ddbfe50feb4b..f2a7c6a76c742aef8df4cbc947a72ca934220dc9 100644 (file)
@@ -12,6 +12,8 @@
 #include "octep_config.h"
 #include "octep_main.h"
 
+static void octep_oq_free_ring_buffers(struct octep_oq *oq);
+
 static void octep_oq_reset_indices(struct octep_oq *oq)
 {
        oq->host_read_idx = 0;
@@ -170,11 +172,15 @@ static int octep_setup_oq(struct octep_device *oct, int q_no)
                goto oq_fill_buff_err;
 
        octep_oq_reset_indices(oq);
-       oct->hw_ops.setup_oq_regs(oct, q_no);
+       if (oct->hw_ops.setup_oq_regs(oct, q_no))
+               goto oq_setup_err;
+
        oct->num_oqs++;
 
        return 0;
 
+oq_setup_err:
+       octep_oq_free_ring_buffers(oq);
 oq_fill_buff_err:
        vfree(oq->buff_info);
        oq->buff_info = NULL;