Skip to content

Commit a477605

Browse files
committed
Merge branch 'dpaa2-eth-add-PFC-support'
Ioana Ciornei says: ==================== dpaa2-eth: add PFC support This patch set adds support for Priority Flow Control in DPAA2 Ethernet devices. The first patch make the necessary changes so that multiple traffic classes are configured. The dequeue priority of the maximum 8 traffic classes is configured to be equal. The second patch adds a static distribution to said traffic classes based on the VLAN PCP field. In the future, this could be extended through the .setapp() DCB callback for dynamic configuration. Also, add support for the congestion group taildrop mechanism that allows us to control the number of frames that can accumulate on a group of Rx frame queues belonging to the same traffic class. The basic subset of the DCB ops is implemented so that the user can query the number of PFC capable traffic classes, their state and reconfigure them if necessary. Changes in v3: - add patches 6-7 which add the PFC functionality - patch 2/7: revert to explicitly cast mask to u16 * to not get into sparse warnings Changes in v4: - really fix the sparse warnings in 2/7 ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3190ca3 + 07beb16 commit a477605

File tree

10 files changed

+787
-57
lines changed

10 files changed

+787
-57
lines changed

drivers/net/ethernet/freescale/dpaa2/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ config FSL_DPAA2_ETH
99
The driver manages network objects discovered on the Freescale
1010
MC bus.
1111

12+
if FSL_DPAA2_ETH
13+
config FSL_DPAA2_ETH_DCB
14+
bool "Data Center Bridging (DCB) Support"
15+
default n
16+
depends on DCB
17+
help
18+
Enable Priority-Based Flow Control (PFC) support for DPAA2 Ethernet
19+
devices.
20+
endif
21+
1222
config FSL_DPAA2_PTP_CLOCK
1323
tristate "Freescale DPAA2 PTP Clock"
1424
depends on FSL_DPAA2_ETH && PTP_1588_CLOCK_QORIQ

drivers/net/ethernet/freescale/dpaa2/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
77
obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK) += fsl-dpaa2-ptp.o
88

99
fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o dpaa2-mac.o dpmac.o
10+
fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DCB} += dpaa2-eth-dcb.o
1011
fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
1112
fsl-dpaa2-ptp-objs := dpaa2-ptp.o dprtc.o
1213

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2+
/* Copyright 2020 NXP */
3+
4+
#include "dpaa2-eth.h"
5+
6+
static int dpaa2_eth_dcbnl_ieee_getpfc(struct net_device *net_dev,
7+
struct ieee_pfc *pfc)
8+
{
9+
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
10+
11+
if (!(priv->link_state.options & DPNI_LINK_OPT_PFC_PAUSE))
12+
return 0;
13+
14+
memcpy(pfc, &priv->pfc, sizeof(priv->pfc));
15+
pfc->pfc_cap = dpaa2_eth_tc_count(priv);
16+
17+
return 0;
18+
}
19+
20+
static inline bool is_prio_enabled(u8 pfc_en, u8 tc)
21+
{
22+
return !!(pfc_en & (1 << tc));
23+
}
24+
25+
static int set_pfc_cn(struct dpaa2_eth_priv *priv, u8 pfc_en)
26+
{
27+
struct dpni_congestion_notification_cfg cfg = {0};
28+
int i, err;
29+
30+
cfg.notification_mode = DPNI_CONG_OPT_FLOW_CONTROL;
31+
cfg.units = DPNI_CONGESTION_UNIT_FRAMES;
32+
cfg.message_iova = 0ULL;
33+
cfg.message_ctx = 0ULL;
34+
35+
for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
36+
if (is_prio_enabled(pfc_en, i)) {
37+
cfg.threshold_entry = DPAA2_ETH_CN_THRESH_ENTRY(priv);
38+
cfg.threshold_exit = DPAA2_ETH_CN_THRESH_EXIT(priv);
39+
} else {
40+
/* For priorities not set in the pfc_en mask, we leave
41+
* the congestion thresholds at zero, which effectively
42+
* disables generation of PFC frames for them
43+
*/
44+
cfg.threshold_entry = 0;
45+
cfg.threshold_exit = 0;
46+
}
47+
48+
err = dpni_set_congestion_notification(priv->mc_io, 0,
49+
priv->mc_token,
50+
DPNI_QUEUE_RX, i, &cfg);
51+
if (err) {
52+
netdev_err(priv->net_dev,
53+
"dpni_set_congestion_notification failed\n");
54+
return err;
55+
}
56+
}
57+
58+
return 0;
59+
}
60+
61+
static int dpaa2_eth_dcbnl_ieee_setpfc(struct net_device *net_dev,
62+
struct ieee_pfc *pfc)
63+
{
64+
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
65+
struct dpni_link_cfg link_cfg = {0};
66+
bool tx_pause;
67+
int err;
68+
69+
if (pfc->mbc || pfc->delay)
70+
return -EOPNOTSUPP;
71+
72+
/* If same PFC enabled mask, nothing to do */
73+
if (priv->pfc.pfc_en == pfc->pfc_en)
74+
return 0;
75+
76+
/* We allow PFC configuration even if it won't have any effect until
77+
* general pause frames are enabled
78+
*/
79+
tx_pause = dpaa2_eth_tx_pause_enabled(priv->link_state.options);
80+
if (!dpaa2_eth_rx_pause_enabled(priv->link_state.options) || !tx_pause)
81+
netdev_warn(net_dev, "Pause support must be enabled in order for PFC to work!\n");
82+
83+
link_cfg.rate = priv->link_state.rate;
84+
link_cfg.options = priv->link_state.options;
85+
if (pfc->pfc_en)
86+
link_cfg.options |= DPNI_LINK_OPT_PFC_PAUSE;
87+
else
88+
link_cfg.options &= ~DPNI_LINK_OPT_PFC_PAUSE;
89+
err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &link_cfg);
90+
if (err) {
91+
netdev_err(net_dev, "dpni_set_link_cfg failed\n");
92+
return err;
93+
}
94+
95+
/* Configure congestion notifications for the enabled priorities */
96+
err = set_pfc_cn(priv, pfc->pfc_en);
97+
if (err)
98+
return err;
99+
100+
memcpy(&priv->pfc, pfc, sizeof(priv->pfc));
101+
priv->pfc_enabled = !!pfc->pfc_en;
102+
103+
dpaa2_eth_set_rx_taildrop(priv, tx_pause, priv->pfc_enabled);
104+
105+
return 0;
106+
}
107+
108+
static u8 dpaa2_eth_dcbnl_getdcbx(struct net_device *net_dev)
109+
{
110+
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
111+
112+
return priv->dcbx_mode;
113+
}
114+
115+
static u8 dpaa2_eth_dcbnl_setdcbx(struct net_device *net_dev, u8 mode)
116+
{
117+
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
118+
119+
return (mode != (priv->dcbx_mode)) ? 1 : 0;
120+
}
121+
122+
static u8 dpaa2_eth_dcbnl_getcap(struct net_device *net_dev, int capid, u8 *cap)
123+
{
124+
struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
125+
126+
switch (capid) {
127+
case DCB_CAP_ATTR_PFC:
128+
*cap = true;
129+
break;
130+
case DCB_CAP_ATTR_PFC_TCS:
131+
*cap = 1 << (dpaa2_eth_tc_count(priv) - 1);
132+
break;
133+
case DCB_CAP_ATTR_DCBX:
134+
*cap = priv->dcbx_mode;
135+
break;
136+
default:
137+
*cap = false;
138+
break;
139+
}
140+
141+
return 0;
142+
}
143+
144+
const struct dcbnl_rtnl_ops dpaa2_eth_dcbnl_ops = {
145+
.ieee_getpfc = dpaa2_eth_dcbnl_ieee_getpfc,
146+
.ieee_setpfc = dpaa2_eth_dcbnl_ieee_setpfc,
147+
.getdcbx = dpaa2_eth_dcbnl_getdcbx,
148+
.setdcbx = dpaa2_eth_dcbnl_setdcbx,
149+
.getcap = dpaa2_eth_dcbnl_getcap,
150+
};

drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-debugfs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,19 @@ static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
8181
int i, err;
8282

8383
seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
84-
seq_printf(file, "%s%16s%16s%16s%16s\n",
85-
"VFQID", "CPU", "Type", "Frames", "Pending frames");
84+
seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
85+
"VFQID", "CPU", "TC", "Type", "Frames", "Pending frames");
8686

8787
for (i = 0; i < priv->num_fqs; i++) {
8888
fq = &priv->fq[i];
8989
err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
9090
if (err)
9191
fcnt = 0;
9292

93-
seq_printf(file, "%5d%16d%16s%16llu%16u\n",
93+
seq_printf(file, "%5d%16d%16d%16s%16llu%16u\n",
9494
fq->fqid,
9595
fq->target_cpu,
96+
fq->tc,
9697
fq_type_to_str(fq),
9798
fq->stats.frames,
9899
fcnt);

0 commit comments

Comments
 (0)