1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2020 NXP */
6 static int dpaa2_eth_dcbnl_ieee_getpfc(struct net_device
*net_dev
,
9 struct dpaa2_eth_priv
*priv
= netdev_priv(net_dev
);
11 if (!(priv
->link_state
.options
& DPNI_LINK_OPT_PFC_PAUSE
))
14 memcpy(pfc
, &priv
->pfc
, sizeof(priv
->pfc
));
15 pfc
->pfc_cap
= dpaa2_eth_tc_count(priv
);
20 static inline bool dpaa2_eth_is_prio_enabled(u8 pfc_en
, u8 tc
)
22 return !!(pfc_en
& (1 << tc
));
25 static int dpaa2_eth_set_pfc_cn(struct dpaa2_eth_priv
*priv
, u8 pfc_en
)
27 struct dpni_congestion_notification_cfg cfg
= {0};
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;
35 for (i
= 0; i
< dpaa2_eth_tc_count(priv
); i
++) {
36 if (dpaa2_eth_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
);
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
44 cfg
.threshold_entry
= 0;
45 cfg
.threshold_exit
= 0;
48 err
= dpni_set_congestion_notification(priv
->mc_io
, 0,
50 DPNI_QUEUE_RX
, i
, &cfg
);
52 netdev_err(priv
->net_dev
,
53 "dpni_set_congestion_notification failed\n");
61 static int dpaa2_eth_dcbnl_ieee_setpfc(struct net_device
*net_dev
,
64 struct dpaa2_eth_priv
*priv
= netdev_priv(net_dev
);
65 struct dpni_link_cfg link_cfg
= {0};
69 if (pfc
->mbc
|| pfc
->delay
)
72 /* If same PFC enabled mask, nothing to do */
73 if (priv
->pfc
.pfc_en
== pfc
->pfc_en
)
76 /* We allow PFC configuration even if it won't have any effect until
77 * general pause frames are enabled
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");
83 link_cfg
.rate
= priv
->link_state
.rate
;
84 link_cfg
.options
= priv
->link_state
.options
;
86 link_cfg
.options
|= DPNI_LINK_OPT_PFC_PAUSE
;
88 link_cfg
.options
&= ~DPNI_LINK_OPT_PFC_PAUSE
;
89 err
= dpni_set_link_cfg(priv
->mc_io
, 0, priv
->mc_token
, &link_cfg
);
91 netdev_err(net_dev
, "dpni_set_link_cfg failed\n");
95 /* Configure congestion notifications for the enabled priorities */
96 err
= dpaa2_eth_set_pfc_cn(priv
, pfc
->pfc_en
);
100 memcpy(&priv
->pfc
, pfc
, sizeof(priv
->pfc
));
101 priv
->pfc_enabled
= !!pfc
->pfc_en
;
103 dpaa2_eth_set_rx_taildrop(priv
, tx_pause
, priv
->pfc_enabled
);
108 static u8
dpaa2_eth_dcbnl_getdcbx(struct net_device
*net_dev
)
110 struct dpaa2_eth_priv
*priv
= netdev_priv(net_dev
);
112 return priv
->dcbx_mode
;
115 static u8
dpaa2_eth_dcbnl_setdcbx(struct net_device
*net_dev
, u8 mode
)
117 struct dpaa2_eth_priv
*priv
= netdev_priv(net_dev
);
119 return (mode
!= (priv
->dcbx_mode
)) ? 1 : 0;
122 static u8
dpaa2_eth_dcbnl_getcap(struct net_device
*net_dev
, int capid
, u8
*cap
)
124 struct dpaa2_eth_priv
*priv
= netdev_priv(net_dev
);
127 case DCB_CAP_ATTR_PFC
:
130 case DCB_CAP_ATTR_PFC_TCS
:
131 *cap
= 1 << (dpaa2_eth_tc_count(priv
) - 1);
133 case DCB_CAP_ATTR_DCBX
:
134 *cap
= priv
->dcbx_mode
;
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
,