|
41 | 41 | #define MLX5E_CEE_STATE_UP 1
|
42 | 42 | #define MLX5E_CEE_STATE_DOWN 0
|
43 | 43 |
|
| 44 | +/* If dcbx mode is non-host set the dcbx mode to host. |
| 45 | + */ |
| 46 | +static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv, |
| 47 | + enum mlx5_dcbx_oper_mode mode) |
| 48 | +{ |
| 49 | + struct mlx5_core_dev *mdev = priv->mdev; |
| 50 | + u32 param[MLX5_ST_SZ_DW(dcbx_param)]; |
| 51 | + int err; |
| 52 | + |
| 53 | + err = mlx5_query_port_dcbx_param(mdev, param); |
| 54 | + if (err) |
| 55 | + return err; |
| 56 | + |
| 57 | + MLX5_SET(dcbx_param, param, version_admin, mode); |
| 58 | + if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST) |
| 59 | + MLX5_SET(dcbx_param, param, willing_admin, 1); |
| 60 | + |
| 61 | + return mlx5_set_port_dcbx_param(mdev, param); |
| 62 | +} |
| 63 | + |
| 64 | +static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv) |
| 65 | +{ |
| 66 | + struct mlx5e_dcbx *dcbx = &priv->dcbx; |
| 67 | + int err; |
| 68 | + |
| 69 | + if (!MLX5_CAP_GEN(priv->mdev, dcbx)) |
| 70 | + return 0; |
| 71 | + |
| 72 | + if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST) |
| 73 | + return 0; |
| 74 | + |
| 75 | + err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST); |
| 76 | + if (err) |
| 77 | + return err; |
| 78 | + |
| 79 | + dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST; |
| 80 | + return 0; |
| 81 | +} |
| 82 | + |
44 | 83 | static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
|
45 | 84 | struct ieee_ets *ets)
|
46 | 85 | {
|
@@ -255,6 +294,9 @@ static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
|
255 | 294 |
|
256 | 295 | static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
|
257 | 296 | {
|
| 297 | + if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev))) |
| 298 | + return 1; |
| 299 | + |
258 | 300 | if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
|
259 | 301 | !(mode & DCB_CAP_DCBX_VER_CEE) ||
|
260 | 302 | !(mode & DCB_CAP_DCBX_VER_IEEE) ||
|
@@ -637,3 +679,52 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
|
637 | 679 | .getpfcstate = mlx5e_dcbnl_getpfcstate,
|
638 | 680 | .setpfcstate = mlx5e_dcbnl_setpfcstate,
|
639 | 681 | };
|
| 682 | + |
| 683 | +static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv, |
| 684 | + enum mlx5_dcbx_oper_mode *mode) |
| 685 | +{ |
| 686 | + u32 out[MLX5_ST_SZ_DW(dcbx_param)]; |
| 687 | + |
| 688 | + *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST; |
| 689 | + |
| 690 | + if (!mlx5_query_port_dcbx_param(priv->mdev, out)) |
| 691 | + *mode = MLX5_GET(dcbx_param, out, version_oper); |
| 692 | + |
| 693 | + /* From driver's point of view, we only care if the mode |
| 694 | + * is host (HOST) or non-host (AUTO) |
| 695 | + */ |
| 696 | + if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST) |
| 697 | + *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO; |
| 698 | +} |
| 699 | + |
| 700 | +static void mlx5e_ets_init(struct mlx5e_priv *priv) |
| 701 | +{ |
| 702 | + int i; |
| 703 | + struct ieee_ets ets; |
| 704 | + |
| 705 | + memset(&ets, 0, sizeof(ets)); |
| 706 | + ets.ets_cap = mlx5_max_tc(priv->mdev) + 1; |
| 707 | + for (i = 0; i < ets.ets_cap; i++) { |
| 708 | + ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC; |
| 709 | + ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; |
| 710 | + ets.prio_tc[i] = i; |
| 711 | + } |
| 712 | + |
| 713 | + memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa)); |
| 714 | + |
| 715 | + /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */ |
| 716 | + ets.prio_tc[0] = 1; |
| 717 | + ets.prio_tc[1] = 0; |
| 718 | + |
| 719 | + mlx5e_dcbnl_ieee_setets_core(priv, &ets); |
| 720 | +} |
| 721 | + |
| 722 | +void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv) |
| 723 | +{ |
| 724 | + struct mlx5e_dcbx *dcbx = &priv->dcbx; |
| 725 | + |
| 726 | + if (MLX5_CAP_GEN(priv->mdev, dcbx)) |
| 727 | + mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode); |
| 728 | + |
| 729 | + mlx5e_ets_init(priv); |
| 730 | +} |
0 commit comments