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