Commit ce8fe3fc authored by Vimlesh Kumar's avatar Vimlesh Kumar Committed by Paolo Abeni
Browse files

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: 0807dc76 ("octeon_ep: support Octeon CN10K devices")
Signed-off-by: default avatarSathesh Edara <sedara@marvell.com>
Signed-off-by: default avatarShinas Rasheed <srasheed@marvell.com>
Signed-off-by: default avatarVimlesh Kumar <vimleshk@marvell.com>
Link: https://patch.msgid.link/20260206111510.1045092-3-vimleshk@marvell.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 73e6ffa3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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 */
+38 −8
Original line number Diff line number Diff line
@@ -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 */
+1 −1
Original line number Diff line number Diff line
@@ -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);
+7 −1
Original line number Diff line number Diff line
@@ -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;