@@ -460,18 +460,32 @@ int cgx_lmac_tx_enable(void *cgxd, int lmac_id, bool enable)
return !!(last & DATA_PKT_TX_EN);
}
-static int cgx_lmac_get_pause_frm_status(void *cgxd, int lmac_id,
- u8 *tx_pause, u8 *rx_pause)
+static int cgx_lmac_get_higig2_pause_frm_status(void *cgxd, int lmac_id,
+ u8 *tx_pause, u8 *rx_pause)
{
struct cgx *cgx = cgxd;
u64 cfg;
- if (is_dev_rpm(cgx))
- return 0;
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL);
+
+ *rx_pause = !!(cfg & CGXX_SMUX_HG2_CONTROL_RX_ENABLE);
+ *tx_pause = !!(cfg & CGXX_SMUX_HG2_CONTROL_TX_ENABLE);
+ return 0;
+}
+
+int cgx_lmac_get_pause_frm_status(void *cgxd, int lmac_id,
+ u8 *tx_pause, u8 *rx_pause)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
if (!is_lmac_valid(cgx, lmac_id))
return -ENODEV;
+ if (is_higig2_enabled(cgxd, lmac_id))
+ return cgx_lmac_get_higig2_pause_frm_status(cgxd, lmac_id,
+ tx_pause, rx_pause);
+
cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
*rx_pause = !!(cfg & CGX_SMUX_RX_FRM_CTL_CTL_BCK);
@@ -480,17 +494,51 @@ static int cgx_lmac_get_pause_frm_status(void *cgxd, int lmac_id,
return 0;
}
-static int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
- u8 tx_pause, u8 rx_pause)
+static int cgx_lmac_enadis_higig2_pause_frm(void *cgxd, int lmac_id,
+ u8 tx_pause, u8 rx_pause)
{
struct cgx *cgx = cgxd;
u64 cfg;
- if (is_dev_rpm(cgx))
- return 0;
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL);
+ cfg &= ~CGXX_SMUX_HG2_CONTROL_RX_ENABLE;
+ cfg |= rx_pause ? CGXX_SMUX_HG2_CONTROL_RX_ENABLE : 0x0;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL, cfg);
- if (!is_lmac_valid(cgx, lmac_id))
- return -ENODEV;
+ /* Forward PAUSE information to TX block */
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
+ cfg &= ~CGX_SMUX_RX_FRM_CTL_CTL_BCK;
+ cfg |= rx_pause ? CGX_SMUX_RX_FRM_CTL_CTL_BCK : 0x0;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL, cfg);
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL);
+ cfg &= ~CGXX_SMUX_HG2_CONTROL_TX_ENABLE;
+ cfg |= tx_pause ? CGXX_SMUX_HG2_CONTROL_TX_ENABLE : 0x0;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL, cfg);
+
+ /* allow intra packet hg2 generation */
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_TX_PAUSE_PKT_INTERVAL);
+ cfg &= ~CGXX_SMUX_TX_PAUSE_PKT_HG2_INTRA_EN;
+ cfg |= tx_pause ? CGXX_SMUX_TX_PAUSE_PKT_HG2_INTRA_EN : 0x0;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_TX_PAUSE_PKT_INTERVAL, cfg);
+
+ cfg = cgx_read(cgx, 0, CGXX_CMR_RX_OVR_BP);
+ if (tx_pause) {
+ cfg &= ~CGX_CMR_RX_OVR_BP_EN(lmac_id);
+ } else {
+ cfg |= CGX_CMR_RX_OVR_BP_EN(lmac_id);
+ cfg &= ~CGX_CMR_RX_OVR_BP_BP(lmac_id);
+ }
+
+ cgx_write(cgx, 0, CGXX_CMR_RX_OVR_BP, cfg);
+ return 0;
+}
+
+static int cgx_lmac_enadis_8023_pause_frm(void *cgxd, int lmac_id,
+ u8 tx_pause, u8 rx_pause)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
cfg &= ~CGX_SMUX_RX_FRM_CTL_CTL_BCK;
@@ -513,6 +561,22 @@ static int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
return 0;
}
+int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
+ u8 tx_pause, u8 rx_pause)
+{
+ struct cgx *cgx = cgxd;
+
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
+ if (is_higig2_enabled(cgxd, lmac_id))
+ return cgx_lmac_enadis_higig2_pause_frm(cgxd, lmac_id,
+ tx_pause, rx_pause);
+ else
+ return cgx_lmac_enadis_8023_pause_frm(cgxd, lmac_id,
+ tx_pause, rx_pause);
+}
+
static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable)
{
struct cgx *cgx = cgxd;
@@ -520,6 +584,7 @@ static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable)
if (!is_lmac_valid(cgx, lmac_id))
return;
+
if (enable) {
/* Enable receive pause frames */
cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
@@ -543,6 +608,12 @@ static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable)
cgx_write(cgx, lmac_id, CGXX_SMUX_TX_PAUSE_PKT_INTERVAL,
cfg | (DEFAULT_PAUSE_TIME / 2));
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_TX_PAUSE_PKT_INTERVAL);
+ cfg = FIELD_SET(HG2_INTRA_INTERVAL, (DEFAULT_PAUSE_TIME / 2),
+ cfg);
+ cgx_write(cgx, lmac_id, CGXX_SMUX_TX_PAUSE_PKT_INTERVAL,
+ cfg);
+
cgx_write(cgx, lmac_id, CGXX_GMP_GMI_TX_PAUSE_PKT_TIME,
DEFAULT_PAUSE_TIME);
@@ -561,10 +632,18 @@ static void cgx_lmac_pause_frm_config(void *cgxd, int lmac_id, bool enable)
cfg &= ~CGX_GMP_GMI_RXX_FRM_CTL_CTL_BCK;
cgx_write(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL, cfg);
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL);
+ cfg &= ~CGXX_SMUX_HG2_CONTROL_RX_ENABLE;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL, cfg);
+
/* Disable pause frames transmission */
cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_TX_CTL);
cfg &= ~CGX_SMUX_TX_CTL_L2P_BP_CONV;
cgx_write(cgx, lmac_id, CGXX_SMUX_TX_CTL, cfg);
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL);
+ cfg &= ~CGXX_SMUX_HG2_CONTROL_TX_ENABLE;
+ cgx_write(cgx, lmac_id, CGXX_SMUX_HG2_CONTROL, cfg);
}
}
@@ -1242,6 +1321,37 @@ unsigned long cgx_get_lmac_bmap(void *cgxd)
return cgx->lmac_bmap;
}
+void cgx_lmac_enadis_higig2(void *cgxd, int lmac_id, bool enable)
+{
+ struct cgx *cgx = cgxd;
+ u64 req = 0, resp;
+
+ /* disable 802.3 pause frames before enabling higig2 */
+ if (enable) {
+ cgx_lmac_enadis_8023_pause_frm(cgxd, lmac_id, false, false);
+ cgx_lmac_enadis_higig2_pause_frm(cgxd, lmac_id, true, true);
+ }
+
+ req = FIELD_SET(CMDREG_ID, CGX_CMD_HIGIG, req);
+ req = FIELD_SET(CMDREG_ENABLE, enable, req);
+ cgx_fwi_cmd_generic(req, &resp, cgx, lmac_id);
+
+ /* enable 802.3 pause frames as higig2 disabled */
+ if (!enable) {
+ cgx_lmac_enadis_higig2_pause_frm(cgxd, lmac_id, false, false);
+ cgx_lmac_enadis_8023_pause_frm(cgxd, lmac_id, true, true);
+ }
+}
+
+bool is_higig2_enabled(void *cgxd, int lmac_id)
+{
+ struct cgx *cgx = cgxd;
+ u64 cfg;
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_TX_CTL);
+ return (cfg & CGXX_SMUX_TX_CTL_HIGIG_EN);
+}
+
static int cgx_lmac_init(struct cgx *cgx)
{
struct lmac *lmac;
@@ -1328,9 +1438,11 @@ static int cgx_lmac_exit(struct cgx *cgx)
static void cgx_populate_features(struct cgx *cgx)
{
if (is_dev_rpm(cgx))
- cgx->hw_features = (RVU_MAC_RPM | RVU_LMAC_FEAT_FC);
+ cgx->hw_features = (RVU_LMAC_FEAT_DMACF | RVU_MAC_RPM |
+ RVU_LMAC_FEAT_FC);
else
- cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP);
+ cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_HIGIG2 |
+ RVU_LMAC_FEAT_PTP | RVU_LMAC_FEAT_DMACF);
}
static struct mac_ops cgx_mac_ops = {
@@ -74,14 +74,20 @@
#define CGX_GMP_GMI_RXX_FRM_CTL_CTL_BCK BIT_ULL(3)
#define CGX_GMP_GMI_RXX_FRM_CTL_PTP_MODE BIT_ULL(12)
#define CGXX_SMUX_TX_CTL 0x20178
+#define CGXX_SMUX_TX_CTL_HIGIG_EN BIT_ULL(8)
#define CGXX_SMUX_TX_PAUSE_PKT_TIME 0x20110
#define CGXX_SMUX_TX_PAUSE_PKT_INTERVAL 0x20120
+#define CGXX_SMUX_TX_PAUSE_PKT_HG2_INTRA_EN BIT_ULL(32)
+#define HG2_INTRA_INTERVAL GENMASK_ULL(31, 16)
#define CGXX_GMP_GMI_TX_PAUSE_PKT_TIME 0x38230
#define CGXX_GMP_GMI_TX_PAUSE_PKT_INTERVAL 0x38248
#define CGX_SMUX_TX_CTL_L2P_BP_CONV BIT_ULL(7)
#define CGXX_CMR_RX_OVR_BP 0x130
#define CGX_CMR_RX_OVR_BP_EN(X) BIT_ULL(((X) + 8))
#define CGX_CMR_RX_OVR_BP_BP(X) BIT_ULL(((X) + 4))
+#define CGXX_SMUX_HG2_CONTROL 0x20210
+#define CGXX_SMUX_HG2_CONTROL_TX_ENABLE BIT_ULL(18)
+#define CGXX_SMUX_HG2_CONTROL_RX_ENABLE BIT_ULL(17)
#define CGX_COMMAND_REG CGXX_SCRATCH1_REG
#define CGX_EVENT_REG CGXX_SCRATCH0_REG
@@ -147,10 +153,10 @@ int cgx_get_link_info(void *cgxd, int lmac_id,
struct cgx_link_user_info *linfo);
int cgx_lmac_linkup_start(void *cgxd);
int cgx_get_fwdata_base(u64 *base);
-int cgx_lmac_get_pause_frm(void *cgxd, int lmac_id,
- u8 *tx_pause, u8 *rx_pause);
-int cgx_lmac_set_pause_frm(void *cgxd, int lmac_id,
- u8 tx_pause, u8 rx_pause);
+int cgx_lmac_get_pause_frm_status(void *cgxd, int lmac_id,
+ u8 *tx_pause, u8 *rx_pause);
+int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
+ u8 tx_pause, u8 rx_pause);
void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable);
u8 cgx_lmac_get_p2x(int cgx_id, int lmac_id);
int cgx_set_fec(u64 fec, int cgx_id, int lmac_id);
@@ -168,4 +174,6 @@ u64 cgx_lmac_read(int cgx_id, int lmac_id, u64 offset);
int cgx_set_phy_mod_type(int mod, void *cgxd, int lmac_id);
int cgx_get_phy_mod_type(void *cgxd, int lmac_id);
int cgx_get_pkind(void *cgxd, u8 lmac_id, int *pkind);
+void cgx_lmac_enadis_higig2(void *cgxd, int lmac_id, bool enable);
+bool is_higig2_enabled(void *cgxd, int lmac_id);
#endif /* CGX_H */
@@ -509,10 +509,13 @@ struct cgx_set_link_mode_rsp {
};
#define RVU_LMAC_FEAT_FC BIT_ULL(0) /* pause frames */
-#define RVU_LMAC_FEAT_PTP BIT_ULL(1) /* precison time protocol */
-#define RVU_MAC_VERSION BIT_ULL(2)
-#define RVU_MAC_CGX BIT_ULL(3)
-#define RVU_MAC_RPM BIT_ULL(4)
+#define RVU_LMAC_FEAT_HIGIG2 BIT_ULL(1)
+ /* flow control from physical link higig2 messages */
+#define RVU_LMAC_FEAT_PTP BIT_ULL(2) /* precison time protocol */
+#define RVU_LMAC_FEAT_DMACF BIT_ULL(3) /* DMAC FILTER */
+#define RVU_MAC_VERSION BIT_ULL(4)
+#define RVU_MAC_CGX BIT_ULL(5)
+#define RVU_MAC_RPM BIT_ULL(6)
struct cgx_features_info_msg {
struct mbox_msghdr hdr;
@@ -631,6 +634,7 @@ enum nix_af_status {
NIX_AF_ERR_TX_VTAG_NOSPC = -421,
NIX_AF_ERR_RX_VTAG_INUSE = -422,
NIX_AF_ERR_NPC_KEY_NOT_SUPP = -423,
+ NIX_AF_ERR_PTP_CONFIG_FAIL = -424,
};
/* For NIX RX vtag action */
@@ -1003,6 +1007,8 @@ enum npc_af_status {
NPC_MCAM_ALLOC_DENIED = -702,
NPC_MCAM_ALLOC_FAILED = -703,
NPC_MCAM_PERM_DENIED = -704,
+ NPC_AF_ERR_HIGIG_CONFIG_FAIL = -705,
+ NPC_AF_ERR_HIGIG_NOT_SUPPORTED = -706,
};
struct npc_mcam_alloc_entry_req {
@@ -618,6 +618,8 @@ int rvu_cgx_nix_cuml_stats(struct rvu *rvu, void *cgxd, int lmac_id, int index,
int rxtxflag, u64 *stat);
bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc);
bool rvu_cgx_is_pkind_config_permitted(struct rvu *rvu, u16 pcifunc);
+void rvu_cgx_enadis_higig2(struct rvu *rvu, int pf, bool enable);
+bool rvu_cgx_is_higig2_enabled(struct rvu *rvu, int pf);
/* NPA APIs */
int rvu_npa_init(struct rvu *rvu);
@@ -639,6 +641,7 @@ int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add);
struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr);
int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr);
void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc);
+u64 rvu_nix_is_ptp_tx_enabled(struct rvu *rvu, u16 pcifunc);
/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
@@ -424,6 +424,36 @@ void rvu_cgx_enadis_rx_bp(struct rvu *rvu, int pf, bool enable)
mac_ops->mac_enadis_rx_pause_fwding(cgxd, lmac_id, false);
}
+void rvu_cgx_enadis_higig2(struct rvu *rvu, int pf, bool enable)
+{
+ u8 cgx_id, lmac_id;
+ void *cgxd;
+
+ if (!is_pf_cgxmapped(rvu, pf))
+ return;
+
+ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+ cgxd = rvu_cgx_pdata(cgx_id, rvu);
+ cgx_lmac_enadis_higig2(cgxd, lmac_id, enable);
+}
+
+bool rvu_cgx_is_higig2_enabled(struct rvu *rvu, int pf)
+{
+ u8 cgx_id, lmac_id;
+ void *cgxd;
+
+ if (is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_HIGIG2) == false)
+ return 0;
+
+ if (!is_pf_cgxmapped(rvu, pf))
+ return false;
+
+ rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
+ cgxd = rvu_cgx_pdata(cgx_id, rvu);
+
+ return is_higig2_enabled(cgxd, lmac_id);
+}
+
int rvu_cgx_config_rxtx(struct rvu *rvu, u16 pcifunc, bool start)
{
int pf = rvu_get_pf(pcifunc);
@@ -604,6 +634,10 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP))
return 0;
+ /* Silicon does not support enabling time stamp in higig mode */
+ if (enable && rvu_cgx_is_higig2_enabled(rvu, pf))
+ return NIX_AF_ERR_PTP_CONFIG_FAIL;
+
/* This msg is expected only from PFs that are mapped to CGX LMACs,
* if received from other PF/VF simply ACK, nothing to do.
*/
@@ -3707,6 +3707,10 @@ static int rvu_nix_lf_ptp_tx_cfg(struct rvu *rvu, u16 pcifunc, bool enable)
if (!is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_PTP))
return 0;
+ /* Silicon does not support enabling time stamp in higig mode */
+ if (rvu_cgx_is_higig2_enabled(rvu, rvu_get_pf(pcifunc)))
+ return NIX_AF_ERR_PTP_CONFIG_FAIL;
+
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
if (blkaddr < 0)
return NIX_AF_ERR_AF_LF_INVALID;
@@ -3799,3 +3803,16 @@ void rvu_nix_reset_mac(struct rvu_pfvf *pfvf, int pcifunc)
if (from_vf)
ether_addr_copy(pfvf->mac_addr, pfvf->default_mac);
}
+
+u64 rvu_nix_is_ptp_tx_enabled(struct rvu *rvu, u16 pcifunc)
+{
+ int blkaddr, nixlf, err;
+ u64 cfg;
+
+ err = nix_get_nixlf(rvu, pcifunc, &nixlf, &blkaddr);
+ if (err)
+ return false;
+
+ cfg = rvu_read64(rvu, blkaddr, NIX_AF_LFX_TX_CFG(nixlf));
+ return (cfg & BIT_ULL(32));
+}
@@ -2850,6 +2850,7 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
u64 pkind)
{
int pf = rvu_get_pf(pcifunc);
+ bool enable_higig2 = false;
int blkaddr, nixlf, rc;
u64 rxpkind, txpkind;
u8 cgx_id, lmac_id;
@@ -2861,8 +2862,17 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
if (mode & OTX2_PRIV_FLAGS_EDSA) {
rxpkind = NPC_RX_EDSA_PKIND;
} else if (mode & OTX2_PRIV_FLAGS_HIGIG) {
+ /* Silicon does not support enabling higig in time stamp mode */
+ if (rvu_nix_is_ptp_tx_enabled(rvu, pcifunc))
+ return NPC_AF_ERR_HIGIG_CONFIG_FAIL;
+
+ if (is_mac_feature_supported(rvu, pf, RVU_LMAC_FEAT_HIGIG2) ==
+ false)
+ return NPC_AF_ERR_HIGIG_NOT_SUPPORTED;
+
rxpkind = NPC_RX_HIGIG_PKIND;
txpkind = NPC_TX_HIGIG_PKIND;
+ enable_higig2 = true;
} else if (mode & OTX2_PRIV_FLAGS_CUSTOM) {
rxpkind = pkind;
txpkind = pkind;
@@ -2889,6 +2899,10 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
txpkind);
}
+
+ if (enable_higig2 ^ rvu_cgx_is_higig2_enabled(rvu, pf))
+ rvu_cgx_enadis_higig2(rvu, pf, enable_higig2);
+
return 0;
}