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