Commit 05cff25e authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'octeontx2-af-misc-rpm-fixes'

Hariprasad Kelam says:

====================
octeontx2-af: misc RPM fixes

There are few issues with the RPM driver, such as FIFO overflow
and network performance problems due to wrong FIFO values. This
patchset adds fixes for the same.

Patch1: Fixes the mismatch between the lmac type reported by the driver
        and the actual hardware configuration.

Patch2: Addresses low network performance observed even on RPMs with
        larger FIFO lengths.

Patch 3 & 4: Fix the stale FEC counters reported by the driver by
             accessing the correct CSRs

Patch 5: Resolves the issue related to RPM FIFO overflow during system
         reboots
====================

Link: https://patch.msgid.link/20241122162035.5842-1-hkelam@marvell.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 407618d6 762ca6ee
Loading
Loading
Loading
Loading
+68 −2
Original line number Diff line number Diff line
@@ -112,6 +112,11 @@ struct mac_ops *get_mac_ops(void *cgxd)
	return ((struct cgx *)cgxd)->mac_ops;
}

u32 cgx_get_fifo_len(void *cgxd)
{
	return ((struct cgx *)cgxd)->fifo_len;
}

void cgx_write(struct cgx *cgx, u64 lmac, u64 offset, u64 val)
{
	writeq(val, cgx->reg_base + (lmac << cgx->mac_ops->lmac_offset) +
@@ -209,6 +214,24 @@ u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id)
	return (cfg & CMR_P2X_SEL_MASK) >> CMR_P2X_SEL_SHIFT;
}

static u8 cgx_get_nix_resetbit(struct cgx *cgx)
{
	int first_lmac;
	u8 p2x;

	/* non 98XX silicons supports only NIX0 block */
	if (cgx->pdev->subsystem_device != PCI_SUBSYS_DEVID_98XX)
		return CGX_NIX0_RESET;

	first_lmac = find_first_bit(&cgx->lmac_bmap, cgx->max_lmac_per_mac);
	p2x = cgx_lmac_get_p2x(cgx->cgx_id, first_lmac);

	if (p2x == CMR_P2X_SEL_NIX1)
		return CGX_NIX1_RESET;
	else
		return CGX_NIX0_RESET;
}

/* Ensure the required lock for event queue(where asynchronous events are
 * posted) is acquired before calling this API. Else an asynchronous event(with
 * latest link status) can reach the destination before this function returns
@@ -501,7 +524,7 @@ static u32 cgx_get_lmac_fifo_len(void *cgxd, int lmac_id)
	u8 num_lmacs;
	u32 fifo_len;

	fifo_len = cgx->mac_ops->fifo_len;
	fifo_len = cgx->fifo_len;
	num_lmacs = cgx->mac_ops->get_nr_lmacs(cgx);

	switch (num_lmacs) {
@@ -1719,6 +1742,8 @@ static int cgx_lmac_init(struct cgx *cgx)
		lmac->lmac_type = cgx->mac_ops->get_lmac_type(cgx, lmac->lmac_id);
	}

	/* Start X2P reset on given MAC block */
	cgx->mac_ops->mac_x2p_reset(cgx, true);
	return cgx_lmac_verify_fwi_version(cgx);

err_bitmap_free:
@@ -1764,7 +1789,7 @@ static void cgx_populate_features(struct cgx *cgx)
	u64 cfg;

	cfg = cgx_read(cgx, 0, CGX_CONST);
	cgx->mac_ops->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
	cgx->fifo_len = FIELD_GET(CGX_CONST_RXFIFO_SIZE, cfg);
	cgx->max_lmac_per_mac = FIELD_GET(CGX_CONST_MAX_LMACS, cfg);

	if (is_dev_rpm(cgx))
@@ -1784,6 +1809,45 @@ static u8 cgx_get_rxid_mapoffset(struct cgx *cgx)
		return 0x60;
}

static void cgx_x2p_reset(void *cgxd, bool enable)
{
	struct cgx *cgx = cgxd;
	int lmac_id;
	u64 cfg;

	if (enable) {
		for_each_set_bit(lmac_id, &cgx->lmac_bmap, cgx->max_lmac_per_mac)
			cgx->mac_ops->mac_enadis_rx(cgx, lmac_id, false);

		usleep_range(1000, 2000);

		cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
		cfg |= cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP;
		cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
	} else {
		cfg = cgx_read(cgx, 0, CGXX_CMR_GLOBAL_CONFIG);
		cfg &= ~(cgx_get_nix_resetbit(cgx) | CGX_NSCI_DROP);
		cgx_write(cgx, 0, CGXX_CMR_GLOBAL_CONFIG, cfg);
	}
}

static int cgx_enadis_rx(void *cgxd, int lmac_id, bool enable)
{
	struct cgx *cgx = cgxd;
	u64 cfg;

	if (!is_lmac_valid(cgx, lmac_id))
		return -ENODEV;

	cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
	if (enable)
		cfg |= DATA_PKT_RX_EN;
	else
		cfg &= ~DATA_PKT_RX_EN;
	cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
	return 0;
}

static struct mac_ops	cgx_mac_ops    = {
	.name		=       "cgx",
	.csr_offset	=       0,
@@ -1815,6 +1879,8 @@ static struct mac_ops cgx_mac_ops = {
	.mac_get_pfc_frm_cfg   =        cgx_lmac_get_pfc_frm_cfg,
	.mac_reset   =			cgx_lmac_reset,
	.mac_stats_reset       =	cgx_stats_reset,
	.mac_x2p_reset                   =      cgx_x2p_reset,
	.mac_enadis_rx			 =      cgx_enadis_rx,
};

static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+5 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@
#define CGX_LMAC_TYPE_MASK		0xF
#define CGXX_CMRX_INT			0x040
#define FW_CGX_INT			BIT_ULL(1)
#define CGXX_CMR_GLOBAL_CONFIG          0x08
#define CGX_NIX0_RESET			BIT_ULL(2)
#define CGX_NIX1_RESET			BIT_ULL(3)
#define CGX_NSCI_DROP			BIT_ULL(9)
#define CGXX_CMRX_INT_ENA_W1S		0x058
#define CGXX_CMRX_RX_ID_MAP		0x060
#define CGXX_CMRX_RX_STAT0		0x070
@@ -185,4 +189,5 @@ int cgx_lmac_get_pfc_frm_cfg(void *cgxd, int lmac_id, u8 *tx_pause,
int verify_lmac_fc_cfg(void *cgxd, int lmac_id, u8 tx_pause, u8 rx_pause,
		       int pfvf_idx);
int cgx_lmac_reset(void *cgxd, int lmac_id, u8 pf_req_flr);
u32 cgx_get_fifo_len(void *cgxd);
#endif /* CGX_H */
+6 −1
Original line number Diff line number Diff line
@@ -72,7 +72,6 @@ struct mac_ops {
	u8			irq_offset;
	u8			int_ena_bit;
	u8			lmac_fwi;
	u32			fifo_len;
	bool			non_contiguous_serdes_lane;
	/* RPM & CGX differs in number of Receive/transmit stats */
	u8			rx_stats_cnt;
@@ -133,6 +132,8 @@ struct mac_ops {
	int			(*get_fec_stats)(void *cgxd, int lmac_id,
						 struct cgx_fec_stats_rsp *rsp);
	int			(*mac_stats_reset)(void *cgxd, int lmac_id);
	void                    (*mac_x2p_reset)(void *cgxd, bool enable);
	int			(*mac_enadis_rx)(void *cgxd, int lmac_id, bool enable);
};

struct cgx {
@@ -142,6 +143,10 @@ struct cgx {
	u8			lmac_count;
	/* number of LMACs per MAC could be 4 or 8 */
	u8			max_lmac_per_mac;
	/* length of fifo varies depending on the number
	 * of LMACS
	 */
	u32			fifo_len;
#define MAX_LMAC_COUNT		8
	struct lmac             *lmac_idmap[MAX_LMAC_COUNT];
	struct			work_struct cgx_cmd_work;
+67 −20
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ static struct mac_ops rpm_mac_ops = {
	.mac_get_pfc_frm_cfg   =        rpm_lmac_get_pfc_frm_cfg,
	.mac_reset   =			rpm_lmac_reset,
	.mac_stats_reset		 =	  rpm_stats_reset,
	.mac_x2p_reset                   =        rpm_x2p_reset,
	.mac_enadis_rx			 =        rpm_enadis_rx,
};

static struct mac_ops		rpm2_mac_ops   = {
@@ -72,6 +74,8 @@ static struct mac_ops rpm2_mac_ops = {
	.mac_get_pfc_frm_cfg   =        rpm_lmac_get_pfc_frm_cfg,
	.mac_reset   =			rpm_lmac_reset,
	.mac_stats_reset	    =	rpm_stats_reset,
	.mac_x2p_reset              =   rpm_x2p_reset,
	.mac_enadis_rx		    =   rpm_enadis_rx,
};

bool is_dev_rpm2(void *rpmd)
@@ -467,7 +471,7 @@ u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
	int err;

	req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req);
	err = cgx_fwi_cmd_generic(req, &resp, rpm, 0);
	err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id);
	if (!err)
		return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp);
	return err;
@@ -480,7 +484,7 @@ u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id)
	u8 num_lmacs;
	u32 fifo_len;

	fifo_len = rpm->mac_ops->fifo_len;
	fifo_len = rpm->fifo_len;
	num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm);

	switch (num_lmacs) {
@@ -533,9 +537,9 @@ u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id)
	 */
	max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF;
	if (max_lmac > 4)
		fifo_len = rpm->mac_ops->fifo_len / 2;
		fifo_len = rpm->fifo_len / 2;
	else
		fifo_len = rpm->mac_ops->fifo_len;
		fifo_len = rpm->fifo_len;

	if (lmac_id < 4) {
		num_lmacs = hweight8(lmac_info & 0xF);
@@ -699,46 +703,51 @@ int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
	if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE)
		return 0;

	/* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common
	 * for all counters. Acquire lock to ensure serialized reads
	 */
	mutex_lock(&rpm->lock);
	if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) {
		val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_CCW_LO);
		val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
		val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id));
		val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
		rsp->fec_corr_blks = (val_hi << 16 | val_lo);

		val_lo = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_VL0_NCCW_LO);
		val_hi = rpm_read(rpm, lmac_id, RPMX_MTI_FCFECX_CW_HI);
		val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id));
		val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id));
		rsp->fec_uncorr_blks = (val_hi << 16 | val_lo);

		/* 50G uses 2 Physical serdes lines */
		if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id ==
		    LMAC_MODE_50G_R) {
			val_lo = rpm_read(rpm, lmac_id,
					  RPMX_MTI_FCFECX_VL1_CCW_LO);
			val_hi = rpm_read(rpm, lmac_id,
					  RPMX_MTI_FCFECX_CW_HI);
			val_lo = rpm_read(rpm, 0,
					  RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id));
			val_hi = rpm_read(rpm, 0,
					  RPMX_MTI_FCFECX_CW_HI(lmac_id));
			rsp->fec_corr_blks += (val_hi << 16 | val_lo);

			val_lo = rpm_read(rpm, lmac_id,
					  RPMX_MTI_FCFECX_VL1_NCCW_LO);
			val_hi = rpm_read(rpm, lmac_id,
					  RPMX_MTI_FCFECX_CW_HI);
			val_lo = rpm_read(rpm, 0,
					  RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id));
			val_hi = rpm_read(rpm, 0,
					  RPMX_MTI_FCFECX_CW_HI(lmac_id));
			rsp->fec_uncorr_blks += (val_hi << 16 | val_lo);
		}
	} else {
		/* enable RS-FEC capture */
		cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL);
		cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL);
		cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id);
		rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg);
		rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg);

		val_lo = rpm_read(rpm, 0,
				  RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2);
		val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
		val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
		rsp->fec_corr_blks = (val_hi << 32 | val_lo);

		val_lo = rpm_read(rpm, 0,
				  RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3);
		val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
		val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC);
		rsp->fec_uncorr_blks = (val_hi << 32 | val_lo);
	}
	mutex_unlock(&rpm->lock);

	return 0;
}
@@ -763,3 +772,41 @@ int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr)

	return 0;
}

void rpm_x2p_reset(void *rpmd, bool enable)
{
	rpm_t *rpm = rpmd;
	int lmac_id;
	u64 cfg;

	if (enable) {
		for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac)
			rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false);

		usleep_range(1000, 2000);

		cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
		rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET);
	} else {
		cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG);
		cfg &= ~RPM_NIX0_RESET;
		rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg);
	}
}

int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable)
{
	rpm_t *rpm = rpmd;
	u64 cfg;

	if (!is_lmac_valid(rpm, lmac_id))
		return -ENODEV;

	cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
	if (enable)
		cfg |= RPM_RX_EN;
	else
		cfg &= ~RPM_RX_EN;
	rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
	return 0;
}
+12 −6
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@

/* Registers */
#define RPMX_CMRX_CFG			0x00
#define RPMX_CMR_GLOBAL_CFG		0x08
#define RPM_NIX0_RESET			BIT_ULL(3)
#define RPMX_RX_TS_PREPEND              BIT_ULL(22)
#define RPMX_TX_PTP_1S_SUPPORT          BIT_ULL(17)
#define RPMX_CMRX_RX_ID_MAP		0x80
@@ -84,16 +86,18 @@
/* FEC stats */
#define RPMX_MTI_STAT_STATN_CONTROL			0x10018
#define RPMX_MTI_STAT_DATA_HI_CDC			0x10038
#define RPMX_RSFEC_RX_CAPTURE				BIT_ULL(27)
#define RPMX_RSFEC_RX_CAPTURE				BIT_ULL(28)
#define RPMX_CMD_CLEAR_RX				BIT_ULL(30)
#define RPMX_CMD_CLEAR_TX				BIT_ULL(31)
#define RPMX_MTI_RSFEC_STAT_STATN_CONTROL               0x40018
#define RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC            0x40000
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2		0x40050
#define RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3		0x40058
#define RPMX_MTI_FCFECX_VL0_CCW_LO			0x38618
#define RPMX_MTI_FCFECX_VL0_NCCW_LO			0x38620
#define RPMX_MTI_FCFECX_VL1_CCW_LO			0x38628
#define RPMX_MTI_FCFECX_VL1_NCCW_LO			0x38630
#define RPMX_MTI_FCFECX_CW_HI				0x38638
#define RPMX_MTI_FCFECX_VL0_CCW_LO(a)			(0x38618 + ((a) * 0x40))
#define RPMX_MTI_FCFECX_VL0_NCCW_LO(a)			(0x38620 + ((a) * 0x40))
#define RPMX_MTI_FCFECX_VL1_CCW_LO(a)			(0x38628 + ((a) * 0x40))
#define RPMX_MTI_FCFECX_VL1_NCCW_LO(a)			(0x38630 + ((a) * 0x40))
#define RPMX_MTI_FCFECX_CW_HI(a)			(0x38638 + ((a) * 0x40))

/* CN10KB CSR Declaration */
#define  RPM2_CMRX_SW_INT				0x1b0
@@ -137,4 +141,6 @@ bool is_dev_rpm2(void *rpmd);
int rpm_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp);
int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr);
int rpm_stats_reset(void *rpmd, int lmac_id);
void rpm_x2p_reset(void *rpmd, bool enable);
int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable);
#endif /* RPM_H */
Loading