Skip to content

Commit 195e4f4

Browse files
Furong Xukuba-moo
authored andcommitted
net: stmmac: support fp parameter of tc-mqprio
tc-mqprio can select whether traffic classes are express or preemptible. After some traffic tests, MAC merge layer statistics are all good. Local device: ethtool --include-statistics --json --show-mm eth1 [ { "ifname": "eth1", "pmac-enabled": true, "tx-enabled": true, "tx-active": true, "tx-min-frag-size": 60, "rx-min-frag-size": 60, "verify-enabled": true, "verify-time": 100, "max-verify-time": 128, "verify-status": "SUCCEEDED", "statistics": { "MACMergeFrameAssErrorCount": 0, "MACMergeFrameSmdErrorCount": 0, "MACMergeFrameAssOkCount": 0, "MACMergeFragCountRx": 0, "MACMergeFragCountTx": 35105, "MACMergeHoldCount": 0 } } ] Remote device: ethtool --include-statistics --json --show-mm end1 [ { "ifname": "end1", "pmac-enabled": true, "tx-enabled": true, "tx-active": true, "tx-min-frag-size": 60, "rx-min-frag-size": 60, "verify-enabled": true, "verify-time": 100, "max-verify-time": 128, "verify-status": "SUCCEEDED", "statistics": { "MACMergeFrameAssErrorCount": 0, "MACMergeFrameSmdErrorCount": 0, "MACMergeFrameAssOkCount": 35105, "MACMergeFragCountRx": 35105, "MACMergeFragCountTx": 0, "MACMergeHoldCount": 0 } } ] Tested on DWMAC CORE 5.10a Signed-off-by: Furong Xu <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Link: https://patch.msgid.link/592965ea93ed8240f0a1b8f6f8ebb8914f69419b.1725631883.git.0x1207@gmail.com Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0f156ac commit 195e4f4

File tree

7 files changed

+172
-3
lines changed

7 files changed

+172
-3
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,7 @@ const struct stmmac_ops dwmac410_ops = {
12661266
.fpe_irq_status = dwmac5_fpe_irq_status,
12671267
.fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
12681268
.fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
1269+
.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
12691270
.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
12701271
.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
12711272
.restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,
@@ -1320,6 +1321,7 @@ const struct stmmac_ops dwmac510_ops = {
13201321
.fpe_irq_status = dwmac5_fpe_irq_status,
13211322
.fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
13221323
.fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
1324+
.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
13231325
.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
13241326
.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
13251327
.restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,

drivers/net/ethernet/stmicro/stmmac/dwmac5.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,58 @@ void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size)
667667
writel(u32_replace_bits(value, add_frag_size, DWMAC5_ADD_FRAG_SZ),
668668
ioaddr + MTL_FPE_CTRL_STS);
669669
}
670+
671+
#define ALG_ERR_MSG "TX algorithm SP is not suitable for one-to-many mapping"
672+
#define WEIGHT_ERR_MSG "TXQ weight %u differs across other TXQs in TC: [%u]"
673+
674+
int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
675+
struct netlink_ext_ack *extack, u32 pclass)
676+
{
677+
u32 val, offset, count, queue_weight, preemptible_txqs = 0;
678+
struct stmmac_priv *priv = netdev_priv(ndev);
679+
u32 num_tc = ndev->num_tc;
680+
681+
if (!pclass)
682+
goto update_mapping;
683+
684+
/* DWMAC CORE4+ can not program TC:TXQ mapping to hardware.
685+
*
686+
* Synopsys Databook:
687+
* "The number of Tx DMA channels is equal to the number of Tx queues,
688+
* and is direct one-to-one mapping."
689+
*/
690+
for (u32 tc = 0; tc < num_tc; tc++) {
691+
count = ndev->tc_to_txq[tc].count;
692+
offset = ndev->tc_to_txq[tc].offset;
693+
694+
if (pclass & BIT(tc))
695+
preemptible_txqs |= GENMASK(offset + count - 1, offset);
696+
697+
/* This is 1:1 mapping, go to next TC */
698+
if (count == 1)
699+
continue;
700+
701+
if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) {
702+
NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG);
703+
return -EINVAL;
704+
}
705+
706+
queue_weight = priv->plat->tx_queues_cfg[offset].weight;
707+
708+
for (u32 i = 1; i < count; i++) {
709+
if (priv->plat->tx_queues_cfg[offset + i].weight !=
710+
queue_weight) {
711+
NL_SET_ERR_MSG_FMT_MOD(extack, WEIGHT_ERR_MSG,
712+
queue_weight, tc);
713+
return -EINVAL;
714+
}
715+
}
716+
}
717+
718+
update_mapping:
719+
val = readl(priv->ioaddr + MTL_FPE_CTRL_STS);
720+
writel(u32_replace_bits(val, preemptible_txqs, DWMAC5_PREEMPTION_CLASS),
721+
priv->ioaddr + MTL_FPE_CTRL_STS);
722+
723+
return 0;
724+
}

drivers/net/ethernet/stmicro/stmmac/dwmac5.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#define MAC_PPSx_WIDTH(x) (0x00000b8c + ((x) * 0x10))
4141

4242
#define MTL_FPE_CTRL_STS 0x00000c90
43+
/* Preemption Classification */
44+
#define DWMAC5_PREEMPTION_CLASS GENMASK(15, 8)
4345
/* Additional Fragment Size of preempted frames */
4446
#define DWMAC5_ADD_FRAG_SZ GENMASK(1, 0)
4547

@@ -115,5 +117,7 @@ void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
115117
int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);
116118
int dwmac5_fpe_get_add_frag_size(const void __iomem *ioaddr);
117119
void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size);
120+
int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
121+
struct netlink_ext_ack *extack, u32 pclass);
118122

119123
#endif /* __DWMAC5_H__ */

drivers/net/ethernet/stmicro/stmmac/hwif.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ static const struct stmmac_hwif_entry {
171171
.mac = &dwmac4_ops,
172172
.hwtimestamp = &stmmac_ptp,
173173
.mode = NULL,
174-
.tc = &dwmac510_tc_ops,
174+
.tc = &dwmac4_tc_ops,
175175
.mmc = &dwmac_mmc_ops,
176176
.est = &dwmac510_est_ops,
177177
.setup = dwmac4_setup,
@@ -252,7 +252,7 @@ static const struct stmmac_hwif_entry {
252252
.mac = &dwxgmac210_ops,
253253
.hwtimestamp = &stmmac_ptp,
254254
.mode = NULL,
255-
.tc = &dwmac510_tc_ops,
255+
.tc = &dwxgmac_tc_ops,
256256
.mmc = &dwxgmac_mmc_ops,
257257
.est = &dwmac510_est_ops,
258258
.setup = dwxgmac2_setup,
@@ -273,7 +273,7 @@ static const struct stmmac_hwif_entry {
273273
.mac = &dwxlgmac2_ops,
274274
.hwtimestamp = &stmmac_ptp,
275275
.mode = NULL,
276-
.tc = &dwmac510_tc_ops,
276+
.tc = &dwxgmac_tc_ops,
277277
.mmc = &dwxgmac_mmc_ops,
278278
.est = &dwmac510_est_ops,
279279
.setup = dwxlgmac2_setup,

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <linux/netdevice.h>
99
#include <linux/stmmac.h>
10+
#include <net/pkt_cls.h>
1011

1112
#define stmmac_do_void_callback(__priv, __module, __cname, __arg0, __args...) \
1213
({ \
@@ -428,6 +429,9 @@ struct stmmac_ops {
428429
int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);
429430
int (*fpe_get_add_frag_size)(const void __iomem *ioaddr);
430431
void (*fpe_set_add_frag_size)(void __iomem *ioaddr, u32 add_frag_size);
432+
int (*fpe_map_preemption_class)(struct net_device *ndev,
433+
struct netlink_ext_ack *extack,
434+
u32 pclass);
431435
};
432436

433437
#define stmmac_core_init(__priv, __args...) \
@@ -536,6 +540,8 @@ struct stmmac_ops {
536540
stmmac_do_callback(__priv, mac, fpe_get_add_frag_size, __args)
537541
#define stmmac_fpe_set_add_frag_size(__priv, __args...) \
538542
stmmac_do_void_callback(__priv, mac, fpe_set_add_frag_size, __args)
543+
#define stmmac_fpe_map_preemption_class(__priv, __args...) \
544+
stmmac_do_void_callback(__priv, mac, fpe_map_preemption_class, __args)
539545

540546
/* PTP and HW Timer helpers */
541547
struct stmmac_hwtimestamp {
@@ -623,6 +629,8 @@ struct stmmac_tc_ops {
623629
struct tc_etf_qopt_offload *qopt);
624630
int (*query_caps)(struct stmmac_priv *priv,
625631
struct tc_query_caps_base *base);
632+
int (*setup_mqprio)(struct stmmac_priv *priv,
633+
struct tc_mqprio_qopt_offload *qopt);
626634
};
627635

628636
#define stmmac_tc_init(__priv, __args...) \
@@ -639,6 +647,8 @@ struct stmmac_tc_ops {
639647
stmmac_do_callback(__priv, tc, setup_etf, __args)
640648
#define stmmac_tc_query_caps(__priv, __args...) \
641649
stmmac_do_callback(__priv, tc, query_caps, __args)
650+
#define stmmac_tc_setup_mqprio(__priv, __args...) \
651+
stmmac_do_callback(__priv, tc, setup_mqprio, __args)
642652

643653
struct stmmac_counters;
644654

@@ -682,7 +692,9 @@ extern const struct stmmac_dma_ops dwmac4_dma_ops;
682692
extern const struct stmmac_ops dwmac410_ops;
683693
extern const struct stmmac_dma_ops dwmac410_dma_ops;
684694
extern const struct stmmac_ops dwmac510_ops;
695+
extern const struct stmmac_tc_ops dwmac4_tc_ops;
685696
extern const struct stmmac_tc_ops dwmac510_tc_ops;
697+
extern const struct stmmac_tc_ops dwxgmac_tc_ops;
686698
extern const struct stmmac_ops dwxgmac210_ops;
687699
extern const struct stmmac_ops dwxlgmac2_ops;
688700
extern const struct stmmac_dma_ops dwxgmac210_dma_ops;

drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6216,6 +6216,8 @@ static int stmmac_setup_tc(struct net_device *ndev, enum tc_setup_type type,
62166216
switch (type) {
62176217
case TC_QUERY_CAPS:
62186218
return stmmac_tc_query_caps(priv, priv, type_data);
6219+
case TC_SETUP_QDISC_MQPRIO:
6220+
return stmmac_tc_setup_mqprio(priv, priv, type_data);
62196221
case TC_SETUP_BLOCK:
62206222
return flow_block_cb_setup_simple(type_data,
62216223
&stmmac_block_cb_list,

drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,13 @@ static int tc_query_caps(struct stmmac_priv *priv,
11741174
struct tc_query_caps_base *base)
11751175
{
11761176
switch (base->type) {
1177+
case TC_SETUP_QDISC_MQPRIO: {
1178+
struct tc_mqprio_caps *caps = base->caps;
1179+
1180+
caps->validate_queue_counts = true;
1181+
1182+
return 0;
1183+
}
11771184
case TC_SETUP_QDISC_TAPRIO: {
11781185
struct tc_taprio_caps *caps = base->caps;
11791186

@@ -1190,6 +1197,81 @@ static int tc_query_caps(struct stmmac_priv *priv,
11901197
}
11911198
}
11921199

1200+
static void stmmac_reset_tc_mqprio(struct net_device *ndev,
1201+
struct netlink_ext_ack *extack)
1202+
{
1203+
struct stmmac_priv *priv = netdev_priv(ndev);
1204+
1205+
netdev_reset_tc(ndev);
1206+
netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use);
1207+
stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
1208+
}
1209+
1210+
static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
1211+
struct tc_mqprio_qopt_offload *mqprio)
1212+
{
1213+
struct netlink_ext_ack *extack = mqprio->extack;
1214+
struct tc_mqprio_qopt *qopt = &mqprio->qopt;
1215+
u32 offset, count, num_stack_tx_queues = 0;
1216+
struct net_device *ndev = priv->dev;
1217+
u32 num_tc = qopt->num_tc;
1218+
int err;
1219+
1220+
if (!num_tc) {
1221+
stmmac_reset_tc_mqprio(ndev, extack);
1222+
return 0;
1223+
}
1224+
1225+
err = netdev_set_num_tc(ndev, num_tc);
1226+
if (err)
1227+
return err;
1228+
1229+
for (u32 tc = 0; tc < num_tc; tc++) {
1230+
offset = qopt->offset[tc];
1231+
count = qopt->count[tc];
1232+
num_stack_tx_queues += count;
1233+
1234+
err = netdev_set_tc_queue(ndev, tc, count, offset);
1235+
if (err)
1236+
goto err_reset_tc;
1237+
}
1238+
1239+
err = netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
1240+
if (err)
1241+
goto err_reset_tc;
1242+
1243+
err = stmmac_fpe_map_preemption_class(priv, ndev, extack,
1244+
mqprio->preemptible_tcs);
1245+
if (err)
1246+
goto err_reset_tc;
1247+
1248+
return 0;
1249+
1250+
err_reset_tc:
1251+
stmmac_reset_tc_mqprio(ndev, extack);
1252+
1253+
return err;
1254+
}
1255+
1256+
static int tc_setup_mqprio_unimplemented(struct stmmac_priv *priv,
1257+
struct tc_mqprio_qopt_offload *mqprio)
1258+
{
1259+
NL_SET_ERR_MSG_MOD(mqprio->extack,
1260+
"mqprio HW offload is not implemented for this MAC");
1261+
return -EOPNOTSUPP;
1262+
}
1263+
1264+
const struct stmmac_tc_ops dwmac4_tc_ops = {
1265+
.init = tc_init,
1266+
.setup_cls_u32 = tc_setup_cls_u32,
1267+
.setup_cbs = tc_setup_cbs,
1268+
.setup_cls = tc_setup_cls,
1269+
.setup_taprio = tc_setup_taprio,
1270+
.setup_etf = tc_setup_etf,
1271+
.query_caps = tc_query_caps,
1272+
.setup_mqprio = tc_setup_mqprio_unimplemented,
1273+
};
1274+
11931275
const struct stmmac_tc_ops dwmac510_tc_ops = {
11941276
.init = tc_init,
11951277
.setup_cls_u32 = tc_setup_cls_u32,
@@ -1198,4 +1280,16 @@ const struct stmmac_tc_ops dwmac510_tc_ops = {
11981280
.setup_taprio = tc_setup_taprio,
11991281
.setup_etf = tc_setup_etf,
12001282
.query_caps = tc_query_caps,
1283+
.setup_mqprio = tc_setup_dwmac510_mqprio,
1284+
};
1285+
1286+
const struct stmmac_tc_ops dwxgmac_tc_ops = {
1287+
.init = tc_init,
1288+
.setup_cls_u32 = tc_setup_cls_u32,
1289+
.setup_cbs = tc_setup_cbs,
1290+
.setup_cls = tc_setup_cls,
1291+
.setup_taprio = tc_setup_taprio,
1292+
.setup_etf = tc_setup_etf,
1293+
.query_caps = tc_query_caps,
1294+
.setup_mqprio = tc_setup_mqprio_unimplemented,
12011295
};

0 commit comments

Comments
 (0)