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