1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2019, Intel Corporation. */ 3 4 #include "ice.h" 5 #include "ice_dcb.h" 6 #include "ice_dcb_lib.h" 7 #include "ice_dcb_nl.h" 8 #include <net/dcbnl.h> 9 10 #define ICE_APP_PROT_ID_ROCE 0x8915 11 12 /** 13 * ice_dcbnl_devreset - perform enough of a ifdown/ifup to sync DCBNL info 14 * @netdev: device associated with interface that needs reset 15 */ 16 static void ice_dcbnl_devreset(struct net_device *netdev) 17 { 18 struct ice_pf *pf = ice_netdev_to_pf(netdev); 19 20 while (ice_is_reset_in_progress(pf->state)) 21 usleep_range(1000, 2000); 22 23 set_bit(__ICE_DCBNL_DEVRESET, pf->state); 24 dev_close(netdev); 25 netdev_state_change(netdev); 26 dev_open(netdev, NULL); 27 netdev_state_change(netdev); 28 clear_bit(__ICE_DCBNL_DEVRESET, pf->state); 29 } 30 31 /** 32 * ice_dcbnl_getets - retrieve local ETS configuration 33 * @netdev: the relevant netdev 34 * @ets: struct to hold ETS configuration 35 */ 36 static int ice_dcbnl_getets(struct net_device *netdev, struct ieee_ets *ets) 37 { 38 struct ice_dcbx_cfg *dcbxcfg; 39 struct ice_port_info *pi; 40 struct ice_pf *pf; 41 42 pf = ice_netdev_to_pf(netdev); 43 pi = pf->hw.port_info; 44 dcbxcfg = &pi->local_dcbx_cfg; 45 46 ets->willing = dcbxcfg->etscfg.willing; 47 ets->ets_cap = dcbxcfg->etscfg.maxtcs; 48 ets->cbs = dcbxcfg->etscfg.cbs; 49 memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_tx_bw)); 50 memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_rx_bw)); 51 memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable, sizeof(ets->tc_tsa)); 52 memcpy(ets->prio_tc, dcbxcfg->etscfg.prio_table, sizeof(ets->prio_tc)); 53 memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable, 54 sizeof(ets->tc_reco_bw)); 55 memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable, 56 sizeof(ets->tc_reco_tsa)); 57 memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prio_table, 58 sizeof(ets->reco_prio_tc)); 59 60 return 0; 61 } 62 63 /** 64 * ice_dcbnl_setets - set IEEE ETS configuration 65 * @netdev: pointer to relevant netdev 66 * @ets: struct to hold ETS configuration 67 */ 68 static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets) 69 { 70 struct ice_pf *pf = ice_netdev_to_pf(netdev); 71 struct ice_dcbx_cfg *new_cfg; 72 int bwcfg = 0, bwrec = 0; 73 int err, i, max_tc = 0; 74 75 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 76 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 77 return -EINVAL; 78 79 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 80 81 mutex_lock(&pf->tc_mutex); 82 83 new_cfg->etscfg.willing = ets->willing; 84 new_cfg->etscfg.cbs = ets->cbs; 85 ice_for_each_traffic_class(i) { 86 new_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i]; 87 bwcfg += ets->tc_tx_bw[i]; 88 new_cfg->etscfg.tsatable[i] = ets->tc_tsa[i]; 89 new_cfg->etscfg.prio_table[i] = ets->prio_tc[i]; 90 if (ets->prio_tc[i] > max_tc) 91 max_tc = ets->prio_tc[i]; 92 new_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i]; 93 bwrec += ets->tc_reco_bw[i]; 94 new_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i]; 95 new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i]; 96 } 97 98 if (ice_dcb_bwchk(pf, new_cfg)) { 99 err = -EINVAL; 100 goto ets_out; 101 } 102 103 max_tc = pf->hw.func_caps.common_cap.maxtc; 104 105 new_cfg->etscfg.maxtcs = max_tc; 106 107 if (!bwcfg) 108 new_cfg->etscfg.tcbwtable[0] = 100; 109 110 if (!bwrec) 111 new_cfg->etsrec.tcbwtable[0] = 100; 112 113 err = ice_pf_dcb_cfg(pf, new_cfg, true); 114 /* return of zero indicates new cfg applied */ 115 if (err == ICE_DCB_HW_CHG_RST) 116 ice_dcbnl_devreset(netdev); 117 if (err == ICE_DCB_NO_HW_CHG) 118 err = ICE_DCB_HW_CHG_RST; 119 120 ets_out: 121 mutex_unlock(&pf->tc_mutex); 122 return err; 123 } 124 125 /** 126 * ice_dcbnl_getnumtcs - Get max number of traffic classes supported 127 * @dev: pointer to netdev struct 128 * @tcid: TC ID 129 * @num: total number of TCs supported by the adapter 130 * 131 * Return the total number of TCs supported 132 */ 133 static int 134 ice_dcbnl_getnumtcs(struct net_device *dev, int __always_unused tcid, u8 *num) 135 { 136 struct ice_pf *pf = ice_netdev_to_pf(dev); 137 138 if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)) 139 return -EINVAL; 140 141 *num = IEEE_8021QAZ_MAX_TCS; 142 return 0; 143 } 144 145 /** 146 * ice_dcbnl_getdcbx - retrieve current DCBX capability 147 * @netdev: pointer to the netdev struct 148 */ 149 static u8 ice_dcbnl_getdcbx(struct net_device *netdev) 150 { 151 struct ice_pf *pf = ice_netdev_to_pf(netdev); 152 153 return pf->dcbx_cap; 154 } 155 156 /** 157 * ice_dcbnl_setdcbx - set required DCBX capability 158 * @netdev: the corresponding netdev 159 * @mode: required mode 160 */ 161 static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode) 162 { 163 struct ice_pf *pf = ice_netdev_to_pf(netdev); 164 165 /* No support for LLD_MANAGED modes or CEE+IEEE */ 166 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) || 167 ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) || 168 !(mode & DCB_CAP_DCBX_HOST)) 169 return ICE_DCB_NO_HW_CHG; 170 171 /* Already set to the given mode no change */ 172 if (mode == pf->dcbx_cap) 173 return ICE_DCB_NO_HW_CHG; 174 175 pf->dcbx_cap = mode; 176 if (mode & DCB_CAP_DCBX_VER_CEE) 177 pf->hw.port_info->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE; 178 else 179 pf->hw.port_info->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE; 180 181 dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode); 182 return ICE_DCB_HW_CHG_RST; 183 } 184 185 /** 186 * ice_dcbnl_get_perm_hw_addr - MAC address used by DCBX 187 * @netdev: pointer to netdev struct 188 * @perm_addr: buffer to return permanent MAC address 189 */ 190 static void ice_dcbnl_get_perm_hw_addr(struct net_device *netdev, u8 *perm_addr) 191 { 192 struct ice_pf *pf = ice_netdev_to_pf(netdev); 193 struct ice_port_info *pi = pf->hw.port_info; 194 int i, j; 195 196 memset(perm_addr, 0xff, MAX_ADDR_LEN); 197 198 for (i = 0; i < netdev->addr_len; i++) 199 perm_addr[i] = pi->mac.perm_addr[i]; 200 201 for (j = 0; j < netdev->addr_len; j++, i++) 202 perm_addr[i] = pi->mac.perm_addr[j]; 203 } 204 205 /** 206 * ice_get_pfc_delay - Retrieve PFC Link Delay 207 * @hw: pointer to HW struct 208 * @delay: holds the PFC Link Delay value 209 */ 210 static void ice_get_pfc_delay(struct ice_hw *hw, u16 *delay) 211 { 212 u32 val; 213 214 val = rd32(hw, PRTDCB_GENC); 215 *delay = (u16)((val & PRTDCB_GENC_PFCLDA_M) >> PRTDCB_GENC_PFCLDA_S); 216 } 217 218 /** 219 * ice_dcbnl_getpfc - retrieve local IEEE PFC config 220 * @netdev: pointer to netdev struct 221 * @pfc: struct to hold PFC info 222 */ 223 static int ice_dcbnl_getpfc(struct net_device *netdev, struct ieee_pfc *pfc) 224 { 225 struct ice_pf *pf = ice_netdev_to_pf(netdev); 226 struct ice_port_info *pi = pf->hw.port_info; 227 struct ice_dcbx_cfg *dcbxcfg; 228 int i; 229 230 dcbxcfg = &pi->local_dcbx_cfg; 231 pfc->pfc_cap = dcbxcfg->pfc.pfccap; 232 pfc->pfc_en = dcbxcfg->pfc.pfcena; 233 pfc->mbc = dcbxcfg->pfc.mbc; 234 ice_get_pfc_delay(&pf->hw, &pfc->delay); 235 236 ice_for_each_traffic_class(i) { 237 pfc->requests[i] = pf->stats.priority_xoff_tx[i]; 238 pfc->indications[i] = pf->stats.priority_xoff_rx[i]; 239 } 240 241 return 0; 242 } 243 244 /** 245 * ice_dcbnl_setpfc - set local IEEE PFC config 246 * @netdev: pointer to relevant netdev 247 * @pfc: pointer to struct holding PFC config 248 */ 249 static int ice_dcbnl_setpfc(struct net_device *netdev, struct ieee_pfc *pfc) 250 { 251 struct ice_pf *pf = ice_netdev_to_pf(netdev); 252 struct ice_dcbx_cfg *new_cfg; 253 int err; 254 255 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 256 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 257 return -EINVAL; 258 259 mutex_lock(&pf->tc_mutex); 260 261 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 262 263 if (pfc->pfc_cap) 264 new_cfg->pfc.pfccap = pfc->pfc_cap; 265 else 266 new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc; 267 268 new_cfg->pfc.pfcena = pfc->pfc_en; 269 270 err = ice_pf_dcb_cfg(pf, new_cfg, true); 271 if (err == ICE_DCB_HW_CHG_RST) 272 ice_dcbnl_devreset(netdev); 273 if (err == ICE_DCB_NO_HW_CHG) 274 err = ICE_DCB_HW_CHG_RST; 275 mutex_unlock(&pf->tc_mutex); 276 return err; 277 } 278 279 /** 280 * ice_dcbnl_get_pfc_cfg - Get CEE PFC config 281 * @netdev: pointer to netdev struct 282 * @prio: corresponding user priority 283 * @setting: the PFC setting for given priority 284 */ 285 static void 286 ice_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, u8 *setting) 287 { 288 struct ice_pf *pf = ice_netdev_to_pf(netdev); 289 struct ice_port_info *pi = pf->hw.port_info; 290 291 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 292 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 293 return; 294 295 if (prio >= ICE_MAX_USER_PRIORITY) 296 return; 297 298 *setting = (pi->local_dcbx_cfg.pfc.pfcena >> prio) & 0x1; 299 dev_dbg(ice_pf_to_dev(pf), "Get PFC Config up=%d, setting=%d, pfcenable=0x%x\n", 300 prio, *setting, pi->local_dcbx_cfg.pfc.pfcena); 301 } 302 303 /** 304 * ice_dcbnl_set_pfc_cfg - Set CEE PFC config 305 * @netdev: the corresponding netdev 306 * @prio: User Priority 307 * @set: PFC setting to apply 308 */ 309 static void ice_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, u8 set) 310 { 311 struct ice_pf *pf = ice_netdev_to_pf(netdev); 312 struct ice_dcbx_cfg *new_cfg; 313 314 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 315 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 316 return; 317 318 if (prio >= ICE_MAX_USER_PRIORITY) 319 return; 320 321 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 322 323 new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc; 324 if (set) 325 new_cfg->pfc.pfcena |= BIT(prio); 326 else 327 new_cfg->pfc.pfcena &= ~BIT(prio); 328 329 dev_dbg(ice_pf_to_dev(pf), "Set PFC config UP:%d set:%d pfcena:0x%x\n", 330 prio, set, new_cfg->pfc.pfcena); 331 } 332 333 /** 334 * ice_dcbnl_getpfcstate - get CEE PFC mode 335 * @netdev: pointer to netdev struct 336 */ 337 static u8 ice_dcbnl_getpfcstate(struct net_device *netdev) 338 { 339 struct ice_pf *pf = ice_netdev_to_pf(netdev); 340 struct ice_port_info *pi = pf->hw.port_info; 341 342 /* Return enabled if any UP enabled for PFC */ 343 if (pi->local_dcbx_cfg.pfc.pfcena) 344 return 1; 345 346 return 0; 347 } 348 349 /** 350 * ice_dcbnl_getstate - get DCB enabled state 351 * @netdev: pointer to netdev struct 352 */ 353 static u8 ice_dcbnl_getstate(struct net_device *netdev) 354 { 355 struct ice_pf *pf = ice_netdev_to_pf(netdev); 356 u8 state = 0; 357 358 state = test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags); 359 360 dev_dbg(ice_pf_to_dev(pf), "DCB enabled state = %d\n", state); 361 return state; 362 } 363 364 /** 365 * ice_dcbnl_setstate - Set CEE DCB state 366 * @netdev: pointer to relevant netdev 367 * @state: state value to set 368 */ 369 static u8 ice_dcbnl_setstate(struct net_device *netdev, u8 state) 370 { 371 struct ice_pf *pf = ice_netdev_to_pf(netdev); 372 373 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 374 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 375 return ICE_DCB_NO_HW_CHG; 376 377 /* Nothing to do */ 378 if (!!state == test_bit(ICE_FLAG_DCB_ENA, pf->flags)) 379 return ICE_DCB_NO_HW_CHG; 380 381 if (state) { 382 set_bit(ICE_FLAG_DCB_ENA, pf->flags); 383 memcpy(&pf->hw.port_info->desired_dcbx_cfg, 384 &pf->hw.port_info->local_dcbx_cfg, 385 sizeof(struct ice_dcbx_cfg)); 386 } else { 387 clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 388 } 389 390 return ICE_DCB_HW_CHG; 391 } 392 393 /** 394 * ice_dcbnl_get_pg_tc_cfg_tx - get CEE PG Tx config 395 * @netdev: pointer to netdev struct 396 * @prio: the corresponding user priority 397 * @prio_type: traffic priority type 398 * @pgid: the BW group ID the traffic class belongs to 399 * @bw_pct: BW percentage for the corresponding BWG 400 * @up_map: prio mapped to corresponding TC 401 */ 402 static void 403 ice_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio, 404 u8 __always_unused *prio_type, u8 *pgid, 405 u8 __always_unused *bw_pct, 406 u8 __always_unused *up_map) 407 { 408 struct ice_pf *pf = ice_netdev_to_pf(netdev); 409 struct ice_port_info *pi = pf->hw.port_info; 410 411 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 412 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 413 return; 414 415 if (prio >= ICE_MAX_USER_PRIORITY) 416 return; 417 418 *pgid = pi->local_dcbx_cfg.etscfg.prio_table[prio]; 419 dev_dbg(ice_pf_to_dev(pf), "Get PG config prio=%d tc=%d\n", prio, 420 *pgid); 421 } 422 423 /** 424 * ice_dcbnl_set_pg_tc_cfg_tx - set CEE PG Tx config 425 * @netdev: pointer to relevant netdev 426 * @tc: the corresponding traffic class 427 * @prio_type: the traffic priority type 428 * @bwg_id: the BW group ID the TC belongs to 429 * @bw_pct: the BW perventage for the BWG 430 * @up_map: prio mapped to corresponding TC 431 */ 432 static void 433 ice_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc, 434 u8 __always_unused prio_type, 435 u8 __always_unused bwg_id, 436 u8 __always_unused bw_pct, u8 up_map) 437 { 438 struct ice_pf *pf = ice_netdev_to_pf(netdev); 439 struct ice_dcbx_cfg *new_cfg; 440 int i; 441 442 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 443 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 444 return; 445 446 if (tc >= ICE_MAX_TRAFFIC_CLASS) 447 return; 448 449 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 450 451 /* prio_type, bwg_id and bw_pct per UP are not supported */ 452 453 ice_for_each_traffic_class(i) { 454 if (up_map & BIT(i)) 455 new_cfg->etscfg.prio_table[i] = tc; 456 } 457 new_cfg->etscfg.tsatable[tc] = ICE_IEEE_TSA_ETS; 458 } 459 460 /** 461 * ice_dcbnl_get_pg_bwg_cfg_tx - Get CEE PGBW config 462 * @netdev: pointer to the netdev struct 463 * @pgid: corresponding traffic class 464 * @bw_pct: the BW percentage for the corresponding TC 465 */ 466 static void 467 ice_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 *bw_pct) 468 { 469 struct ice_pf *pf = ice_netdev_to_pf(netdev); 470 struct ice_port_info *pi = pf->hw.port_info; 471 472 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 473 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 474 return; 475 476 if (pgid >= ICE_MAX_TRAFFIC_CLASS) 477 return; 478 479 *bw_pct = pi->local_dcbx_cfg.etscfg.tcbwtable[pgid]; 480 dev_dbg(ice_pf_to_dev(pf), "Get PG BW config tc=%d bw_pct=%d\n", 481 pgid, *bw_pct); 482 } 483 484 /** 485 * ice_dcbnl_set_pg_bwg_cfg_tx - set CEE PG Tx BW config 486 * @netdev: the corresponding netdev 487 * @pgid: Correspongind traffic class 488 * @bw_pct: the BW percentage for the specified TC 489 */ 490 static void 491 ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 bw_pct) 492 { 493 struct ice_pf *pf = ice_netdev_to_pf(netdev); 494 struct ice_dcbx_cfg *new_cfg; 495 496 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 497 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 498 return; 499 500 if (pgid >= ICE_MAX_TRAFFIC_CLASS) 501 return; 502 503 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 504 505 new_cfg->etscfg.tcbwtable[pgid] = bw_pct; 506 } 507 508 /** 509 * ice_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config 510 * @netdev: pointer to netdev struct 511 * @prio: the corresponding user priority 512 * @prio_type: the traffic priority type 513 * @pgid: the PG ID 514 * @bw_pct: the BW percentage for the corresponding BWG 515 * @up_map: prio mapped to corresponding TC 516 */ 517 static void 518 ice_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, 519 u8 __always_unused *prio_type, u8 *pgid, 520 u8 __always_unused *bw_pct, 521 u8 __always_unused *up_map) 522 { 523 struct ice_pf *pf = ice_netdev_to_pf(netdev); 524 struct ice_port_info *pi = pf->hw.port_info; 525 526 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 527 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 528 return; 529 530 if (prio >= ICE_MAX_USER_PRIORITY) 531 return; 532 533 *pgid = pi->local_dcbx_cfg.etscfg.prio_table[prio]; 534 } 535 536 /** 537 * ice_dcbnl_set_pg_tc_cfg_rx 538 * @netdev: relevant netdev struct 539 * @prio: corresponding user priority 540 * @prio_type: the traffic priority type 541 * @pgid: the PG ID 542 * @bw_pct: BW percentage for corresponding BWG 543 * @up_map: prio mapped to corresponding TC 544 * 545 * lldpad requires this function pointer to be non-NULL to complete CEE config. 546 */ 547 static void 548 ice_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, 549 int __always_unused prio, 550 u8 __always_unused prio_type, 551 u8 __always_unused pgid, 552 u8 __always_unused bw_pct, 553 u8 __always_unused up_map) 554 { 555 struct ice_pf *pf = ice_netdev_to_pf(netdev); 556 557 dev_dbg(ice_pf_to_dev(pf), "Rx TC PG Config Not Supported.\n"); 558 } 559 560 /** 561 * ice_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config 562 * @netdev: pointer to netdev struct 563 * @pgid: the corresponding traffic class 564 * @bw_pct: the BW percentage for the corresponding TC 565 */ 566 static void 567 ice_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid, 568 u8 *bw_pct) 569 { 570 struct ice_pf *pf = ice_netdev_to_pf(netdev); 571 572 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 573 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 574 return; 575 576 *bw_pct = 0; 577 } 578 579 /** 580 * ice_dcbnl_set_pg_bwg_cfg_rx 581 * @netdev: the corresponding netdev 582 * @pgid: corresponding TC 583 * @bw_pct: BW percentage for given TC 584 * 585 * lldpad requires this function pointer to be non-NULL to complete CEE config. 586 */ 587 static void 588 ice_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid, 589 u8 __always_unused bw_pct) 590 { 591 struct ice_pf *pf = ice_netdev_to_pf(netdev); 592 593 dev_dbg(ice_pf_to_dev(pf), "Rx BWG PG Config Not Supported.\n"); 594 } 595 596 /** 597 * ice_dcbnl_get_cap - Get DCBX capabilities of adapter 598 * @netdev: pointer to netdev struct 599 * @capid: the capability type 600 * @cap: the capability value 601 */ 602 static u8 ice_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap) 603 { 604 struct ice_pf *pf = ice_netdev_to_pf(netdev); 605 606 if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))) 607 return ICE_DCB_NO_HW_CHG; 608 609 switch (capid) { 610 case DCB_CAP_ATTR_PG: 611 *cap = true; 612 break; 613 case DCB_CAP_ATTR_PFC: 614 *cap = true; 615 break; 616 case DCB_CAP_ATTR_UP2TC: 617 *cap = false; 618 break; 619 case DCB_CAP_ATTR_PG_TCS: 620 *cap = 0x80; 621 break; 622 case DCB_CAP_ATTR_PFC_TCS: 623 *cap = 0x80; 624 break; 625 case DCB_CAP_ATTR_GSP: 626 *cap = false; 627 break; 628 case DCB_CAP_ATTR_BCN: 629 *cap = false; 630 break; 631 case DCB_CAP_ATTR_DCBX: 632 *cap = pf->dcbx_cap; 633 break; 634 default: 635 *cap = false; 636 break; 637 } 638 639 dev_dbg(ice_pf_to_dev(pf), "DCBX Get Capability cap=%d capval=0x%x\n", 640 capid, *cap); 641 return 0; 642 } 643 644 /** 645 * ice_dcbnl_getapp - get CEE APP 646 * @netdev: pointer to netdev struct 647 * @idtype: the App selector 648 * @id: the App ethtype or port number 649 */ 650 static int ice_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id) 651 { 652 struct ice_pf *pf = ice_netdev_to_pf(netdev); 653 struct dcb_app app = { 654 .selector = idtype, 655 .protocol = id, 656 }; 657 658 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 659 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 660 return -EINVAL; 661 662 return dcb_getapp(netdev, &app); 663 } 664 665 /** 666 * ice_dcbnl_find_app - Search for APP in given DCB config 667 * @cfg: struct to hold DCBX config 668 * @app: struct to hold app data to look for 669 */ 670 static bool 671 ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg, 672 struct ice_dcb_app_priority_table *app) 673 { 674 int i; 675 676 for (i = 0; i < cfg->numapps; i++) { 677 if (app->selector == cfg->app[i].selector && 678 app->prot_id == cfg->app[i].prot_id && 679 app->priority == cfg->app[i].priority) 680 return true; 681 } 682 683 return false; 684 } 685 686 /** 687 * ice_dcbnl_setapp - set local IEEE App config 688 * @netdev: relevant netdev struct 689 * @app: struct to hold app config info 690 */ 691 static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app) 692 { 693 struct ice_pf *pf = ice_netdev_to_pf(netdev); 694 struct ice_dcb_app_priority_table new_app; 695 struct ice_dcbx_cfg *old_cfg, *new_cfg; 696 int ret; 697 698 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 699 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)) 700 return -EINVAL; 701 702 mutex_lock(&pf->tc_mutex); 703 704 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 705 706 old_cfg = &pf->hw.port_info->local_dcbx_cfg; 707 708 if (old_cfg->numapps == ICE_DCBX_MAX_APPS) { 709 ret = -EINVAL; 710 goto setapp_out; 711 } 712 713 ret = dcb_ieee_setapp(netdev, app); 714 if (ret) 715 goto setapp_out; 716 717 new_app.selector = app->selector; 718 new_app.prot_id = app->protocol; 719 new_app.priority = app->priority; 720 if (ice_dcbnl_find_app(old_cfg, &new_app)) { 721 ret = 0; 722 goto setapp_out; 723 } 724 725 new_cfg->app[new_cfg->numapps++] = new_app; 726 ret = ice_pf_dcb_cfg(pf, new_cfg, true); 727 /* return of zero indicates new cfg applied */ 728 if (ret == ICE_DCB_HW_CHG_RST) 729 ice_dcbnl_devreset(netdev); 730 if (ret == ICE_DCB_NO_HW_CHG) 731 ret = ICE_DCB_HW_CHG_RST; 732 733 setapp_out: 734 mutex_unlock(&pf->tc_mutex); 735 return ret; 736 } 737 738 /** 739 * ice_dcbnl_delapp - Delete local IEEE App config 740 * @netdev: relevant netdev 741 * @app: struct to hold app too delete 742 * 743 * Will not delete first application required by the FW 744 */ 745 static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app) 746 { 747 struct ice_pf *pf = ice_netdev_to_pf(netdev); 748 struct ice_dcbx_cfg *old_cfg, *new_cfg; 749 int i, j, ret = 0; 750 751 if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) 752 return -EINVAL; 753 754 mutex_lock(&pf->tc_mutex); 755 old_cfg = &pf->hw.port_info->local_dcbx_cfg; 756 757 if (old_cfg->numapps <= 1) 758 goto delapp_out; 759 760 ret = dcb_ieee_delapp(netdev, app); 761 if (ret) 762 goto delapp_out; 763 764 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 765 766 for (i = 1; i < new_cfg->numapps; i++) { 767 if (app->selector == new_cfg->app[i].selector && 768 app->protocol == new_cfg->app[i].prot_id && 769 app->priority == new_cfg->app[i].priority) { 770 new_cfg->app[i].selector = 0; 771 new_cfg->app[i].prot_id = 0; 772 new_cfg->app[i].priority = 0; 773 break; 774 } 775 } 776 777 /* Did not find DCB App */ 778 if (i == new_cfg->numapps) { 779 ret = -EINVAL; 780 goto delapp_out; 781 } 782 783 new_cfg->numapps--; 784 785 for (j = i; j < new_cfg->numapps; j++) { 786 new_cfg->app[i].selector = old_cfg->app[j + 1].selector; 787 new_cfg->app[i].prot_id = old_cfg->app[j + 1].prot_id; 788 new_cfg->app[i].priority = old_cfg->app[j + 1].priority; 789 } 790 791 ret = ice_pf_dcb_cfg(pf, new_cfg, true); 792 /* return of zero indicates new cfg applied */ 793 if (ret == ICE_DCB_HW_CHG_RST) 794 ice_dcbnl_devreset(netdev); 795 if (ret == ICE_DCB_NO_HW_CHG) 796 ret = ICE_DCB_HW_CHG_RST; 797 798 delapp_out: 799 mutex_unlock(&pf->tc_mutex); 800 return ret; 801 } 802 803 /** 804 * ice_dcbnl_cee_set_all - Commit CEE DCB settings to HW 805 * @netdev: the corresponding netdev 806 */ 807 static u8 ice_dcbnl_cee_set_all(struct net_device *netdev) 808 { 809 struct ice_pf *pf = ice_netdev_to_pf(netdev); 810 struct ice_dcbx_cfg *new_cfg; 811 int err; 812 813 if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) || 814 !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE)) 815 return ICE_DCB_NO_HW_CHG; 816 817 new_cfg = &pf->hw.port_info->desired_dcbx_cfg; 818 819 mutex_lock(&pf->tc_mutex); 820 821 err = ice_pf_dcb_cfg(pf, new_cfg, true); 822 823 mutex_unlock(&pf->tc_mutex); 824 return (err != ICE_DCB_HW_CHG_RST) ? ICE_DCB_NO_HW_CHG : err; 825 } 826 827 static const struct dcbnl_rtnl_ops dcbnl_ops = { 828 /* IEEE 802.1Qaz std */ 829 .ieee_getets = ice_dcbnl_getets, 830 .ieee_setets = ice_dcbnl_setets, 831 .ieee_getpfc = ice_dcbnl_getpfc, 832 .ieee_setpfc = ice_dcbnl_setpfc, 833 .ieee_setapp = ice_dcbnl_setapp, 834 .ieee_delapp = ice_dcbnl_delapp, 835 836 /* CEE std */ 837 .getstate = ice_dcbnl_getstate, 838 .setstate = ice_dcbnl_setstate, 839 .getpermhwaddr = ice_dcbnl_get_perm_hw_addr, 840 .setpgtccfgtx = ice_dcbnl_set_pg_tc_cfg_tx, 841 .setpgbwgcfgtx = ice_dcbnl_set_pg_bwg_cfg_tx, 842 .setpgtccfgrx = ice_dcbnl_set_pg_tc_cfg_rx, 843 .setpgbwgcfgrx = ice_dcbnl_set_pg_bwg_cfg_rx, 844 .getpgtccfgtx = ice_dcbnl_get_pg_tc_cfg_tx, 845 .getpgbwgcfgtx = ice_dcbnl_get_pg_bwg_cfg_tx, 846 .getpgtccfgrx = ice_dcbnl_get_pg_tc_cfg_rx, 847 .getpgbwgcfgrx = ice_dcbnl_get_pg_bwg_cfg_rx, 848 .setpfccfg = ice_dcbnl_set_pfc_cfg, 849 .getpfccfg = ice_dcbnl_get_pfc_cfg, 850 .setall = ice_dcbnl_cee_set_all, 851 .getcap = ice_dcbnl_get_cap, 852 .getnumtcs = ice_dcbnl_getnumtcs, 853 .getpfcstate = ice_dcbnl_getpfcstate, 854 .getapp = ice_dcbnl_getapp, 855 856 /* DCBX configuration */ 857 .getdcbx = ice_dcbnl_getdcbx, 858 .setdcbx = ice_dcbnl_setdcbx, 859 }; 860 861 /** 862 * ice_dcbnl_set_all - set all the apps and ieee data from DCBX config 863 * @vsi: pointer to VSI struct 864 */ 865 void ice_dcbnl_set_all(struct ice_vsi *vsi) 866 { 867 struct net_device *netdev = vsi->netdev; 868 struct ice_dcbx_cfg *dcbxcfg; 869 struct ice_port_info *pi; 870 struct dcb_app sapp; 871 struct ice_pf *pf; 872 int i; 873 874 if (!netdev) 875 return; 876 877 pf = ice_netdev_to_pf(netdev); 878 pi = pf->hw.port_info; 879 880 /* SW DCB taken care of by SW Default Config */ 881 if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) 882 return; 883 884 /* DCB not enabled */ 885 if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags)) 886 return; 887 888 dcbxcfg = &pi->local_dcbx_cfg; 889 890 for (i = 0; i < dcbxcfg->numapps; i++) { 891 u8 prio, tc_map; 892 893 prio = dcbxcfg->app[i].priority; 894 tc_map = BIT(dcbxcfg->etscfg.prio_table[prio]); 895 896 /* Add APP only if the TC is enabled for this VSI */ 897 if (tc_map & vsi->tc_cfg.ena_tc) { 898 sapp.selector = dcbxcfg->app[i].selector; 899 sapp.protocol = dcbxcfg->app[i].prot_id; 900 sapp.priority = prio; 901 dcb_ieee_setapp(netdev, &sapp); 902 } 903 } 904 /* Notify user-space of the changes */ 905 dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0); 906 } 907 908 /** 909 * ice_dcbnl_vsi_del_app - Delete APP on all VSIs 910 * @vsi: pointer to the main VSI 911 * @app: APP to delete 912 * 913 * Delete given APP from all the VSIs for given PF 914 */ 915 static void 916 ice_dcbnl_vsi_del_app(struct ice_vsi *vsi, 917 struct ice_dcb_app_priority_table *app) 918 { 919 struct dcb_app sapp; 920 int err; 921 922 sapp.selector = app->selector; 923 sapp.protocol = app->prot_id; 924 sapp.priority = app->priority; 925 err = ice_dcbnl_delapp(vsi->netdev, &sapp); 926 dev_dbg(ice_pf_to_dev(vsi->back), "Deleting app for VSI idx=%d err=%d sel=%d proto=0x%x, prio=%d\n", 927 vsi->idx, err, app->selector, app->prot_id, app->priority); 928 } 929 930 /** 931 * ice_dcbnl_flush_apps - Delete all removed APPs 932 * @pf: the corresponding PF 933 * @old_cfg: old DCBX configuration data 934 * @new_cfg: new DCBX configuration data 935 * 936 * Find and delete all APPS that are not present in the passed 937 * DCB configuration 938 */ 939 void 940 ice_dcbnl_flush_apps(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg, 941 struct ice_dcbx_cfg *new_cfg) 942 { 943 struct ice_vsi *main_vsi = ice_get_main_vsi(pf); 944 int i; 945 946 if (!main_vsi) 947 return; 948 949 for (i = 0; i < old_cfg->numapps; i++) { 950 struct ice_dcb_app_priority_table app = old_cfg->app[i]; 951 952 /* The APP is not available anymore delete it */ 953 if (!ice_dcbnl_find_app(new_cfg, &app)) 954 ice_dcbnl_vsi_del_app(main_vsi, &app); 955 } 956 } 957 958 /** 959 * ice_dcbnl_setup - setup DCBNL 960 * @vsi: VSI to get associated netdev from 961 */ 962 void ice_dcbnl_setup(struct ice_vsi *vsi) 963 { 964 struct net_device *netdev = vsi->netdev; 965 struct ice_pf *pf; 966 967 pf = ice_netdev_to_pf(netdev); 968 if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)) 969 return; 970 971 netdev->dcbnl_ops = &dcbnl_ops; 972 ice_dcbnl_set_all(vsi); 973 } 974