aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEran Ben Elisha <eranbe@mellanox.com>2018-03-27 07:41:18 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-27 12:02:30 -0400
commit6e8814ceb7e8f468659ef9253bd212c07ae19584 (patch)
tree969970bea901bed43c6901258c0e0ed7f7cdecb9
parentab6f6dd18ab801fcbbaa05fb5401e91f48778e04 (diff)
net/mlx4_en: Fix mixed PFC and Global pause user control requests
Global pause and PFC configuration should be mutually exclusive (i.e. only one of them at most can be set). However, once PFC was turned off, driver automatically turned Global pause on. This is a bug. Fix the driver behaviour to turn off PFC/Global once the user turned the other on. This also fixed a weird behaviour that at a current time, the profile had both PFC and global pause configuration turned on, which is Hardware-wise impossible and caused returning false positive indication to query tools. In addition, fix error code when setting global pause or PFC to change metadata only upon successful change. Also, removed useless debug print. Fixes: af7d51852631 ("net/mlx4_en: Add DCB PFC support through CEE netlink commands") Fixes: c27a02cd94d6 ("mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC") Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com> Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c72
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_ethtool.c33
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_main.c4
3 files changed, 62 insertions, 47 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
index 1a0c3bf86ead..752a72499b4f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
@@ -156,57 +156,63 @@ static int mlx4_en_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
156static u8 mlx4_en_dcbnl_set_all(struct net_device *netdev) 156static u8 mlx4_en_dcbnl_set_all(struct net_device *netdev)
157{ 157{
158 struct mlx4_en_priv *priv = netdev_priv(netdev); 158 struct mlx4_en_priv *priv = netdev_priv(netdev);
159 struct mlx4_en_port_profile *prof = priv->prof;
159 struct mlx4_en_dev *mdev = priv->mdev; 160 struct mlx4_en_dev *mdev = priv->mdev;
161 u8 tx_pause, tx_ppp, rx_pause, rx_ppp;
160 162
161 if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 163 if (!(priv->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
162 return 1; 164 return 1;
163 165
164 if (priv->cee_config.pfc_state) { 166 if (priv->cee_config.pfc_state) {
165 int tc; 167 int tc;
168 rx_ppp = prof->rx_ppp;
169 tx_ppp = prof->tx_ppp;
166 170
167 priv->prof->rx_pause = 0;
168 priv->prof->tx_pause = 0;
169 for (tc = 0; tc < CEE_DCBX_MAX_PRIO; tc++) { 171 for (tc = 0; tc < CEE_DCBX_MAX_PRIO; tc++) {
170 u8 tc_mask = 1 << tc; 172 u8 tc_mask = 1 << tc;
171 173
172 switch (priv->cee_config.dcb_pfc[tc]) { 174 switch (priv->cee_config.dcb_pfc[tc]) {
173 case pfc_disabled: 175 case pfc_disabled:
174 priv->prof->tx_ppp &= ~tc_mask; 176 tx_ppp &= ~tc_mask;
175 priv->prof->rx_ppp &= ~tc_mask; 177 rx_ppp &= ~tc_mask;
176 break; 178 break;
177 case pfc_enabled_full: 179 case pfc_enabled_full:
178 priv->prof->tx_ppp |= tc_mask; 180 tx_ppp |= tc_mask;
179 priv->prof->rx_ppp |= tc_mask; 181 rx_ppp |= tc_mask;
180 break; 182 break;
181 case pfc_enabled_tx: 183 case pfc_enabled_tx:
182 priv->prof->tx_ppp |= tc_mask; 184 tx_ppp |= tc_mask;
183 priv->prof->rx_ppp &= ~tc_mask; 185 rx_ppp &= ~tc_mask;
184 break; 186 break;
185 case pfc_enabled_rx: 187 case pfc_enabled_rx:
186 priv->prof->tx_ppp &= ~tc_mask; 188 tx_ppp &= ~tc_mask;
187 priv->prof->rx_ppp |= tc_mask; 189 rx_ppp |= tc_mask;
188 break; 190 break;
189 default: 191 default:
190 break; 192 break;
191 } 193 }
192 } 194 }
193 en_dbg(DRV, priv, "Set pfc on\n"); 195 rx_pause = !!(rx_ppp || tx_ppp) ? 0 : prof->rx_pause;
196 tx_pause = !!(rx_ppp || tx_ppp) ? 0 : prof->tx_pause;
194 } else { 197 } else {
195 priv->prof->rx_pause = 1; 198 rx_ppp = 0;
196 priv->prof->tx_pause = 1; 199 tx_ppp = 0;
197 en_dbg(DRV, priv, "Set pfc off\n"); 200 rx_pause = prof->rx_pause;
201 tx_pause = prof->tx_pause;
198 } 202 }
199 203
200 if (mlx4_SET_PORT_general(mdev->dev, priv->port, 204 if (mlx4_SET_PORT_general(mdev->dev, priv->port,
201 priv->rx_skb_size + ETH_FCS_LEN, 205 priv->rx_skb_size + ETH_FCS_LEN,
202 priv->prof->tx_pause, 206 tx_pause, tx_ppp, rx_pause, rx_ppp)) {
203 priv->prof->tx_ppp,
204 priv->prof->rx_pause,
205 priv->prof->rx_ppp)) {
206 en_err(priv, "Failed setting pause params\n"); 207 en_err(priv, "Failed setting pause params\n");
207 return 1; 208 return 1;
208 } 209 }
209 210
211 prof->tx_ppp = tx_ppp;
212 prof->rx_ppp = rx_ppp;
213 prof->tx_pause = tx_pause;
214 prof->rx_pause = rx_pause;
215
210 return 0; 216 return 0;
211} 217}
212 218
@@ -408,6 +414,7 @@ static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev,
408 struct mlx4_en_priv *priv = netdev_priv(dev); 414 struct mlx4_en_priv *priv = netdev_priv(dev);
409 struct mlx4_en_port_profile *prof = priv->prof; 415 struct mlx4_en_port_profile *prof = priv->prof;
410 struct mlx4_en_dev *mdev = priv->mdev; 416 struct mlx4_en_dev *mdev = priv->mdev;
417 u32 tx_pause, tx_ppp, rx_pause, rx_ppp;
411 int err; 418 int err;
412 419
413 en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n", 420 en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n",
@@ -416,23 +423,26 @@ static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev,
416 pfc->mbc, 423 pfc->mbc,
417 pfc->delay); 424 pfc->delay);
418 425
419 prof->rx_pause = !pfc->pfc_en; 426 rx_pause = prof->rx_pause && !pfc->pfc_en;
420 prof->tx_pause = !pfc->pfc_en; 427 tx_pause = prof->tx_pause && !pfc->pfc_en;
421 prof->rx_ppp = pfc->pfc_en; 428 rx_ppp = pfc->pfc_en;
422 prof->tx_ppp = pfc->pfc_en; 429 tx_ppp = pfc->pfc_en;
423 430
424 err = mlx4_SET_PORT_general(mdev->dev, priv->port, 431 err = mlx4_SET_PORT_general(mdev->dev, priv->port,
425 priv->rx_skb_size + ETH_FCS_LEN, 432 priv->rx_skb_size + ETH_FCS_LEN,
426 prof->tx_pause, 433 tx_pause, tx_ppp, rx_pause, rx_ppp);
427 prof->tx_ppp, 434 if (err) {
428 prof->rx_pause,
429 prof->rx_ppp);
430 if (err)
431 en_err(priv, "Failed setting pause params\n"); 435 en_err(priv, "Failed setting pause params\n");
432 else 436 return err;
433 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap, 437 }
434 prof->rx_ppp, prof->rx_pause, 438
435 prof->tx_ppp, prof->tx_pause); 439 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap,
440 rx_ppp, rx_pause, tx_ppp, tx_pause);
441
442 prof->tx_ppp = tx_ppp;
443 prof->rx_ppp = rx_ppp;
444 prof->rx_pause = rx_pause;
445 prof->tx_pause = tx_pause;
436 446
437 return err; 447 return err;
438} 448}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
index ebc1f566a4d9..f3302edba8b4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1046,27 +1046,32 @@ static int mlx4_en_set_pauseparam(struct net_device *dev,
1046{ 1046{
1047 struct mlx4_en_priv *priv = netdev_priv(dev); 1047 struct mlx4_en_priv *priv = netdev_priv(dev);
1048 struct mlx4_en_dev *mdev = priv->mdev; 1048 struct mlx4_en_dev *mdev = priv->mdev;
1049 u8 tx_pause, tx_ppp, rx_pause, rx_ppp;
1049 int err; 1050 int err;
1050 1051
1051 if (pause->autoneg) 1052 if (pause->autoneg)
1052 return -EINVAL; 1053 return -EINVAL;
1053 1054
1054 priv->prof->tx_pause = pause->tx_pause != 0; 1055 tx_pause = !!(pause->tx_pause);
1055 priv->prof->rx_pause = pause->rx_pause != 0; 1056 rx_pause = !!(pause->rx_pause);
1057 rx_ppp = priv->prof->rx_ppp && !(tx_pause || rx_pause);
1058 tx_ppp = priv->prof->tx_ppp && !(tx_pause || rx_pause);
1059
1056 err = mlx4_SET_PORT_general(mdev->dev, priv->port, 1060 err = mlx4_SET_PORT_general(mdev->dev, priv->port,
1057 priv->rx_skb_size + ETH_FCS_LEN, 1061 priv->rx_skb_size + ETH_FCS_LEN,
1058 priv->prof->tx_pause, 1062 tx_pause, tx_ppp, rx_pause, rx_ppp);
1059 priv->prof->tx_ppp, 1063 if (err) {
1060 priv->prof->rx_pause, 1064 en_err(priv, "Failed setting pause params, err = %d\n", err);
1061 priv->prof->rx_ppp); 1065 return err;
1062 if (err) 1066 }
1063 en_err(priv, "Failed setting pause params\n"); 1067
1064 else 1068 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap,
1065 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap, 1069 rx_ppp, rx_pause, tx_ppp, tx_pause);
1066 priv->prof->rx_ppp, 1070
1067 priv->prof->rx_pause, 1071 priv->prof->tx_pause = tx_pause;
1068 priv->prof->tx_ppp, 1072 priv->prof->rx_pause = rx_pause;
1069 priv->prof->tx_pause); 1073 priv->prof->tx_ppp = tx_ppp;
1074 priv->prof->rx_ppp = rx_ppp;
1070 1075
1071 return err; 1076 return err;
1072} 1077}
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_main.c b/drivers/net/ethernet/mellanox/mlx4/en_main.c
index 2c2965497ed3..d25e16d2c319 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_main.c
@@ -163,9 +163,9 @@ static void mlx4_en_get_profile(struct mlx4_en_dev *mdev)
163 params->udp_rss = 0; 163 params->udp_rss = 0;
164 } 164 }
165 for (i = 1; i <= MLX4_MAX_PORTS; i++) { 165 for (i = 1; i <= MLX4_MAX_PORTS; i++) {
166 params->prof[i].rx_pause = 1; 166 params->prof[i].rx_pause = !(pfcrx || pfctx);
167 params->prof[i].rx_ppp = pfcrx; 167 params->prof[i].rx_ppp = pfcrx;
168 params->prof[i].tx_pause = 1; 168 params->prof[i].tx_pause = !(pfcrx || pfctx);
169 params->prof[i].tx_ppp = pfctx; 169 params->prof[i].tx_ppp = pfctx;
170 params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE; 170 params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
171 params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE; 171 params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;