162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Marvell MCS driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2022 Marvell.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/delay.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/module.h>
1162306a36Sopenharmony_ci#include <linux/pci.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "mcs.h"
1462306a36Sopenharmony_ci#include "mcs_reg.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define DRV_NAME	"Marvell MCS Driver"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define PCI_CFG_REG_BAR_NUM	0
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic const struct pci_device_id mcs_id_table[] = {
2162306a36Sopenharmony_ci	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CN10K_MCS) },
2262306a36Sopenharmony_ci	{ 0, }  /* end of table */
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic LIST_HEAD(mcs_list);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_civoid mcs_get_tx_secy_stats(struct mcs *mcs, struct mcs_secy_stats *stats, int id)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	u64 reg;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTCTLBCPKTSX(id);
3262306a36Sopenharmony_ci	stats->ctl_pkt_bcast_cnt = mcs_reg_read(mcs, reg);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTCTLMCPKTSX(id);
3562306a36Sopenharmony_ci	stats->ctl_pkt_mcast_cnt = mcs_reg_read(mcs, reg);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTCTLOCTETSX(id);
3862306a36Sopenharmony_ci	stats->ctl_octet_cnt = mcs_reg_read(mcs, reg);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTCTLUCPKTSX(id);
4162306a36Sopenharmony_ci	stats->ctl_pkt_ucast_cnt = mcs_reg_read(mcs, reg);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTUNCTLBCPKTSX(id);
4462306a36Sopenharmony_ci	stats->unctl_pkt_bcast_cnt = mcs_reg_read(mcs, reg);
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTUNCTLMCPKTSX(id);
4762306a36Sopenharmony_ci	stats->unctl_pkt_mcast_cnt = mcs_reg_read(mcs, reg);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTUNCTLOCTETSX(id);
5062306a36Sopenharmony_ci	stats->unctl_octet_cnt = mcs_reg_read(mcs, reg);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_IFOUTUNCTLUCPKTSX(id);
5362306a36Sopenharmony_ci	stats->unctl_pkt_ucast_cnt = mcs_reg_read(mcs, reg);
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_OUTOCTETSSECYENCRYPTEDX(id);
5662306a36Sopenharmony_ci	stats->octet_encrypted_cnt =  mcs_reg_read(mcs, reg);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_OUTOCTETSSECYPROTECTEDX(id);
5962306a36Sopenharmony_ci	stats->octet_protected_cnt =  mcs_reg_read(mcs, reg);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSECYNOACTIVESAX(id);
6262306a36Sopenharmony_ci	stats->pkt_noactivesa_cnt =  mcs_reg_read(mcs, reg);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSECYTOOLONGX(id);
6562306a36Sopenharmony_ci	stats->pkt_toolong_cnt =  mcs_reg_read(mcs, reg);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSECYUNTAGGEDX(id);
6862306a36Sopenharmony_ci	stats->pkt_untagged_cnt =  mcs_reg_read(mcs, reg);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_civoid mcs_get_rx_secy_stats(struct mcs *mcs, struct mcs_secy_stats *stats, int id)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	u64 reg;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINCTLBCPKTSX(id);
7662306a36Sopenharmony_ci	stats->ctl_pkt_bcast_cnt = mcs_reg_read(mcs, reg);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINCTLMCPKTSX(id);
7962306a36Sopenharmony_ci	stats->ctl_pkt_mcast_cnt = mcs_reg_read(mcs, reg);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINCTLOCTETSX(id);
8262306a36Sopenharmony_ci	stats->ctl_octet_cnt = mcs_reg_read(mcs, reg);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINCTLUCPKTSX(id);
8562306a36Sopenharmony_ci	stats->ctl_pkt_ucast_cnt = mcs_reg_read(mcs, reg);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINUNCTLBCPKTSX(id);
8862306a36Sopenharmony_ci	stats->unctl_pkt_bcast_cnt = mcs_reg_read(mcs, reg);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINUNCTLMCPKTSX(id);
9162306a36Sopenharmony_ci	stats->unctl_pkt_mcast_cnt = mcs_reg_read(mcs, reg);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINUNCTLOCTETSX(id);
9462306a36Sopenharmony_ci	stats->unctl_octet_cnt = mcs_reg_read(mcs, reg);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_IFINUNCTLUCPKTSX(id);
9762306a36Sopenharmony_ci	stats->unctl_pkt_ucast_cnt = mcs_reg_read(mcs, reg);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INOCTETSSECYDECRYPTEDX(id);
10062306a36Sopenharmony_ci	stats->octet_decrypted_cnt =  mcs_reg_read(mcs, reg);
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INOCTETSSECYVALIDATEX(id);
10362306a36Sopenharmony_ci	stats->octet_validated_cnt =  mcs_reg_read(mcs, reg);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSCTRLPORTDISABLEDX(id);
10662306a36Sopenharmony_ci	stats->pkt_port_disabled_cnt =  mcs_reg_read(mcs, reg);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYBADTAGX(id);
10962306a36Sopenharmony_ci	stats->pkt_badtag_cnt =  mcs_reg_read(mcs, reg);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYNOSAX(id);
11262306a36Sopenharmony_ci	stats->pkt_nosa_cnt = mcs_reg_read(mcs, reg);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYNOSAERRORX(id);
11562306a36Sopenharmony_ci	stats->pkt_nosaerror_cnt = mcs_reg_read(mcs, reg);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYTAGGEDCTLX(id);
11862306a36Sopenharmony_ci	stats->pkt_tagged_ctl_cnt = mcs_reg_read(mcs, reg);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYUNTAGGEDX(id);
12162306a36Sopenharmony_ci	stats->pkt_untaged_cnt = mcs_reg_read(mcs, reg);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYCTLX(id);
12462306a36Sopenharmony_ci	stats->pkt_ctl_cnt = mcs_reg_read(mcs, reg);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1) {
12762306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSECYNOTAGX(id);
12862306a36Sopenharmony_ci		stats->pkt_notag_cnt = mcs_reg_read(mcs, reg);
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_civoid mcs_get_flowid_stats(struct mcs *mcs, struct mcs_flowid_stats *stats,
13362306a36Sopenharmony_ci			  int id, int dir)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	u64 reg;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (dir == MCS_RX)
13862306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSFLOWIDTCAMHITX(id);
13962306a36Sopenharmony_ci	else
14062306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSFLOWIDTCAMHITX(id);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	stats->tcam_hit_cnt = mcs_reg_read(mcs, reg);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_civoid mcs_get_port_stats(struct mcs *mcs, struct mcs_port_stats *stats,
14662306a36Sopenharmony_ci			int id, int dir)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	u64 reg;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if (dir == MCS_RX) {
15162306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSFLOWIDTCAMMISSX(id);
15262306a36Sopenharmony_ci		stats->tcam_miss_cnt = mcs_reg_read(mcs, reg);
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSPARSEERRX(id);
15562306a36Sopenharmony_ci		stats->parser_err_cnt = mcs_reg_read(mcs, reg);
15662306a36Sopenharmony_ci		if (mcs->hw->mcs_blks > 1) {
15762306a36Sopenharmony_ci			reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSEARLYPREEMPTERRX(id);
15862306a36Sopenharmony_ci			stats->preempt_err_cnt = mcs_reg_read(mcs, reg);
15962306a36Sopenharmony_ci		}
16062306a36Sopenharmony_ci	} else {
16162306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSFLOWIDTCAMMISSX(id);
16262306a36Sopenharmony_ci		stats->tcam_miss_cnt = mcs_reg_read(mcs, reg);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSPARSEERRX(id);
16562306a36Sopenharmony_ci		stats->parser_err_cnt = mcs_reg_read(mcs, reg);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSECTAGINSERTIONERRX(id);
16862306a36Sopenharmony_ci		stats->sectag_insert_err_cnt = mcs_reg_read(mcs, reg);
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_civoid mcs_get_sa_stats(struct mcs *mcs, struct mcs_sa_stats *stats, int id, int dir)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	u64 reg;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (dir == MCS_RX) {
17762306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSAINVALIDX(id);
17862306a36Sopenharmony_ci		stats->pkt_invalid_cnt = mcs_reg_read(mcs, reg);
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSANOTUSINGSAERRORX(id);
18162306a36Sopenharmony_ci		stats->pkt_nosaerror_cnt = mcs_reg_read(mcs, reg);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSANOTVALIDX(id);
18462306a36Sopenharmony_ci		stats->pkt_notvalid_cnt = mcs_reg_read(mcs, reg);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSAOKX(id);
18762306a36Sopenharmony_ci		stats->pkt_ok_cnt = mcs_reg_read(mcs, reg);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSAUNUSEDSAX(id);
19062306a36Sopenharmony_ci		stats->pkt_nosa_cnt = mcs_reg_read(mcs, reg);
19162306a36Sopenharmony_ci	} else {
19262306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSAENCRYPTEDX(id);
19362306a36Sopenharmony_ci		stats->pkt_encrypt_cnt = mcs_reg_read(mcs, reg);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSAPROTECTEDX(id);
19662306a36Sopenharmony_ci		stats->pkt_protected_cnt = mcs_reg_read(mcs, reg);
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_civoid mcs_get_sc_stats(struct mcs *mcs, struct mcs_sc_stats *stats,
20162306a36Sopenharmony_ci		      int id, int dir)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	u64 reg;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	if (dir == MCS_RX) {
20662306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCCAMHITX(id);
20762306a36Sopenharmony_ci		stats->hit_cnt = mcs_reg_read(mcs, reg);
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCINVALIDX(id);
21062306a36Sopenharmony_ci		stats->pkt_invalid_cnt = mcs_reg_read(mcs, reg);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCLATEORDELAYEDX(id);
21362306a36Sopenharmony_ci		stats->pkt_late_cnt = mcs_reg_read(mcs, reg);
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCNOTVALIDX(id);
21662306a36Sopenharmony_ci		stats->pkt_notvalid_cnt = mcs_reg_read(mcs, reg);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCUNCHECKEDX(id);
21962306a36Sopenharmony_ci		stats->pkt_unchecked_cnt = mcs_reg_read(mcs, reg);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		if (mcs->hw->mcs_blks > 1) {
22262306a36Sopenharmony_ci			reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCDELAYEDX(id);
22362306a36Sopenharmony_ci			stats->pkt_delay_cnt = mcs_reg_read(mcs, reg);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci			reg = MCSX_CSE_RX_MEM_SLAVE_INPKTSSCOKX(id);
22662306a36Sopenharmony_ci			stats->pkt_ok_cnt = mcs_reg_read(mcs, reg);
22762306a36Sopenharmony_ci		}
22862306a36Sopenharmony_ci		if (mcs->hw->mcs_blks == 1) {
22962306a36Sopenharmony_ci			reg = MCSX_CSE_RX_MEM_SLAVE_INOCTETSSCDECRYPTEDX(id);
23062306a36Sopenharmony_ci			stats->octet_decrypt_cnt = mcs_reg_read(mcs, reg);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci			reg = MCSX_CSE_RX_MEM_SLAVE_INOCTETSSCVALIDATEX(id);
23362306a36Sopenharmony_ci			stats->octet_validate_cnt = mcs_reg_read(mcs, reg);
23462306a36Sopenharmony_ci		}
23562306a36Sopenharmony_ci	} else {
23662306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSCENCRYPTEDX(id);
23762306a36Sopenharmony_ci		stats->pkt_encrypt_cnt = mcs_reg_read(mcs, reg);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci		reg = MCSX_CSE_TX_MEM_SLAVE_OUTPKTSSCPROTECTEDX(id);
24062306a36Sopenharmony_ci		stats->pkt_protected_cnt = mcs_reg_read(mcs, reg);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci		if (mcs->hw->mcs_blks == 1) {
24362306a36Sopenharmony_ci			reg = MCSX_CSE_TX_MEM_SLAVE_OUTOCTETSSCENCRYPTEDX(id);
24462306a36Sopenharmony_ci			stats->octet_encrypt_cnt = mcs_reg_read(mcs, reg);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci			reg = MCSX_CSE_TX_MEM_SLAVE_OUTOCTETSSCPROTECTEDX(id);
24762306a36Sopenharmony_ci			stats->octet_protected_cnt = mcs_reg_read(mcs, reg);
24862306a36Sopenharmony_ci		}
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_civoid mcs_clear_stats(struct mcs *mcs, u8 type, u8 id, int dir)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct mcs_flowid_stats flowid_st;
25562306a36Sopenharmony_ci	struct mcs_port_stats port_st;
25662306a36Sopenharmony_ci	struct mcs_secy_stats secy_st;
25762306a36Sopenharmony_ci	struct mcs_sc_stats sc_st;
25862306a36Sopenharmony_ci	struct mcs_sa_stats sa_st;
25962306a36Sopenharmony_ci	u64 reg;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (dir == MCS_RX)
26262306a36Sopenharmony_ci		reg = MCSX_CSE_RX_SLAVE_CTRL;
26362306a36Sopenharmony_ci	else
26462306a36Sopenharmony_ci		reg = MCSX_CSE_TX_SLAVE_CTRL;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, BIT_ULL(0));
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	switch (type) {
26962306a36Sopenharmony_ci	case MCS_FLOWID_STATS:
27062306a36Sopenharmony_ci		mcs_get_flowid_stats(mcs, &flowid_st, id, dir);
27162306a36Sopenharmony_ci		break;
27262306a36Sopenharmony_ci	case MCS_SECY_STATS:
27362306a36Sopenharmony_ci		if (dir == MCS_RX)
27462306a36Sopenharmony_ci			mcs_get_rx_secy_stats(mcs, &secy_st, id);
27562306a36Sopenharmony_ci		else
27662306a36Sopenharmony_ci			mcs_get_tx_secy_stats(mcs, &secy_st, id);
27762306a36Sopenharmony_ci		break;
27862306a36Sopenharmony_ci	case MCS_SC_STATS:
27962306a36Sopenharmony_ci		mcs_get_sc_stats(mcs, &sc_st, id, dir);
28062306a36Sopenharmony_ci		break;
28162306a36Sopenharmony_ci	case MCS_SA_STATS:
28262306a36Sopenharmony_ci		mcs_get_sa_stats(mcs, &sa_st, id, dir);
28362306a36Sopenharmony_ci		break;
28462306a36Sopenharmony_ci	case MCS_PORT_STATS:
28562306a36Sopenharmony_ci		mcs_get_port_stats(mcs, &port_st, id, dir);
28662306a36Sopenharmony_ci		break;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, 0x0);
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ciint mcs_clear_all_stats(struct mcs *mcs, u16 pcifunc, int dir)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	struct mcs_rsrc_map *map;
29562306a36Sopenharmony_ci	int id;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	if (dir == MCS_RX)
29862306a36Sopenharmony_ci		map = &mcs->rx;
29962306a36Sopenharmony_ci	else
30062306a36Sopenharmony_ci		map = &mcs->tx;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	/* Clear FLOWID stats */
30362306a36Sopenharmony_ci	for (id = 0; id < map->flow_ids.max; id++) {
30462306a36Sopenharmony_ci		if (map->flowid2pf_map[id] != pcifunc)
30562306a36Sopenharmony_ci			continue;
30662306a36Sopenharmony_ci		mcs_clear_stats(mcs, MCS_FLOWID_STATS, id, dir);
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/* Clear SECY stats */
31062306a36Sopenharmony_ci	for (id = 0; id < map->secy.max; id++) {
31162306a36Sopenharmony_ci		if (map->secy2pf_map[id] != pcifunc)
31262306a36Sopenharmony_ci			continue;
31362306a36Sopenharmony_ci		mcs_clear_stats(mcs, MCS_SECY_STATS, id, dir);
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* Clear SC stats */
31762306a36Sopenharmony_ci	for (id = 0; id < map->secy.max; id++) {
31862306a36Sopenharmony_ci		if (map->sc2pf_map[id] != pcifunc)
31962306a36Sopenharmony_ci			continue;
32062306a36Sopenharmony_ci		mcs_clear_stats(mcs, MCS_SC_STATS, id, dir);
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* Clear SA stats */
32462306a36Sopenharmony_ci	for (id = 0; id < map->sa.max; id++) {
32562306a36Sopenharmony_ci		if (map->sa2pf_map[id] != pcifunc)
32662306a36Sopenharmony_ci			continue;
32762306a36Sopenharmony_ci		mcs_clear_stats(mcs, MCS_SA_STATS, id, dir);
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci	return 0;
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_civoid mcs_pn_table_write(struct mcs *mcs, u8 pn_id, u64 next_pn, u8 dir)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	u64 reg;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	if (dir == MCS_RX)
33762306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_SA_PN_TABLE_MEMX(pn_id);
33862306a36Sopenharmony_ci	else
33962306a36Sopenharmony_ci		reg = MCSX_CPM_TX_SLAVE_SA_PN_TABLE_MEMX(pn_id);
34062306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, next_pn);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_civoid cn10kb_mcs_tx_sa_mem_map_write(struct mcs *mcs, struct mcs_tx_sc_sa_map *map)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	u64 reg, val;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	val = (map->sa_index0 & 0xFF) |
34862306a36Sopenharmony_ci	      (map->sa_index1 & 0xFF) << 9 |
34962306a36Sopenharmony_ci	      (map->rekey_ena & 0x1) << 18 |
35062306a36Sopenharmony_ci	      (map->sa_index0_vld & 0x1) << 19 |
35162306a36Sopenharmony_ci	      (map->sa_index1_vld & 0x1) << 20 |
35262306a36Sopenharmony_ci	      (map->tx_sa_active & 0x1) << 21 |
35362306a36Sopenharmony_ci	      map->sectag_sci << 22;
35462306a36Sopenharmony_ci	reg = MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(map->sc_id);
35562306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	val = map->sectag_sci >> 42;
35862306a36Sopenharmony_ci	reg = MCSX_CPM_TX_SLAVE_SA_MAP_MEM_1X(map->sc_id);
35962306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_civoid cn10kb_mcs_rx_sa_mem_map_write(struct mcs *mcs, struct mcs_rx_sc_sa_map *map)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	u64 val, reg;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	val = (map->sa_index & 0xFF) | map->sa_in_use << 9;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	reg = MCSX_CPM_RX_SLAVE_SA_MAP_MEMX((4 * map->sc_id) + map->an);
36962306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_civoid mcs_sa_plcy_write(struct mcs *mcs, u64 *plcy, int sa_id, int dir)
37362306a36Sopenharmony_ci{
37462306a36Sopenharmony_ci	int reg_id;
37562306a36Sopenharmony_ci	u64 reg;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (dir == MCS_RX) {
37862306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 8; reg_id++) {
37962306a36Sopenharmony_ci			reg =  MCSX_CPM_RX_SLAVE_SA_PLCY_MEMX(reg_id, sa_id);
38062306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, plcy[reg_id]);
38162306a36Sopenharmony_ci		}
38262306a36Sopenharmony_ci	} else {
38362306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 9; reg_id++) {
38462306a36Sopenharmony_ci			reg =  MCSX_CPM_TX_SLAVE_SA_PLCY_MEMX(reg_id, sa_id);
38562306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, plcy[reg_id]);
38662306a36Sopenharmony_ci		}
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_civoid mcs_ena_dis_sc_cam_entry(struct mcs *mcs, int sc_id, int ena)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	u64 reg, val;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	reg = MCSX_CPM_RX_SLAVE_SC_CAM_ENA(0);
39562306a36Sopenharmony_ci	if (sc_id > 63)
39662306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_SC_CAM_ENA(1);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	if (ena)
39962306a36Sopenharmony_ci		val = mcs_reg_read(mcs, reg) | BIT_ULL(sc_id);
40062306a36Sopenharmony_ci	else
40162306a36Sopenharmony_ci		val = mcs_reg_read(mcs, reg) & ~BIT_ULL(sc_id);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_civoid mcs_rx_sc_cam_write(struct mcs *mcs, u64 sci, u64 secy, int sc_id)
40762306a36Sopenharmony_ci{
40862306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CPM_RX_SLAVE_SC_CAMX(0, sc_id), sci);
40962306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CPM_RX_SLAVE_SC_CAMX(1, sc_id), secy);
41062306a36Sopenharmony_ci	/* Enable SC CAM */
41162306a36Sopenharmony_ci	mcs_ena_dis_sc_cam_entry(mcs, sc_id, true);
41262306a36Sopenharmony_ci}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_civoid mcs_secy_plcy_write(struct mcs *mcs, u64 plcy, int secy_id, int dir)
41562306a36Sopenharmony_ci{
41662306a36Sopenharmony_ci	u64 reg;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (dir == MCS_RX)
41962306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_SECY_PLCY_MEM_0X(secy_id);
42062306a36Sopenharmony_ci	else
42162306a36Sopenharmony_ci		reg = MCSX_CPM_TX_SLAVE_SECY_PLCY_MEMX(secy_id);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, plcy);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	if (mcs->hw->mcs_blks == 1 && dir == MCS_RX)
42662306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_CPM_RX_SLAVE_SECY_PLCY_MEM_1X(secy_id), 0x0ull);
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_civoid cn10kb_mcs_flowid_secy_map(struct mcs *mcs, struct secy_mem_map *map, int dir)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	u64 reg, val;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	val = (map->secy & 0x7F) | (map->ctrl_pkt & 0x1) << 8;
43462306a36Sopenharmony_ci	if (dir == MCS_RX) {
43562306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_SECY_MAP_MEMX(map->flow_id);
43662306a36Sopenharmony_ci	} else {
43762306a36Sopenharmony_ci		val |= (map->sc & 0x7F) << 9;
43862306a36Sopenharmony_ci		reg = MCSX_CPM_TX_SLAVE_SECY_MAP_MEM_0X(map->flow_id);
43962306a36Sopenharmony_ci	}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_civoid mcs_ena_dis_flowid_entry(struct mcs *mcs, int flow_id, int dir, int ena)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	u64 reg, val;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (dir == MCS_RX) {
44962306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_FLOWID_TCAM_ENA_0;
45062306a36Sopenharmony_ci		if (flow_id > 63)
45162306a36Sopenharmony_ci			reg = MCSX_CPM_RX_SLAVE_FLOWID_TCAM_ENA_1;
45262306a36Sopenharmony_ci	} else {
45362306a36Sopenharmony_ci		reg = MCSX_CPM_TX_SLAVE_FLOWID_TCAM_ENA_0;
45462306a36Sopenharmony_ci		if (flow_id > 63)
45562306a36Sopenharmony_ci			reg = MCSX_CPM_TX_SLAVE_FLOWID_TCAM_ENA_1;
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	/* Enable/Disable the tcam entry */
45962306a36Sopenharmony_ci	if (ena)
46062306a36Sopenharmony_ci		val = mcs_reg_read(mcs, reg) | BIT_ULL(flow_id);
46162306a36Sopenharmony_ci	else
46262306a36Sopenharmony_ci		val = mcs_reg_read(mcs, reg) & ~BIT_ULL(flow_id);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
46562306a36Sopenharmony_ci}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_civoid mcs_flowid_entry_write(struct mcs *mcs, u64 *data, u64 *mask, int flow_id, int dir)
46862306a36Sopenharmony_ci{
46962306a36Sopenharmony_ci	int reg_id;
47062306a36Sopenharmony_ci	u64 reg;
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	if (dir == MCS_RX) {
47362306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 4; reg_id++) {
47462306a36Sopenharmony_ci			reg = MCSX_CPM_RX_SLAVE_FLOWID_TCAM_DATAX(reg_id, flow_id);
47562306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, data[reg_id]);
47662306a36Sopenharmony_ci		}
47762306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 4; reg_id++) {
47862306a36Sopenharmony_ci			reg = MCSX_CPM_RX_SLAVE_FLOWID_TCAM_MASKX(reg_id, flow_id);
47962306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, mask[reg_id]);
48062306a36Sopenharmony_ci		}
48162306a36Sopenharmony_ci	} else {
48262306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 4; reg_id++) {
48362306a36Sopenharmony_ci			reg = MCSX_CPM_TX_SLAVE_FLOWID_TCAM_DATAX(reg_id, flow_id);
48462306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, data[reg_id]);
48562306a36Sopenharmony_ci		}
48662306a36Sopenharmony_ci		for (reg_id = 0; reg_id < 4; reg_id++) {
48762306a36Sopenharmony_ci			reg = MCSX_CPM_TX_SLAVE_FLOWID_TCAM_MASKX(reg_id, flow_id);
48862306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, mask[reg_id]);
48962306a36Sopenharmony_ci		}
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ciint mcs_install_flowid_bypass_entry(struct mcs *mcs)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	int flow_id, secy_id, reg_id;
49662306a36Sopenharmony_ci	struct secy_mem_map map;
49762306a36Sopenharmony_ci	u64 reg, plcy = 0;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	/* Flow entry */
50062306a36Sopenharmony_ci	flow_id = mcs->hw->tcam_entries - MCS_RSRC_RSVD_CNT;
50162306a36Sopenharmony_ci	__set_bit(flow_id, mcs->rx.flow_ids.bmap);
50262306a36Sopenharmony_ci	__set_bit(flow_id, mcs->tx.flow_ids.bmap);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	for (reg_id = 0; reg_id < 4; reg_id++) {
50562306a36Sopenharmony_ci		reg = MCSX_CPM_RX_SLAVE_FLOWID_TCAM_MASKX(reg_id, flow_id);
50662306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, GENMASK_ULL(63, 0));
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci	for (reg_id = 0; reg_id < 4; reg_id++) {
50962306a36Sopenharmony_ci		reg = MCSX_CPM_TX_SLAVE_FLOWID_TCAM_MASKX(reg_id, flow_id);
51062306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, GENMASK_ULL(63, 0));
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci	/* secy */
51362306a36Sopenharmony_ci	secy_id = mcs->hw->secy_entries - MCS_RSRC_RSVD_CNT;
51462306a36Sopenharmony_ci	__set_bit(secy_id, mcs->rx.secy.bmap);
51562306a36Sopenharmony_ci	__set_bit(secy_id, mcs->tx.secy.bmap);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	/* Set validate frames to NULL and enable control port */
51862306a36Sopenharmony_ci	plcy = 0x7ull;
51962306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1)
52062306a36Sopenharmony_ci		plcy = BIT_ULL(0) | 0x3ull << 4;
52162306a36Sopenharmony_ci	mcs_secy_plcy_write(mcs, plcy, secy_id, MCS_RX);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* Enable control port and set mtu to max */
52462306a36Sopenharmony_ci	plcy = BIT_ULL(0) | GENMASK_ULL(43, 28);
52562306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1)
52662306a36Sopenharmony_ci		plcy = BIT_ULL(0) | GENMASK_ULL(63, 48);
52762306a36Sopenharmony_ci	mcs_secy_plcy_write(mcs, plcy, secy_id, MCS_TX);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	/* Map flowid to secy */
53062306a36Sopenharmony_ci	map.secy = secy_id;
53162306a36Sopenharmony_ci	map.ctrl_pkt = 0;
53262306a36Sopenharmony_ci	map.flow_id = flow_id;
53362306a36Sopenharmony_ci	mcs->mcs_ops->mcs_flowid_secy_map(mcs, &map, MCS_RX);
53462306a36Sopenharmony_ci	map.sc = secy_id;
53562306a36Sopenharmony_ci	mcs->mcs_ops->mcs_flowid_secy_map(mcs, &map, MCS_TX);
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	/* Enable Flowid entry */
53862306a36Sopenharmony_ci	mcs_ena_dis_flowid_entry(mcs, flow_id, MCS_RX, true);
53962306a36Sopenharmony_ci	mcs_ena_dis_flowid_entry(mcs, flow_id, MCS_TX, true);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	return 0;
54262306a36Sopenharmony_ci}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_civoid mcs_clear_secy_plcy(struct mcs *mcs, int secy_id, int dir)
54562306a36Sopenharmony_ci{
54662306a36Sopenharmony_ci	struct mcs_rsrc_map *map;
54762306a36Sopenharmony_ci	int flow_id;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	if (dir == MCS_RX)
55062306a36Sopenharmony_ci		map = &mcs->rx;
55162306a36Sopenharmony_ci	else
55262306a36Sopenharmony_ci		map = &mcs->tx;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* Clear secy memory to zero */
55562306a36Sopenharmony_ci	mcs_secy_plcy_write(mcs, 0, secy_id, dir);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	/* Disable the tcam entry using this secy */
55862306a36Sopenharmony_ci	for (flow_id = 0; flow_id < map->flow_ids.max; flow_id++) {
55962306a36Sopenharmony_ci		if (map->flowid2secy_map[flow_id] != secy_id)
56062306a36Sopenharmony_ci			continue;
56162306a36Sopenharmony_ci		mcs_ena_dis_flowid_entry(mcs, flow_id, dir, false);
56262306a36Sopenharmony_ci	}
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ciint mcs_alloc_ctrlpktrule(struct rsrc_bmap *rsrc, u16 *pf_map, u16 offset, u16 pcifunc)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	int rsrc_id;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (!rsrc->bmap)
57062306a36Sopenharmony_ci		return -EINVAL;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	rsrc_id = bitmap_find_next_zero_area(rsrc->bmap, rsrc->max, offset, 1, 0);
57362306a36Sopenharmony_ci	if (rsrc_id >= rsrc->max)
57462306a36Sopenharmony_ci		return -ENOSPC;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	bitmap_set(rsrc->bmap, rsrc_id, 1);
57762306a36Sopenharmony_ci	pf_map[rsrc_id] = pcifunc;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	return rsrc_id;
58062306a36Sopenharmony_ci}
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ciint mcs_free_ctrlpktrule(struct mcs *mcs, struct mcs_free_ctrl_pkt_rule_req *req)
58362306a36Sopenharmony_ci{
58462306a36Sopenharmony_ci	u16 pcifunc = req->hdr.pcifunc;
58562306a36Sopenharmony_ci	struct mcs_rsrc_map *map;
58662306a36Sopenharmony_ci	u64 dis, reg;
58762306a36Sopenharmony_ci	int id, rc;
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_RULE_ENABLE : MCSX_PEX_TX_SLAVE_RULE_ENABLE;
59062306a36Sopenharmony_ci	map = (req->dir == MCS_RX) ? &mcs->rx : &mcs->tx;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	if (req->all) {
59362306a36Sopenharmony_ci		for (id = 0; id < map->ctrlpktrule.max; id++) {
59462306a36Sopenharmony_ci			if (map->ctrlpktrule2pf_map[id] != pcifunc)
59562306a36Sopenharmony_ci				continue;
59662306a36Sopenharmony_ci			mcs_free_rsrc(&map->ctrlpktrule, map->ctrlpktrule2pf_map, id, pcifunc);
59762306a36Sopenharmony_ci			dis = mcs_reg_read(mcs, reg);
59862306a36Sopenharmony_ci			dis &= ~BIT_ULL(id);
59962306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, dis);
60062306a36Sopenharmony_ci		}
60162306a36Sopenharmony_ci		return 0;
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	rc = mcs_free_rsrc(&map->ctrlpktrule, map->ctrlpktrule2pf_map, req->rule_idx, pcifunc);
60562306a36Sopenharmony_ci	dis = mcs_reg_read(mcs, reg);
60662306a36Sopenharmony_ci	dis &= ~BIT_ULL(req->rule_idx);
60762306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, dis);
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	return rc;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ciint mcs_ctrlpktrule_write(struct mcs *mcs, struct mcs_ctrl_pkt_rule_write_req *req)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	u64 reg, enb;
61562306a36Sopenharmony_ci	u64 idx;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	switch (req->rule_type) {
61862306a36Sopenharmony_ci	case MCS_CTRL_PKT_RULE_TYPE_ETH:
61962306a36Sopenharmony_ci		req->data0 &= GENMASK(15, 0);
62062306a36Sopenharmony_ci		if (req->data0 != ETH_P_PAE)
62162306a36Sopenharmony_ci			return -EINVAL;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci		idx = req->rule_idx - MCS_CTRLPKT_ETYPE_RULE_OFFSET;
62462306a36Sopenharmony_ci		reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_RULE_ETYPE_CFGX(idx) :
62562306a36Sopenharmony_ci		      MCSX_PEX_TX_SLAVE_RULE_ETYPE_CFGX(idx);
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, req->data0);
62862306a36Sopenharmony_ci		break;
62962306a36Sopenharmony_ci	case MCS_CTRL_PKT_RULE_TYPE_DA:
63062306a36Sopenharmony_ci		if (!(req->data0 & BIT_ULL(40)))
63162306a36Sopenharmony_ci			return -EINVAL;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci		idx = req->rule_idx - MCS_CTRLPKT_DA_RULE_OFFSET;
63462306a36Sopenharmony_ci		reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_RULE_DAX(idx) :
63562306a36Sopenharmony_ci		      MCSX_PEX_TX_SLAVE_RULE_DAX(idx);
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
63862306a36Sopenharmony_ci		break;
63962306a36Sopenharmony_ci	case MCS_CTRL_PKT_RULE_TYPE_RANGE:
64062306a36Sopenharmony_ci		if (!(req->data0 & BIT_ULL(40)) || !(req->data1 & BIT_ULL(40)))
64162306a36Sopenharmony_ci			return -EINVAL;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci		idx = req->rule_idx - MCS_CTRLPKT_DA_RANGE_RULE_OFFSET;
64462306a36Sopenharmony_ci		if (req->dir == MCS_RX) {
64562306a36Sopenharmony_ci			reg = MCSX_PEX_RX_SLAVE_RULE_DA_RANGE_MINX(idx);
64662306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
64762306a36Sopenharmony_ci			reg = MCSX_PEX_RX_SLAVE_RULE_DA_RANGE_MAXX(idx);
64862306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data1 & GENMASK_ULL(47, 0));
64962306a36Sopenharmony_ci		} else {
65062306a36Sopenharmony_ci			reg = MCSX_PEX_TX_SLAVE_RULE_DA_RANGE_MINX(idx);
65162306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
65262306a36Sopenharmony_ci			reg = MCSX_PEX_TX_SLAVE_RULE_DA_RANGE_MAXX(idx);
65362306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data1 & GENMASK_ULL(47, 0));
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci		break;
65662306a36Sopenharmony_ci	case MCS_CTRL_PKT_RULE_TYPE_COMBO:
65762306a36Sopenharmony_ci		req->data2 &= GENMASK(15, 0);
65862306a36Sopenharmony_ci		if (req->data2 != ETH_P_PAE || !(req->data0 & BIT_ULL(40)) ||
65962306a36Sopenharmony_ci		    !(req->data1 & BIT_ULL(40)))
66062306a36Sopenharmony_ci			return -EINVAL;
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci		idx = req->rule_idx - MCS_CTRLPKT_COMBO_RULE_OFFSET;
66362306a36Sopenharmony_ci		if (req->dir == MCS_RX) {
66462306a36Sopenharmony_ci			reg = MCSX_PEX_RX_SLAVE_RULE_COMBO_MINX(idx);
66562306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
66662306a36Sopenharmony_ci			reg = MCSX_PEX_RX_SLAVE_RULE_COMBO_MAXX(idx);
66762306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data1 & GENMASK_ULL(47, 0));
66862306a36Sopenharmony_ci			reg = MCSX_PEX_RX_SLAVE_RULE_COMBO_ETX(idx);
66962306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data2);
67062306a36Sopenharmony_ci		} else {
67162306a36Sopenharmony_ci			reg = MCSX_PEX_TX_SLAVE_RULE_COMBO_MINX(idx);
67262306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
67362306a36Sopenharmony_ci			reg = MCSX_PEX_TX_SLAVE_RULE_COMBO_MAXX(idx);
67462306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data1 & GENMASK_ULL(47, 0));
67562306a36Sopenharmony_ci			reg = MCSX_PEX_TX_SLAVE_RULE_COMBO_ETX(idx);
67662306a36Sopenharmony_ci			mcs_reg_write(mcs, reg, req->data2);
67762306a36Sopenharmony_ci		}
67862306a36Sopenharmony_ci		break;
67962306a36Sopenharmony_ci	case MCS_CTRL_PKT_RULE_TYPE_MAC:
68062306a36Sopenharmony_ci		if (!(req->data0 & BIT_ULL(40)))
68162306a36Sopenharmony_ci			return -EINVAL;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci		idx = req->rule_idx - MCS_CTRLPKT_MAC_EN_RULE_OFFSET;
68462306a36Sopenharmony_ci		reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_RULE_MAC :
68562306a36Sopenharmony_ci		      MCSX_PEX_TX_SLAVE_RULE_MAC;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, req->data0 & GENMASK_ULL(47, 0));
68862306a36Sopenharmony_ci		break;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_RULE_ENABLE : MCSX_PEX_TX_SLAVE_RULE_ENABLE;
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	enb = mcs_reg_read(mcs, reg);
69462306a36Sopenharmony_ci	enb |= BIT_ULL(req->rule_idx);
69562306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, enb);
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	return 0;
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ciint mcs_free_rsrc(struct rsrc_bmap *rsrc, u16 *pf_map, int rsrc_id, u16 pcifunc)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	/* Check if the rsrc_id is mapped to PF/VF */
70362306a36Sopenharmony_ci	if (pf_map[rsrc_id] != pcifunc)
70462306a36Sopenharmony_ci		return -EINVAL;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	rvu_free_rsrc(rsrc, rsrc_id);
70762306a36Sopenharmony_ci	pf_map[rsrc_id] = 0;
70862306a36Sopenharmony_ci	return 0;
70962306a36Sopenharmony_ci}
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci/* Free all the cam resources mapped to pf */
71262306a36Sopenharmony_ciint mcs_free_all_rsrc(struct mcs *mcs, int dir, u16 pcifunc)
71362306a36Sopenharmony_ci{
71462306a36Sopenharmony_ci	struct mcs_rsrc_map *map;
71562306a36Sopenharmony_ci	int id;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci	if (dir == MCS_RX)
71862306a36Sopenharmony_ci		map = &mcs->rx;
71962306a36Sopenharmony_ci	else
72062306a36Sopenharmony_ci		map = &mcs->tx;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	/* free tcam entries */
72362306a36Sopenharmony_ci	for (id = 0; id < map->flow_ids.max; id++) {
72462306a36Sopenharmony_ci		if (map->flowid2pf_map[id] != pcifunc)
72562306a36Sopenharmony_ci			continue;
72662306a36Sopenharmony_ci		mcs_free_rsrc(&map->flow_ids, map->flowid2pf_map,
72762306a36Sopenharmony_ci			      id, pcifunc);
72862306a36Sopenharmony_ci		mcs_ena_dis_flowid_entry(mcs, id, dir, false);
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	/* free secy entries */
73262306a36Sopenharmony_ci	for (id = 0; id < map->secy.max; id++) {
73362306a36Sopenharmony_ci		if (map->secy2pf_map[id] != pcifunc)
73462306a36Sopenharmony_ci			continue;
73562306a36Sopenharmony_ci		mcs_free_rsrc(&map->secy, map->secy2pf_map,
73662306a36Sopenharmony_ci			      id, pcifunc);
73762306a36Sopenharmony_ci		mcs_clear_secy_plcy(mcs, id, dir);
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	/* free sc entries */
74162306a36Sopenharmony_ci	for (id = 0; id < map->secy.max; id++) {
74262306a36Sopenharmony_ci		if (map->sc2pf_map[id] != pcifunc)
74362306a36Sopenharmony_ci			continue;
74462306a36Sopenharmony_ci		mcs_free_rsrc(&map->sc, map->sc2pf_map, id, pcifunc);
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci		/* Disable SC CAM only on RX side */
74762306a36Sopenharmony_ci		if (dir == MCS_RX)
74862306a36Sopenharmony_ci			mcs_ena_dis_sc_cam_entry(mcs, id, false);
74962306a36Sopenharmony_ci	}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	/* free sa entries */
75262306a36Sopenharmony_ci	for (id = 0; id < map->sa.max; id++) {
75362306a36Sopenharmony_ci		if (map->sa2pf_map[id] != pcifunc)
75462306a36Sopenharmony_ci			continue;
75562306a36Sopenharmony_ci		mcs_free_rsrc(&map->sa, map->sa2pf_map, id, pcifunc);
75662306a36Sopenharmony_ci	}
75762306a36Sopenharmony_ci	return 0;
75862306a36Sopenharmony_ci}
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ciint mcs_alloc_rsrc(struct rsrc_bmap *rsrc, u16 *pf_map, u16 pcifunc)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	int rsrc_id;
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_ci	rsrc_id = rvu_alloc_rsrc(rsrc);
76562306a36Sopenharmony_ci	if (rsrc_id < 0)
76662306a36Sopenharmony_ci		return -ENOMEM;
76762306a36Sopenharmony_ci	pf_map[rsrc_id] = pcifunc;
76862306a36Sopenharmony_ci	return rsrc_id;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ciint mcs_alloc_all_rsrc(struct mcs *mcs, u8 *flow_id, u8 *secy_id,
77262306a36Sopenharmony_ci		       u8 *sc_id, u8 *sa1_id, u8 *sa2_id, u16 pcifunc, int dir)
77362306a36Sopenharmony_ci{
77462306a36Sopenharmony_ci	struct mcs_rsrc_map *map;
77562306a36Sopenharmony_ci	int id;
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	if (dir == MCS_RX)
77862306a36Sopenharmony_ci		map = &mcs->rx;
77962306a36Sopenharmony_ci	else
78062306a36Sopenharmony_ci		map = &mcs->tx;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	id = mcs_alloc_rsrc(&map->flow_ids, map->flowid2pf_map, pcifunc);
78362306a36Sopenharmony_ci	if (id < 0)
78462306a36Sopenharmony_ci		return -ENOMEM;
78562306a36Sopenharmony_ci	*flow_id = id;
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	id = mcs_alloc_rsrc(&map->secy, map->secy2pf_map, pcifunc);
78862306a36Sopenharmony_ci	if (id < 0)
78962306a36Sopenharmony_ci		return -ENOMEM;
79062306a36Sopenharmony_ci	*secy_id = id;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	id = mcs_alloc_rsrc(&map->sc, map->sc2pf_map, pcifunc);
79362306a36Sopenharmony_ci	if (id < 0)
79462306a36Sopenharmony_ci		return -ENOMEM;
79562306a36Sopenharmony_ci	*sc_id = id;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci	id =  mcs_alloc_rsrc(&map->sa, map->sa2pf_map, pcifunc);
79862306a36Sopenharmony_ci	if (id < 0)
79962306a36Sopenharmony_ci		return -ENOMEM;
80062306a36Sopenharmony_ci	*sa1_id = id;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	id =  mcs_alloc_rsrc(&map->sa, map->sa2pf_map, pcifunc);
80362306a36Sopenharmony_ci	if (id < 0)
80462306a36Sopenharmony_ci		return -ENOMEM;
80562306a36Sopenharmony_ci	*sa2_id = id;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	return 0;
80862306a36Sopenharmony_ci}
80962306a36Sopenharmony_ci
81062306a36Sopenharmony_cistatic void cn10kb_mcs_tx_pn_wrapped_handler(struct mcs *mcs)
81162306a36Sopenharmony_ci{
81262306a36Sopenharmony_ci	struct mcs_intr_event event = { 0 };
81362306a36Sopenharmony_ci	struct rsrc_bmap *sc_bmap;
81462306a36Sopenharmony_ci	u64 val;
81562306a36Sopenharmony_ci	int sc;
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	sc_bmap = &mcs->tx.sc;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	event.mcs_id = mcs->mcs_id;
82062306a36Sopenharmony_ci	event.intr_mask = MCS_CPM_TX_PACKET_XPN_EQ0_INT;
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
82362306a36Sopenharmony_ci		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci		if (mcs->tx_sa_active[sc])
82662306a36Sopenharmony_ci			/* SA_index1 was used and got expired */
82762306a36Sopenharmony_ci			event.sa_id = (val >> 9) & 0xFF;
82862306a36Sopenharmony_ci		else
82962306a36Sopenharmony_ci			/* SA_index0 was used and got expired */
83062306a36Sopenharmony_ci			event.sa_id = val & 0xFF;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
83362306a36Sopenharmony_ci		mcs_add_intr_wq_entry(mcs, &event);
83462306a36Sopenharmony_ci	}
83562306a36Sopenharmony_ci}
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_cistatic void cn10kb_mcs_tx_pn_thresh_reached_handler(struct mcs *mcs)
83862306a36Sopenharmony_ci{
83962306a36Sopenharmony_ci	struct mcs_intr_event event = { 0 };
84062306a36Sopenharmony_ci	struct rsrc_bmap *sc_bmap;
84162306a36Sopenharmony_ci	u64 val, status;
84262306a36Sopenharmony_ci	int sc;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	sc_bmap = &mcs->tx.sc;
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	event.mcs_id = mcs->mcs_id;
84762306a36Sopenharmony_ci	event.intr_mask = MCS_CPM_TX_PN_THRESH_REACHED_INT;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	/* TX SA interrupt is raised only if autorekey is enabled.
85062306a36Sopenharmony_ci	 * MCS_CPM_TX_SLAVE_SA_MAP_MEM_0X[sc].tx_sa_active bit gets toggled if
85162306a36Sopenharmony_ci	 * one of two SAs mapped to SC gets expired. If tx_sa_active=0 implies
85262306a36Sopenharmony_ci	 * SA in SA_index1 got expired else SA in SA_index0 got expired.
85362306a36Sopenharmony_ci	 */
85462306a36Sopenharmony_ci	for_each_set_bit(sc, sc_bmap->bmap, mcs->hw->sc_entries) {
85562306a36Sopenharmony_ci		val = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_SA_MAP_MEM_0X(sc));
85662306a36Sopenharmony_ci		/* Auto rekey is enable */
85762306a36Sopenharmony_ci		if (!((val >> 18) & 0x1))
85862306a36Sopenharmony_ci			continue;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci		status = (val >> 21) & 0x1;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci		/* Check if tx_sa_active status had changed */
86362306a36Sopenharmony_ci		if (status == mcs->tx_sa_active[sc])
86462306a36Sopenharmony_ci			continue;
86562306a36Sopenharmony_ci		/* SA_index0 is expired */
86662306a36Sopenharmony_ci		if (status)
86762306a36Sopenharmony_ci			event.sa_id = val & 0xFF;
86862306a36Sopenharmony_ci		else
86962306a36Sopenharmony_ci			event.sa_id = (val >> 9) & 0xFF;
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci		event.pcifunc = mcs->tx.sa2pf_map[event.sa_id];
87262306a36Sopenharmony_ci		mcs_add_intr_wq_entry(mcs, &event);
87362306a36Sopenharmony_ci	}
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cistatic void mcs_rx_pn_thresh_reached_handler(struct mcs *mcs)
87762306a36Sopenharmony_ci{
87862306a36Sopenharmony_ci	struct mcs_intr_event event = { 0 };
87962306a36Sopenharmony_ci	int sa, reg;
88062306a36Sopenharmony_ci	u64 intr;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci	/* Check expired SAs */
88362306a36Sopenharmony_ci	for (reg = 0; reg < (mcs->hw->sa_entries / 64); reg++) {
88462306a36Sopenharmony_ci		/* Bit high in *PN_THRESH_REACHEDX implies
88562306a36Sopenharmony_ci		 * corresponding SAs are expired.
88662306a36Sopenharmony_ci		 */
88762306a36Sopenharmony_ci		intr = mcs_reg_read(mcs, MCSX_CPM_RX_SLAVE_PN_THRESH_REACHEDX(reg));
88862306a36Sopenharmony_ci		for (sa = 0; sa < 64; sa++) {
88962306a36Sopenharmony_ci			if (!(intr & BIT_ULL(sa)))
89062306a36Sopenharmony_ci				continue;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci			event.mcs_id = mcs->mcs_id;
89362306a36Sopenharmony_ci			event.intr_mask = MCS_CPM_RX_PN_THRESH_REACHED_INT;
89462306a36Sopenharmony_ci			event.sa_id = sa + (reg * 64);
89562306a36Sopenharmony_ci			event.pcifunc = mcs->rx.sa2pf_map[event.sa_id];
89662306a36Sopenharmony_ci			mcs_add_intr_wq_entry(mcs, &event);
89762306a36Sopenharmony_ci		}
89862306a36Sopenharmony_ci	}
89962306a36Sopenharmony_ci}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_cistatic void mcs_rx_misc_intr_handler(struct mcs *mcs, u64 intr)
90262306a36Sopenharmony_ci{
90362306a36Sopenharmony_ci	struct mcs_intr_event event = { 0 };
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	event.mcs_id = mcs->mcs_id;
90662306a36Sopenharmony_ci	event.pcifunc = mcs->pf_map[0];
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_SECTAG_V_EQ1)
90962306a36Sopenharmony_ci		event.intr_mask = MCS_CPM_RX_SECTAG_V_EQ1_INT;
91062306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_SECTAG_E_EQ0_C_EQ1)
91162306a36Sopenharmony_ci		event.intr_mask |= MCS_CPM_RX_SECTAG_E_EQ0_C_EQ1_INT;
91262306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_SL_GTE48)
91362306a36Sopenharmony_ci		event.intr_mask |= MCS_CPM_RX_SECTAG_SL_GTE48_INT;
91462306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_ES_EQ1_SC_EQ1)
91562306a36Sopenharmony_ci		event.intr_mask |= MCS_CPM_RX_SECTAG_ES_EQ1_SC_EQ1_INT;
91662306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_SC_EQ1_SCB_EQ1)
91762306a36Sopenharmony_ci		event.intr_mask |= MCS_CPM_RX_SECTAG_SC_EQ1_SCB_EQ1_INT;
91862306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_PACKET_XPN_EQ0)
91962306a36Sopenharmony_ci		event.intr_mask |= MCS_CPM_RX_PACKET_XPN_EQ0_INT;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	mcs_add_intr_wq_entry(mcs, &event);
92262306a36Sopenharmony_ci}
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_cistatic void mcs_tx_misc_intr_handler(struct mcs *mcs, u64 intr)
92562306a36Sopenharmony_ci{
92662306a36Sopenharmony_ci	struct mcs_intr_event event = { 0 };
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	if (!(intr & MCS_CPM_TX_INT_SA_NOT_VALID))
92962306a36Sopenharmony_ci		return;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	event.mcs_id = mcs->mcs_id;
93262306a36Sopenharmony_ci	event.pcifunc = mcs->pf_map[0];
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci	event.intr_mask = MCS_CPM_TX_SA_NOT_VALID_INT;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	mcs_add_intr_wq_entry(mcs, &event);
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_civoid cn10kb_mcs_bbe_intr_handler(struct mcs *mcs, u64 intr,
94062306a36Sopenharmony_ci				 enum mcs_direction dir)
94162306a36Sopenharmony_ci{
94262306a36Sopenharmony_ci	u64 val, reg;
94362306a36Sopenharmony_ci	int lmac;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	if (!(intr & 0x6ULL))
94662306a36Sopenharmony_ci		return;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	if (intr & BIT_ULL(1))
94962306a36Sopenharmony_ci		reg = (dir == MCS_RX) ? MCSX_BBE_RX_SLAVE_DFIFO_OVERFLOW_0 :
95062306a36Sopenharmony_ci					MCSX_BBE_TX_SLAVE_DFIFO_OVERFLOW_0;
95162306a36Sopenharmony_ci	else
95262306a36Sopenharmony_ci		reg = (dir == MCS_RX) ? MCSX_BBE_RX_SLAVE_PLFIFO_OVERFLOW_0 :
95362306a36Sopenharmony_ci					MCSX_BBE_TX_SLAVE_PLFIFO_OVERFLOW_0;
95462306a36Sopenharmony_ci	val = mcs_reg_read(mcs, reg);
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	/* policy/data over flow occurred */
95762306a36Sopenharmony_ci	for (lmac = 0; lmac < mcs->hw->lmac_cnt; lmac++) {
95862306a36Sopenharmony_ci		if (!(val & BIT_ULL(lmac)))
95962306a36Sopenharmony_ci			continue;
96062306a36Sopenharmony_ci		dev_warn(mcs->dev, "BEE:Policy or data overflow occurred on lmac:%d\n", lmac);
96162306a36Sopenharmony_ci	}
96262306a36Sopenharmony_ci}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_civoid cn10kb_mcs_pab_intr_handler(struct mcs *mcs, u64 intr,
96562306a36Sopenharmony_ci				 enum mcs_direction dir)
96662306a36Sopenharmony_ci{
96762306a36Sopenharmony_ci	int lmac;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (!(intr & 0xFFFFFULL))
97062306a36Sopenharmony_ci		return;
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	for (lmac = 0; lmac < mcs->hw->lmac_cnt; lmac++) {
97362306a36Sopenharmony_ci		if (intr & BIT_ULL(lmac))
97462306a36Sopenharmony_ci			dev_warn(mcs->dev, "PAB: overflow occurred on lmac:%d\n", lmac);
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_cistatic irqreturn_t mcs_ip_intr_handler(int irq, void *mcs_irq)
97962306a36Sopenharmony_ci{
98062306a36Sopenharmony_ci	struct mcs *mcs = (struct mcs *)mcs_irq;
98162306a36Sopenharmony_ci	u64 intr, cpm_intr, bbe_intr, pab_intr;
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	/* Disable  the interrupt */
98462306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_IP_INT_ENA_W1C, BIT_ULL(0));
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	/* Check which block has interrupt*/
98762306a36Sopenharmony_ci	intr = mcs_reg_read(mcs, MCSX_TOP_SLAVE_INT_SUM);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	/* CPM RX */
99062306a36Sopenharmony_ci	if (intr & MCS_CPM_RX_INT_ENA) {
99162306a36Sopenharmony_ci		/* Check for PN thresh interrupt bit */
99262306a36Sopenharmony_ci		cpm_intr = mcs_reg_read(mcs, MCSX_CPM_RX_SLAVE_RX_INT);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci		if (cpm_intr & MCS_CPM_RX_INT_PN_THRESH_REACHED)
99562306a36Sopenharmony_ci			mcs_rx_pn_thresh_reached_handler(mcs);
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci		if (cpm_intr & MCS_CPM_RX_INT_ALL)
99862306a36Sopenharmony_ci			mcs_rx_misc_intr_handler(mcs, cpm_intr);
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci		/* Clear the interrupt */
100162306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_CPM_RX_SLAVE_RX_INT, cpm_intr);
100262306a36Sopenharmony_ci	}
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	/* CPM TX */
100562306a36Sopenharmony_ci	if (intr & MCS_CPM_TX_INT_ENA) {
100662306a36Sopenharmony_ci		cpm_intr = mcs_reg_read(mcs, MCSX_CPM_TX_SLAVE_TX_INT);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci		if (cpm_intr & MCS_CPM_TX_INT_PN_THRESH_REACHED) {
100962306a36Sopenharmony_ci			if (mcs->hw->mcs_blks > 1)
101062306a36Sopenharmony_ci				cnf10kb_mcs_tx_pn_thresh_reached_handler(mcs);
101162306a36Sopenharmony_ci			else
101262306a36Sopenharmony_ci				cn10kb_mcs_tx_pn_thresh_reached_handler(mcs);
101362306a36Sopenharmony_ci		}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci		if (cpm_intr & MCS_CPM_TX_INT_SA_NOT_VALID)
101662306a36Sopenharmony_ci			mcs_tx_misc_intr_handler(mcs, cpm_intr);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci		if (cpm_intr & MCS_CPM_TX_INT_PACKET_XPN_EQ0) {
101962306a36Sopenharmony_ci			if (mcs->hw->mcs_blks > 1)
102062306a36Sopenharmony_ci				cnf10kb_mcs_tx_pn_wrapped_handler(mcs);
102162306a36Sopenharmony_ci			else
102262306a36Sopenharmony_ci				cn10kb_mcs_tx_pn_wrapped_handler(mcs);
102362306a36Sopenharmony_ci		}
102462306a36Sopenharmony_ci		/* Clear the interrupt */
102562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_TX_INT, cpm_intr);
102662306a36Sopenharmony_ci	}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	/* BBE RX */
102962306a36Sopenharmony_ci	if (intr & MCS_BBE_RX_INT_ENA) {
103062306a36Sopenharmony_ci		bbe_intr = mcs_reg_read(mcs, MCSX_BBE_RX_SLAVE_BBE_INT);
103162306a36Sopenharmony_ci		mcs->mcs_ops->mcs_bbe_intr_handler(mcs, bbe_intr, MCS_RX);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci		/* Clear the interrupt */
103462306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_BBE_RX_SLAVE_BBE_INT_INTR_RW, 0);
103562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_BBE_RX_SLAVE_BBE_INT, bbe_intr);
103662306a36Sopenharmony_ci	}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	/* BBE TX */
103962306a36Sopenharmony_ci	if (intr & MCS_BBE_TX_INT_ENA) {
104062306a36Sopenharmony_ci		bbe_intr = mcs_reg_read(mcs, MCSX_BBE_TX_SLAVE_BBE_INT);
104162306a36Sopenharmony_ci		mcs->mcs_ops->mcs_bbe_intr_handler(mcs, bbe_intr, MCS_TX);
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci		/* Clear the interrupt */
104462306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_BBE_TX_SLAVE_BBE_INT_INTR_RW, 0);
104562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_BBE_TX_SLAVE_BBE_INT, bbe_intr);
104662306a36Sopenharmony_ci	}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	/* PAB RX */
104962306a36Sopenharmony_ci	if (intr & MCS_PAB_RX_INT_ENA) {
105062306a36Sopenharmony_ci		pab_intr = mcs_reg_read(mcs, MCSX_PAB_RX_SLAVE_PAB_INT);
105162306a36Sopenharmony_ci		mcs->mcs_ops->mcs_pab_intr_handler(mcs, pab_intr, MCS_RX);
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci		/* Clear the interrupt */
105462306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PAB_RX_SLAVE_PAB_INT_INTR_RW, 0);
105562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PAB_RX_SLAVE_PAB_INT, pab_intr);
105662306a36Sopenharmony_ci	}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	/* PAB TX */
105962306a36Sopenharmony_ci	if (intr & MCS_PAB_TX_INT_ENA) {
106062306a36Sopenharmony_ci		pab_intr = mcs_reg_read(mcs, MCSX_PAB_TX_SLAVE_PAB_INT);
106162306a36Sopenharmony_ci		mcs->mcs_ops->mcs_pab_intr_handler(mcs, pab_intr, MCS_TX);
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci		/* Clear the interrupt */
106462306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PAB_TX_SLAVE_PAB_INT_INTR_RW, 0);
106562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PAB_TX_SLAVE_PAB_INT, pab_intr);
106662306a36Sopenharmony_ci	}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	/* Clear and enable the interrupt */
106962306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_IP_INT, BIT_ULL(0));
107062306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_IP_INT_ENA_W1S, BIT_ULL(0));
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	return IRQ_HANDLED;
107362306a36Sopenharmony_ci}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_cistatic void *alloc_mem(struct mcs *mcs, int n)
107662306a36Sopenharmony_ci{
107762306a36Sopenharmony_ci	return devm_kcalloc(mcs->dev, n, sizeof(u16), GFP_KERNEL);
107862306a36Sopenharmony_ci}
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_cistatic int mcs_alloc_struct_mem(struct mcs *mcs, struct mcs_rsrc_map *res)
108162306a36Sopenharmony_ci{
108262306a36Sopenharmony_ci	struct hwinfo *hw = mcs->hw;
108362306a36Sopenharmony_ci	int err;
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	res->flowid2pf_map = alloc_mem(mcs, hw->tcam_entries);
108662306a36Sopenharmony_ci	if (!res->flowid2pf_map)
108762306a36Sopenharmony_ci		return -ENOMEM;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	res->secy2pf_map = alloc_mem(mcs, hw->secy_entries);
109062306a36Sopenharmony_ci	if (!res->secy2pf_map)
109162306a36Sopenharmony_ci		return -ENOMEM;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	res->sc2pf_map = alloc_mem(mcs, hw->sc_entries);
109462306a36Sopenharmony_ci	if (!res->sc2pf_map)
109562306a36Sopenharmony_ci		return -ENOMEM;
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_ci	res->sa2pf_map = alloc_mem(mcs, hw->sa_entries);
109862306a36Sopenharmony_ci	if (!res->sa2pf_map)
109962306a36Sopenharmony_ci		return -ENOMEM;
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	res->flowid2secy_map = alloc_mem(mcs, hw->tcam_entries);
110262306a36Sopenharmony_ci	if (!res->flowid2secy_map)
110362306a36Sopenharmony_ci		return -ENOMEM;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	res->ctrlpktrule2pf_map = alloc_mem(mcs, MCS_MAX_CTRLPKT_RULES);
110662306a36Sopenharmony_ci	if (!res->ctrlpktrule2pf_map)
110762306a36Sopenharmony_ci		return -ENOMEM;
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci	res->flow_ids.max = hw->tcam_entries - MCS_RSRC_RSVD_CNT;
111062306a36Sopenharmony_ci	err = rvu_alloc_bitmap(&res->flow_ids);
111162306a36Sopenharmony_ci	if (err)
111262306a36Sopenharmony_ci		return err;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	res->secy.max = hw->secy_entries - MCS_RSRC_RSVD_CNT;
111562306a36Sopenharmony_ci	err = rvu_alloc_bitmap(&res->secy);
111662306a36Sopenharmony_ci	if (err)
111762306a36Sopenharmony_ci		return err;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	res->sc.max = hw->sc_entries;
112062306a36Sopenharmony_ci	err = rvu_alloc_bitmap(&res->sc);
112162306a36Sopenharmony_ci	if (err)
112262306a36Sopenharmony_ci		return err;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	res->sa.max = hw->sa_entries;
112562306a36Sopenharmony_ci	err = rvu_alloc_bitmap(&res->sa);
112662306a36Sopenharmony_ci	if (err)
112762306a36Sopenharmony_ci		return err;
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	res->ctrlpktrule.max = MCS_MAX_CTRLPKT_RULES;
113062306a36Sopenharmony_ci	err = rvu_alloc_bitmap(&res->ctrlpktrule);
113162306a36Sopenharmony_ci	if (err)
113262306a36Sopenharmony_ci		return err;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	return 0;
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_cistatic int mcs_register_interrupts(struct mcs *mcs)
113862306a36Sopenharmony_ci{
113962306a36Sopenharmony_ci	int ret = 0;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	mcs->num_vec = pci_msix_vec_count(mcs->pdev);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	ret = pci_alloc_irq_vectors(mcs->pdev, mcs->num_vec,
114462306a36Sopenharmony_ci				    mcs->num_vec, PCI_IRQ_MSIX);
114562306a36Sopenharmony_ci	if (ret < 0) {
114662306a36Sopenharmony_ci		dev_err(mcs->dev, "MCS Request for %d msix vector failed err:%d\n",
114762306a36Sopenharmony_ci			mcs->num_vec, ret);
114862306a36Sopenharmony_ci		return ret;
114962306a36Sopenharmony_ci	}
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	ret = request_irq(pci_irq_vector(mcs->pdev, mcs->hw->ip_vec),
115262306a36Sopenharmony_ci			  mcs_ip_intr_handler, 0, "MCS_IP", mcs);
115362306a36Sopenharmony_ci	if (ret) {
115462306a36Sopenharmony_ci		dev_err(mcs->dev, "MCS IP irq registration failed\n");
115562306a36Sopenharmony_ci		goto exit;
115662306a36Sopenharmony_ci	}
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	/* MCS enable IP interrupts */
115962306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_IP_INT_ENA_W1S, BIT_ULL(0));
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	/* Enable CPM Rx/Tx interrupts */
116262306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_TOP_SLAVE_INT_SUM_ENB,
116362306a36Sopenharmony_ci		      MCS_CPM_RX_INT_ENA | MCS_CPM_TX_INT_ENA |
116462306a36Sopenharmony_ci		      MCS_BBE_RX_INT_ENA | MCS_BBE_TX_INT_ENA |
116562306a36Sopenharmony_ci		      MCS_PAB_RX_INT_ENA | MCS_PAB_TX_INT_ENA);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CPM_TX_SLAVE_TX_INT_ENB, 0x7ULL);
116862306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CPM_RX_SLAVE_RX_INT_ENB, 0x7FULL);
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_BBE_RX_SLAVE_BBE_INT_ENB, 0xFFULL);
117162306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_BBE_TX_SLAVE_BBE_INT_ENB, 0xFFULL);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_PAB_RX_SLAVE_PAB_INT_ENB, 0xFFFFFULL);
117462306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_PAB_TX_SLAVE_PAB_INT_ENB, 0xFFFFFULL);
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci	mcs->tx_sa_active = alloc_mem(mcs, mcs->hw->sc_entries);
117762306a36Sopenharmony_ci	if (!mcs->tx_sa_active) {
117862306a36Sopenharmony_ci		ret = -ENOMEM;
117962306a36Sopenharmony_ci		goto free_irq;
118062306a36Sopenharmony_ci	}
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	return ret;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_cifree_irq:
118562306a36Sopenharmony_ci	free_irq(pci_irq_vector(mcs->pdev, mcs->hw->ip_vec), mcs);
118662306a36Sopenharmony_ciexit:
118762306a36Sopenharmony_ci	pci_free_irq_vectors(mcs->pdev);
118862306a36Sopenharmony_ci	mcs->num_vec = 0;
118962306a36Sopenharmony_ci	return ret;
119062306a36Sopenharmony_ci}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ciint mcs_get_blkcnt(void)
119362306a36Sopenharmony_ci{
119462306a36Sopenharmony_ci	struct mcs *mcs;
119562306a36Sopenharmony_ci	int idmax = -ENODEV;
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	/* Check MCS block is present in hardware */
119862306a36Sopenharmony_ci	if (!pci_dev_present(mcs_id_table))
119962306a36Sopenharmony_ci		return 0;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	list_for_each_entry(mcs, &mcs_list, mcs_list)
120262306a36Sopenharmony_ci		if (mcs->mcs_id > idmax)
120362306a36Sopenharmony_ci			idmax = mcs->mcs_id;
120462306a36Sopenharmony_ci
120562306a36Sopenharmony_ci	if (idmax < 0)
120662306a36Sopenharmony_ci		return 0;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	return idmax + 1;
120962306a36Sopenharmony_ci}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_cistruct mcs *mcs_get_pdata(int mcs_id)
121262306a36Sopenharmony_ci{
121362306a36Sopenharmony_ci	struct mcs *mcs_dev;
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	list_for_each_entry(mcs_dev, &mcs_list, mcs_list) {
121662306a36Sopenharmony_ci		if (mcs_dev->mcs_id == mcs_id)
121762306a36Sopenharmony_ci			return mcs_dev;
121862306a36Sopenharmony_ci	}
121962306a36Sopenharmony_ci	return NULL;
122062306a36Sopenharmony_ci}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_cibool is_mcs_bypass(int mcs_id)
122362306a36Sopenharmony_ci{
122462306a36Sopenharmony_ci	struct mcs *mcs_dev;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	list_for_each_entry(mcs_dev, &mcs_list, mcs_list) {
122762306a36Sopenharmony_ci		if (mcs_dev->mcs_id == mcs_id)
122862306a36Sopenharmony_ci			return mcs_dev->bypass;
122962306a36Sopenharmony_ci	}
123062306a36Sopenharmony_ci	return true;
123162306a36Sopenharmony_ci}
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_civoid mcs_set_port_cfg(struct mcs *mcs, struct mcs_port_cfg_set_req *req)
123462306a36Sopenharmony_ci{
123562306a36Sopenharmony_ci	u64 val = 0;
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_PAB_RX_SLAVE_PORT_CFGX(req->port_id),
123862306a36Sopenharmony_ci		      req->port_mode & MCS_PORT_MODE_MASK);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	req->cstm_tag_rel_mode_sel &= 0x3;
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1) {
124362306a36Sopenharmony_ci		req->fifo_skid &= MCS_PORT_FIFO_SKID_MASK;
124462306a36Sopenharmony_ci		val = (u32)req->fifo_skid << 0x10;
124562306a36Sopenharmony_ci		val |= req->fifo_skid;
124662306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PAB_RX_SLAVE_FIFO_SKID_CFGX(req->port_id), val);
124762306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PEX_TX_SLAVE_CUSTOM_TAG_REL_MODE_SEL(req->port_id),
124862306a36Sopenharmony_ci			      req->cstm_tag_rel_mode_sel);
124962306a36Sopenharmony_ci		val = mcs_reg_read(mcs, MCSX_PEX_RX_SLAVE_PEX_CONFIGURATION);
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci		if (req->custom_hdr_enb)
125262306a36Sopenharmony_ci			val |= BIT_ULL(req->port_id);
125362306a36Sopenharmony_ci		else
125462306a36Sopenharmony_ci			val &= ~BIT_ULL(req->port_id);
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PEX_RX_SLAVE_PEX_CONFIGURATION, val);
125762306a36Sopenharmony_ci	} else {
125862306a36Sopenharmony_ci		val = mcs_reg_read(mcs, MCSX_PEX_TX_SLAVE_PORT_CONFIG(req->port_id));
125962306a36Sopenharmony_ci		val |= (req->cstm_tag_rel_mode_sel << 2);
126062306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_PEX_TX_SLAVE_PORT_CONFIG(req->port_id), val);
126162306a36Sopenharmony_ci	}
126262306a36Sopenharmony_ci}
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_civoid mcs_get_port_cfg(struct mcs *mcs, struct mcs_port_cfg_get_req *req,
126562306a36Sopenharmony_ci		      struct mcs_port_cfg_get_rsp *rsp)
126662306a36Sopenharmony_ci{
126762306a36Sopenharmony_ci	u64 reg = 0;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	rsp->port_mode = mcs_reg_read(mcs, MCSX_PAB_RX_SLAVE_PORT_CFGX(req->port_id)) &
127062306a36Sopenharmony_ci			 MCS_PORT_MODE_MASK;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1) {
127362306a36Sopenharmony_ci		reg = MCSX_PAB_RX_SLAVE_FIFO_SKID_CFGX(req->port_id);
127462306a36Sopenharmony_ci		rsp->fifo_skid = mcs_reg_read(mcs, reg) & MCS_PORT_FIFO_SKID_MASK;
127562306a36Sopenharmony_ci		reg = MCSX_PEX_TX_SLAVE_CUSTOM_TAG_REL_MODE_SEL(req->port_id);
127662306a36Sopenharmony_ci		rsp->cstm_tag_rel_mode_sel = mcs_reg_read(mcs, reg) & 0x3;
127762306a36Sopenharmony_ci		if (mcs_reg_read(mcs, MCSX_PEX_RX_SLAVE_PEX_CONFIGURATION) & BIT_ULL(req->port_id))
127862306a36Sopenharmony_ci			rsp->custom_hdr_enb = 1;
127962306a36Sopenharmony_ci	} else {
128062306a36Sopenharmony_ci		reg = MCSX_PEX_TX_SLAVE_PORT_CONFIG(req->port_id);
128162306a36Sopenharmony_ci		rsp->cstm_tag_rel_mode_sel = mcs_reg_read(mcs, reg) >> 2;
128262306a36Sopenharmony_ci	}
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	rsp->port_id = req->port_id;
128562306a36Sopenharmony_ci	rsp->mcs_id = req->mcs_id;
128662306a36Sopenharmony_ci}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_civoid mcs_get_custom_tag_cfg(struct mcs *mcs, struct mcs_custom_tag_cfg_get_req *req,
128962306a36Sopenharmony_ci			    struct mcs_custom_tag_cfg_get_rsp *rsp)
129062306a36Sopenharmony_ci{
129162306a36Sopenharmony_ci	u64 reg = 0, val = 0;
129262306a36Sopenharmony_ci	u8 idx;
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_ci	for (idx = 0; idx < MCS_MAX_CUSTOM_TAGS; idx++) {
129562306a36Sopenharmony_ci		if (mcs->hw->mcs_blks > 1)
129662306a36Sopenharmony_ci			reg  = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_CUSTOM_TAGX(idx) :
129762306a36Sopenharmony_ci				MCSX_PEX_TX_SLAVE_CUSTOM_TAGX(idx);
129862306a36Sopenharmony_ci		else
129962306a36Sopenharmony_ci			reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_VLAN_CFGX(idx) :
130062306a36Sopenharmony_ci				MCSX_PEX_TX_SLAVE_VLAN_CFGX(idx);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci		val = mcs_reg_read(mcs, reg);
130362306a36Sopenharmony_ci		if (mcs->hw->mcs_blks > 1) {
130462306a36Sopenharmony_ci			rsp->cstm_etype[idx] = val & GENMASK(15, 0);
130562306a36Sopenharmony_ci			rsp->cstm_indx[idx] = (val >> 0x16) & 0x3;
130662306a36Sopenharmony_ci			reg = (req->dir == MCS_RX) ? MCSX_PEX_RX_SLAVE_ETYPE_ENABLE :
130762306a36Sopenharmony_ci				MCSX_PEX_TX_SLAVE_ETYPE_ENABLE;
130862306a36Sopenharmony_ci			rsp->cstm_etype_en = mcs_reg_read(mcs, reg) & 0xFF;
130962306a36Sopenharmony_ci		} else {
131062306a36Sopenharmony_ci			rsp->cstm_etype[idx] = (val >> 0x1) & GENMASK(15, 0);
131162306a36Sopenharmony_ci			rsp->cstm_indx[idx] = (val >> 0x11) & 0x3;
131262306a36Sopenharmony_ci			rsp->cstm_etype_en |= (val & 0x1) << idx;
131362306a36Sopenharmony_ci		}
131462306a36Sopenharmony_ci	}
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	rsp->mcs_id = req->mcs_id;
131762306a36Sopenharmony_ci	rsp->dir = req->dir;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_civoid mcs_reset_port(struct mcs *mcs, u8 port_id, u8 reset)
132162306a36Sopenharmony_ci{
132262306a36Sopenharmony_ci	u64 reg = MCSX_MCS_TOP_SLAVE_PORT_RESET(port_id);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, reset & 0x1);
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci/* Set lmac to bypass/operational mode */
132862306a36Sopenharmony_civoid mcs_set_lmac_mode(struct mcs *mcs, int lmac_id, u8 mode)
132962306a36Sopenharmony_ci{
133062306a36Sopenharmony_ci	u64 reg;
133162306a36Sopenharmony_ci	int id = lmac_id * 2;
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	reg = MCSX_MCS_TOP_SLAVE_CHANNEL_CFG(id);
133462306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, (u64)mode);
133562306a36Sopenharmony_ci	reg = MCSX_MCS_TOP_SLAVE_CHANNEL_CFG((id + 1));
133662306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, (u64)mode);
133762306a36Sopenharmony_ci}
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_civoid mcs_pn_threshold_set(struct mcs *mcs, struct mcs_set_pn_threshold *pn)
134062306a36Sopenharmony_ci{
134162306a36Sopenharmony_ci	u64 reg;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (pn->dir == MCS_RX)
134462306a36Sopenharmony_ci		reg = pn->xpn ? MCSX_CPM_RX_SLAVE_XPN_THRESHOLD : MCSX_CPM_RX_SLAVE_PN_THRESHOLD;
134562306a36Sopenharmony_ci	else
134662306a36Sopenharmony_ci		reg = pn->xpn ? MCSX_CPM_TX_SLAVE_XPN_THRESHOLD : MCSX_CPM_TX_SLAVE_PN_THRESHOLD;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, pn->threshold);
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_civoid cn10kb_mcs_parser_cfg(struct mcs *mcs)
135262306a36Sopenharmony_ci{
135362306a36Sopenharmony_ci	u64 reg, val;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	/* VLAN CTag */
135662306a36Sopenharmony_ci	val = BIT_ULL(0) | (0x8100ull & 0xFFFF) << 1 | BIT_ULL(17);
135762306a36Sopenharmony_ci	/* RX */
135862306a36Sopenharmony_ci	reg = MCSX_PEX_RX_SLAVE_VLAN_CFGX(0);
135962306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	/* TX */
136262306a36Sopenharmony_ci	reg = MCSX_PEX_TX_SLAVE_VLAN_CFGX(0);
136362306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci	/* VLAN STag */
136662306a36Sopenharmony_ci	val = BIT_ULL(0) | (0x88a8ull & 0xFFFF) << 1 | BIT_ULL(18);
136762306a36Sopenharmony_ci	/* RX */
136862306a36Sopenharmony_ci	reg = MCSX_PEX_RX_SLAVE_VLAN_CFGX(1);
136962306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	/* TX */
137262306a36Sopenharmony_ci	reg = MCSX_PEX_TX_SLAVE_VLAN_CFGX(1);
137362306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, val);
137462306a36Sopenharmony_ci}
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_cistatic void mcs_lmac_init(struct mcs *mcs, int lmac_id)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	u64 reg;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	/* Port mode 25GB */
138162306a36Sopenharmony_ci	reg = MCSX_PAB_RX_SLAVE_PORT_CFGX(lmac_id);
138262306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, 0);
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	if (mcs->hw->mcs_blks > 1) {
138562306a36Sopenharmony_ci		reg = MCSX_PAB_RX_SLAVE_FIFO_SKID_CFGX(lmac_id);
138662306a36Sopenharmony_ci		mcs_reg_write(mcs, reg, 0xe000e);
138762306a36Sopenharmony_ci		return;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	reg = MCSX_PAB_TX_SLAVE_PORT_CFGX(lmac_id);
139162306a36Sopenharmony_ci	mcs_reg_write(mcs, reg, 0);
139262306a36Sopenharmony_ci}
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ciint mcs_set_lmac_channels(int mcs_id, u16 base)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	struct mcs *mcs;
139762306a36Sopenharmony_ci	int lmac;
139862306a36Sopenharmony_ci	u64 cfg;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	mcs = mcs_get_pdata(mcs_id);
140162306a36Sopenharmony_ci	if (!mcs)
140262306a36Sopenharmony_ci		return -ENODEV;
140362306a36Sopenharmony_ci	for (lmac = 0; lmac < mcs->hw->lmac_cnt; lmac++) {
140462306a36Sopenharmony_ci		cfg = mcs_reg_read(mcs, MCSX_LINK_LMACX_CFG(lmac));
140562306a36Sopenharmony_ci		cfg &= ~(MCSX_LINK_LMAC_BASE_MASK | MCSX_LINK_LMAC_RANGE_MASK);
140662306a36Sopenharmony_ci		cfg |=	FIELD_PREP(MCSX_LINK_LMAC_RANGE_MASK, ilog2(16));
140762306a36Sopenharmony_ci		cfg |=	FIELD_PREP(MCSX_LINK_LMAC_BASE_MASK, base);
140862306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_LINK_LMACX_CFG(lmac), cfg);
140962306a36Sopenharmony_ci		base += 16;
141062306a36Sopenharmony_ci	}
141162306a36Sopenharmony_ci	return 0;
141262306a36Sopenharmony_ci}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_cistatic int mcs_x2p_calibration(struct mcs *mcs)
141562306a36Sopenharmony_ci{
141662306a36Sopenharmony_ci	unsigned long timeout = jiffies + usecs_to_jiffies(20000);
141762306a36Sopenharmony_ci	int i, err = 0;
141862306a36Sopenharmony_ci	u64 val;
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	/* set X2P calibration */
142162306a36Sopenharmony_ci	val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
142262306a36Sopenharmony_ci	val |= BIT_ULL(5);
142362306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci	/* Wait for calibration to complete */
142662306a36Sopenharmony_ci	while (!(mcs_reg_read(mcs, MCSX_MIL_RX_GBL_STATUS) & BIT_ULL(0))) {
142762306a36Sopenharmony_ci		if (time_before(jiffies, timeout)) {
142862306a36Sopenharmony_ci			usleep_range(80, 100);
142962306a36Sopenharmony_ci			continue;
143062306a36Sopenharmony_ci		} else {
143162306a36Sopenharmony_ci			err = -EBUSY;
143262306a36Sopenharmony_ci			dev_err(mcs->dev, "MCS X2P calibration failed..ignoring\n");
143362306a36Sopenharmony_ci			return err;
143462306a36Sopenharmony_ci		}
143562306a36Sopenharmony_ci	}
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	val = mcs_reg_read(mcs, MCSX_MIL_RX_GBL_STATUS);
143862306a36Sopenharmony_ci	for (i = 0; i < mcs->hw->mcs_x2p_intf; i++) {
143962306a36Sopenharmony_ci		if (val & BIT_ULL(1 + i))
144062306a36Sopenharmony_ci			continue;
144162306a36Sopenharmony_ci		err = -EBUSY;
144262306a36Sopenharmony_ci		dev_err(mcs->dev, "MCS:%d didn't respond to X2P calibration\n", i);
144362306a36Sopenharmony_ci	}
144462306a36Sopenharmony_ci	/* Clear X2P calibrate */
144562306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_MIL_GLOBAL, mcs_reg_read(mcs, MCSX_MIL_GLOBAL) & ~BIT_ULL(5));
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	return err;
144862306a36Sopenharmony_ci}
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_cistatic void mcs_set_external_bypass(struct mcs *mcs, bool bypass)
145162306a36Sopenharmony_ci{
145262306a36Sopenharmony_ci	u64 val;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	/* Set MCS to external bypass */
145562306a36Sopenharmony_ci	val = mcs_reg_read(mcs, MCSX_MIL_GLOBAL);
145662306a36Sopenharmony_ci	if (bypass)
145762306a36Sopenharmony_ci		val |= BIT_ULL(6);
145862306a36Sopenharmony_ci	else
145962306a36Sopenharmony_ci		val &= ~BIT_ULL(6);
146062306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_MIL_GLOBAL, val);
146162306a36Sopenharmony_ci	mcs->bypass = bypass;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistatic void mcs_global_cfg(struct mcs *mcs)
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	/* Disable external bypass */
146762306a36Sopenharmony_ci	mcs_set_external_bypass(mcs, false);
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	/* Reset TX/RX stats memory */
147062306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CSE_RX_SLAVE_STATS_CLEAR, 0x1F);
147162306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_CSE_TX_SLAVE_STATS_CLEAR, 0x1F);
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	/* Set MCS to perform standard IEEE802.1AE macsec processing */
147462306a36Sopenharmony_ci	if (mcs->hw->mcs_blks == 1) {
147562306a36Sopenharmony_ci		mcs_reg_write(mcs, MCSX_IP_MODE, BIT_ULL(3));
147662306a36Sopenharmony_ci		return;
147762306a36Sopenharmony_ci	}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_BBE_RX_SLAVE_CAL_ENTRY, 0xe4);
148062306a36Sopenharmony_ci	mcs_reg_write(mcs, MCSX_BBE_RX_SLAVE_CAL_LEN, 4);
148162306a36Sopenharmony_ci}
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_civoid cn10kb_mcs_set_hw_capabilities(struct mcs *mcs)
148462306a36Sopenharmony_ci{
148562306a36Sopenharmony_ci	struct hwinfo *hw = mcs->hw;
148662306a36Sopenharmony_ci
148762306a36Sopenharmony_ci	hw->tcam_entries = 128;		/* TCAM entries */
148862306a36Sopenharmony_ci	hw->secy_entries  = 128;	/* SecY entries */
148962306a36Sopenharmony_ci	hw->sc_entries = 128;		/* SC CAM entries */
149062306a36Sopenharmony_ci	hw->sa_entries = 256;		/* SA entries */
149162306a36Sopenharmony_ci	hw->lmac_cnt = 20;		/* lmacs/ports per mcs block */
149262306a36Sopenharmony_ci	hw->mcs_x2p_intf = 5;		/* x2p clabration intf */
149362306a36Sopenharmony_ci	hw->mcs_blks = 1;		/* MCS blocks */
149462306a36Sopenharmony_ci	hw->ip_vec = MCS_CN10KB_INT_VEC_IP; /* IP vector */
149562306a36Sopenharmony_ci}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_cistatic struct mcs_ops cn10kb_mcs_ops = {
149862306a36Sopenharmony_ci	.mcs_set_hw_capabilities	= cn10kb_mcs_set_hw_capabilities,
149962306a36Sopenharmony_ci	.mcs_parser_cfg			= cn10kb_mcs_parser_cfg,
150062306a36Sopenharmony_ci	.mcs_tx_sa_mem_map_write	= cn10kb_mcs_tx_sa_mem_map_write,
150162306a36Sopenharmony_ci	.mcs_rx_sa_mem_map_write	= cn10kb_mcs_rx_sa_mem_map_write,
150262306a36Sopenharmony_ci	.mcs_flowid_secy_map		= cn10kb_mcs_flowid_secy_map,
150362306a36Sopenharmony_ci	.mcs_bbe_intr_handler		= cn10kb_mcs_bbe_intr_handler,
150462306a36Sopenharmony_ci	.mcs_pab_intr_handler		= cn10kb_mcs_pab_intr_handler,
150562306a36Sopenharmony_ci};
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_cistatic int mcs_probe(struct pci_dev *pdev, const struct pci_device_id *id)
150862306a36Sopenharmony_ci{
150962306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
151062306a36Sopenharmony_ci	int lmac, err = 0;
151162306a36Sopenharmony_ci	struct mcs *mcs;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	mcs = devm_kzalloc(dev, sizeof(*mcs), GFP_KERNEL);
151462306a36Sopenharmony_ci	if (!mcs)
151562306a36Sopenharmony_ci		return -ENOMEM;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	mcs->hw = devm_kzalloc(dev, sizeof(struct hwinfo), GFP_KERNEL);
151862306a36Sopenharmony_ci	if (!mcs->hw)
151962306a36Sopenharmony_ci		return -ENOMEM;
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	err = pci_enable_device(pdev);
152262306a36Sopenharmony_ci	if (err) {
152362306a36Sopenharmony_ci		dev_err(dev, "Failed to enable PCI device\n");
152462306a36Sopenharmony_ci		pci_set_drvdata(pdev, NULL);
152562306a36Sopenharmony_ci		return err;
152662306a36Sopenharmony_ci	}
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	err = pci_request_regions(pdev, DRV_NAME);
152962306a36Sopenharmony_ci	if (err) {
153062306a36Sopenharmony_ci		dev_err(dev, "PCI request regions failed 0x%x\n", err);
153162306a36Sopenharmony_ci		goto exit;
153262306a36Sopenharmony_ci	}
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	mcs->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
153562306a36Sopenharmony_ci	if (!mcs->reg_base) {
153662306a36Sopenharmony_ci		dev_err(dev, "mcs: Cannot map CSR memory space, aborting\n");
153762306a36Sopenharmony_ci		err = -ENOMEM;
153862306a36Sopenharmony_ci		goto exit;
153962306a36Sopenharmony_ci	}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci	pci_set_drvdata(pdev, mcs);
154262306a36Sopenharmony_ci	mcs->pdev = pdev;
154362306a36Sopenharmony_ci	mcs->dev = &pdev->dev;
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci	if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_B)
154662306a36Sopenharmony_ci		mcs->mcs_ops = &cn10kb_mcs_ops;
154762306a36Sopenharmony_ci	else
154862306a36Sopenharmony_ci		mcs->mcs_ops = cnf10kb_get_mac_ops();
154962306a36Sopenharmony_ci
155062306a36Sopenharmony_ci	/* Set hardware capabilities */
155162306a36Sopenharmony_ci	mcs->mcs_ops->mcs_set_hw_capabilities(mcs);
155262306a36Sopenharmony_ci
155362306a36Sopenharmony_ci	mcs_global_cfg(mcs);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	/* Perform X2P clibration */
155662306a36Sopenharmony_ci	err = mcs_x2p_calibration(mcs);
155762306a36Sopenharmony_ci	if (err)
155862306a36Sopenharmony_ci		goto err_x2p;
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci	mcs->mcs_id = (pci_resource_start(pdev, PCI_CFG_REG_BAR_NUM) >> 24)
156162306a36Sopenharmony_ci			& MCS_ID_MASK;
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	/* Set mcs tx side resources */
156462306a36Sopenharmony_ci	err = mcs_alloc_struct_mem(mcs, &mcs->tx);
156562306a36Sopenharmony_ci	if (err)
156662306a36Sopenharmony_ci		goto err_x2p;
156762306a36Sopenharmony_ci
156862306a36Sopenharmony_ci	/* Set mcs rx side resources */
156962306a36Sopenharmony_ci	err = mcs_alloc_struct_mem(mcs, &mcs->rx);
157062306a36Sopenharmony_ci	if (err)
157162306a36Sopenharmony_ci		goto err_x2p;
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci	/* per port config */
157462306a36Sopenharmony_ci	for (lmac = 0; lmac < mcs->hw->lmac_cnt; lmac++)
157562306a36Sopenharmony_ci		mcs_lmac_init(mcs, lmac);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci	/* Parser configuration */
157862306a36Sopenharmony_ci	mcs->mcs_ops->mcs_parser_cfg(mcs);
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	err = mcs_register_interrupts(mcs);
158162306a36Sopenharmony_ci	if (err)
158262306a36Sopenharmony_ci		goto exit;
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	list_add(&mcs->mcs_list, &mcs_list);
158562306a36Sopenharmony_ci	mutex_init(&mcs->stats_lock);
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	return 0;
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_cierr_x2p:
159062306a36Sopenharmony_ci	/* Enable external bypass */
159162306a36Sopenharmony_ci	mcs_set_external_bypass(mcs, true);
159262306a36Sopenharmony_ciexit:
159362306a36Sopenharmony_ci	pci_release_regions(pdev);
159462306a36Sopenharmony_ci	pci_disable_device(pdev);
159562306a36Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
159662306a36Sopenharmony_ci	return err;
159762306a36Sopenharmony_ci}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_cistatic void mcs_remove(struct pci_dev *pdev)
160062306a36Sopenharmony_ci{
160162306a36Sopenharmony_ci	struct mcs *mcs = pci_get_drvdata(pdev);
160262306a36Sopenharmony_ci
160362306a36Sopenharmony_ci	/* Set MCS to external bypass */
160462306a36Sopenharmony_ci	mcs_set_external_bypass(mcs, true);
160562306a36Sopenharmony_ci	free_irq(pci_irq_vector(pdev, mcs->hw->ip_vec), mcs);
160662306a36Sopenharmony_ci	pci_free_irq_vectors(pdev);
160762306a36Sopenharmony_ci	pci_release_regions(pdev);
160862306a36Sopenharmony_ci	pci_disable_device(pdev);
160962306a36Sopenharmony_ci	pci_set_drvdata(pdev, NULL);
161062306a36Sopenharmony_ci}
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_cistruct pci_driver mcs_driver = {
161362306a36Sopenharmony_ci	.name = DRV_NAME,
161462306a36Sopenharmony_ci	.id_table = mcs_id_table,
161562306a36Sopenharmony_ci	.probe = mcs_probe,
161662306a36Sopenharmony_ci	.remove = mcs_remove,
161762306a36Sopenharmony_ci};
1618