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