Skip to content

Commit c7b9e80

Browse files
vladimirolteankuba-moo
authored andcommitted
net: enetc: add support for MAC Merge layer
Add PF driver support for viewing and changing the MAC Merge sublayer parameters, and seeing the verification state machine's current state. The verification handshake with the link partner is driven by hardware. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20230206094531.444988-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent cc74ca3 commit c7b9e80

File tree

4 files changed

+182
-3
lines changed

4 files changed

+182
-3
lines changed

drivers/net/ethernet/freescale/enetc/enetc.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,6 @@ struct psfp_cap {
314314
};
315315

316316
#define ENETC_F_TX_TSTAMP_MASK 0xff
317-
/* TODO: more hardware offloads */
318317
enum enetc_active_offloads {
319318
/* 8 bits reserved for TX timestamp types (hwtstamp_tx_types) */
320319
ENETC_F_TX_TSTAMP = BIT(0),
@@ -323,6 +322,7 @@ enum enetc_active_offloads {
323322
ENETC_F_RX_TSTAMP = BIT(8),
324323
ENETC_F_QBV = BIT(9),
325324
ENETC_F_QCI = BIT(10),
325+
ENETC_F_QBU = BIT(11),
326326
};
327327

328328
enum enetc_flags_bit {
@@ -382,6 +382,11 @@ struct enetc_ndev_priv {
382382

383383
struct work_struct tx_onestep_tstamp;
384384
struct sk_buff_head tx_skbs;
385+
386+
/* Serialize access to MAC Merge state between ethtool requests
387+
* and link state updates
388+
*/
389+
struct mutex mm_lock;
385390
};
386391

387392
/* Messaging */
@@ -427,6 +432,7 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
427432

428433
/* ethtool */
429434
void enetc_set_ethtool_ops(struct net_device *ndev);
435+
void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
430436

431437
/* control buffer descriptor ring (CBDR) */
432438
int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,

drivers/net/ethernet/freescale/enetc/enetc_ethtool.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,148 @@ static int enetc_set_link_ksettings(struct net_device *dev,
863863
return phylink_ethtool_ksettings_set(priv->phylink, cmd);
864864
}
865865

866+
static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
867+
{
868+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
869+
struct enetc_si *si = priv->si;
870+
struct enetc_hw *hw = &si->hw;
871+
u32 lafs, rafs, val;
872+
873+
if (!(si->hw_features & ENETC_SI_F_QBU))
874+
return -EOPNOTSUPP;
875+
876+
mutex_lock(&priv->mm_lock);
877+
878+
val = enetc_port_rd(hw, ENETC_PFPMR);
879+
state->pmac_enabled = !!(val & ENETC_PFPMR_PMACE);
880+
881+
val = enetc_port_rd(hw, ENETC_MMCSR);
882+
883+
switch (ENETC_MMCSR_GET_VSTS(val)) {
884+
case 0:
885+
state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
886+
break;
887+
case 2:
888+
state->verify_status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
889+
break;
890+
case 3:
891+
state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
892+
break;
893+
case 4:
894+
state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
895+
break;
896+
case 5:
897+
default:
898+
state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
899+
break;
900+
}
901+
902+
rafs = ENETC_MMCSR_GET_RAFS(val);
903+
state->tx_min_frag_size = ethtool_mm_frag_size_add_to_min(rafs);
904+
lafs = ENETC_MMCSR_GET_LAFS(val);
905+
state->rx_min_frag_size = ethtool_mm_frag_size_add_to_min(lafs);
906+
state->tx_enabled = !!(val & ENETC_MMCSR_LPE); /* mirror of MMCSR_ME */
907+
state->tx_active = !!(val & ENETC_MMCSR_LPA);
908+
state->verify_enabled = !(val & ENETC_MMCSR_VDIS);
909+
state->verify_time = ENETC_MMCSR_GET_VT(val);
910+
/* A verifyTime of 128 ms would exceed the 7 bit width
911+
* of the ENETC_MMCSR_VT field
912+
*/
913+
state->max_verify_time = 127;
914+
915+
mutex_unlock(&priv->mm_lock);
916+
917+
return 0;
918+
}
919+
920+
static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
921+
struct netlink_ext_ack *extack)
922+
{
923+
struct enetc_ndev_priv *priv = netdev_priv(ndev);
924+
struct enetc_hw *hw = &priv->si->hw;
925+
struct enetc_si *si = priv->si;
926+
u32 val, add_frag_size;
927+
int err;
928+
929+
if (!(si->hw_features & ENETC_SI_F_QBU))
930+
return -EOPNOTSUPP;
931+
932+
err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size,
933+
&add_frag_size, extack);
934+
if (err)
935+
return err;
936+
937+
mutex_lock(&priv->mm_lock);
938+
939+
val = enetc_port_rd(hw, ENETC_PFPMR);
940+
if (cfg->pmac_enabled)
941+
val |= ENETC_PFPMR_PMACE;
942+
else
943+
val &= ~ENETC_PFPMR_PMACE;
944+
enetc_port_wr(hw, ENETC_PFPMR, val);
945+
946+
val = enetc_port_rd(hw, ENETC_MMCSR);
947+
948+
if (cfg->verify_enabled)
949+
val &= ~ENETC_MMCSR_VDIS;
950+
else
951+
val |= ENETC_MMCSR_VDIS;
952+
953+
if (cfg->tx_enabled)
954+
priv->active_offloads |= ENETC_F_QBU;
955+
else
956+
priv->active_offloads &= ~ENETC_F_QBU;
957+
958+
/* If link is up, enable MAC Merge right away */
959+
if (!!(priv->active_offloads & ENETC_F_QBU) &&
960+
!(val & ENETC_MMCSR_LINK_FAIL))
961+
val |= ENETC_MMCSR_ME;
962+
963+
val &= ~ENETC_MMCSR_VT_MASK;
964+
val |= ENETC_MMCSR_VT(cfg->verify_time);
965+
966+
val &= ~ENETC_MMCSR_RAFS_MASK;
967+
val |= ENETC_MMCSR_RAFS(add_frag_size);
968+
969+
enetc_port_wr(hw, ENETC_MMCSR, val);
970+
971+
mutex_unlock(&priv->mm_lock);
972+
973+
return 0;
974+
}
975+
976+
/* When the link is lost, the verification state machine goes to the FAILED
977+
* state and doesn't restart on its own after a new link up event.
978+
* According to 802.3 Figure 99-8 - Verify state diagram, the LINK_FAIL bit
979+
* should have been sufficient to re-trigger verification, but for ENETC it
980+
* doesn't. As a workaround, we need to toggle the Merge Enable bit to
981+
* re-trigger verification when link comes up.
982+
*/
983+
void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link)
984+
{
985+
struct enetc_hw *hw = &priv->si->hw;
986+
u32 val;
987+
988+
mutex_lock(&priv->mm_lock);
989+
990+
val = enetc_port_rd(hw, ENETC_MMCSR);
991+
992+
if (link) {
993+
val &= ~ENETC_MMCSR_LINK_FAIL;
994+
if (priv->active_offloads & ENETC_F_QBU)
995+
val |= ENETC_MMCSR_ME;
996+
} else {
997+
val |= ENETC_MMCSR_LINK_FAIL;
998+
if (priv->active_offloads & ENETC_F_QBU)
999+
val &= ~ENETC_MMCSR_ME;
1000+
}
1001+
1002+
enetc_port_wr(hw, ENETC_MMCSR, val);
1003+
1004+
mutex_unlock(&priv->mm_lock);
1005+
}
1006+
EXPORT_SYMBOL_GPL(enetc_mm_link_state_update);
1007+
8661008
static const struct ethtool_ops enetc_pf_ethtool_ops = {
8671009
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
8681010
ETHTOOL_COALESCE_MAX_FRAMES |
@@ -893,6 +1035,8 @@ static const struct ethtool_ops enetc_pf_ethtool_ops = {
8931035
.set_wol = enetc_set_wol,
8941036
.get_pauseparam = enetc_get_pauseparam,
8951037
.set_pauseparam = enetc_set_pauseparam,
1038+
.get_mm = enetc_get_mm,
1039+
.set_mm = enetc_set_mm,
8961040
};
8971041

8981042
static const struct ethtool_ops enetc_vf_ethtool_ops = {

drivers/net/ethernet/freescale/enetc/enetc_hw.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,24 @@ enum enetc_bdr_type {TX, RX};
222222
#define ENETC_PSIVHFR0(n) (0x1e00 + (n) * 8) /* n = SI index */
223223
#define ENETC_PSIVHFR1(n) (0x1e04 + (n) * 8) /* n = SI index */
224224
#define ENETC_MMCSR 0x1f00
225-
#define ENETC_MMCSR_ME BIT(16)
225+
#define ENETC_MMCSR_LINK_FAIL BIT(31)
226+
#define ENETC_MMCSR_VT_MASK GENMASK(29, 23) /* Verify Time */
227+
#define ENETC_MMCSR_VT(x) (((x) << 23) & ENETC_MMCSR_VT_MASK)
228+
#define ENETC_MMCSR_GET_VT(x) (((x) & ENETC_MMCSR_VT_MASK) >> 23)
229+
#define ENETC_MMCSR_TXSTS_MASK GENMASK(22, 21) /* Merge Status */
230+
#define ENETC_MMCSR_GET_TXSTS(x) (((x) & ENETC_MMCSR_TXSTS_MASK) >> 21)
231+
#define ENETC_MMCSR_VSTS_MASK GENMASK(20, 18) /* Verify Status */
232+
#define ENETC_MMCSR_GET_VSTS(x) (((x) & ENETC_MMCSR_VSTS_MASK) >> 18)
233+
#define ENETC_MMCSR_VDIS BIT(17) /* Verify Disabled */
234+
#define ENETC_MMCSR_ME BIT(16) /* Merge Enabled */
235+
#define ENETC_MMCSR_RAFS_MASK GENMASK(9, 8) /* Remote Additional Fragment Size */
236+
#define ENETC_MMCSR_RAFS(x) (((x) << 8) & ENETC_MMCSR_RAFS_MASK)
237+
#define ENETC_MMCSR_GET_RAFS(x) (((x) & ENETC_MMCSR_RAFS_MASK) >> 8)
238+
#define ENETC_MMCSR_LAFS_MASK GENMASK(4, 3) /* Local Additional Fragment Size */
239+
#define ENETC_MMCSR_GET_LAFS(x) (((x) & ENETC_MMCSR_LAFS_MASK) >> 3)
240+
#define ENETC_MMCSR_LPA BIT(2) /* Local Preemption Active */
241+
#define ENETC_MMCSR_LPE BIT(1) /* Local Preemption Enabled */
242+
#define ENETC_MMCSR_LPS BIT(0) /* Local Preemption Supported */
226243
#define ENETC_PTCMSDUR(n) (0x2020 + (n) * 4) /* n = TC index [0..7] */
227244

228245
#define ENETC_PMAC_OFFSET 0x1000

drivers/net/ethernet/freescale/enetc/enetc_pf.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,15 +1083,25 @@ static void enetc_pl_mac_link_up(struct phylink_config *config,
10831083
enetc_port_mac_wr(si, ENETC_PM0_CMD_CFG, cmd_cfg);
10841084

10851085
enetc_mac_enable(si, true);
1086+
1087+
if (si->hw_features & ENETC_SI_F_QBU)
1088+
enetc_mm_link_state_update(priv, true);
10861089
}
10871090

10881091
static void enetc_pl_mac_link_down(struct phylink_config *config,
10891092
unsigned int mode,
10901093
phy_interface_t interface)
10911094
{
10921095
struct enetc_pf *pf = phylink_to_enetc_pf(config);
1096+
struct enetc_si *si = pf->si;
1097+
struct enetc_ndev_priv *priv;
10931098

1094-
enetc_mac_enable(pf->si, false);
1099+
priv = netdev_priv(si->ndev);
1100+
1101+
if (si->hw_features & ENETC_SI_F_QBU)
1102+
enetc_mm_link_state_update(priv, false);
1103+
1104+
enetc_mac_enable(si, false);
10951105
}
10961106

10971107
static const struct phylink_mac_ops enetc_mac_phylink_ops = {
@@ -1284,6 +1294,8 @@ static int enetc_pf_probe(struct pci_dev *pdev,
12841294

12851295
priv = netdev_priv(ndev);
12861296

1297+
mutex_init(&priv->mm_lock);
1298+
12871299
enetc_init_si_rings_params(priv);
12881300

12891301
err = enetc_alloc_si_resources(priv);

0 commit comments

Comments
 (0)