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