]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
octeon_ep_vf: ensure dbell BADDR updation
authorVimlesh Kumar <vimleshk@marvell.com>
Fri, 6 Feb 2026 11:15:08 +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: 2c0c32c72be29 ("octeon_ep_vf: add hardware configuration APIs")
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-4-vimleshk@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c
drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cnxk.c
drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h
drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c

index 88937fce75f1400e2ee6c96da3eb482b7a76deff..4c769b27c27892a005e614d9cc300dcd45513b81 100644 (file)
@@ -196,7 +196,7 @@ static void octep_vf_setup_iq_regs_cn93(struct octep_vf_device *oct, int iq_no)
 }
 
 /* Setup registers for a hardware Rx Queue  */
-static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
+static int octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
 {
        struct octep_vf_oq *oq = oct->oq[oq_no];
        u32 time_threshold = 0;
@@ -239,6 +239,7 @@ static void octep_vf_setup_oq_regs_cn93(struct octep_vf_device *oct, int oq_no)
        time_threshold = CFG_GET_OQ_INTR_TIME(oct->conf);
        reg_val = ((u64)time_threshold << 32) | CFG_GET_OQ_INTR_PKT(oct->conf);
        octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(oq_no), reg_val);
+       return 0;
 }
 
 /* Setup registers for a VF mailbox */
index 1f79dfad42c626ea72f9d869504b247994a74d56..a968b93a67943ba082902e7106c5b3a39aa6386d 100644 (file)
@@ -199,11 +199,13 @@ static void octep_vf_setup_iq_regs_cnxk(struct octep_vf_device *oct, int iq_no)
 }
 
 /* Setup registers for a hardware Rx Queue  */
-static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
+static int octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
 {
        struct octep_vf_oq *oq = oct->oq[oq_no];
+       unsigned long t_out_jiffies;
        u32 time_threshold = 0;
        u64 oq_ctl = ULL(0);
+       u64 reg_ba_val;
        u64 reg_val;
 
        reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
@@ -214,6 +216,38 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
                        reg_val = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
                } while (!(reg_val & CNXK_VF_R_OUT_CTL_IDLE));
        }
+       octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no),
+                            oq->max_count);
+       /* Wait for WMARK to get applied */
+       usleep_range(10, 15);
+
+       octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no),
+                            oq->desc_ring_dma);
+       octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(oq_no),
+                            oq->max_count);
+       reg_ba_val = octep_vf_read_csr64(oct,
+                                        CNXK_VF_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_vf_write_csr64(oct,
+                                            CNXK_VF_SDP_R_OUT_SLIST_BADDR
+                                            (oq_no), oq->desc_ring_dma);
+                       octep_vf_write_csr64(oct,
+                                            CNXK_VF_SDP_R_OUT_SLIST_RSIZE
+                                            (oq_no), oq->max_count);
+                       reg_ba_val =
+                       octep_vf_read_csr64(oct,
+                                           CNXK_VF_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_VF_R_OUT_CTL_IMODE);
        reg_val &= ~(CNXK_VF_R_OUT_CTL_ROR_P);
@@ -227,8 +261,6 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
        reg_val |= (CNXK_VF_R_OUT_CTL_ES_P);
 
        octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no), reg_val);
-       octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_BADDR(oq_no), oq->desc_ring_dma);
-       octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_SLIST_RSIZE(oq_no), oq->max_count);
 
        oq_ctl = octep_vf_read_csr64(oct, CNXK_VF_SDP_R_OUT_CONTROL(oq_no));
        /* Clear the ISIZE and BSIZE (22-0) */
@@ -250,6 +282,7 @@ static void octep_vf_setup_oq_regs_cnxk(struct octep_vf_device *oct, int oq_no)
        reg_val &= ~GENMASK_ULL(31, 0);
        reg_val |= CFG_GET_OQ_WMARK(oct->conf);
        octep_vf_write_csr64(oct, CNXK_VF_SDP_R_OUT_WMARK(oq_no), reg_val);
+       return 0;
 }
 
 /* Setup registers for a VF mailbox */
index b9f13506f4620556e5e019e5083de989c05aeb3c..c74cd2369e90d441663c5577cd40b5790f14e434 100644 (file)
@@ -55,7 +55,7 @@ struct octep_vf_mmio {
 
 struct octep_vf_hw_ops {
        void (*setup_iq_regs)(struct octep_vf_device *oct, int q);
-       void (*setup_oq_regs)(struct octep_vf_device *oct, int q);
+       int (*setup_oq_regs)(struct octep_vf_device *oct, int q);
        void (*setup_mbox_regs)(struct octep_vf_device *oct, int mbox);
 
        irqreturn_t (*non_ioq_intr_handler)(void *ioq_vector);
index d70c8be3cfc40b42cff53d224063da5cea34c8bb..6f865dbbba6c67030bb9b84626460618ac185c07 100644 (file)
@@ -12,6 +12,8 @@
 #include "octep_vf_config.h"
 #include "octep_vf_main.h"
 
+static void octep_vf_oq_free_ring_buffers(struct octep_vf_oq *oq);
+
 static void octep_vf_oq_reset_indices(struct octep_vf_oq *oq)
 {
        oq->host_read_idx = 0;
@@ -171,11 +173,15 @@ static int octep_vf_setup_oq(struct octep_vf_device *oct, int q_no)
                goto oq_fill_buff_err;
 
        octep_vf_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_vf_oq_free_ring_buffers(oq);
 oq_fill_buff_err:
        vfree(oq->buff_info);
        oq->buff_info = NULL;