Skip to content

Commit b7b871f

Browse files
committed
Merge branch 'ethtool-mm-api-consolidation'
Vladimir Oltean says: ==================== ethtool mm API consolidation This series consolidates the behavior of the 2 drivers that implement the ethtool MAC Merge layer by making NXP ENETC commit its preemptible traffic classes to hardware only when MM TX is active (same as Ocelot). Then, after resolving an issue with the ENETC driver, it restricts user space from entering 2 states which don't make sense: - pmac-enabled off tx-enabled on verify-enabled * - pmac-enabled * tx-enabled off verify-enabled on Then, it introduces a selftest (ethtool_mm.sh) which puts everything together and tests all valid configurations known to me. This is simultaneously the v2 of "[PATCH net-next 0/2] ethtool mm API improvements": https://lore.kernel.org/netdev/20230415173454.3970647-1-vladimir.oltean@nxp.com/ which had caused some problems to openlldp. Those were solved in the meantime, see: intel/openlldp@11171b4 and of "[RFC PATCH net-next] selftests: forwarding: add a test for MAC Merge layer": https://lore.kernel.org/netdev/20230210221243.228932-1-vladimir.oltean@nxp.com/ ==================== Link: https://lore.kernel.org/r/20230418111459.811553-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 787e614 + e699138 commit b7b871f

20 files changed

Lines changed: 486 additions & 66 deletions

File tree

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

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,12 @@ void enetc_port_mac_wr(struct enetc_si *si, u32 reg, u32 val)
2525
}
2626
EXPORT_SYMBOL_GPL(enetc_port_mac_wr);
2727

28-
void enetc_set_ptcfpr(struct enetc_hw *hw, unsigned long preemptible_tcs)
28+
static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
29+
u8 preemptible_tcs)
2930
{
30-
u32 val;
31-
int tc;
32-
33-
for (tc = 0; tc < 8; tc++) {
34-
val = enetc_port_rd(hw, ENETC_PTCFPR(tc));
35-
36-
if (preemptible_tcs & BIT(tc))
37-
val |= ENETC_PTCFPR_FPE;
38-
else
39-
val &= ~ENETC_PTCFPR_FPE;
40-
41-
enetc_port_wr(hw, ENETC_PTCFPR(tc), val);
42-
}
31+
priv->preemptible_tcs = preemptible_tcs;
32+
enetc_mm_commit_preemptible_tcs(priv);
4333
}
44-
EXPORT_SYMBOL_GPL(enetc_set_ptcfpr);
4534

4635
static int enetc_num_stack_tx_queues(struct enetc_ndev_priv *priv)
4736
{
@@ -2659,7 +2648,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev)
26592648

26602649
enetc_debug_tx_ring_prios(priv);
26612650

2662-
enetc_set_ptcfpr(hw, 0);
2651+
enetc_change_preemptible_tcs(priv, 0);
26632652
}
26642653

26652654
int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
@@ -2714,7 +2703,7 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
27142703

27152704
enetc_debug_tx_ring_prios(priv);
27162705

2717-
enetc_set_ptcfpr(hw, mqprio->preemptible_tcs);
2706+
enetc_change_preemptible_tcs(priv, mqprio->preemptible_tcs);
27182707

27192708
return 0;
27202709

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,9 @@ struct enetc_ndev_priv {
355355
u16 rx_bd_count, tx_bd_count;
356356

357357
u16 msg_enable;
358+
359+
u8 preemptible_tcs;
360+
358361
enum enetc_active_offloads active_offloads;
359362

360363
u32 speed; /* store speed for compare update pspeed */
@@ -433,6 +436,7 @@ int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
433436
/* ethtool */
434437
void enetc_set_ethtool_ops(struct net_device *ndev);
435438
void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link);
439+
void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv);
436440

437441
/* control buffer descriptor ring (CBDR) */
438442
int enetc_setup_cbdr(struct device *dev, struct enetc_hw *hw, int bd_count,
@@ -486,7 +490,6 @@ static inline void enetc_cbd_free_data_mem(struct enetc_si *si, int size,
486490

487491
void enetc_reset_ptcmsdur(struct enetc_hw *hw);
488492
void enetc_set_ptcmsdur(struct enetc_hw *hw, u32 *queue_max_sdu);
489-
void enetc_set_ptcfpr(struct enetc_hw *hw, unsigned long preemptible_tcs);
490493

491494
#ifdef CONFIG_FSL_ENETC_QOS
492495
int enetc_qos_query_caps(struct net_device *ndev, void *type_data);

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

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ static const u32 enetc_port_regs[] = {
3232
ENETC_PM0_CMD_CFG, ENETC_PM0_MAXFRM, ENETC_PM0_IF_MODE
3333
};
3434

35+
static const u32 enetc_port_mm_regs[] = {
36+
ENETC_MMCSR, ENETC_PFPMR, ENETC_PTCFPR(0), ENETC_PTCFPR(1),
37+
ENETC_PTCFPR(2), ENETC_PTCFPR(3), ENETC_PTCFPR(4), ENETC_PTCFPR(5),
38+
ENETC_PTCFPR(6), ENETC_PTCFPR(7),
39+
};
40+
3541
static int enetc_get_reglen(struct net_device *ndev)
3642
{
3743
struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -45,6 +51,9 @@ static int enetc_get_reglen(struct net_device *ndev)
4551
if (hw->port)
4652
len += ARRAY_SIZE(enetc_port_regs);
4753

54+
if (hw->port && !!(priv->si->hw_features & ENETC_SI_F_QBU))
55+
len += ARRAY_SIZE(enetc_port_mm_regs);
56+
4857
len *= sizeof(u32) * 2; /* store 2 entries per reg: addr and value */
4958

5059
return len;
@@ -90,6 +99,14 @@ static void enetc_get_regs(struct net_device *ndev, struct ethtool_regs *regs,
9099
*buf++ = addr;
91100
*buf++ = enetc_rd(hw, addr);
92101
}
102+
103+
if (priv->si->hw_features & ENETC_SI_F_QBU) {
104+
for (i = 0; i < ARRAY_SIZE(enetc_port_mm_regs); i++) {
105+
addr = ENETC_PORT_BASE + enetc_port_mm_regs[i];
106+
*buf++ = addr;
107+
*buf++ = enetc_rd(hw, addr);
108+
}
109+
}
93110
}
94111

95112
static const struct {
@@ -976,7 +993,9 @@ static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
976993
lafs = ENETC_MMCSR_GET_LAFS(val);
977994
state->rx_min_frag_size = ethtool_mm_frag_size_add_to_min(lafs);
978995
state->tx_enabled = !!(val & ENETC_MMCSR_LPE); /* mirror of MMCSR_ME */
979-
state->tx_active = !!(val & ENETC_MMCSR_LPA);
996+
state->tx_active = state->tx_enabled &&
997+
(state->verify_status == ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED ||
998+
state->verify_status == ETHTOOL_MM_VERIFY_STATUS_DISABLED);
980999
state->verify_enabled = !(val & ENETC_MMCSR_VDIS);
9811000
state->verify_time = ENETC_MMCSR_GET_VT(val);
9821001
/* A verifyTime of 128 ms would exceed the 7 bit width
@@ -989,6 +1008,64 @@ static int enetc_get_mm(struct net_device *ndev, struct ethtool_mm_state *state)
9891008
return 0;
9901009
}
9911010

1011+
static int enetc_mm_wait_tx_active(struct enetc_hw *hw, int verify_time)
1012+
{
1013+
int timeout = verify_time * USEC_PER_MSEC * ENETC_MM_VERIFY_RETRIES;
1014+
u32 val;
1015+
1016+
/* This will time out after the standard value of 3 verification
1017+
* attempts. To not sleep forever, it relies on a non-zero verify_time,
1018+
* guarantee which is provided by the ethtool nlattr policy.
1019+
*/
1020+
return read_poll_timeout(enetc_port_rd, val,
1021+
ENETC_MMCSR_GET_VSTS(val) == 3,
1022+
ENETC_MM_VERIFY_SLEEP_US, timeout,
1023+
true, hw, ENETC_MMCSR);
1024+
}
1025+
1026+
static void enetc_set_ptcfpr(struct enetc_hw *hw, u8 preemptible_tcs)
1027+
{
1028+
u32 val;
1029+
int tc;
1030+
1031+
for (tc = 0; tc < 8; tc++) {
1032+
val = enetc_port_rd(hw, ENETC_PTCFPR(tc));
1033+
1034+
if (preemptible_tcs & BIT(tc))
1035+
val |= ENETC_PTCFPR_FPE;
1036+
else
1037+
val &= ~ENETC_PTCFPR_FPE;
1038+
1039+
enetc_port_wr(hw, ENETC_PTCFPR(tc), val);
1040+
}
1041+
}
1042+
1043+
/* ENETC does not have an IRQ to notify changes to the MAC Merge TX status
1044+
* (active/inactive), but the preemptible traffic classes should only be
1045+
* committed to hardware once TX is active. Resort to polling.
1046+
*/
1047+
void enetc_mm_commit_preemptible_tcs(struct enetc_ndev_priv *priv)
1048+
{
1049+
struct enetc_hw *hw = &priv->si->hw;
1050+
u8 preemptible_tcs = 0;
1051+
u32 val;
1052+
int err;
1053+
1054+
val = enetc_port_rd(hw, ENETC_MMCSR);
1055+
if (!(val & ENETC_MMCSR_ME))
1056+
goto out;
1057+
1058+
if (!(val & ENETC_MMCSR_VDIS)) {
1059+
err = enetc_mm_wait_tx_active(hw, ENETC_MMCSR_GET_VT(val));
1060+
if (err)
1061+
goto out;
1062+
}
1063+
1064+
preemptible_tcs = priv->preemptible_tcs;
1065+
out:
1066+
enetc_set_ptcfpr(hw, preemptible_tcs);
1067+
}
1068+
9921069
/* FIXME: Workaround for the link partner's verification failing if ENETC
9931070
* priorly received too much express traffic. The documentation doesn't
9941071
* suggest this is needed.
@@ -1041,10 +1118,13 @@ static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
10411118
else
10421119
priv->active_offloads &= ~ENETC_F_QBU;
10431120

1044-
/* If link is up, enable MAC Merge right away */
1045-
if (!!(priv->active_offloads & ENETC_F_QBU) &&
1046-
!(val & ENETC_MMCSR_LINK_FAIL))
1047-
val |= ENETC_MMCSR_ME;
1121+
/* If link is up, enable/disable MAC Merge right away */
1122+
if (!(val & ENETC_MMCSR_LINK_FAIL)) {
1123+
if (!!(priv->active_offloads & ENETC_F_QBU))
1124+
val |= ENETC_MMCSR_ME;
1125+
else
1126+
val &= ~ENETC_MMCSR_ME;
1127+
}
10481128

10491129
val &= ~ENETC_MMCSR_VT_MASK;
10501130
val |= ENETC_MMCSR_VT(cfg->verify_time);
@@ -1056,6 +1136,8 @@ static int enetc_set_mm(struct net_device *ndev, struct ethtool_mm_cfg *cfg,
10561136

10571137
enetc_restart_emac_rx(priv->si);
10581138

1139+
enetc_mm_commit_preemptible_tcs(priv);
1140+
10591141
mutex_unlock(&priv->mm_lock);
10601142

10611143
return 0;
@@ -1089,6 +1171,8 @@ void enetc_mm_link_state_update(struct enetc_ndev_priv *priv, bool link)
10891171

10901172
enetc_port_wr(hw, ENETC_MMCSR, val);
10911173

1174+
enetc_mm_commit_preemptible_tcs(priv);
1175+
10921176
mutex_unlock(&priv->mm_lock);
10931177
}
10941178
EXPORT_SYMBOL_GPL(enetc_mm_link_state_update);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#include <linux/bitops.h>
55

6+
#define ENETC_MM_VERIFY_SLEEP_US USEC_PER_MSEC
7+
#define ENETC_MM_VERIFY_RETRIES 3
8+
69
/* ENETC device IDs */
710
#define ENETC_DEV_ID_PF 0xe100
811
#define ENETC_DEV_ID_VF 0xef00

net/ethtool/mm.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ static int ethnl_set_mm(struct ethnl_req_info *req_info, struct genl_info *info)
214214
return -ERANGE;
215215
}
216216

217+
if (cfg.verify_enabled && !cfg.tx_enabled) {
218+
NL_SET_ERR_MSG(extack, "Verification requires TX enabled");
219+
return -EINVAL;
220+
}
221+
222+
if (cfg.tx_enabled && !cfg.pmac_enabled) {
223+
NL_SET_ERR_MSG(extack, "TX enabled requires pMAC enabled");
224+
return -EINVAL;
225+
}
226+
217227
ret = dev->ethtool_ops->set_mm(dev, &cfg, extack);
218228
return ret < 0 ? ret : 1;
219229
}

tools/testing/selftests/drivers/net/mlxsw/qos_headroom.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ lib_dir=$(dirname $0)/../../../net/forwarding
1818
NUM_NETIFS=0
1919
source $lib_dir/lib.sh
2020
source $lib_dir/devlink_lib.sh
21-
source qos_lib.sh
2221

2322
swp=$NETIF_NO_CABLE
2423

@@ -371,7 +370,7 @@ test_tc_int_buf()
371370
tc qdisc delete dev $swp root
372371
}
373372

374-
bail_on_lldpad
373+
bail_on_lldpad "configure DCB" "configure Qdiscs"
375374

376375
trap cleanup EXIT
377376
setup_wait

tools/testing/selftests/drivers/net/mlxsw/qos_lib.sh

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,3 @@ measure_rate()
5454
echo $ir $er
5555
return $ret
5656
}
57-
58-
bail_on_lldpad()
59-
{
60-
if systemctl is-active --quiet lldpad; then
61-
62-
cat >/dev/stderr <<-EOF
63-
WARNING: lldpad is running
64-
65-
lldpad will likely configure DCB, and this test will
66-
configure Qdiscs. mlxsw does not support both at the
67-
same time, one of them is arbitrarily going to overwrite
68-
the other. That will cause spurious failures (or,
69-
unlikely, passes) of this test.
70-
EOF
71-
72-
if [[ -z $ALLOW_LLDPAD ]]; then
73-
cat >/dev/stderr <<-EOF
74-
75-
If you want to run the test anyway, please set
76-
an environment variable ALLOW_LLDPAD to a
77-
non-empty string.
78-
EOF
79-
exit 1
80-
else
81-
return
82-
fi
83-
fi
84-
}

tools/testing/selftests/drivers/net/mlxsw/qos_pfc.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ lib_dir=$(dirname $0)/../../../net/forwarding
7979
NUM_NETIFS=6
8080
source $lib_dir/lib.sh
8181
source $lib_dir/devlink_lib.sh
82-
source qos_lib.sh
8382

8483
_1KB=1000
8584
_100KB=$((100 * _1KB))
@@ -393,7 +392,7 @@ test_qos_pfc()
393392
log_test "PFC"
394393
}
395394

396-
bail_on_lldpad
395+
bail_on_lldpad "configure DCB" "configure Qdiscs"
397396

398397
trap cleanup EXIT
399398
setup_prepare

tools/testing/selftests/drivers/net/mlxsw/sch_ets.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
lib_dir=$(dirname $0)/../../../net/forwarding
66
source $lib_dir/sch_ets_core.sh
77
source $lib_dir/devlink_lib.sh
8-
source qos_lib.sh
98

109
ALL_TESTS="
1110
ping_ipv4
@@ -78,5 +77,5 @@ collect_stats()
7877
done
7978
}
8079

81-
bail_on_lldpad
80+
bail_on_lldpad "configure DCB" "configure Qdiscs"
8281
ets_run

tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ lib_dir=$(dirname $0)/../../../net/forwarding
7474
source $lib_dir/lib.sh
7575
source $lib_dir/devlink_lib.sh
7676
source mlxsw_lib.sh
77-
source qos_lib.sh
7877

7978
ipaddr()
8079
{

0 commit comments

Comments
 (0)