| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 7a342f60e569047e1632f6af91f503993769a2ec Mon Sep 17 00:00:00 2001 |
| 2 | From: Ioana Radulescu <ruxandra.radulescu@nxp.com> |
| 3 | Date: Tue, 17 Sep 2019 19:51:15 +0300 |
| 4 | Subject: [PATCH] dpaa2-eth: Enable Rx PFC |
| 5 | |
| 6 | Instruct the hardware to respond to received PFC frames. |
| 7 | |
| 8 | Current firmware doesn't allow us to selectively enable PFC |
| 9 | on the Rx side for some priorities only, so we will react to |
| 10 | all incoming PFC frames (and stop transmitting on the traffic |
| 11 | classes specified in the frame). |
| 12 | |
| 13 | PFC depends on the PAUSE flag also being set in link options. |
| 14 | Don't set it implicitly when user configures PFC, but issue |
| 15 | a warning if the two settings are not in sync. |
| 16 | |
| 17 | For the Tx side, setting the PFC_PAUSE flag in the link options |
| 18 | is necessary but not sufficient, so PFC frame generation is |
| 19 | not enabled yet. |
| 20 | |
| 21 | Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com> |
| 22 | --- |
| 23 | drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 23 +++++++++++++++++++++++ |
| 24 | drivers/net/ethernet/freescale/dpaa2/dpni.h | 5 +++++ |
| 25 | 2 files changed, 28 insertions(+) |
| 26 | |
| 27 | --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c |
| 28 | +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c |
| 29 | @@ -3620,6 +3620,9 @@ static int dpaa2_eth_dcbnl_ieee_getpfc(s |
| 30 | { |
| 31 | struct dpaa2_eth_priv *priv = netdev_priv(net_dev); |
| 32 | |
| 33 | + if (!(priv->link_state.options & DPNI_LINK_OPT_PFC_PAUSE)) |
| 34 | + return 0; |
| 35 | + |
| 36 | memcpy(pfc, &priv->pfc, sizeof(priv->pfc)); |
| 37 | pfc->pfc_cap = dpaa2_eth_tc_count(priv); |
| 38 | |
| 39 | @@ -3630,6 +3633,8 @@ static int dpaa2_eth_dcbnl_ieee_setpfc(s |
| 40 | struct ieee_pfc *pfc) |
| 41 | { |
| 42 | struct dpaa2_eth_priv *priv = netdev_priv(net_dev); |
| 43 | + struct dpni_link_cfg link_cfg = {0}; |
| 44 | + int err; |
| 45 | |
| 46 | if (pfc->mbc || pfc->delay) |
| 47 | return -EOPNOTSUPP; |
| 48 | @@ -3638,6 +3643,24 @@ static int dpaa2_eth_dcbnl_ieee_setpfc(s |
| 49 | if (priv->pfc.pfc_en == pfc->pfc_en) |
| 50 | return 0; |
| 51 | |
| 52 | + /* We allow PFC configuration even if it won't have any effect until |
| 53 | + * general pause frames are enabled |
| 54 | + */ |
| 55 | + if (!dpaa2_eth_rx_pause_enabled(priv->link_state.options)) |
| 56 | + netdev_warn(net_dev, "Pause support must be enabled in order for PFC to work!\n"); |
| 57 | + |
| 58 | + link_cfg.rate = priv->link_state.rate; |
| 59 | + link_cfg.options = priv->link_state.options; |
| 60 | + if (pfc->pfc_en) |
| 61 | + link_cfg.options |= DPNI_LINK_OPT_PFC_PAUSE; |
| 62 | + else |
| 63 | + link_cfg.options &= ~DPNI_LINK_OPT_PFC_PAUSE; |
| 64 | + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &link_cfg); |
| 65 | + if (err) { |
| 66 | + netdev_err(net_dev, "dpni_set_link_cfg failed\n"); |
| 67 | + return err; |
| 68 | + } |
| 69 | + |
| 70 | memcpy(&priv->pfc, pfc, sizeof(priv->pfc)); |
| 71 | |
| 72 | return 0; |
| 73 | --- a/drivers/net/ethernet/freescale/dpaa2/dpni.h |
| 74 | +++ b/drivers/net/ethernet/freescale/dpaa2/dpni.h |
| 75 | @@ -514,6 +514,11 @@ int dpni_get_statistics(struct fsl_mc_io |
| 76 | #define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL |
| 77 | |
| 78 | /** |
| 79 | + * Enable priority flow control pause frames |
| 80 | + */ |
| 81 | +#define DPNI_LINK_OPT_PFC_PAUSE 0x0000000000000010ULL |
| 82 | + |
| 83 | +/** |
| 84 | * struct - Structure representing DPNI link configuration |
| 85 | * @rate: Rate |
| 86 | * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values |