cxgb4_dcb.c (33783B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2013-2014 Chelsio Communications. All rights reserved. 4 * 5 * Written by Anish Bhatt (anish@chelsio.com) 6 * Casey Leedom (leedom@chelsio.com) 7 */ 8 9#include "cxgb4.h" 10 11/* DCBx version control 12 */ 13const char * const dcb_ver_array[] = { 14 "Unknown", 15 "DCBx-CIN", 16 "DCBx-CEE 1.01", 17 "DCBx-IEEE", 18 "", "", "", 19 "Auto Negotiated" 20}; 21 22static inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state) 23{ 24 if (state == CXGB4_DCB_STATE_FW_ALLSYNCED || 25 state == CXGB4_DCB_STATE_HOST) 26 return true; 27 else 28 return false; 29} 30 31/* Initialize a port's Data Center Bridging state. 32 */ 33void cxgb4_dcb_state_init(struct net_device *dev) 34{ 35 struct port_info *pi = netdev2pinfo(dev); 36 struct port_dcb_info *dcb = &pi->dcb; 37 int version_temp = dcb->dcb_version; 38 39 memset(dcb, 0, sizeof(struct port_dcb_info)); 40 dcb->state = CXGB4_DCB_STATE_START; 41 if (version_temp) 42 dcb->dcb_version = version_temp; 43 44 netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n", 45 __func__, pi->port_id); 46} 47 48void cxgb4_dcb_version_init(struct net_device *dev) 49{ 50 struct port_info *pi = netdev2pinfo(dev); 51 struct port_dcb_info *dcb = &pi->dcb; 52 53 /* Any writes here are only done on kernels that exlicitly need 54 * a specific version, say < 2.6.38 which only support CEE 55 */ 56 dcb->dcb_version = FW_PORT_DCB_VER_AUTO; 57} 58 59static void cxgb4_dcb_cleanup_apps(struct net_device *dev) 60{ 61 struct port_info *pi = netdev2pinfo(dev); 62 struct adapter *adap = pi->adapter; 63 struct port_dcb_info *dcb = &pi->dcb; 64 struct dcb_app app; 65 int i, err; 66 67 /* zero priority implies remove */ 68 app.priority = 0; 69 70 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) { 71 /* Check if app list is exhausted */ 72 if (!dcb->app_priority[i].protocolid) 73 break; 74 75 app.protocol = dcb->app_priority[i].protocolid; 76 77 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) { 78 app.priority = dcb->app_priority[i].user_prio_map; 79 app.selector = dcb->app_priority[i].sel_field + 1; 80 err = dcb_ieee_delapp(dev, &app); 81 } else { 82 app.selector = !!(dcb->app_priority[i].sel_field); 83 err = dcb_setapp(dev, &app); 84 } 85 86 if (err) { 87 dev_err(adap->pdev_dev, 88 "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, , err=%d\n", 89 dcb_ver_array[dcb->dcb_version], app.selector, 90 app.protocol, -err); 91 break; 92 } 93 } 94} 95 96/* Reset a port's Data Center Bridging state. Typically used after a 97 * Link Down event. 98 */ 99void cxgb4_dcb_reset(struct net_device *dev) 100{ 101 cxgb4_dcb_cleanup_apps(dev); 102 cxgb4_dcb_state_init(dev); 103} 104 105/* update the dcb port support, if version is IEEE then set it to 106 * FW_PORT_DCB_VER_IEEE and if DCB_CAP_DCBX_VER_CEE is already set then 107 * clear that. and if it is set to CEE then set dcb supported to 108 * DCB_CAP_DCBX_VER_CEE & if DCB_CAP_DCBX_VER_IEEE is set, clear it 109 */ 110static inline void cxgb4_dcb_update_support(struct port_dcb_info *dcb) 111{ 112 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) { 113 if (dcb->supported & DCB_CAP_DCBX_VER_CEE) 114 dcb->supported &= ~DCB_CAP_DCBX_VER_CEE; 115 dcb->supported |= DCB_CAP_DCBX_VER_IEEE; 116 } else if (dcb->dcb_version == FW_PORT_DCB_VER_CEE1D01) { 117 if (dcb->supported & DCB_CAP_DCBX_VER_IEEE) 118 dcb->supported &= ~DCB_CAP_DCBX_VER_IEEE; 119 dcb->supported |= DCB_CAP_DCBX_VER_CEE; 120 } 121} 122 123/* Finite State machine for Data Center Bridging. 124 */ 125void cxgb4_dcb_state_fsm(struct net_device *dev, 126 enum cxgb4_dcb_state_input transition_to) 127{ 128 struct port_info *pi = netdev2pinfo(dev); 129 struct port_dcb_info *dcb = &pi->dcb; 130 struct adapter *adap = pi->adapter; 131 enum cxgb4_dcb_state current_state = dcb->state; 132 133 netdev_dbg(dev, "%s: State change from %d to %d for %s\n", 134 __func__, dcb->state, transition_to, dev->name); 135 136 switch (current_state) { 137 case CXGB4_DCB_STATE_START: { 138 switch (transition_to) { 139 case CXGB4_DCB_INPUT_FW_DISABLED: { 140 /* we're going to use Host DCB */ 141 dcb->state = CXGB4_DCB_STATE_HOST; 142 dcb->supported = CXGB4_DCBX_HOST_SUPPORT; 143 break; 144 } 145 146 case CXGB4_DCB_INPUT_FW_ENABLED: { 147 /* we're going to use Firmware DCB */ 148 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE; 149 dcb->supported = DCB_CAP_DCBX_LLD_MANAGED; 150 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) 151 dcb->supported |= DCB_CAP_DCBX_VER_IEEE; 152 else 153 dcb->supported |= DCB_CAP_DCBX_VER_CEE; 154 break; 155 } 156 157 case CXGB4_DCB_INPUT_FW_INCOMPLETE: { 158 /* expected transition */ 159 break; 160 } 161 162 case CXGB4_DCB_INPUT_FW_ALLSYNCED: { 163 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED; 164 break; 165 } 166 167 default: 168 goto bad_state_input; 169 } 170 break; 171 } 172 173 case CXGB4_DCB_STATE_FW_INCOMPLETE: { 174 if (transition_to != CXGB4_DCB_INPUT_FW_DISABLED) { 175 /* during this CXGB4_DCB_STATE_FW_INCOMPLETE state, 176 * check if the dcb version is changed (there can be 177 * mismatch in default config & the negotiated switch 178 * configuration at FW, so update the dcb support 179 * accordingly. 180 */ 181 cxgb4_dcb_update_support(dcb); 182 } 183 switch (transition_to) { 184 case CXGB4_DCB_INPUT_FW_ENABLED: { 185 /* we're alreaady in firmware DCB mode */ 186 break; 187 } 188 189 case CXGB4_DCB_INPUT_FW_INCOMPLETE: { 190 /* we're already incomplete */ 191 break; 192 } 193 194 case CXGB4_DCB_INPUT_FW_ALLSYNCED: { 195 dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED; 196 dcb->enabled = 1; 197 linkwatch_fire_event(dev); 198 break; 199 } 200 201 default: 202 goto bad_state_input; 203 } 204 break; 205 } 206 207 case CXGB4_DCB_STATE_FW_ALLSYNCED: { 208 switch (transition_to) { 209 case CXGB4_DCB_INPUT_FW_ENABLED: { 210 /* we're alreaady in firmware DCB mode */ 211 break; 212 } 213 214 case CXGB4_DCB_INPUT_FW_INCOMPLETE: { 215 /* We were successfully running with firmware DCB but 216 * now it's telling us that it's in an "incomplete 217 * state. We need to reset back to a ground state 218 * of incomplete. 219 */ 220 cxgb4_dcb_reset(dev); 221 dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE; 222 dcb->supported = CXGB4_DCBX_FW_SUPPORT; 223 linkwatch_fire_event(dev); 224 break; 225 } 226 227 case CXGB4_DCB_INPUT_FW_ALLSYNCED: { 228 /* we're already all sync'ed 229 * this is only applicable for IEEE or 230 * when another VI already completed negotiaton 231 */ 232 dcb->enabled = 1; 233 linkwatch_fire_event(dev); 234 break; 235 } 236 237 default: 238 goto bad_state_input; 239 } 240 break; 241 } 242 243 case CXGB4_DCB_STATE_HOST: { 244 switch (transition_to) { 245 case CXGB4_DCB_INPUT_FW_DISABLED: { 246 /* we're alreaady in Host DCB mode */ 247 break; 248 } 249 250 default: 251 goto bad_state_input; 252 } 253 break; 254 } 255 256 default: 257 goto bad_state_transition; 258 } 259 return; 260 261bad_state_input: 262 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n", 263 transition_to); 264 return; 265 266bad_state_transition: 267 dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n", 268 current_state, transition_to); 269} 270 271/* Handle a DCB/DCBX update message from the firmware. 272 */ 273void cxgb4_dcb_handle_fw_update(struct adapter *adap, 274 const struct fw_port_cmd *pcmd) 275{ 276 const union fw_port_dcb *fwdcb = &pcmd->u.dcb; 277 int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid)); 278 struct net_device *dev = adap->port[adap->chan_map[port]]; 279 struct port_info *pi = netdev_priv(dev); 280 struct port_dcb_info *dcb = &pi->dcb; 281 int dcb_type = pcmd->u.dcb.pgid.type; 282 int dcb_running_version; 283 284 /* Handle Firmware DCB Control messages separately since they drive 285 * our state machine. 286 */ 287 if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) { 288 enum cxgb4_dcb_state_input input = 289 ((pcmd->u.dcb.control.all_syncd_pkd & 290 FW_PORT_CMD_ALL_SYNCD_F) 291 ? CXGB4_DCB_INPUT_FW_ALLSYNCED 292 : CXGB4_DCB_INPUT_FW_INCOMPLETE); 293 294 if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) { 295 dcb_running_version = FW_PORT_CMD_DCB_VERSION_G( 296 be16_to_cpu( 297 pcmd->u.dcb.control.dcb_version_to_app_state)); 298 if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 || 299 dcb_running_version == FW_PORT_DCB_VER_IEEE) { 300 dcb->dcb_version = dcb_running_version; 301 dev_warn(adap->pdev_dev, "Interface %s is running %s\n", 302 dev->name, 303 dcb_ver_array[dcb->dcb_version]); 304 } else { 305 dev_warn(adap->pdev_dev, 306 "Something screwed up, requested firmware for %s, but firmware returned %s instead\n", 307 dcb_ver_array[dcb->dcb_version], 308 dcb_ver_array[dcb_running_version]); 309 dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN; 310 } 311 } 312 313 cxgb4_dcb_state_fsm(dev, input); 314 return; 315 } 316 317 /* It's weird, and almost certainly an error, to get Firmware DCB 318 * messages when we either haven't been told whether we're going to be 319 * doing Host or Firmware DCB; and even worse when we've been told 320 * that we're doing Host DCB! 321 */ 322 if (dcb->state == CXGB4_DCB_STATE_START || 323 dcb->state == CXGB4_DCB_STATE_HOST) { 324 dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n", 325 dcb->state); 326 return; 327 } 328 329 /* Now handle the general Firmware DCB update messages ... 330 */ 331 switch (dcb_type) { 332 case FW_PORT_DCB_TYPE_PGID: 333 dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid); 334 dcb->msgs |= CXGB4_DCB_FW_PGID; 335 break; 336 337 case FW_PORT_DCB_TYPE_PGRATE: 338 dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported; 339 memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate, 340 sizeof(dcb->pgrate)); 341 memcpy(dcb->tsa, &fwdcb->pgrate.tsa, 342 sizeof(dcb->tsa)); 343 dcb->msgs |= CXGB4_DCB_FW_PGRATE; 344 if (dcb->msgs & CXGB4_DCB_FW_PGID) 345 IEEE_FAUX_SYNC(dev, dcb); 346 break; 347 348 case FW_PORT_DCB_TYPE_PRIORATE: 349 memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate, 350 sizeof(dcb->priorate)); 351 dcb->msgs |= CXGB4_DCB_FW_PRIORATE; 352 break; 353 354 case FW_PORT_DCB_TYPE_PFC: 355 dcb->pfcen = fwdcb->pfc.pfcen; 356 dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs; 357 dcb->msgs |= CXGB4_DCB_FW_PFC; 358 IEEE_FAUX_SYNC(dev, dcb); 359 break; 360 361 case FW_PORT_DCB_TYPE_APP_ID: { 362 const struct fw_port_app_priority *fwap = &fwdcb->app_priority; 363 int idx = fwap->idx; 364 struct app_priority *ap = &dcb->app_priority[idx]; 365 366 struct dcb_app app = { 367 .protocol = be16_to_cpu(fwap->protocolid), 368 }; 369 int err; 370 371 /* Convert from firmware format to relevant format 372 * when using app selector 373 */ 374 if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) { 375 app.selector = (fwap->sel_field + 1); 376 app.priority = ffs(fwap->user_prio_map) - 1; 377 err = dcb_ieee_setapp(dev, &app); 378 IEEE_FAUX_SYNC(dev, dcb); 379 } else { 380 /* Default is CEE */ 381 app.selector = !!(fwap->sel_field); 382 app.priority = fwap->user_prio_map; 383 err = dcb_setapp(dev, &app); 384 } 385 386 if (err) 387 dev_err(adap->pdev_dev, 388 "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n", 389 app.selector, app.protocol, app.priority, -err); 390 391 ap->user_prio_map = fwap->user_prio_map; 392 ap->sel_field = fwap->sel_field; 393 ap->protocolid = be16_to_cpu(fwap->protocolid); 394 dcb->msgs |= CXGB4_DCB_FW_APP_ID; 395 break; 396 } 397 398 default: 399 dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n", 400 dcb_type); 401 break; 402 } 403} 404 405/* Data Center Bridging netlink operations. 406 */ 407 408 409/* Get current DCB enabled/disabled state. 410 */ 411static u8 cxgb4_getstate(struct net_device *dev) 412{ 413 struct port_info *pi = netdev2pinfo(dev); 414 415 return pi->dcb.enabled; 416} 417 418/* Set DCB enabled/disabled. 419 */ 420static u8 cxgb4_setstate(struct net_device *dev, u8 enabled) 421{ 422 struct port_info *pi = netdev2pinfo(dev); 423 424 /* If DCBx is host-managed, dcb is enabled by outside lldp agents */ 425 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) { 426 pi->dcb.enabled = enabled; 427 return 0; 428 } 429 430 /* Firmware doesn't provide any mechanism to control the DCB state. 431 */ 432 if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED)) 433 return 1; 434 435 return 0; 436} 437 438static void cxgb4_getpgtccfg(struct net_device *dev, int tc, 439 u8 *prio_type, u8 *pgid, u8 *bw_per, 440 u8 *up_tc_map, int local) 441{ 442 struct fw_port_cmd pcmd; 443 struct port_info *pi = netdev2pinfo(dev); 444 struct adapter *adap = pi->adapter; 445 int err; 446 447 *prio_type = *pgid = *bw_per = *up_tc_map = 0; 448 449 if (local) 450 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 451 else 452 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 453 454 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID; 455 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 456 if (err != FW_PORT_DCB_CFG_SUCCESS) { 457 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err); 458 return; 459 } 460 *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf; 461 462 if (local) 463 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 464 else 465 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 466 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 467 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 468 if (err != FW_PORT_DCB_CFG_SUCCESS) { 469 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 470 -err); 471 return; 472 } 473 474 *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid]; 475 *up_tc_map = (1 << tc); 476 477 /* prio_type is link strict */ 478 if (*pgid != 0xF) 479 *prio_type = 0x2; 480} 481 482static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc, 483 u8 *prio_type, u8 *pgid, u8 *bw_per, 484 u8 *up_tc_map) 485{ 486 /* tc 0 is written at MSB position */ 487 return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per, 488 up_tc_map, 1); 489} 490 491 492static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc, 493 u8 *prio_type, u8 *pgid, u8 *bw_per, 494 u8 *up_tc_map) 495{ 496 /* tc 0 is written at MSB position */ 497 return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per, 498 up_tc_map, 0); 499} 500 501static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc, 502 u8 prio_type, u8 pgid, u8 bw_per, 503 u8 up_tc_map) 504{ 505 struct fw_port_cmd pcmd; 506 struct port_info *pi = netdev2pinfo(dev); 507 struct adapter *adap = pi->adapter; 508 int fw_tc = 7 - tc; 509 u32 _pgid; 510 int err; 511 512 if (pgid == DCB_ATTR_VALUE_UNDEFINED) 513 return; 514 if (bw_per == DCB_ATTR_VALUE_UNDEFINED) 515 return; 516 517 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 518 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID; 519 520 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 521 if (err != FW_PORT_DCB_CFG_SUCCESS) { 522 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err); 523 return; 524 } 525 526 _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid); 527 _pgid &= ~(0xF << (fw_tc * 4)); 528 _pgid |= pgid << (fw_tc * 4); 529 pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid); 530 531 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); 532 533 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 534 if (err != FW_PORT_DCB_CFG_SUCCESS) { 535 dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n", 536 -err); 537 return; 538 } 539 540 memset(&pcmd, 0, sizeof(struct fw_port_cmd)); 541 542 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 543 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 544 545 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 546 if (err != FW_PORT_DCB_CFG_SUCCESS) { 547 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 548 -err); 549 return; 550 } 551 552 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per; 553 554 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); 555 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) 556 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); 557 558 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 559 if (err != FW_PORT_DCB_CFG_SUCCESS) 560 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n", 561 -err); 562} 563 564static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per, 565 int local) 566{ 567 struct fw_port_cmd pcmd; 568 struct port_info *pi = netdev2pinfo(dev); 569 struct adapter *adap = pi->adapter; 570 int err; 571 572 if (local) 573 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 574 else 575 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 576 577 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 578 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 579 if (err != FW_PORT_DCB_CFG_SUCCESS) { 580 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 581 -err); 582 return; 583 } 584 585 *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid]; 586} 587 588static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per) 589{ 590 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1); 591} 592 593static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per) 594{ 595 return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0); 596} 597 598static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid, 599 u8 bw_per) 600{ 601 struct fw_port_cmd pcmd; 602 struct port_info *pi = netdev2pinfo(dev); 603 struct adapter *adap = pi->adapter; 604 int err; 605 606 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 607 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 608 609 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 610 if (err != FW_PORT_DCB_CFG_SUCCESS) { 611 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 612 -err); 613 return; 614 } 615 616 pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per; 617 618 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); 619 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) 620 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); 621 622 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 623 624 if (err != FW_PORT_DCB_CFG_SUCCESS) 625 dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n", 626 -err); 627} 628 629/* Return whether the specified Traffic Class Priority has Priority Pause 630 * Frames enabled. 631 */ 632static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg) 633{ 634 struct port_info *pi = netdev2pinfo(dev); 635 struct port_dcb_info *dcb = &pi->dcb; 636 637 if (!cxgb4_dcb_state_synced(dcb->state) || 638 priority >= CXGB4_MAX_PRIORITY) 639 *pfccfg = 0; 640 else 641 *pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1; 642} 643 644/* Enable/disable Priority Pause Frames for the specified Traffic Class 645 * Priority. 646 */ 647static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg) 648{ 649 struct fw_port_cmd pcmd; 650 struct port_info *pi = netdev2pinfo(dev); 651 struct adapter *adap = pi->adapter; 652 int err; 653 654 if (!cxgb4_dcb_state_synced(pi->dcb.state) || 655 priority >= CXGB4_MAX_PRIORITY) 656 return; 657 658 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); 659 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) 660 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); 661 662 pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC; 663 pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen; 664 665 if (pfccfg) 666 pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority)); 667 else 668 pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority))); 669 670 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 671 if (err != FW_PORT_DCB_CFG_SUCCESS) { 672 dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err); 673 return; 674 } 675 676 pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen; 677} 678 679static u8 cxgb4_setall(struct net_device *dev) 680{ 681 return 0; 682} 683 684/* Return DCB capabilities. 685 */ 686static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps) 687{ 688 struct port_info *pi = netdev2pinfo(dev); 689 690 switch (cap_id) { 691 case DCB_CAP_ATTR_PG: 692 case DCB_CAP_ATTR_PFC: 693 *caps = true; 694 break; 695 696 case DCB_CAP_ATTR_PG_TCS: 697 /* 8 priorities for PG represented by bitmap */ 698 *caps = 0x80; 699 break; 700 701 case DCB_CAP_ATTR_PFC_TCS: 702 /* 8 priorities for PFC represented by bitmap */ 703 *caps = 0x80; 704 break; 705 706 case DCB_CAP_ATTR_GSP: 707 *caps = true; 708 break; 709 710 case DCB_CAP_ATTR_UP2TC: 711 case DCB_CAP_ATTR_BCN: 712 *caps = false; 713 break; 714 715 case DCB_CAP_ATTR_DCBX: 716 *caps = pi->dcb.supported; 717 break; 718 719 default: 720 *caps = false; 721 } 722 723 return 0; 724} 725 726/* Return the number of Traffic Classes for the indicated Traffic Class ID. 727 */ 728static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num) 729{ 730 struct port_info *pi = netdev2pinfo(dev); 731 732 switch (tcs_id) { 733 case DCB_NUMTCS_ATTR_PG: 734 if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE) 735 *num = pi->dcb.pg_num_tcs_supported; 736 else 737 *num = 0x8; 738 break; 739 740 case DCB_NUMTCS_ATTR_PFC: 741 *num = 0x8; 742 break; 743 744 default: 745 return -EINVAL; 746 } 747 748 return 0; 749} 750 751/* Set the number of Traffic Classes supported for the indicated Traffic Class 752 * ID. 753 */ 754static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num) 755{ 756 /* Setting the number of Traffic Classes isn't supported. 757 */ 758 return -ENOSYS; 759} 760 761/* Return whether Priority Flow Control is enabled. */ 762static u8 cxgb4_getpfcstate(struct net_device *dev) 763{ 764 struct port_info *pi = netdev2pinfo(dev); 765 766 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 767 return false; 768 769 return pi->dcb.pfcen != 0; 770} 771 772/* Enable/disable Priority Flow Control. */ 773static void cxgb4_setpfcstate(struct net_device *dev, u8 state) 774{ 775 /* We can't enable/disable Priority Flow Control but we also can't 776 * return an error ... 777 */ 778} 779 780/* Return the Application User Priority Map associated with the specified 781 * Application ID. 782 */ 783static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id, 784 int peer) 785{ 786 struct port_info *pi = netdev2pinfo(dev); 787 struct adapter *adap = pi->adapter; 788 int i; 789 790 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 791 return 0; 792 793 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) { 794 struct fw_port_cmd pcmd; 795 int err; 796 797 if (peer) 798 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 799 else 800 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 801 802 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; 803 pcmd.u.dcb.app_priority.idx = i; 804 805 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 806 if (err != FW_PORT_DCB_CFG_SUCCESS) { 807 dev_err(adap->pdev_dev, "DCB APP read failed with %d\n", 808 -err); 809 return err; 810 } 811 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) 812 if (pcmd.u.dcb.app_priority.sel_field == app_idtype) 813 return pcmd.u.dcb.app_priority.user_prio_map; 814 815 /* exhausted app list */ 816 if (!pcmd.u.dcb.app_priority.protocolid) 817 break; 818 } 819 820 return -EEXIST; 821} 822 823/* Return the Application User Priority Map associated with the specified 824 * Application ID. 825 */ 826static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id) 827{ 828 /* Convert app_idtype to firmware format before querying */ 829 return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ? 830 app_idtype : 3, app_id, 0); 831} 832 833/* Write a new Application User Priority Map for the specified Application ID 834 */ 835static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id, 836 u8 app_prio) 837{ 838 struct fw_port_cmd pcmd; 839 struct port_info *pi = netdev2pinfo(dev); 840 struct adapter *adap = pi->adapter; 841 int i, err; 842 843 844 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 845 return -EINVAL; 846 847 /* DCB info gets thrown away on link up */ 848 if (!netif_carrier_ok(dev)) 849 return -ENOLINK; 850 851 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) { 852 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 853 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; 854 pcmd.u.dcb.app_priority.idx = i; 855 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 856 857 if (err != FW_PORT_DCB_CFG_SUCCESS) { 858 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n", 859 -err); 860 return err; 861 } 862 if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) { 863 /* overwrite existing app table */ 864 pcmd.u.dcb.app_priority.protocolid = 0; 865 break; 866 } 867 /* find first empty slot */ 868 if (!pcmd.u.dcb.app_priority.protocolid) 869 break; 870 } 871 872 if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) { 873 /* no empty slots available */ 874 dev_err(adap->pdev_dev, "DCB app table full\n"); 875 return -EBUSY; 876 } 877 878 /* write out new app table entry */ 879 INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id); 880 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) 881 pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F); 882 883 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; 884 pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id); 885 pcmd.u.dcb.app_priority.sel_field = app_idtype; 886 pcmd.u.dcb.app_priority.user_prio_map = app_prio; 887 pcmd.u.dcb.app_priority.idx = i; 888 889 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 890 if (err != FW_PORT_DCB_CFG_SUCCESS) { 891 dev_err(adap->pdev_dev, "DCB app table write failed with %d\n", 892 -err); 893 return err; 894 } 895 896 return 0; 897} 898 899/* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */ 900static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id, 901 u8 app_prio) 902{ 903 int ret; 904 struct dcb_app app = { 905 .selector = app_idtype, 906 .protocol = app_id, 907 .priority = app_prio, 908 }; 909 910 if (app_idtype != DCB_APP_IDTYPE_ETHTYPE && 911 app_idtype != DCB_APP_IDTYPE_PORTNUM) 912 return -EINVAL; 913 914 /* Convert app_idtype to a format that firmware understands */ 915 ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ? 916 app_idtype : 3, app_id, app_prio); 917 if (ret) 918 return ret; 919 920 return dcb_setapp(dev, &app); 921} 922 923/* Return whether IEEE Data Center Bridging has been negotiated. 924 */ 925static inline int 926cxgb4_ieee_negotiation_complete(struct net_device *dev, 927 enum cxgb4_dcb_fw_msgs dcb_subtype) 928{ 929 struct port_info *pi = netdev2pinfo(dev); 930 struct port_dcb_info *dcb = &pi->dcb; 931 932 if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED) 933 if (dcb_subtype && !(dcb->msgs & dcb_subtype)) 934 return 0; 935 936 return (cxgb4_dcb_state_synced(dcb->state) && 937 (dcb->supported & DCB_CAP_DCBX_VER_IEEE)); 938} 939 940static int cxgb4_ieee_read_ets(struct net_device *dev, struct ieee_ets *ets, 941 int local) 942{ 943 struct port_info *pi = netdev2pinfo(dev); 944 struct port_dcb_info *dcb = &pi->dcb; 945 struct adapter *adap = pi->adapter; 946 uint32_t tc_info; 947 struct fw_port_cmd pcmd; 948 int i, bwg, err; 949 950 if (!(dcb->msgs & (CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE))) 951 return 0; 952 953 ets->ets_cap = dcb->pg_num_tcs_supported; 954 955 if (local) { 956 ets->willing = 1; 957 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 958 } else { 959 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 960 } 961 962 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID; 963 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 964 if (err != FW_PORT_DCB_CFG_SUCCESS) { 965 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err); 966 return err; 967 } 968 969 tc_info = be32_to_cpu(pcmd.u.dcb.pgid.pgid); 970 971 if (local) 972 INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id); 973 else 974 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 975 976 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 977 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 978 if (err != FW_PORT_DCB_CFG_SUCCESS) { 979 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 980 -err); 981 return err; 982 } 983 984 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 985 bwg = (tc_info >> ((7 - i) * 4)) & 0xF; 986 ets->prio_tc[i] = bwg; 987 ets->tc_tx_bw[i] = pcmd.u.dcb.pgrate.pgrate[i]; 988 ets->tc_rx_bw[i] = ets->tc_tx_bw[i]; 989 ets->tc_tsa[i] = pcmd.u.dcb.pgrate.tsa[i]; 990 } 991 992 return 0; 993} 994 995static int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets) 996{ 997 return cxgb4_ieee_read_ets(dev, ets, 1); 998} 999 1000/* We reuse this for peer PFC as well, as we can't have it enabled one way */ 1001static int cxgb4_ieee_get_pfc(struct net_device *dev, struct ieee_pfc *pfc) 1002{ 1003 struct port_info *pi = netdev2pinfo(dev); 1004 struct port_dcb_info *dcb = &pi->dcb; 1005 1006 memset(pfc, 0, sizeof(struct ieee_pfc)); 1007 1008 if (!(dcb->msgs & CXGB4_DCB_FW_PFC)) 1009 return 0; 1010 1011 pfc->pfc_cap = dcb->pfc_num_tcs_supported; 1012 pfc->pfc_en = bitswap_1(dcb->pfcen); 1013 1014 return 0; 1015} 1016 1017static int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets) 1018{ 1019 return cxgb4_ieee_read_ets(dev, ets, 0); 1020} 1021 1022/* Fill in the Application User Priority Map associated with the 1023 * specified Application. 1024 * Priority for IEEE dcb_app is an integer, with 0 being a valid value 1025 */ 1026static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app) 1027{ 1028 int prio; 1029 1030 if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID)) 1031 return -EINVAL; 1032 if (!(app->selector && app->protocol)) 1033 return -EINVAL; 1034 1035 /* Try querying firmware first, use firmware format */ 1036 prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0); 1037 1038 if (prio < 0) 1039 prio = dcb_ieee_getapp_mask(dev, app); 1040 1041 app->priority = ffs(prio) - 1; 1042 return 0; 1043} 1044 1045/* Write a new Application User Priority Map for the specified Application ID. 1046 * Priority for IEEE dcb_app is an integer, with 0 being a valid value 1047 */ 1048static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app) 1049{ 1050 int ret; 1051 1052 if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID)) 1053 return -EINVAL; 1054 if (!(app->selector && app->protocol)) 1055 return -EINVAL; 1056 1057 if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE && 1058 app->selector < IEEE_8021QAZ_APP_SEL_ANY)) 1059 return -EINVAL; 1060 1061 /* change selector to a format that firmware understands */ 1062 ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol, 1063 (1 << app->priority)); 1064 if (ret) 1065 return ret; 1066 1067 return dcb_ieee_setapp(dev, app); 1068} 1069 1070/* Return our DCBX parameters. 1071 */ 1072static u8 cxgb4_getdcbx(struct net_device *dev) 1073{ 1074 struct port_info *pi = netdev2pinfo(dev); 1075 1076 /* This is already set by cxgb4_set_dcb_caps, so just return it */ 1077 return pi->dcb.supported; 1078} 1079 1080/* Set our DCBX parameters. 1081 */ 1082static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request) 1083{ 1084 struct port_info *pi = netdev2pinfo(dev); 1085 1086 /* Filter out requests which exceed our capabilities. 1087 */ 1088 if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT)) 1089 != dcb_request) 1090 return 1; 1091 1092 /* Can't enable DCB if we haven't successfully negotiated it. 1093 */ 1094 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 1095 return 1; 1096 1097 /* There's currently no mechanism to allow for the firmware DCBX 1098 * negotiation to be changed from the Host Driver. If the caller 1099 * requests exactly the same parameters that we already have then 1100 * we'll allow them to be successfully "set" ... 1101 */ 1102 if (dcb_request != pi->dcb.supported) 1103 return 1; 1104 1105 pi->dcb.supported = dcb_request; 1106 return 0; 1107} 1108 1109static int cxgb4_getpeer_app(struct net_device *dev, 1110 struct dcb_peer_app_info *info, u16 *app_count) 1111{ 1112 struct fw_port_cmd pcmd; 1113 struct port_info *pi = netdev2pinfo(dev); 1114 struct adapter *adap = pi->adapter; 1115 int i, err = 0; 1116 1117 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 1118 return 1; 1119 1120 info->willing = 0; 1121 info->error = 0; 1122 1123 *app_count = 0; 1124 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) { 1125 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 1126 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; 1127 pcmd.u.dcb.app_priority.idx = *app_count; 1128 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 1129 1130 if (err != FW_PORT_DCB_CFG_SUCCESS) { 1131 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n", 1132 -err); 1133 return err; 1134 } 1135 1136 /* find first empty slot */ 1137 if (!pcmd.u.dcb.app_priority.protocolid) 1138 break; 1139 } 1140 *app_count = i; 1141 return err; 1142} 1143 1144static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table) 1145{ 1146 struct fw_port_cmd pcmd; 1147 struct port_info *pi = netdev2pinfo(dev); 1148 struct adapter *adap = pi->adapter; 1149 int i, err = 0; 1150 1151 if (!cxgb4_dcb_state_synced(pi->dcb.state)) 1152 return 1; 1153 1154 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) { 1155 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 1156 pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID; 1157 pcmd.u.dcb.app_priority.idx = i; 1158 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 1159 1160 if (err != FW_PORT_DCB_CFG_SUCCESS) { 1161 dev_err(adap->pdev_dev, "DCB app table read failed with %d\n", 1162 -err); 1163 return err; 1164 } 1165 1166 /* find first empty slot */ 1167 if (!pcmd.u.dcb.app_priority.protocolid) 1168 break; 1169 1170 table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1); 1171 table[i].protocol = 1172 be16_to_cpu(pcmd.u.dcb.app_priority.protocolid); 1173 table[i].priority = 1174 ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1; 1175 } 1176 return err; 1177} 1178 1179/* Return Priority Group information. 1180 */ 1181static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg) 1182{ 1183 struct fw_port_cmd pcmd; 1184 struct port_info *pi = netdev2pinfo(dev); 1185 struct adapter *adap = pi->adapter; 1186 u32 pgid; 1187 int i, err; 1188 1189 /* We're always "willing" -- the Switch Fabric always dictates the 1190 * DCBX parameters to us. 1191 */ 1192 pg->willing = true; 1193 1194 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 1195 pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID; 1196 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 1197 if (err != FW_PORT_DCB_CFG_SUCCESS) { 1198 dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err); 1199 return err; 1200 } 1201 pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid); 1202 1203 for (i = 0; i < CXGB4_MAX_PRIORITY; i++) 1204 pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF; 1205 1206 INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id); 1207 pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE; 1208 err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd); 1209 if (err != FW_PORT_DCB_CFG_SUCCESS) { 1210 dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n", 1211 -err); 1212 return err; 1213 } 1214 1215 for (i = 0; i < CXGB4_MAX_PRIORITY; i++) 1216 pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i]; 1217 1218 pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported; 1219 1220 return 0; 1221} 1222 1223/* Return Priority Flow Control information. 1224 */ 1225static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc) 1226{ 1227 struct port_info *pi = netdev2pinfo(dev); 1228 1229 cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported)); 1230 1231 /* Firmware sends this to us in a formwat that is a bit flipped version 1232 * of spec, correct it before we send it to host. This is taken care of 1233 * by bit shifting in other uses of pfcen 1234 */ 1235 pfc->pfc_en = bitswap_1(pi->dcb.pfcen); 1236 1237 pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported; 1238 1239 return 0; 1240} 1241 1242const struct dcbnl_rtnl_ops cxgb4_dcb_ops = { 1243 .ieee_getets = cxgb4_ieee_get_ets, 1244 .ieee_getpfc = cxgb4_ieee_get_pfc, 1245 .ieee_getapp = cxgb4_ieee_getapp, 1246 .ieee_setapp = cxgb4_ieee_setapp, 1247 .ieee_peer_getets = cxgb4_ieee_peer_ets, 1248 .ieee_peer_getpfc = cxgb4_ieee_get_pfc, 1249 1250 /* CEE std */ 1251 .getstate = cxgb4_getstate, 1252 .setstate = cxgb4_setstate, 1253 .getpgtccfgtx = cxgb4_getpgtccfg_tx, 1254 .getpgbwgcfgtx = cxgb4_getpgbwgcfg_tx, 1255 .getpgtccfgrx = cxgb4_getpgtccfg_rx, 1256 .getpgbwgcfgrx = cxgb4_getpgbwgcfg_rx, 1257 .setpgtccfgtx = cxgb4_setpgtccfg_tx, 1258 .setpgbwgcfgtx = cxgb4_setpgbwgcfg_tx, 1259 .setpfccfg = cxgb4_setpfccfg, 1260 .getpfccfg = cxgb4_getpfccfg, 1261 .setall = cxgb4_setall, 1262 .getcap = cxgb4_getcap, 1263 .getnumtcs = cxgb4_getnumtcs, 1264 .setnumtcs = cxgb4_setnumtcs, 1265 .getpfcstate = cxgb4_getpfcstate, 1266 .setpfcstate = cxgb4_setpfcstate, 1267 .getapp = cxgb4_getapp, 1268 .setapp = cxgb4_setapp, 1269 1270 /* DCBX configuration */ 1271 .getdcbx = cxgb4_getdcbx, 1272 .setdcbx = cxgb4_setdcbx, 1273 1274 /* peer apps */ 1275 .peer_getappinfo = cxgb4_getpeer_app, 1276 .peer_getapptable = cxgb4_getpeerapp_tbl, 1277 1278 /* CEE peer */ 1279 .cee_peer_getpg = cxgb4_cee_peer_getpg, 1280 .cee_peer_getpfc = cxgb4_cee_peer_getpfc, 1281};