octeon_ep: ensure dbell BADDR updation

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: 0807dc76f3 ("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>
This commit is contained in:
Vimlesh Kumar 2026-02-06 11:15:07 +00:00 committed by Paolo Abeni
parent 73e6ffa37c
commit ce8fe3fc4f
4 changed files with 48 additions and 11 deletions

View 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 */

View 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 */

View 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);

View 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;