1/* 2 * Copyright (c) 2011 Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 * 32 */ 33 34#include <linux/dcbnl.h> 35#include <linux/math64.h> 36 37#include "mlx4_en.h" 38#include "fw_qos.h" 39 40/* Definitions for QCN 41 */ 42 43struct mlx4_congestion_control_mb_prio_802_1_qau_params { 44 __be32 modify_enable_high; 45 __be32 modify_enable_low; 46 __be32 reserved1; 47 __be32 extended_enable; 48 __be32 rppp_max_rps; 49 __be32 rpg_time_reset; 50 __be32 rpg_byte_reset; 51 __be32 rpg_threshold; 52 __be32 rpg_max_rate; 53 __be32 rpg_ai_rate; 54 __be32 rpg_hai_rate; 55 __be32 rpg_gd; 56 __be32 rpg_min_dec_fac; 57 __be32 rpg_min_rate; 58 __be32 max_time_rise; 59 __be32 max_byte_rise; 60 __be32 max_qdelta; 61 __be32 min_qoffset; 62 __be32 gd_coefficient; 63 __be32 reserved2[5]; 64 __be32 cp_sample_base; 65 __be32 reserved3[39]; 66}; 67 68struct mlx4_congestion_control_mb_prio_802_1_qau_statistics { 69 __be64 rppp_rp_centiseconds; 70 __be32 reserved1; 71 __be32 ignored_cnm; 72 __be32 rppp_created_rps; 73 __be32 estimated_total_rate; 74 __be32 max_active_rate_limiter_index; 75 __be32 dropped_cnms_busy_fw; 76 __be32 reserved2; 77 __be32 cnms_handled_successfully; 78 __be32 min_total_limiters_rate; 79 __be32 max_total_limiters_rate; 80 __be32 reserved3[4]; 81}; 82 83static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev, 84 struct ieee_ets *ets) 85{ 86 struct mlx4_en_priv *priv = netdev_priv(dev); 87 struct ieee_ets *my_ets = &priv->ets; 88 89 /* No IEEE PFC settings available */ 90 if (!my_ets) 91 return -EINVAL; 92 93 ets->ets_cap = IEEE_8021QAZ_MAX_TCS; 94 ets->cbs = my_ets->cbs; 95 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); 96 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); 97 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); 98 99 return 0; 100} 101 102static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets) 103{ 104 int i; 105 int total_ets_bw = 0; 106 int has_ets_tc = 0; 107 108 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 109 if (ets->prio_tc[i] >= MLX4_EN_NUM_UP) { 110 en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n", 111 i, ets->prio_tc[i]); 112 return -EINVAL; 113 } 114 115 switch (ets->tc_tsa[i]) { 116 case IEEE_8021QAZ_TSA_STRICT: 117 break; 118 case IEEE_8021QAZ_TSA_ETS: 119 has_ets_tc = 1; 120 total_ets_bw += ets->tc_tx_bw[i]; 121 break; 122 default: 123 en_err(priv, "TC[%d]: Not supported TSA: %d\n", 124 i, ets->tc_tsa[i]); 125 return -ENOTSUPP; 126 } 127 } 128 129 if (has_ets_tc && total_ets_bw != MLX4_EN_BW_MAX) { 130 en_err(priv, "Bad ETS BW sum: %d. Should be exactly 100%%\n", 131 total_ets_bw); 132 return -EINVAL; 133 } 134 135 return 0; 136} 137 138static int mlx4_en_config_port_scheduler(struct mlx4_en_priv *priv, 139 struct ieee_ets *ets, u16 *ratelimit) 140{ 141 struct mlx4_en_dev *mdev = priv->mdev; 142 int num_strict = 0; 143 int i; 144 __u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS] = { 0 }; 145 __u8 pg[IEEE_8021QAZ_MAX_TCS] = { 0 }; 146 147 ets = ets ?: &priv->ets; 148 ratelimit = ratelimit ?: priv->maxrate; 149 150 /* higher TC means higher priority => lower pg */ 151 for (i = IEEE_8021QAZ_MAX_TCS - 1; i >= 0; i--) { 152 switch (ets->tc_tsa[i]) { 153 case IEEE_8021QAZ_TSA_STRICT: 154 pg[i] = num_strict++; 155 tc_tx_bw[i] = MLX4_EN_BW_MAX; 156 break; 157 case IEEE_8021QAZ_TSA_ETS: 158 pg[i] = MLX4_EN_TC_ETS; 159 tc_tx_bw[i] = ets->tc_tx_bw[i] ?: MLX4_EN_BW_MIN; 160 break; 161 } 162 } 163 164 return mlx4_SET_PORT_SCHEDULER(mdev->dev, priv->port, tc_tx_bw, pg, 165 ratelimit); 166} 167 168static int 169mlx4_en_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) 170{ 171 struct mlx4_en_priv *priv = netdev_priv(dev); 172 struct mlx4_en_dev *mdev = priv->mdev; 173 int err; 174 175 err = mlx4_en_ets_validate(priv, ets); 176 if (err) 177 return err; 178 179 err = mlx4_SET_PORT_PRIO2TC(mdev->dev, priv->port, ets->prio_tc); 180 if (err) 181 return err; 182 183 err = mlx4_en_config_port_scheduler(priv, ets, NULL); 184 if (err) 185 return err; 186 187 memcpy(&priv->ets, ets, sizeof(priv->ets)); 188 189 return 0; 190} 191 192static int mlx4_en_dcbnl_ieee_getpfc(struct net_device *dev, 193 struct ieee_pfc *pfc) 194{ 195 struct mlx4_en_priv *priv = netdev_priv(dev); 196 197 pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS; 198 pfc->pfc_en = priv->prof->tx_ppp; 199 200 return 0; 201} 202 203static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev, 204 struct ieee_pfc *pfc) 205{ 206 struct mlx4_en_priv *priv = netdev_priv(dev); 207 struct mlx4_en_port_profile *prof = priv->prof; 208 struct mlx4_en_dev *mdev = priv->mdev; 209 int err; 210 211 en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n", 212 pfc->pfc_cap, 213 pfc->pfc_en, 214 pfc->mbc, 215 pfc->delay); 216 217 prof->rx_pause = !pfc->pfc_en; 218 prof->tx_pause = !pfc->pfc_en; 219 prof->rx_ppp = pfc->pfc_en; 220 prof->tx_ppp = pfc->pfc_en; 221 222 err = mlx4_SET_PORT_general(mdev->dev, priv->port, 223 priv->rx_skb_size + ETH_FCS_LEN, 224 prof->tx_pause, 225 prof->tx_ppp, 226 prof->rx_pause, 227 prof->rx_ppp); 228 if (err) 229 en_err(priv, "Failed setting pause params\n"); 230 else 231 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap, 232 prof->rx_ppp, prof->rx_pause, 233 prof->tx_ppp, prof->tx_pause); 234 235 return err; 236} 237 238static u8 mlx4_en_dcbnl_getdcbx(struct net_device *dev) 239{ 240 return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; 241} 242 243static u8 mlx4_en_dcbnl_setdcbx(struct net_device *dev, u8 mode) 244{ 245 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || 246 (mode & DCB_CAP_DCBX_VER_CEE) || 247 !(mode & DCB_CAP_DCBX_VER_IEEE) || 248 !(mode & DCB_CAP_DCBX_HOST)) 249 return 1; 250 251 return 0; 252} 253 254#define MLX4_RATELIMIT_UNITS_IN_KB 100000 /* rate-limit HW unit in Kbps */ 255static int mlx4_en_dcbnl_ieee_getmaxrate(struct net_device *dev, 256 struct ieee_maxrate *maxrate) 257{ 258 struct mlx4_en_priv *priv = netdev_priv(dev); 259 int i; 260 261 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 262 maxrate->tc_maxrate[i] = 263 priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB; 264 265 return 0; 266} 267 268static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev, 269 struct ieee_maxrate *maxrate) 270{ 271 struct mlx4_en_priv *priv = netdev_priv(dev); 272 u16 tmp[IEEE_8021QAZ_MAX_TCS]; 273 int i, err; 274 275 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 276 /* Convert from Kbps into HW units, rounding result up. 277 * Setting to 0, means unlimited BW. 278 */ 279 tmp[i] = div_u64(maxrate->tc_maxrate[i] + 280 MLX4_RATELIMIT_UNITS_IN_KB - 1, 281 MLX4_RATELIMIT_UNITS_IN_KB); 282 } 283 284 err = mlx4_en_config_port_scheduler(priv, NULL, tmp); 285 if (err) 286 return err; 287 288 memcpy(priv->maxrate, tmp, sizeof(priv->maxrate)); 289 290 return 0; 291} 292 293#define RPG_ENABLE_BIT 31 294#define CN_TAG_BIT 30 295 296static int mlx4_en_dcbnl_ieee_getqcn(struct net_device *dev, 297 struct ieee_qcn *qcn) 298{ 299 struct mlx4_en_priv *priv = netdev_priv(dev); 300 struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn; 301 struct mlx4_cmd_mailbox *mailbox_out = NULL; 302 u64 mailbox_in_dma = 0; 303 u32 inmod = 0; 304 int i, err; 305 306 if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) 307 return -EOPNOTSUPP; 308 309 mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev); 310 if (IS_ERR(mailbox_out)) 311 return -ENOMEM; 312 hw_qcn = 313 (struct mlx4_congestion_control_mb_prio_802_1_qau_params *) 314 mailbox_out->buf; 315 316 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 317 inmod = priv->port | ((1 << i) << 8) | 318 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); 319 err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma, 320 mailbox_out->dma, 321 inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS, 322 MLX4_CMD_CONGESTION_CTRL_OPCODE, 323 MLX4_CMD_TIME_CLASS_C, 324 MLX4_CMD_NATIVE); 325 if (err) { 326 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); 327 return err; 328 } 329 330 qcn->rpg_enable[i] = 331 be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT; 332 qcn->rppp_max_rps[i] = 333 be32_to_cpu(hw_qcn->rppp_max_rps); 334 qcn->rpg_time_reset[i] = 335 be32_to_cpu(hw_qcn->rpg_time_reset); 336 qcn->rpg_byte_reset[i] = 337 be32_to_cpu(hw_qcn->rpg_byte_reset); 338 qcn->rpg_threshold[i] = 339 be32_to_cpu(hw_qcn->rpg_threshold); 340 qcn->rpg_max_rate[i] = 341 be32_to_cpu(hw_qcn->rpg_max_rate); 342 qcn->rpg_ai_rate[i] = 343 be32_to_cpu(hw_qcn->rpg_ai_rate); 344 qcn->rpg_hai_rate[i] = 345 be32_to_cpu(hw_qcn->rpg_hai_rate); 346 qcn->rpg_gd[i] = 347 be32_to_cpu(hw_qcn->rpg_gd); 348 qcn->rpg_min_dec_fac[i] = 349 be32_to_cpu(hw_qcn->rpg_min_dec_fac); 350 qcn->rpg_min_rate[i] = 351 be32_to_cpu(hw_qcn->rpg_min_rate); 352 qcn->cndd_state_machine[i] = 353 priv->cndd_state[i]; 354 } 355 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); 356 return 0; 357} 358 359static int mlx4_en_dcbnl_ieee_setqcn(struct net_device *dev, 360 struct ieee_qcn *qcn) 361{ 362 struct mlx4_en_priv *priv = netdev_priv(dev); 363 struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn; 364 struct mlx4_cmd_mailbox *mailbox_in = NULL; 365 u64 mailbox_in_dma = 0; 366 u32 inmod = 0; 367 int i, err; 368#define MODIFY_ENABLE_HIGH_MASK 0xc0000000 369#define MODIFY_ENABLE_LOW_MASK 0xffc00000 370 371 if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) 372 return -EOPNOTSUPP; 373 374 mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev); 375 if (IS_ERR(mailbox_in)) 376 return -ENOMEM; 377 378 mailbox_in_dma = mailbox_in->dma; 379 hw_qcn = 380 (struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf; 381 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 382 inmod = priv->port | ((1 << i) << 8) | 383 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); 384 385 /* Before updating QCN parameter, 386 * need to set it's modify enable bit to 1 387 */ 388 389 hw_qcn->modify_enable_high = cpu_to_be32( 390 MODIFY_ENABLE_HIGH_MASK); 391 hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK); 392 393 hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT); 394 hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]); 395 hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]); 396 hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]); 397 hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]); 398 hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]); 399 hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]); 400 hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]); 401 hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]); 402 hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]); 403 hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]); 404 priv->cndd_state[i] = qcn->cndd_state_machine[i]; 405 if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY) 406 hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT); 407 408 err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod, 409 MLX4_CONGESTION_CONTROL_SET_PARAMS, 410 MLX4_CMD_CONGESTION_CTRL_OPCODE, 411 MLX4_CMD_TIME_CLASS_C, 412 MLX4_CMD_NATIVE); 413 if (err) { 414 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in); 415 return err; 416 } 417 } 418 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in); 419 return 0; 420} 421 422static int mlx4_en_dcbnl_ieee_getqcnstats(struct net_device *dev, 423 struct ieee_qcn_stats *qcn_stats) 424{ 425 struct mlx4_en_priv *priv = netdev_priv(dev); 426 struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats; 427 struct mlx4_cmd_mailbox *mailbox_out = NULL; 428 u64 mailbox_in_dma = 0; 429 u32 inmod = 0; 430 int i, err; 431 432 if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN)) 433 return -EOPNOTSUPP; 434 435 mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev); 436 if (IS_ERR(mailbox_out)) 437 return -ENOMEM; 438 439 hw_qcn_stats = 440 (struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *) 441 mailbox_out->buf; 442 443 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 444 inmod = priv->port | ((1 << i) << 8) | 445 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16); 446 err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma, 447 mailbox_out->dma, inmod, 448 MLX4_CONGESTION_CONTROL_GET_STATISTICS, 449 MLX4_CMD_CONGESTION_CTRL_OPCODE, 450 MLX4_CMD_TIME_CLASS_C, 451 MLX4_CMD_NATIVE); 452 if (err) { 453 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); 454 return err; 455 } 456 qcn_stats->rppp_rp_centiseconds[i] = 457 be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds); 458 qcn_stats->rppp_created_rps[i] = 459 be32_to_cpu(hw_qcn_stats->rppp_created_rps); 460 } 461 mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out); 462 return 0; 463} 464 465const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = { 466 .ieee_getets = mlx4_en_dcbnl_ieee_getets, 467 .ieee_setets = mlx4_en_dcbnl_ieee_setets, 468 .ieee_getmaxrate = mlx4_en_dcbnl_ieee_getmaxrate, 469 .ieee_setmaxrate = mlx4_en_dcbnl_ieee_setmaxrate, 470 .ieee_getpfc = mlx4_en_dcbnl_ieee_getpfc, 471 .ieee_setpfc = mlx4_en_dcbnl_ieee_setpfc, 472 473 .getdcbx = mlx4_en_dcbnl_getdcbx, 474 .setdcbx = mlx4_en_dcbnl_setdcbx, 475 .ieee_getqcn = mlx4_en_dcbnl_ieee_getqcn, 476 .ieee_setqcn = mlx4_en_dcbnl_ieee_setqcn, 477 .ieee_getqcnstats = mlx4_en_dcbnl_ieee_getqcnstats, 478}; 479 480const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = { 481 .ieee_getpfc = mlx4_en_dcbnl_ieee_getpfc, 482 .ieee_setpfc = mlx4_en_dcbnl_ieee_setpfc, 483 484 .getdcbx = mlx4_en_dcbnl_getdcbx, 485 .setdcbx = mlx4_en_dcbnl_setdcbx, 486}; 487