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