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