i40e_dcb_nl.c (28383B)
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2013 - 2021 Intel Corporation. */ 3 4#ifdef CONFIG_I40E_DCB 5#include "i40e.h" 6#include <net/dcbnl.h> 7 8#define I40E_DCBNL_STATUS_SUCCESS 0 9#define I40E_DCBNL_STATUS_ERROR 1 10static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg, 11 struct i40e_dcb_app_priority_table *app); 12/** 13 * i40e_get_pfc_delay - retrieve PFC Link Delay 14 * @hw: pointer to hardware struct 15 * @delay: holds the PFC Link delay value 16 * 17 * Returns PFC Link Delay from the PRTDCB_GENC.PFCLDA 18 **/ 19static void i40e_get_pfc_delay(struct i40e_hw *hw, u16 *delay) 20{ 21 u32 val; 22 23 val = rd32(hw, I40E_PRTDCB_GENC); 24 *delay = (u16)((val & I40E_PRTDCB_GENC_PFCLDA_MASK) >> 25 I40E_PRTDCB_GENC_PFCLDA_SHIFT); 26} 27 28/** 29 * i40e_dcbnl_ieee_getets - retrieve local IEEE ETS configuration 30 * @dev: the corresponding netdev 31 * @ets: structure to hold the ETS information 32 * 33 * Returns local IEEE ETS configuration 34 **/ 35static int i40e_dcbnl_ieee_getets(struct net_device *dev, 36 struct ieee_ets *ets) 37{ 38 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 39 struct i40e_dcbx_config *dcbxcfg; 40 41 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 42 return -EINVAL; 43 44 dcbxcfg = &pf->hw.local_dcbx_config; 45 ets->willing = dcbxcfg->etscfg.willing; 46 ets->ets_cap = I40E_MAX_TRAFFIC_CLASS; 47 ets->cbs = dcbxcfg->etscfg.cbs; 48 memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable, 49 sizeof(ets->tc_tx_bw)); 50 memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable, 51 sizeof(ets->tc_rx_bw)); 52 memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable, 53 sizeof(ets->tc_tsa)); 54 memcpy(ets->prio_tc, dcbxcfg->etscfg.prioritytable, 55 sizeof(ets->prio_tc)); 56 memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable, 57 sizeof(ets->tc_reco_bw)); 58 memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable, 59 sizeof(ets->tc_reco_tsa)); 60 memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prioritytable, 61 sizeof(ets->reco_prio_tc)); 62 63 return 0; 64} 65 66/** 67 * i40e_dcbnl_ieee_getpfc - retrieve local IEEE PFC configuration 68 * @dev: the corresponding netdev 69 * @pfc: structure to hold the PFC information 70 * 71 * Returns local IEEE PFC configuration 72 **/ 73static int i40e_dcbnl_ieee_getpfc(struct net_device *dev, 74 struct ieee_pfc *pfc) 75{ 76 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 77 struct i40e_dcbx_config *dcbxcfg; 78 struct i40e_hw *hw = &pf->hw; 79 int i; 80 81 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 82 return -EINVAL; 83 84 dcbxcfg = &hw->local_dcbx_config; 85 pfc->pfc_cap = dcbxcfg->pfc.pfccap; 86 pfc->pfc_en = dcbxcfg->pfc.pfcenable; 87 pfc->mbc = dcbxcfg->pfc.mbc; 88 i40e_get_pfc_delay(hw, &pfc->delay); 89 90 /* Get Requests/Indications */ 91 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 92 pfc->requests[i] = pf->stats.priority_xoff_tx[i]; 93 pfc->indications[i] = pf->stats.priority_xoff_rx[i]; 94 } 95 96 return 0; 97} 98 99/** 100 * i40e_dcbnl_ieee_setets - set IEEE ETS configuration 101 * @netdev: the corresponding netdev 102 * @ets: structure to hold the ETS information 103 * 104 * Set IEEE ETS configuration 105 **/ 106static int i40e_dcbnl_ieee_setets(struct net_device *netdev, 107 struct ieee_ets *ets) 108{ 109 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 110 struct i40e_dcbx_config *old_cfg; 111 int i, ret; 112 113 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 114 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 115 return -EINVAL; 116 117 old_cfg = &pf->hw.local_dcbx_config; 118 /* Copy current config into temp */ 119 pf->tmp_cfg = *old_cfg; 120 121 /* Update the ETS configuration for temp */ 122 pf->tmp_cfg.etscfg.willing = ets->willing; 123 pf->tmp_cfg.etscfg.maxtcs = I40E_MAX_TRAFFIC_CLASS; 124 pf->tmp_cfg.etscfg.cbs = ets->cbs; 125 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 126 pf->tmp_cfg.etscfg.tcbwtable[i] = ets->tc_tx_bw[i]; 127 pf->tmp_cfg.etscfg.tsatable[i] = ets->tc_tsa[i]; 128 pf->tmp_cfg.etscfg.prioritytable[i] = ets->prio_tc[i]; 129 pf->tmp_cfg.etsrec.tcbwtable[i] = ets->tc_reco_bw[i]; 130 pf->tmp_cfg.etsrec.tsatable[i] = ets->tc_reco_tsa[i]; 131 pf->tmp_cfg.etsrec.prioritytable[i] = ets->reco_prio_tc[i]; 132 } 133 134 /* Commit changes to HW */ 135 ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg); 136 if (ret) { 137 dev_info(&pf->pdev->dev, 138 "Failed setting DCB ETS configuration err %s aq_err %s\n", 139 i40e_stat_str(&pf->hw, ret), 140 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); 141 return -EINVAL; 142 } 143 144 return 0; 145} 146 147/** 148 * i40e_dcbnl_ieee_setpfc - set local IEEE PFC configuration 149 * @netdev: the corresponding netdev 150 * @pfc: structure to hold the PFC information 151 * 152 * Sets local IEEE PFC configuration 153 **/ 154static int i40e_dcbnl_ieee_setpfc(struct net_device *netdev, 155 struct ieee_pfc *pfc) 156{ 157 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 158 struct i40e_dcbx_config *old_cfg; 159 int ret; 160 161 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 162 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 163 return -EINVAL; 164 165 old_cfg = &pf->hw.local_dcbx_config; 166 /* Copy current config into temp */ 167 pf->tmp_cfg = *old_cfg; 168 if (pfc->pfc_cap) 169 pf->tmp_cfg.pfc.pfccap = pfc->pfc_cap; 170 else 171 pf->tmp_cfg.pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 172 pf->tmp_cfg.pfc.pfcenable = pfc->pfc_en; 173 174 ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg); 175 if (ret) { 176 dev_info(&pf->pdev->dev, 177 "Failed setting DCB PFC configuration err %s aq_err %s\n", 178 i40e_stat_str(&pf->hw, ret), 179 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); 180 return -EINVAL; 181 } 182 183 return 0; 184} 185 186/** 187 * i40e_dcbnl_ieee_setapp - set local IEEE App configuration 188 * @netdev: the corresponding netdev 189 * @app: structure to hold the Application information 190 * 191 * Sets local IEEE App configuration 192 **/ 193static int i40e_dcbnl_ieee_setapp(struct net_device *netdev, 194 struct dcb_app *app) 195{ 196 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 197 struct i40e_dcb_app_priority_table new_app; 198 struct i40e_dcbx_config *old_cfg; 199 int ret; 200 201 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 202 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 203 return -EINVAL; 204 205 old_cfg = &pf->hw.local_dcbx_config; 206 if (old_cfg->numapps == I40E_DCBX_MAX_APPS) 207 return -EINVAL; 208 209 ret = dcb_ieee_setapp(netdev, app); 210 if (ret) 211 return ret; 212 213 new_app.selector = app->selector; 214 new_app.protocolid = app->protocol; 215 new_app.priority = app->priority; 216 /* Already internally available */ 217 if (i40e_dcbnl_find_app(old_cfg, &new_app)) 218 return 0; 219 220 /* Copy current config into temp */ 221 pf->tmp_cfg = *old_cfg; 222 /* Add the app */ 223 pf->tmp_cfg.app[pf->tmp_cfg.numapps++] = new_app; 224 225 ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg); 226 if (ret) { 227 dev_info(&pf->pdev->dev, 228 "Failed setting DCB configuration err %s aq_err %s\n", 229 i40e_stat_str(&pf->hw, ret), 230 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); 231 return -EINVAL; 232 } 233 234 return 0; 235} 236 237/** 238 * i40e_dcbnl_ieee_delapp - delete local IEEE App configuration 239 * @netdev: the corresponding netdev 240 * @app: structure to hold the Application information 241 * 242 * Deletes local IEEE App configuration other than the first application 243 * required by firmware 244 **/ 245static int i40e_dcbnl_ieee_delapp(struct net_device *netdev, 246 struct dcb_app *app) 247{ 248 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 249 struct i40e_dcbx_config *old_cfg; 250 int i, j, ret; 251 252 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 253 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 254 return -EINVAL; 255 256 ret = dcb_ieee_delapp(netdev, app); 257 if (ret) 258 return ret; 259 260 old_cfg = &pf->hw.local_dcbx_config; 261 /* Need one app for FW so keep it */ 262 if (old_cfg->numapps == 1) 263 return 0; 264 265 /* Copy current config into temp */ 266 pf->tmp_cfg = *old_cfg; 267 268 /* Find and reset the app */ 269 for (i = 1; i < pf->tmp_cfg.numapps; i++) { 270 if (app->selector == pf->tmp_cfg.app[i].selector && 271 app->protocol == pf->tmp_cfg.app[i].protocolid && 272 app->priority == pf->tmp_cfg.app[i].priority) { 273 /* Reset the app data */ 274 pf->tmp_cfg.app[i].selector = 0; 275 pf->tmp_cfg.app[i].protocolid = 0; 276 pf->tmp_cfg.app[i].priority = 0; 277 break; 278 } 279 } 280 281 /* If the specific DCB app not found */ 282 if (i == pf->tmp_cfg.numapps) 283 return -EINVAL; 284 285 pf->tmp_cfg.numapps--; 286 /* Overwrite the tmp_cfg app */ 287 for (j = i; j < pf->tmp_cfg.numapps; j++) 288 pf->tmp_cfg.app[j] = old_cfg->app[j + 1]; 289 290 ret = i40e_hw_dcb_config(pf, &pf->tmp_cfg); 291 if (ret) { 292 dev_info(&pf->pdev->dev, 293 "Failed setting DCB configuration err %s aq_err %s\n", 294 i40e_stat_str(&pf->hw, ret), 295 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); 296 return -EINVAL; 297 } 298 299 return 0; 300} 301 302/** 303 * i40e_dcbnl_getstate - Get DCB enabled state 304 * @netdev: the corresponding netdev 305 * 306 * Get the current DCB enabled state 307 **/ 308static u8 i40e_dcbnl_getstate(struct net_device *netdev) 309{ 310 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 311 312 dev_dbg(&pf->pdev->dev, "DCB state=%d\n", 313 !!(pf->flags & I40E_FLAG_DCB_ENABLED)); 314 return !!(pf->flags & I40E_FLAG_DCB_ENABLED); 315} 316 317/** 318 * i40e_dcbnl_setstate - Set DCB state 319 * @netdev: the corresponding netdev 320 * @state: enable or disable 321 * 322 * Set the DCB state 323 **/ 324static u8 i40e_dcbnl_setstate(struct net_device *netdev, u8 state) 325{ 326 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 327 int ret = I40E_DCBNL_STATUS_SUCCESS; 328 329 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 330 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 331 return ret; 332 333 dev_dbg(&pf->pdev->dev, "new state=%d current state=%d\n", 334 state, (pf->flags & I40E_FLAG_DCB_ENABLED) ? 1 : 0); 335 /* Nothing to do */ 336 if (!state == !(pf->flags & I40E_FLAG_DCB_ENABLED)) 337 return ret; 338 339 if (i40e_is_sw_dcb(pf)) { 340 if (state) { 341 pf->flags |= I40E_FLAG_DCB_ENABLED; 342 memcpy(&pf->hw.desired_dcbx_config, 343 &pf->hw.local_dcbx_config, 344 sizeof(struct i40e_dcbx_config)); 345 } else { 346 pf->flags &= ~I40E_FLAG_DCB_ENABLED; 347 } 348 } else { 349 /* Cannot directly manipulate FW LLDP Agent */ 350 ret = I40E_DCBNL_STATUS_ERROR; 351 } 352 return ret; 353} 354 355/** 356 * i40e_dcbnl_set_pg_tc_cfg_tx - Set CEE PG Tx config 357 * @netdev: the corresponding netdev 358 * @tc: the corresponding traffic class 359 * @prio_type: the traffic priority type 360 * @bwg_id: the BW group id the traffic class belongs to 361 * @bw_pct: the BW percentage for the corresponding BWG 362 * @up_map: prio mapped to corresponding tc 363 * 364 * Set Tx PG settings for CEE mode 365 **/ 366static void i40e_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, 367 u8 prio_type, u8 bwg_id, u8 bw_pct, 368 u8 up_map) 369{ 370 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 371 int i; 372 373 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 374 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 375 return; 376 377 /* LLTC not supported yet */ 378 if (tc >= I40E_MAX_TRAFFIC_CLASS) 379 return; 380 381 /* prio_type, bwg_id and bw_pct per UP are not supported */ 382 383 /* Use only up_map to map tc */ 384 for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) { 385 if (up_map & BIT(i)) 386 pf->tmp_cfg.etscfg.prioritytable[i] = tc; 387 } 388 pf->tmp_cfg.etscfg.tsatable[tc] = I40E_IEEE_TSA_ETS; 389 dev_dbg(&pf->pdev->dev, 390 "Set PG config tc=%d bwg_id=%d prio_type=%d bw_pct=%d up_map=%d\n", 391 tc, bwg_id, prio_type, bw_pct, up_map); 392} 393 394/** 395 * i40e_dcbnl_set_pg_bwg_cfg_tx - Set CEE PG Tx BW config 396 * @netdev: the corresponding netdev 397 * @pgid: the corresponding traffic class 398 * @bw_pct: the BW percentage for the specified traffic class 399 * 400 * Set Tx BW settings for CEE mode 401 **/ 402static void i40e_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, 403 u8 bw_pct) 404{ 405 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 406 407 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 408 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 409 return; 410 411 /* LLTC not supported yet */ 412 if (pgid >= I40E_MAX_TRAFFIC_CLASS) 413 return; 414 415 pf->tmp_cfg.etscfg.tcbwtable[pgid] = bw_pct; 416 dev_dbg(&pf->pdev->dev, "Set PG BW config tc=%d bw_pct=%d\n", 417 pgid, bw_pct); 418} 419 420/** 421 * i40e_dcbnl_set_pg_tc_cfg_rx - Set CEE PG Rx config 422 * @netdev: the corresponding netdev 423 * @prio: the corresponding traffic class 424 * @prio_type: the traffic priority type 425 * @pgid: the BW group id the traffic class belongs to 426 * @bw_pct: the BW percentage for the corresponding BWG 427 * @up_map: prio mapped to corresponding tc 428 * 429 * Set Rx BW settings for CEE mode. The hardware does not support this 430 * so we won't allow setting of this parameter. 431 **/ 432static void i40e_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, 433 int __always_unused prio, 434 u8 __always_unused prio_type, 435 u8 __always_unused pgid, 436 u8 __always_unused bw_pct, 437 u8 __always_unused up_map) 438{ 439 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 440 441 dev_dbg(&pf->pdev->dev, "Rx TC PG Config Not Supported.\n"); 442} 443 444/** 445 * i40e_dcbnl_set_pg_bwg_cfg_rx - Set CEE PG Rx config 446 * @netdev: the corresponding netdev 447 * @pgid: the corresponding traffic class 448 * @bw_pct: the BW percentage for the specified traffic class 449 * 450 * Set Rx BW settings for CEE mode. The hardware does not support this 451 * so we won't allow setting of this parameter. 452 **/ 453static void i40e_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, 454 u8 bw_pct) 455{ 456 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 457 458 dev_dbg(&pf->pdev->dev, "Rx BWG PG Config Not Supported.\n"); 459} 460 461/** 462 * i40e_dcbnl_get_pg_tc_cfg_tx - Get CEE PG Tx config 463 * @netdev: the corresponding netdev 464 * @prio: the corresponding user priority 465 * @prio_type: traffic priority type 466 * @pgid: the BW group ID the traffic class belongs to 467 * @bw_pct: BW percentage for the corresponding BWG 468 * @up_map: prio mapped to corresponding TC 469 * 470 * Get Tx PG settings for CEE mode 471 **/ 472static void i40e_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio, 473 u8 __always_unused *prio_type, 474 u8 *pgid, 475 u8 __always_unused *bw_pct, 476 u8 __always_unused *up_map) 477{ 478 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 479 480 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 481 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 482 return; 483 484 if (prio >= I40E_MAX_USER_PRIORITY) 485 return; 486 487 *pgid = pf->hw.local_dcbx_config.etscfg.prioritytable[prio]; 488 dev_dbg(&pf->pdev->dev, "Get PG config prio=%d tc=%d\n", 489 prio, *pgid); 490} 491 492/** 493 * i40e_dcbnl_get_pg_bwg_cfg_tx - Get CEE PG BW config 494 * @netdev: the corresponding netdev 495 * @pgid: the corresponding traffic class 496 * @bw_pct: the BW percentage for the corresponding TC 497 * 498 * Get Tx BW settings for given TC in CEE mode 499 **/ 500static void i40e_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, 501 u8 *bw_pct) 502{ 503 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 504 505 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 506 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 507 return; 508 509 if (pgid >= I40E_MAX_TRAFFIC_CLASS) 510 return; 511 512 *bw_pct = pf->hw.local_dcbx_config.etscfg.tcbwtable[pgid]; 513 dev_dbg(&pf->pdev->dev, "Get PG BW config tc=%d bw_pct=%d\n", 514 pgid, *bw_pct); 515} 516 517/** 518 * i40e_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config 519 * @netdev: the corresponding netdev 520 * @prio: the corresponding user priority 521 * @prio_type: the traffic priority type 522 * @pgid: the PG ID 523 * @bw_pct: the BW percentage for the corresponding BWG 524 * @up_map: prio mapped to corresponding TC 525 * 526 * Get Rx PG settings for CEE mode. The UP2TC map is applied in same 527 * manner for Tx and Rx (symmetrical) so return the TC information for 528 * given priority accordingly. 529 **/ 530static void i40e_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, 531 u8 *prio_type, u8 *pgid, u8 *bw_pct, 532 u8 *up_map) 533{ 534 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 535 536 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 537 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 538 return; 539 540 if (prio >= I40E_MAX_USER_PRIORITY) 541 return; 542 543 *pgid = pf->hw.local_dcbx_config.etscfg.prioritytable[prio]; 544} 545 546/** 547 * i40e_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config 548 * @netdev: the corresponding netdev 549 * @pgid: the corresponding traffic class 550 * @bw_pct: the BW percentage for the corresponding TC 551 * 552 * Get Rx BW settings for given TC in CEE mode 553 * The adapter doesn't support Rx ETS and runs in strict priority 554 * mode in Rx path and hence just return 0. 555 **/ 556static void i40e_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, 557 u8 *bw_pct) 558{ 559 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 560 561 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 562 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 563 return; 564 *bw_pct = 0; 565} 566 567/** 568 * i40e_dcbnl_set_pfc_cfg - Set CEE PFC configuration 569 * @netdev: the corresponding netdev 570 * @prio: the corresponding user priority 571 * @setting: the PFC setting for given priority 572 * 573 * Set the PFC enabled/disabled setting for given user priority 574 **/ 575static void i40e_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, 576 u8 setting) 577{ 578 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 579 580 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 581 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 582 return; 583 584 if (prio >= I40E_MAX_USER_PRIORITY) 585 return; 586 587 pf->tmp_cfg.pfc.pfccap = I40E_MAX_TRAFFIC_CLASS; 588 if (setting) 589 pf->tmp_cfg.pfc.pfcenable |= BIT(prio); 590 else 591 pf->tmp_cfg.pfc.pfcenable &= ~BIT(prio); 592 dev_dbg(&pf->pdev->dev, 593 "Set PFC Config up=%d setting=%d pfcenable=0x%x\n", 594 prio, setting, pf->tmp_cfg.pfc.pfcenable); 595} 596 597/** 598 * i40e_dcbnl_get_pfc_cfg - Get CEE PFC configuration 599 * @netdev: the corresponding netdev 600 * @prio: the corresponding user priority 601 * @setting: the PFC setting for given priority 602 * 603 * Get the PFC enabled/disabled setting for given user priority 604 **/ 605static void i40e_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, 606 u8 *setting) 607{ 608 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 609 610 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 611 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 612 return; 613 614 if (prio >= I40E_MAX_USER_PRIORITY) 615 return; 616 617 *setting = (pf->hw.local_dcbx_config.pfc.pfcenable >> prio) & 0x1; 618 dev_dbg(&pf->pdev->dev, 619 "Get PFC Config up=%d setting=%d pfcenable=0x%x\n", 620 prio, *setting, pf->hw.local_dcbx_config.pfc.pfcenable); 621} 622 623/** 624 * i40e_dcbnl_cee_set_all - Commit CEE DCB settings to hardware 625 * @netdev: the corresponding netdev 626 * 627 * Commit the current DCB configuration to hardware 628 **/ 629static u8 i40e_dcbnl_cee_set_all(struct net_device *netdev) 630{ 631 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 632 int err; 633 634 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 635 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 636 return I40E_DCBNL_STATUS_ERROR; 637 638 dev_dbg(&pf->pdev->dev, "Commit DCB Configuration to the hardware\n"); 639 err = i40e_hw_dcb_config(pf, &pf->tmp_cfg); 640 641 return err ? I40E_DCBNL_STATUS_ERROR : I40E_DCBNL_STATUS_SUCCESS; 642} 643 644/** 645 * i40e_dcbnl_get_cap - Get DCBX capabilities of adapter 646 * @netdev: the corresponding netdev 647 * @capid: the capability type 648 * @cap: the capability value 649 * 650 * Return the capability value for a given capability type 651 **/ 652static u8 i40e_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap) 653{ 654 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 655 656 if (!(pf->flags & I40E_FLAG_DCB_CAPABLE)) 657 return I40E_DCBNL_STATUS_ERROR; 658 659 switch (capid) { 660 case DCB_CAP_ATTR_PG: 661 case DCB_CAP_ATTR_PFC: 662 *cap = true; 663 break; 664 case DCB_CAP_ATTR_PG_TCS: 665 case DCB_CAP_ATTR_PFC_TCS: 666 *cap = 0x80; 667 break; 668 case DCB_CAP_ATTR_DCBX: 669 *cap = pf->dcbx_cap; 670 break; 671 case DCB_CAP_ATTR_UP2TC: 672 case DCB_CAP_ATTR_GSP: 673 case DCB_CAP_ATTR_BCN: 674 default: 675 *cap = false; 676 break; 677 } 678 679 dev_dbg(&pf->pdev->dev, "Get Capability cap=%d capval=0x%x\n", 680 capid, *cap); 681 return I40E_DCBNL_STATUS_SUCCESS; 682} 683 684/** 685 * i40e_dcbnl_getnumtcs - Get max number of traffic classes supported 686 * @netdev: the corresponding netdev 687 * @tcid: the TC id 688 * @num: total number of TCs supported by the device 689 * 690 * Return the total number of TCs supported by the adapter 691 **/ 692static int i40e_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num) 693{ 694 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 695 696 if (!(pf->flags & I40E_FLAG_DCB_CAPABLE)) 697 return -EINVAL; 698 699 *num = I40E_MAX_TRAFFIC_CLASS; 700 return 0; 701} 702 703/** 704 * i40e_dcbnl_setnumtcs - Set CEE number of traffic classes 705 * @netdev: the corresponding netdev 706 * @tcid: the TC id 707 * @num: total number of TCs 708 * 709 * Set the total number of TCs (Unsupported) 710 **/ 711static int i40e_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num) 712{ 713 return -EINVAL; 714} 715 716/** 717 * i40e_dcbnl_getpfcstate - Get CEE PFC mode 718 * @netdev: the corresponding netdev 719 * 720 * Get the current PFC enabled state 721 **/ 722static u8 i40e_dcbnl_getpfcstate(struct net_device *netdev) 723{ 724 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 725 726 /* Return enabled if any PFC enabled UP */ 727 if (pf->hw.local_dcbx_config.pfc.pfcenable) 728 return 1; 729 else 730 return 0; 731} 732 733/** 734 * i40e_dcbnl_setpfcstate - Set CEE PFC mode 735 * @netdev: the corresponding netdev 736 * @state: required state 737 * 738 * The PFC state to be set; this is enabled/disabled based on the PFC 739 * priority settings and not via this call for i40e driver 740 **/ 741static void i40e_dcbnl_setpfcstate(struct net_device *netdev, u8 state) 742{ 743 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 744 745 dev_dbg(&pf->pdev->dev, "PFC State is modified via PFC config.\n"); 746} 747 748/** 749 * i40e_dcbnl_getapp - Get CEE APP 750 * @netdev: the corresponding netdev 751 * @idtype: the App selector 752 * @id: the App ethtype or port number 753 * 754 * Return the CEE mode app for the given idtype and id 755 **/ 756static int i40e_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) 757{ 758 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 759 struct dcb_app app = { 760 .selector = idtype, 761 .protocol = id, 762 }; 763 764 if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE) || 765 (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)) 766 return -EINVAL; 767 768 return dcb_getapp(netdev, &app); 769} 770 771/** 772 * i40e_dcbnl_setdcbx - set required DCBx capability 773 * @netdev: the corresponding netdev 774 * @mode: new DCB mode managed or CEE+IEEE 775 * 776 * Set DCBx capability features 777 **/ 778static u8 i40e_dcbnl_setdcbx(struct net_device *netdev, u8 mode) 779{ 780 struct i40e_pf *pf = i40e_netdev_to_pf(netdev); 781 782 /* Do not allow to set mode if managed by Firmware */ 783 if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) 784 return I40E_DCBNL_STATUS_ERROR; 785 786 /* No support for LLD_MANAGED modes or CEE+IEEE */ 787 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || 788 ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || 789 !(mode & DCB_CAP_DCBX_HOST)) 790 return I40E_DCBNL_STATUS_ERROR; 791 792 /* Already set to the given mode no change */ 793 if (mode == pf->dcbx_cap) 794 return I40E_DCBNL_STATUS_SUCCESS; 795 796 pf->dcbx_cap = mode; 797 if (mode & DCB_CAP_DCBX_VER_CEE) 798 pf->hw.local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_CEE; 799 else 800 pf->hw.local_dcbx_config.dcbx_mode = I40E_DCBX_MODE_IEEE; 801 802 dev_dbg(&pf->pdev->dev, "mode=%d\n", mode); 803 return I40E_DCBNL_STATUS_SUCCESS; 804} 805 806/** 807 * i40e_dcbnl_getdcbx - retrieve current DCBx capability 808 * @dev: the corresponding netdev 809 * 810 * Returns DCBx capability features 811 **/ 812static u8 i40e_dcbnl_getdcbx(struct net_device *dev) 813{ 814 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 815 816 return pf->dcbx_cap; 817} 818 819/** 820 * i40e_dcbnl_get_perm_hw_addr - MAC address used by DCBx 821 * @dev: the corresponding netdev 822 * @perm_addr: buffer to store the MAC address 823 * 824 * Returns the SAN MAC address used for LLDP exchange 825 **/ 826static void i40e_dcbnl_get_perm_hw_addr(struct net_device *dev, 827 u8 *perm_addr) 828{ 829 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 830 int i, j; 831 832 memset(perm_addr, 0xff, MAX_ADDR_LEN); 833 834 for (i = 0; i < dev->addr_len; i++) 835 perm_addr[i] = pf->hw.mac.perm_addr[i]; 836 837 for (j = 0; j < dev->addr_len; j++, i++) 838 perm_addr[i] = pf->hw.mac.san_addr[j]; 839} 840 841static const struct dcbnl_rtnl_ops dcbnl_ops = { 842 .ieee_getets = i40e_dcbnl_ieee_getets, 843 .ieee_getpfc = i40e_dcbnl_ieee_getpfc, 844 .getdcbx = i40e_dcbnl_getdcbx, 845 .getpermhwaddr = i40e_dcbnl_get_perm_hw_addr, 846 .ieee_setets = i40e_dcbnl_ieee_setets, 847 .ieee_setpfc = i40e_dcbnl_ieee_setpfc, 848 .ieee_setapp = i40e_dcbnl_ieee_setapp, 849 .ieee_delapp = i40e_dcbnl_ieee_delapp, 850 .getstate = i40e_dcbnl_getstate, 851 .setstate = i40e_dcbnl_setstate, 852 .setpgtccfgtx = i40e_dcbnl_set_pg_tc_cfg_tx, 853 .setpgbwgcfgtx = i40e_dcbnl_set_pg_bwg_cfg_tx, 854 .setpgtccfgrx = i40e_dcbnl_set_pg_tc_cfg_rx, 855 .setpgbwgcfgrx = i40e_dcbnl_set_pg_bwg_cfg_rx, 856 .getpgtccfgtx = i40e_dcbnl_get_pg_tc_cfg_tx, 857 .getpgbwgcfgtx = i40e_dcbnl_get_pg_bwg_cfg_tx, 858 .getpgtccfgrx = i40e_dcbnl_get_pg_tc_cfg_rx, 859 .getpgbwgcfgrx = i40e_dcbnl_get_pg_bwg_cfg_rx, 860 .setpfccfg = i40e_dcbnl_set_pfc_cfg, 861 .getpfccfg = i40e_dcbnl_get_pfc_cfg, 862 .setall = i40e_dcbnl_cee_set_all, 863 .getcap = i40e_dcbnl_get_cap, 864 .getnumtcs = i40e_dcbnl_getnumtcs, 865 .setnumtcs = i40e_dcbnl_setnumtcs, 866 .getpfcstate = i40e_dcbnl_getpfcstate, 867 .setpfcstate = i40e_dcbnl_setpfcstate, 868 .getapp = i40e_dcbnl_getapp, 869 .setdcbx = i40e_dcbnl_setdcbx, 870}; 871 872/** 873 * i40e_dcbnl_set_all - set all the apps and ieee data from DCBx config 874 * @vsi: the corresponding vsi 875 * 876 * Set up all the IEEE APPs in the DCBNL App Table and generate event for 877 * other settings 878 **/ 879void i40e_dcbnl_set_all(struct i40e_vsi *vsi) 880{ 881 struct net_device *dev = vsi->netdev; 882 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 883 struct i40e_dcbx_config *dcbxcfg; 884 struct i40e_hw *hw = &pf->hw; 885 struct dcb_app sapp; 886 u8 prio, tc_map; 887 int i; 888 889 /* SW DCB taken care by DCBNL set calls */ 890 if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) 891 return; 892 893 /* DCB not enabled */ 894 if (!(pf->flags & I40E_FLAG_DCB_ENABLED)) 895 return; 896 897 /* MFP mode but not an iSCSI PF so return */ 898 if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(hw->func_caps.iscsi)) 899 return; 900 901 dcbxcfg = &hw->local_dcbx_config; 902 903 /* Set up all the App TLVs if DCBx is negotiated */ 904 for (i = 0; i < dcbxcfg->numapps; i++) { 905 prio = dcbxcfg->app[i].priority; 906 tc_map = BIT(dcbxcfg->etscfg.prioritytable[prio]); 907 908 /* Add APP only if the TC is enabled for this VSI */ 909 if (tc_map & vsi->tc_config.enabled_tc) { 910 sapp.selector = dcbxcfg->app[i].selector; 911 sapp.protocol = dcbxcfg->app[i].protocolid; 912 sapp.priority = prio; 913 dcb_ieee_setapp(dev, &sapp); 914 } 915 } 916 917 /* Notify user-space of the changes */ 918 dcbnl_ieee_notify(dev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0); 919} 920 921/** 922 * i40e_dcbnl_vsi_del_app - Delete APP for given VSI 923 * @vsi: the corresponding vsi 924 * @app: APP to delete 925 * 926 * Delete given APP from the DCBNL APP table for given 927 * VSI 928 **/ 929static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi, 930 struct i40e_dcb_app_priority_table *app) 931{ 932 struct net_device *dev = vsi->netdev; 933 struct dcb_app sapp; 934 935 if (!dev) 936 return -EINVAL; 937 938 sapp.selector = app->selector; 939 sapp.protocol = app->protocolid; 940 sapp.priority = app->priority; 941 return dcb_ieee_delapp(dev, &sapp); 942} 943 944/** 945 * i40e_dcbnl_del_app - Delete APP on all VSIs 946 * @pf: the corresponding PF 947 * @app: APP to delete 948 * 949 * Delete given APP from all the VSIs for given PF 950 **/ 951static void i40e_dcbnl_del_app(struct i40e_pf *pf, 952 struct i40e_dcb_app_priority_table *app) 953{ 954 int v, err; 955 956 for (v = 0; v < pf->num_alloc_vsi; v++) { 957 if (pf->vsi[v] && pf->vsi[v]->netdev) { 958 err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app); 959 dev_dbg(&pf->pdev->dev, "Deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n", 960 pf->vsi[v]->seid, err, app->selector, 961 app->protocolid, app->priority); 962 } 963 } 964} 965 966/** 967 * i40e_dcbnl_find_app - Search APP in given DCB config 968 * @cfg: DCBX configuration data 969 * @app: APP to search for 970 * 971 * Find given APP in the DCB configuration 972 **/ 973static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg, 974 struct i40e_dcb_app_priority_table *app) 975{ 976 int i; 977 978 for (i = 0; i < cfg->numapps; i++) { 979 if (app->selector == cfg->app[i].selector && 980 app->protocolid == cfg->app[i].protocolid && 981 app->priority == cfg->app[i].priority) 982 return true; 983 } 984 985 return false; 986} 987 988/** 989 * i40e_dcbnl_flush_apps - Delete all removed APPs 990 * @pf: the corresponding PF 991 * @old_cfg: old DCBX configuration data 992 * @new_cfg: new DCBX configuration data 993 * 994 * Find and delete all APPs that are not present in the passed 995 * DCB configuration 996 **/ 997void i40e_dcbnl_flush_apps(struct i40e_pf *pf, 998 struct i40e_dcbx_config *old_cfg, 999 struct i40e_dcbx_config *new_cfg) 1000{ 1001 struct i40e_dcb_app_priority_table app; 1002 int i; 1003 1004 /* MFP mode but not an iSCSI PF so return */ 1005 if ((pf->flags & I40E_FLAG_MFP_ENABLED) && !(pf->hw.func_caps.iscsi)) 1006 return; 1007 1008 for (i = 0; i < old_cfg->numapps; i++) { 1009 app = old_cfg->app[i]; 1010 /* The APP is not available anymore delete it */ 1011 if (!i40e_dcbnl_find_app(new_cfg, &app)) 1012 i40e_dcbnl_del_app(pf, &app); 1013 } 1014} 1015 1016/** 1017 * i40e_dcbnl_setup - DCBNL setup 1018 * @vsi: the corresponding vsi 1019 * 1020 * Set up DCBNL ops and initial APP TLVs 1021 **/ 1022void i40e_dcbnl_setup(struct i40e_vsi *vsi) 1023{ 1024 struct net_device *dev = vsi->netdev; 1025 struct i40e_pf *pf = i40e_netdev_to_pf(dev); 1026 1027 /* Not DCB capable */ 1028 if (!(pf->flags & I40E_FLAG_DCB_CAPABLE)) 1029 return; 1030 1031 dev->dcbnl_ops = &dcbnl_ops; 1032 1033 /* Set initial IEEE DCB settings */ 1034 i40e_dcbnl_set_all(vsi); 1035} 1036#endif /* CONFIG_I40E_DCB */