aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/marvell/octeontx2/af
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/marvell/octeontx2/af')
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.c37
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/cgx.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h26
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/npc.h4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/ptp.c155
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/ptp.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rpm.c17
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.c2
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu.h12
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c12
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c9
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c35
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c20
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c6
15 files changed, 259 insertions, 83 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
index 592037f4e55b..e06f77ad6106 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -55,6 +55,7 @@ static const char *cgx_lmactype_string[LMAC_MODE_MAX] = {
[LMAC_MODE_50G_R] = "50G_R",
[LMAC_MODE_100G_R] = "100G_R",
[LMAC_MODE_USXGMII] = "USXGMII",
+ [LMAC_MODE_USGMII] = "USGMII",
};
/* CGX PHY management internal APIs */
@@ -223,24 +224,6 @@ int cgx_get_link_info(void *cgxd, int lmac_id,
return 0;
}
-static u64 mac2u64 (u8 *mac_addr)
-{
- u64 mac = 0;
- int index;
-
- for (index = ETH_ALEN - 1; index >= 0; index--)
- mac |= ((u64)*mac_addr++) << (8 * index);
- return mac;
-}
-
-static void cfg2mac(u64 cfg, u8 *mac_addr)
-{
- int i, index = 0;
-
- for (i = ETH_ALEN - 1; i >= 0; i--, index++)
- mac_addr[i] = (cfg >> (8 * index)) & 0xFF;
-}
-
int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
{
struct cgx *cgx_dev = cgx_get_pdata(cgx_id);
@@ -249,13 +232,16 @@ int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
int index, id;
u64 cfg;
+ if (!lmac)
+ return -ENODEV;
+
/* access mac_ops to know csr_offset */
mac_ops = cgx_dev->mac_ops;
/* copy 6bytes from macaddr */
/* memcpy(&cfg, mac_addr, 6); */
- cfg = mac2u64 (mac_addr);
+ cfg = ether_addr_to_u64(mac_addr);
id = get_sequence_id_of_lmac(cgx_dev, lmac_id);
@@ -322,7 +308,7 @@ int cgx_lmac_addr_add(u8 cgx_id, u8 lmac_id, u8 *mac_addr)
index = id * lmac->mac_to_index_bmap.max + idx;
- cfg = mac2u64 (mac_addr);
+ cfg = ether_addr_to_u64(mac_addr);
cfg |= CGX_DMAC_CAM_ADDR_ENABLE;
cfg |= ((u64)lmac_id << 49);
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg);
@@ -405,7 +391,7 @@ int cgx_lmac_addr_update(u8 cgx_id, u8 lmac_id, u8 *mac_addr, u8 index)
cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)));
cfg &= ~CGX_RX_DMAC_ADR_MASK;
- cfg |= mac2u64 (mac_addr);
+ cfg |= ether_addr_to_u64(mac_addr);
cgx_write(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)), cfg);
return 0;
@@ -441,7 +427,7 @@ int cgx_lmac_addr_del(u8 cgx_id, u8 lmac_id, u8 index)
/* Read MAC address to check whether it is ucast or mcast */
cfg = cgx_read(cgx_dev, 0, (CGXX_CMRX_RX_DMAC_CAM0 + (index * 0x8)));
- cfg2mac(cfg, mac);
+ u64_to_ether_addr(cfg, mac);
if (is_multicast_ether_addr(mac))
lmac->mcast_filters_count--;
@@ -567,15 +553,16 @@ void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable)
{
struct cgx *cgx = cgx_get_pdata(cgx_id);
struct lmac *lmac = lmac_pdata(lmac_id, cgx);
- u16 max_dmac = lmac->mac_to_index_bmap.max;
struct mac_ops *mac_ops;
+ u16 max_dmac;
int index, i;
u64 cfg = 0;
int id;
- if (!cgx)
+ if (!cgx || !lmac)
return;
+ max_dmac = lmac->mac_to_index_bmap.max;
id = get_sequence_id_of_lmac(cgx, lmac_id);
mac_ops = cgx->mac_ops;
@@ -748,7 +735,7 @@ int cgx_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp)
int corr_reg, uncorr_reg;
struct cgx *cgx = cgxd;
- if (!cgx || lmac_id >= cgx->lmac_count)
+ if (!is_lmac_valid(cgx, lmac_id))
return -ENODEV;
if (cgx->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
index 574114179688..6f7d1dee5830 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
@@ -110,6 +110,7 @@ enum LMAC_TYPE {
LMAC_MODE_50G_R = 8,
LMAC_MODE_100G_R = 9,
LMAC_MODE_USXGMII = 10,
+ LMAC_MODE_USGMII = 11,
LMAC_MODE_MAX,
};
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index eba307eee2b2..6b5b06c2b4e9 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -136,6 +136,7 @@ M(GET_HW_CAP, 0x008, get_hw_cap, msg_req, get_hw_cap_rsp) \
M(LMTST_TBL_SETUP, 0x00a, lmtst_tbl_setup, lmtst_tbl_setup_req, \
msg_rsp) \
M(SET_VF_PERM, 0x00b, set_vf_perm, set_vf_perm, msg_rsp) \
+M(PTP_GET_CAP, 0x00c, ptp_get_cap, msg_req, ptp_get_cap_rsp) \
/* CGX mbox IDs (range 0x200 - 0x3FF) */ \
M(CGX_START_RXTX, 0x200, cgx_start_rxtx, msg_req, msg_rsp) \
M(CGX_STOP_RXTX, 0x201, cgx_stop_rxtx, msg_req, msg_rsp) \
@@ -235,7 +236,7 @@ M(NPC_GET_KEX_CFG, 0x600c, npc_get_kex_cfg, \
M(NPC_INSTALL_FLOW, 0x600d, npc_install_flow, \
npc_install_flow_req, npc_install_flow_rsp) \
M(NPC_DELETE_FLOW, 0x600e, npc_delete_flow, \
- npc_delete_flow_req, msg_rsp) \
+ npc_delete_flow_req, npc_delete_flow_rsp) \
M(NPC_MCAM_READ_ENTRY, 0x600f, npc_mcam_read_entry, \
npc_mcam_read_entry_req, \
npc_mcam_read_entry_rsp) \
@@ -1437,6 +1438,12 @@ struct npc_get_kex_cfg_rsp {
u8 mkex_pfl_name[MKEX_NAME_LEN];
};
+struct ptp_get_cap_rsp {
+ struct mbox_msghdr hdr;
+#define PTP_CAP_HW_ATOMIC_UPDATE BIT_ULL(0)
+ u64 cap;
+};
+
struct flow_msg {
unsigned char dmac[6];
unsigned char smac[6];
@@ -1451,6 +1458,10 @@ struct flow_msg {
__be32 ip4dst;
__be32 ip6dst[4];
};
+ union {
+ __be32 spi;
+ };
+
u8 tos;
u8 ip_ver;
u8 ip_proto;
@@ -1461,6 +1472,7 @@ struct flow_msg {
u8 ip_flag;
u8 next_header;
};
+ __be16 vlan_itci;
};
struct npc_install_flow_req {
@@ -1491,6 +1503,8 @@ struct npc_install_flow_req {
u8 vtag0_op;
u16 vtag1_def;
u8 vtag1_op;
+ /* old counter value */
+ u16 cntr_val;
};
struct npc_install_flow_rsp {
@@ -1506,6 +1520,11 @@ struct npc_delete_flow_req {
u8 all; /* PF + VFs */
};
+struct npc_delete_flow_rsp {
+ struct mbox_msghdr hdr;
+ u16 cntr_val;
+};
+
struct npc_mcam_read_entry_req {
struct mbox_msghdr hdr;
u16 entry; /* MCAM entry to read */
@@ -1556,6 +1575,8 @@ enum ptp_op {
PTP_OP_GET_TSTMP = 2,
PTP_OP_SET_THRESH = 3,
PTP_OP_EXTTS_ON = 4,
+ PTP_OP_ADJTIME = 5,
+ PTP_OP_SET_CLOCK = 6,
};
struct ptp_req {
@@ -1564,11 +1585,14 @@ struct ptp_req {
s64 scaled_ppm;
u64 thresh;
int extts_on;
+ s64 delta;
+ u64 clk;
};
struct ptp_rsp {
struct mbox_msghdr hdr;
u64 clk;
+ u64 tsc;
};
struct npc_get_field_status_req {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index 9beeead56d7b..de9fbd98dfb7 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -184,6 +184,7 @@ enum key_fields {
NPC_VLAN_ETYPE_CTAG, /* 0x8100 */
NPC_VLAN_ETYPE_STAG, /* 0x88A8 */
NPC_OUTER_VID,
+ NPC_INNER_VID,
NPC_TOS,
NPC_IPFRAG_IPV4,
NPC_SIP_IPV4,
@@ -204,6 +205,7 @@ enum key_fields {
NPC_DPORT_UDP,
NPC_SPORT_SCTP,
NPC_DPORT_SCTP,
+ NPC_IPSEC_SPI,
NPC_HEADER_FIELDS_MAX,
NPC_CHAN = NPC_HEADER_FIELDS_MAX, /* Valid when Rx */
NPC_PF_FUNC, /* Valid when Tx */
@@ -229,6 +231,8 @@ enum key_fields {
NPC_VLAN_TAG1,
/* outer vlan tci for double tagged frame */
NPC_VLAN_TAG2,
+ /* inner vlan tci for double tagged frame */
+ NPC_VLAN_TAG3,
/* other header fields programmed to extract but not of our interest */
NPC_UNKNOWN,
NPC_KEY_FIELDS_MAX,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
index 0ee420a489fc..ffbd22797163 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c
@@ -12,8 +12,8 @@
#include <linux/hrtimer.h>
#include <linux/ktime.h>
-#include "ptp.h"
#include "mbox.h"
+#include "ptp.h"
#include "rvu.h"
#define DRV_NAME "Marvell PTP Driver"
@@ -40,6 +40,7 @@
#define PTP_CLOCK_CFG_TSTMP_EDGE BIT_ULL(9)
#define PTP_CLOCK_CFG_TSTMP_EN BIT_ULL(8)
#define PTP_CLOCK_CFG_TSTMP_IN_MASK GENMASK_ULL(15, 10)
+#define PTP_CLOCK_CFG_ATOMIC_OP_MASK GENMASK_ULL(28, 26)
#define PTP_CLOCK_CFG_PPS_EN BIT_ULL(30)
#define PTP_CLOCK_CFG_PPS_INV BIT_ULL(31)
@@ -53,36 +54,62 @@
#define PTP_TIMESTAMP 0xF20ULL
#define PTP_CLOCK_SEC 0xFD0ULL
#define PTP_SEC_ROLLOVER 0xFD8ULL
+/* Atomic update related CSRs */
+#define PTP_FRNS_TIMESTAMP 0xFE0ULL
+#define PTP_NXT_ROLLOVER_SET 0xFE8ULL
+#define PTP_CURR_ROLLOVER_SET 0xFF0ULL
+#define PTP_NANO_TIMESTAMP 0xFF8ULL
+#define PTP_SEC_TIMESTAMP 0x1000ULL
#define CYCLE_MULT 1000
+#define is_rev_A0(ptp) (((ptp)->pdev->revision & 0x0F) == 0x0)
+#define is_rev_A1(ptp) (((ptp)->pdev->revision & 0x0F) == 0x1)
+
+/* PTP atomic update operation type */
+enum atomic_opcode {
+ ATOMIC_SET = 1,
+ ATOMIC_INC = 3,
+ ATOMIC_DEC = 4
+};
+
static struct ptp *first_ptp_block;
static const struct pci_device_id ptp_id_table[];
-static bool is_ptp_dev_cnf10kb(struct ptp *ptp)
+static bool is_ptp_dev_cnf10ka(struct ptp *ptp)
{
- return (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_B_PTP) ? true : false;
+ return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP;
}
-static bool is_ptp_dev_cn10k(struct ptp *ptp)
+static bool is_ptp_dev_cn10ka(struct ptp *ptp)
{
- return (ptp->pdev->device == PCI_DEVID_CN10K_PTP) ? true : false;
+ return ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP;
}
static bool cn10k_ptp_errata(struct ptp *ptp)
{
- if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
- ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
+ if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) &&
+ (is_rev_A0(ptp) || is_rev_A1(ptp)))
return true;
+
return false;
}
-static bool is_ptp_tsfmt_sec_nsec(struct ptp *ptp)
+static bool is_tstmp_atomic_update_supported(struct rvu *rvu)
{
- if (ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_PTP ||
- ptp->pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A_PTP)
- return true;
- return false;
+ struct ptp *ptp = rvu->ptp;
+
+ if (is_rvu_otx2(rvu))
+ return false;
+
+ /* On older silicon variants of CN10K, atomic update feature
+ * is not available.
+ */
+ if ((is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) &&
+ (is_rev_A0(ptp) || is_rev_A1(ptp)))
+ return false;
+
+ return true;
}
static enum hrtimer_restart ptp_reset_thresh(struct hrtimer *hrtimer)
@@ -222,6 +249,65 @@ void ptp_put(struct ptp *ptp)
pci_dev_put(ptp->pdev);
}
+static void ptp_atomic_update(struct ptp *ptp, u64 timestamp)
+{
+ u64 regval, curr_rollover_set, nxt_rollover_set;
+
+ /* First setup NSECs and SECs */
+ writeq(timestamp, ptp->reg_base + PTP_NANO_TIMESTAMP);
+ writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+ writeq(timestamp / NSEC_PER_SEC,
+ ptp->reg_base + PTP_SEC_TIMESTAMP);
+
+ nxt_rollover_set = roundup(timestamp, NSEC_PER_SEC);
+ curr_rollover_set = nxt_rollover_set - NSEC_PER_SEC;
+ writeq(nxt_rollover_set, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
+ writeq(curr_rollover_set, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
+
+ /* Now, initiate atomic update */
+ regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
+ regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+ regval |= (ATOMIC_SET << 26);
+ writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
+}
+
+static void ptp_atomic_adjtime(struct ptp *ptp, s64 delta)
+{
+ bool neg_adj = false, atomic_inc_dec = false;
+ u64 regval, ptp_clock_hi;
+
+ if (delta < 0) {
+ delta = -delta;
+ neg_adj = true;
+ }
+
+ /* use atomic inc/dec when delta < 1 second */
+ if (delta < NSEC_PER_SEC)
+ atomic_inc_dec = true;
+
+ if (!atomic_inc_dec) {
+ ptp_clock_hi = readq(ptp->reg_base + PTP_CLOCK_HI);
+ if (neg_adj) {
+ if (ptp_clock_hi > delta)
+ ptp_clock_hi -= delta;
+ else
+ ptp_clock_hi = delta - ptp_clock_hi;
+ } else {
+ ptp_clock_hi += delta;
+ }
+ ptp_atomic_update(ptp, ptp_clock_hi);
+ } else {
+ writeq(delta, ptp->reg_base + PTP_NANO_TIMESTAMP);
+ writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+
+ /* initiate atomic inc/dec */
+ regval = readq(ptp->reg_base + PTP_CLOCK_CFG);
+ regval &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+ regval |= neg_adj ? (ATOMIC_DEC << 26) : (ATOMIC_INC << 26);
+ writeq(regval, ptp->reg_base + PTP_CLOCK_CFG);
+ }
+}
+
static int ptp_adjfine(struct ptp *ptp, long scaled_ppm)
{
bool neg_adj = false;
@@ -277,8 +363,9 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk)
return 0;
}
-void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
+void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts)
{
+ struct ptp *ptp = rvu->ptp;
struct pci_dev *pdev;
u64 clock_comp;
u64 clock_cfg;
@@ -297,8 +384,14 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
ptp->clock_rate = sclk * 1000000;
/* Program the seconds rollover value to 1 second */
- if (is_ptp_dev_cnf10kb(ptp))
+ if (is_tstmp_atomic_update_supported(rvu)) {
+ writeq(0, ptp->reg_base + PTP_NANO_TIMESTAMP);
+ writeq(0, ptp->reg_base + PTP_FRNS_TIMESTAMP);
+ writeq(0, ptp->reg_base + PTP_SEC_TIMESTAMP);
+ writeq(0, ptp->reg_base + PTP_CURR_ROLLOVER_SET);
+ writeq(0x3b9aca00, ptp->reg_base + PTP_NXT_ROLLOVER_SET);
writeq(0x3b9aca00, ptp->reg_base + PTP_SEC_ROLLOVER);
+ }
/* Enable PTP clock */
clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
@@ -320,6 +413,10 @@ void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;
writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
+ clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
+ clock_cfg &= ~PTP_CLOCK_CFG_ATOMIC_OP_MASK;
+ clock_cfg |= (ATOMIC_SET << 26);
+ writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
/* Set 50% duty cycle for 1Hz output */
writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR);
@@ -350,7 +447,7 @@ static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)
{
u64 timestamp;
- if (is_ptp_dev_cn10k(ptp)) {
+ if (is_ptp_dev_cn10ka(ptp) || is_ptp_dev_cnf10ka(ptp)) {
timestamp = readq(ptp->reg_base + PTP_TIMESTAMP);
*clk = (timestamp >> 32) * NSEC_PER_SEC + (timestamp & 0xFFFFFFFF);
} else {
@@ -414,14 +511,12 @@ static int ptp_probe(struct pci_dev *pdev,
first_ptp_block = ptp;
spin_lock_init(&ptp->ptp_lock);
- if (is_ptp_tsfmt_sec_nsec(ptp))
- ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
- else
- ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
-
if (cn10k_ptp_errata(ptp)) {
+ ptp->read_ptp_tstmp = &read_ptp_tstmp_sec_nsec;
hrtimer_init(&ptp->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ptp->hrtimer.function = ptp_reset_thresh;
+ } else {
+ ptp->read_ptp_tstmp = &read_ptp_tstmp_nsec;
}
return 0;
@@ -521,6 +616,12 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
case PTP_OP_EXTTS_ON:
err = ptp_extts_on(rvu->ptp, req->extts_on);
break;
+ case PTP_OP_ADJTIME:
+ ptp_atomic_adjtime(rvu->ptp, req->delta);
+ break;
+ case PTP_OP_SET_CLOCK:
+ ptp_atomic_update(rvu->ptp, (u64)req->clk);
+ break;
default:
err = -EINVAL;
break;
@@ -528,3 +629,17 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
return err;
}
+
+int rvu_mbox_handler_ptp_get_cap(struct rvu *rvu, struct msg_req *req,
+ struct ptp_get_cap_rsp *rsp)
+{
+ if (!rvu->ptp)
+ return -ENODEV;
+
+ if (is_tstmp_atomic_update_supported(rvu))
+ rsp->cap |= PTP_CAP_HW_ATOMIC_UPDATE;
+ else
+ rsp->cap &= ~BIT_ULL_MASK(0);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
index b9d92abc3844..1229344c7279 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h
@@ -23,9 +23,10 @@ struct ptp {
u32 clock_period;
};
+struct rvu;
struct ptp *ptp_get(void);
void ptp_put(struct ptp *ptp);
-void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts);
+void ptp_start(struct rvu *rvu, u64 sclk, u32 ext_clk_freq, u32 extts);
extern struct pci_driver ptp_driver;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
index b4fcb20c3f4f..af21e2030cff 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c
@@ -355,8 +355,8 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause,
void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
{
+ u64 cfg, pfc_class_mask_cfg;
rpm_t *rpm = rpmd;
- u64 cfg;
/* ALL pause frames received are completely ignored */
cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
@@ -380,9 +380,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL);
/* Disable all PFC classes */
- cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
+ pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
+ RPMX_CMRX_PRT_CBFC_CTL;
+ cfg = rpm_read(rpm, lmac_id, pfc_class_mask_cfg);
cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg);
- rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg);
+ rpm_write(rpm, lmac_id, pfc_class_mask_cfg, cfg);
}
int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat)
@@ -605,8 +607,11 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
if (!is_lmac_valid(rpm, lmac_id))
return -ENODEV;
+ pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
+ RPMX_CMRX_PRT_CBFC_CTL;
+
cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
- class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
+ class_en = rpm_read(rpm, lmac_id, pfc_class_mask_cfg);
pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en);
if (rx_pause) {
@@ -635,10 +640,6 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p
cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE;
rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
-
- pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL :
- RPMX_CMRX_PRT_CBFC_CTL;
-
rpm_write(rpm, lmac_id, pfc_class_mask_cfg, class_en);
return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 73df2d564545..22c395c7d040 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -3322,7 +3322,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_init(&rvu->rswitch.switch_lock);
if (rvu->fwdata)
- ptp_start(rvu->ptp, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate,
+ ptp_start(rvu, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate,
rvu->fwdata->ptp_ext_tstamp);
return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index e8e65fd7888d..c4d999ef5ab4 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -17,6 +17,7 @@
#include "mbox.h"
#include "npc.h"
#include "rvu_reg.h"
+#include "ptp.h"
/* PCI device IDs */
#define PCI_DEVID_OCTEONTX2_RVU_AF 0xA065
@@ -26,6 +27,7 @@
#define PCI_SUBSYS_DEVID_98XX 0xB100
#define PCI_SUBSYS_DEVID_96XX 0xB200
#define PCI_SUBSYS_DEVID_CN10K_A 0xB900
+#define PCI_SUBSYS_DEVID_CNF10K_A 0xBA00
#define PCI_SUBSYS_DEVID_CNF10K_B 0xBC00
#define PCI_SUBSYS_DEVID_CN10K_B 0xBD00
@@ -634,6 +636,16 @@ static inline bool is_rvu_otx2(struct rvu *rvu)
midr == PCI_REVISION_ID_95XXMM || midr == PCI_REVISION_ID_95XXO);
}
+static inline bool is_cnf10ka_a0(struct rvu *rvu)
+{
+ struct pci_dev *pdev = rvu->pdev;
+
+ if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CNF10K_A &&
+ (pdev->revision & 0x0F) == 0x0)
+ return true;
+ return false;
+}
+
static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu)
{
u64 npc_const3;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
index 095b2cc4a699..f2b1edf1bb43 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
@@ -236,6 +236,11 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
linfo = &event->link_uinfo;
pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id);
+ if (!pfmap) {
+ dev_err(rvu->dev, "CGX port%d:%d not mapped with PF\n",
+ event->cgx_id, event->lmac_id);
+ return;
+ }
do {
pfid = find_first_bit(&pfmap,
@@ -345,7 +350,7 @@ int rvu_cgx_init(struct rvu *rvu)
rvu->cgx_cnt_max = cgx_get_cgxcnt_max();
if (!rvu->cgx_cnt_max) {
dev_info(rvu->dev, "No CGX devices found!\n");
- return -ENODEV;
+ return 0;
}
rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max *
@@ -686,7 +691,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu,
{
int pf = rvu_get_pf(req->hdr.pcifunc);
u8 cgx_id, lmac_id;
- int rc = 0, i;
+ int rc = 0;
u64 cfg;
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
@@ -697,8 +702,7 @@ int rvu_mbox_handler_cgx_mac_addr_get(struct rvu *rvu,
rsp->hdr.rc = rc;
cfg = cgx_lmac_addr_get(cgx_id, lmac_id);
/* copy 48 bit mac address to req->mac_addr */
- for (i = 0; i < ETH_ALEN; i++)
- rsp->mac_addr[i] = cfg >> (ETH_ALEN - 1 - i) * 8;
+ u64_to_ether_addr(cfg, rsp->mac_addr);
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
index 3b26893efdf8..d30e84803481 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
@@ -2787,6 +2787,11 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
seq_printf(s, "mask 0x%x\n",
ntohs(rule->mask.vlan_tci));
break;
+ case NPC_INNER_VID:
+ seq_printf(s, "0x%x ", ntohs(rule->packet.vlan_itci));
+ seq_printf(s, "mask 0x%x\n",
+ ntohs(rule->mask.vlan_itci));
+ break;
case NPC_TOS:
seq_printf(s, "%d ", rule->packet.tos);
seq_printf(s, "mask 0x%x\n", rule->mask.tos);
@@ -2827,6 +2832,10 @@ static void rvu_dbg_npc_mcam_show_flows(struct seq_file *s,
seq_printf(s, "%d ", ntohs(rule->packet.dport));
seq_printf(s, "mask 0x%x\n", ntohs(rule->mask.dport));
break;
+ case NPC_IPSEC_SPI:
+ seq_printf(s, "0x%x ", ntohl(rule->packet.spi));
+ seq_printf(s, "mask 0x%x\n", ntohl(rule->mask.spi));
+ break;
default:
seq_puts(s, "\n");
break;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 04b0e885f9d2..c2f68678e947 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -4270,9 +4270,10 @@ rx_frscfg:
if (link < 0)
return NIX_AF_ERR_RX_LINK_INVALID;
- nix_find_link_frs(rvu, req, pcifunc);
linkcfg:
+ nix_find_link_frs(rvu, req, pcifunc);
+
cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link));
cfg = (cfg & ~(0xFFFFULL << 16)) | ((u64)req->maxlen << 16);
if (req->update_minlen)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
index 952319453701..237f82082ebe 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
@@ -20,6 +20,7 @@ static const char * const npc_flow_names[] = {
[NPC_VLAN_ETYPE_CTAG] = "vlan ether type ctag",
[NPC_VLAN_ETYPE_STAG] = "vlan ether type stag",
[NPC_OUTER_VID] = "outer vlan id",
+ [NPC_INNER_VID] = "inner vlan id",
[NPC_TOS] = "tos",
[NPC_IPFRAG_IPV4] = "fragmented IPv4 header ",
[NPC_SIP_IPV4] = "ipv4 source ip",
@@ -41,6 +42,7 @@ static const char * const npc_flow_names[] = {
[NPC_SPORT_SCTP] = "sctp source port",
[NPC_DPORT_SCTP] = "sctp destination port",
[NPC_LXMB] = "Mcast/Bcast header ",
+ [NPC_IPSEC_SPI] = "SPI ",
[NPC_UNKNOWN] = "unknown",
};
@@ -327,6 +329,8 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
*/
struct npc_key_field *vlan_tag1;
struct npc_key_field *vlan_tag2;
+ /* Inner VLAN TCI for double tagged frames */
+ struct npc_key_field *vlan_tag3;
u64 *features;
u8 start_lid;
int i;
@@ -349,6 +353,7 @@ static void npc_handle_multi_layer_fields(struct rvu *rvu, int blkaddr, u8 intf)
etype_tag2 = &key_fields[NPC_ETYPE_TAG2];
vlan_tag1 = &key_fields[NPC_VLAN_TAG1];
vlan_tag2 = &key_fields[NPC_VLAN_TAG2];
+ vlan_tag3 = &key_fields[NPC_VLAN_TAG3];
/* if key profile programmed does not extract Ethertype at all */
if (!etype_ether->nr_kws && !etype_tag1->nr_kws && !etype_tag2->nr_kws) {
@@ -430,6 +435,12 @@ vlan_tci:
goto done;
}
*features |= BIT_ULL(NPC_OUTER_VID);
+
+ /* If key profile extracts inner vlan tci */
+ if (vlan_tag3->nr_kws) {
+ key_fields[NPC_INNER_VID] = *vlan_tag3;
+ *features |= BIT_ULL(NPC_INNER_VID);
+ }
done:
return;
}
@@ -512,7 +523,12 @@ do { \
NPC_SCAN_HDR(NPC_ETYPE_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 8, 2);
NPC_SCAN_HDR(NPC_VLAN_TAG1, NPC_LID_LB, NPC_LT_LB_CTAG, 2, 2);
NPC_SCAN_HDR(NPC_VLAN_TAG2, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 2, 2);
+ NPC_SCAN_HDR(NPC_VLAN_TAG3, NPC_LID_LB, NPC_LT_LB_STAG_QINQ, 6, 2);
NPC_SCAN_HDR(NPC_DMAC, NPC_LID_LA, la_ltype, la_start, 6);
+
+ NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LD, NPC_LT_LD_AH, 4, 4);
+ NPC_SCAN_HDR(NPC_IPSEC_SPI, NPC_LID_LE, NPC_LT_LE_ESP, 0, 4);
+
/* SMAC follows the DMAC(which is 6 bytes) */
NPC_SCAN_HDR(NPC_SMAC, NPC_LID_LA, la_ltype, la_start + 6, 6);
/* PF_FUNC is 2 bytes at 0th byte of NPC_LT_LA_IH_NIX_ETHER */
@@ -564,6 +580,11 @@ static void npc_set_features(struct rvu *rvu, int blkaddr, u8 intf)
if (!npc_check_field(rvu, blkaddr, NPC_LB, intf))
*features &= ~BIT_ULL(NPC_OUTER_VID);
+ /* Set SPI flag only if AH/ESP and IPSEC_SPI are in the key */
+ if (npc_check_field(rvu, blkaddr, NPC_IPSEC_SPI, intf) &&
+ (*features & (BIT_ULL(NPC_IPPROTO_ESP) | BIT_ULL(NPC_IPPROTO_AH))))
+ *features |= BIT_ULL(NPC_IPSEC_SPI);
+
/* for vlan ethertypes corresponding layer type should be in the key */
if (npc_check_field(rvu, blkaddr, NPC_LB, intf))
*features |= BIT_ULL(NPC_VLAN_ETYPE_CTAG) |
@@ -930,8 +951,13 @@ do { \
NPC_WRITE_FLOW(NPC_DPORT_SCTP, dport, ntohs(pkt->dport), 0,
ntohs(mask->dport), 0);
+ NPC_WRITE_FLOW(NPC_IPSEC_SPI, spi, ntohl(pkt->spi), 0,
+ ntohl(mask->spi), 0);
+
NPC_WRITE_FLOW(NPC_OUTER_VID, vlan_tci, ntohs(pkt->vlan_tci), 0,
ntohs(mask->vlan_tci), 0);
+ NPC_WRITE_FLOW(NPC_INNER_VID, vlan_itci, ntohs(pkt->vlan_itci), 0,
+ ntohs(mask->vlan_itci), 0);
NPC_WRITE_FLOW(NPC_IPFRAG_IPV6, next_header, pkt->next_header, 0,
mask->next_header, 0);
@@ -1192,7 +1218,7 @@ find_rule:
write_req.enable_entry = (u8)enable;
/* if counter is available then clear and use it */
if (req->set_cntr && rule->has_cntr) {
- rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), 0x00);
+ rvu_write64(rvu, blkaddr, NPC_AF_MATCH_STATX(rule->cntr), req->cntr_val);
write_req.set_cntr = 1;
write_req.cntr = rule->cntr;
}
@@ -1407,12 +1433,13 @@ static int npc_delete_flow(struct rvu *rvu, struct rvu_npc_mcam_rule *rule,
int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu,
struct npc_delete_flow_req *req,
- struct msg_rsp *rsp)
+ struct npc_delete_flow_rsp *rsp)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_npc_mcam_rule *iter, *tmp;
u16 pcifunc = req->hdr.pcifunc;
struct list_head del_list;
+ int blkaddr;
INIT_LIST_HEAD(&del_list);
@@ -1428,6 +1455,10 @@ int rvu_mbox_handler_npc_delete_flow(struct rvu *rvu,
list_move_tail(&iter->list, &del_list);
/* single rule */
} else if (req->entry == iter->entry) {
+ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+ if (blkaddr)
+ rsp->cntr_val = rvu_read64(rvu, blkaddr,
+ NPC_AF_MATCH_STATX(iter->cntr));
list_move_tail(&iter->list, &del_list);
break;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
index 7e20282c12d0..d2661e7fabdb 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
@@ -391,22 +391,6 @@ int rvu_mbox_handler_npc_get_field_hash_info(struct rvu *rvu,
}
/**
- * rvu_npc_exact_mac2u64 - utility function to convert mac address to u64.
- * @mac_addr: MAC address.
- * Return: mdata for exact match table.
- */
-static u64 rvu_npc_exact_mac2u64(u8 *mac_addr)
-{
- u64 mac = 0;
- int index;
-
- for (index = ETH_ALEN - 1; index >= 0; index--)
- mac |= ((u64)*mac_addr++) << (8 * index);
-
- return mac;
-}
-
-/**
* rvu_exact_prepare_mdata - Make mdata for mcam entry
* @mac: MAC address
* @chan: Channel number.
@@ -416,7 +400,7 @@ static u64 rvu_npc_exact_mac2u64(u8 *mac_addr)
*/
static u64 rvu_exact_prepare_mdata(u8 *mac, u16 chan, u16 ctype, u64 mask)
{
- u64 ldata = rvu_npc_exact_mac2u64(mac);
+ u64 ldata = ether_addr_to_u64(mac);
/* Please note that mask is 48bit which excludes chan and ctype.
* Increase mask bits if we need to include them as well.
@@ -604,7 +588,7 @@ static u64 rvu_exact_prepare_table_entry(struct rvu *rvu, bool enable,
u8 ctype, u16 chan, u8 *mac_addr)
{
- u64 ldata = rvu_npc_exact_mac2u64(mac_addr);
+ u64 ldata = ether_addr_to_u64(mac_addr);
/* Enable or disable */
u64 mdata = FIELD_PREP(GENMASK_ULL(63, 63), enable ? 1 : 0);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
index 592b317f4637..854045ed3b06 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c
@@ -158,6 +158,7 @@ void rvu_switch_enable(struct rvu *rvu)
struct npc_mcam_alloc_entry_req alloc_req = { 0 };
struct npc_mcam_alloc_entry_rsp alloc_rsp = { 0 };
struct npc_delete_flow_req uninstall_req = { 0 };
+ struct npc_delete_flow_rsp uninstall_rsp = { 0 };
struct npc_mcam_free_entry_req free_req = { 0 };
struct rvu_switch *rswitch = &rvu->rswitch;
struct msg_rsp rsp;
@@ -197,7 +198,7 @@ void rvu_switch_enable(struct rvu *rvu)
uninstall_rules:
uninstall_req.start = rswitch->start_entry;
uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1;
- rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
+ rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
kfree(rswitch->entry2pcifunc);
free_entries:
free_req.all = 1;
@@ -209,6 +210,7 @@ exit:
void rvu_switch_disable(struct rvu *rvu)
{
struct npc_delete_flow_req uninstall_req = { 0 };
+ struct npc_delete_flow_rsp uninstall_rsp = { 0 };
struct npc_mcam_free_entry_req free_req = { 0 };
struct rvu_switch *rswitch = &rvu->rswitch;
struct rvu_hwinfo *hw = rvu->hw;
@@ -250,7 +252,7 @@ void rvu_switch_disable(struct rvu *rvu)
uninstall_req.start = rswitch->start_entry;
uninstall_req.end = rswitch->start_entry + rswitch->used_entries - 1;
free_req.all = 1;
- rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &rsp);
+ rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp);
rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &rsp);
rswitch->used_entries = 0;
kfree(rswitch->entry2pcifunc);