Commit 762ca6ee authored by Hariprasad Kelam's avatar Hariprasad Kelam Committed by Paolo Abeni
Browse files

octeontx2-af: Quiesce traffic before NIX block reset



During initialization, the AF driver resets all blocks. The RPM (MAC)
block and NIX block operate on a credit-based model. When the NIX block
resets during active traffic flow, it doesn't release credits to the RPM
block. This causes the RPM FIFO to overflow, leading to receive traffic
struck.

To address this issue, the patch introduces the following changes:
1. Stop receiving traffic at the MAC level during AF driver
   initialization.
2. Perform an X2P reset (prevents RXFIFO of all LMACS from pushing data)
3. Reset the NIX block.
4. Clear the X2P reset and re-enable receiving traffic.

Fixes: 54d55781 ("octeontx2-af: Reset all RVU blocks")
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 6fc21641
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -214,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
@@ -1724,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:
@@ -1789,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,
@@ -1820,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)
+4 −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
+2 −0
Original line number Diff line number Diff line
@@ -132,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 {
+42 −0
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)
@@ -768,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;
}
+4 −0
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
@@ -139,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