1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 QLogic Corporation 24 * The contents of this file are subject to the terms of the 25 * QLogic End User License (the "License"). 26 * You may not use this file except in compliance with the License. 27 * 28 * You can obtain a copy of the License at 29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 30 * QLogic_End_User_Software_License.txt 31 * See the License for the specific language governing permissions 32 * and limitations under the License. 33 */ 34 35 /* 36 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 #include "bnxe.h" 40 41 42 #ifdef BNXE_DEBUG_DMA_LIST 43 44 static void BnxeVerifySavedDmaList(um_device_t * pUM) 45 { 46 BnxeMemDma * pTmp; 47 int i; 48 49 BNXE_LOCK_ENTER_MEM(pUM); 50 51 pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaListSaved); 52 while (pTmp) 53 { 54 BnxeLogWarn(pUM, "testing dma block %p / %p %d", 55 pTmp, pTmp->pDmaVirt, pTmp->size); 56 for (i = 0; i < pTmp->size; i++) 57 { 58 if (((u8_t *)pTmp->pDmaVirt)[i] != 0x0) 59 { 60 BnxeDbgBreakMsg(pUM, "old dma block wacked %p (byte %i)", 61 pTmp, i); 62 } 63 } 64 65 pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link); 66 } 67 68 BNXE_LOCK_EXIT_MEM(pUM); 69 } 70 71 #endif /* BNXE_DEBUG_DMA_LIST */ 72 73 74 static boolean_t BnxeRssEnable(um_device_t * pUM) 75 { 76 #define BNXE_RSS_HASH_KEY_SIZE 40 77 u8_t hashKey[BNXE_RSS_HASH_KEY_SIZE]; 78 #define BNXE_RSS_INDIRECTION_TABLE_SIZE 128 /* must be a power of 2 */ 79 u8_t indirectionTable[BNXE_RSS_INDIRECTION_TABLE_SIZE]; 80 lm_rss_hash_t hashType; 81 int i, rc; 82 83 if (!pUM->devParams.numRings) 84 { 85 return B_TRUE; 86 } 87 88 /* fill out the indirection table */ 89 for (i = 0; i < BNXE_RSS_INDIRECTION_TABLE_SIZE; i++) 90 { 91 indirectionTable[i] = (i % pUM->devParams.numRings); 92 } 93 94 /* seed the hash function with random data */ 95 random_get_pseudo_bytes(hashKey, BNXE_RSS_HASH_KEY_SIZE); 96 97 hashType = (LM_RSS_HASH_IPV4 | 98 LM_RSS_HASH_TCP_IPV4 | 99 LM_RSS_HASH_IPV6 | 100 LM_RSS_HASH_TCP_IPV6); 101 102 rc = lm_enable_rss((lm_device_t *)pUM, 103 indirectionTable, 104 BNXE_RSS_INDIRECTION_TABLE_SIZE, 105 hashKey, 106 BNXE_RSS_HASH_KEY_SIZE, 107 hashType, 108 FALSE, 109 NULL); 110 111 if (rc == LM_STATUS_PENDING) 112 { 113 if ((rc = lm_wait_config_rss_done(&pUM->lm_dev)) != LM_STATUS_SUCCESS) 114 { 115 BnxeLogWarn(pUM, "Failed to enable RSS from pending operation (%d)", rc); 116 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 117 } 118 } 119 else if (rc != LM_STATUS_SUCCESS) 120 { 121 BnxeLogWarn(pUM, "Failed to enable RSS (%d)", rc); 122 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 123 } 124 125 return (rc == LM_STATUS_SUCCESS) ? B_TRUE : B_FALSE; 126 } 127 128 129 static lm_status_t BnxeRssDisable(um_device_t * pUM) 130 { 131 int rc; 132 133 rc = lm_disable_rss((lm_device_t *)pUM, FALSE, NULL); 134 135 if (rc == LM_STATUS_PENDING) 136 { 137 if ((rc = lm_wait_config_rss_done(&pUM->lm_dev)) != LM_STATUS_SUCCESS) 138 { 139 BnxeLogWarn(pUM, "Failed to disable RSS from pending operation (%d)", rc); 140 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 141 } 142 } 143 else if (rc != LM_STATUS_SUCCESS) 144 { 145 BnxeLogWarn(pUM, "Failed to disable RSS (%d)", rc); 146 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 147 } 148 149 return (rc == LM_STATUS_SUCCESS) ? B_TRUE : B_FALSE; 150 } 151 152 153 lm_medium_t BnxeHwReqPhyMediumSettings(um_device_t * pUM) 154 { 155 lm_device_t * pLM = &pUM->lm_dev; 156 lm_medium_t medium = 0; 157 char buf[128]; 158 int i; 159 160 memset(pUM->hwinit.supported, 0, sizeof(pUM->hwinit.supported)); 161 162 switch (pLM->params.link.num_phys) 163 { 164 case 1: 165 166 pUM->hwinit.supported[0] = 167 pLM->params.link.phy[ELINK_INT_PHY].supported; 168 pUM->hwinit.phy_cfg_size = 1; 169 break; 170 171 case 2: 172 173 pUM->hwinit.supported[0] = 174 pLM->params.link.phy[ELINK_EXT_PHY1].supported; 175 pUM->hwinit.phy_cfg_size = 1; 176 break; 177 178 case 3: 179 180 if (pLM->params.link.multi_phy_config & 181 PORT_HW_CFG_PHY_SWAPPED_ENABLED) 182 { 183 pUM->hwinit.supported[1] = 184 pLM->params.link.phy[ELINK_EXT_PHY1].supported; 185 pUM->hwinit.supported[0] = 186 pLM->params.link.phy[ELINK_EXT_PHY2].supported; 187 } 188 else 189 { 190 pUM->hwinit.supported[0] = 191 pLM->params.link.phy[ELINK_EXT_PHY1].supported; 192 pUM->hwinit.supported[1] = 193 pLM->params.link.phy[ELINK_EXT_PHY2].supported; 194 } 195 196 pUM->hwinit.phy_cfg_size = 2; 197 break; 198 199 default: 200 201 BnxeLogWarn(pUM, "Unexpected number of phys, check nvram config! (%d)", 202 pLM->params.link.num_phys); 203 return 0; 204 } 205 206 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++) 207 { 208 *buf = 0; 209 snprintf(buf, sizeof(buf), "Phy %d supported:", i); 210 211 if (!(pLM->params.link.speed_cap_mask[i] & 212 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)) 213 { 214 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10baseT_Half; 215 } 216 else 217 { 218 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 219 " 10M/half"); 220 } 221 222 if (!(pLM->params.link.speed_cap_mask[i] & 223 PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL)) 224 { 225 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10baseT_Full; 226 } 227 else 228 { 229 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 230 " 10M/full"); 231 } 232 233 if (!(pLM->params.link.speed_cap_mask[i] & 234 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)) 235 { 236 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_100baseT_Half; 237 } 238 else 239 { 240 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 241 " 100M/half"); 242 } 243 244 if (!(pLM->params.link.speed_cap_mask[i] & 245 PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL)) 246 { 247 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_100baseT_Full; 248 } 249 else 250 { 251 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 252 " 100M/full"); 253 } 254 255 if (!(pLM->params.link.speed_cap_mask[i] & 256 PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) 257 { 258 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_1000baseT_Full; 259 } 260 else 261 { 262 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 263 " 1G"); 264 } 265 266 if (!(pLM->params.link.speed_cap_mask[i] & 267 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) 268 { 269 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_2500baseX_Full; 270 } 271 else 272 { 273 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 274 " 2.5G"); 275 } 276 277 if (!(pLM->params.link.speed_cap_mask[i] & 278 PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) 279 { 280 pUM->hwinit.supported[i] &= ~ELINK_SUPPORTED_10000baseT_Full; 281 } 282 else 283 { 284 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 285 " 10G"); 286 } 287 288 if (!(pLM->params.link.speed_cap_mask[i] & 289 PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) 290 { 291 pUM->hwinit.supported[i] &= ~(ELINK_SUPPORTED_20000baseMLD2_Full | 292 ELINK_SUPPORTED_20000baseKR2_Full); 293 } 294 else 295 { 296 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 297 " 20G"); 298 } 299 300 BnxeLogInfo(pUM, buf); 301 302 *buf = 0; 303 snprintf(buf, sizeof(buf), "Phy %d link config:", i); 304 305 switch ((uint32_t)pLM->hw_info.link_config[i] & 306 PORT_FEATURE_CONNECTED_SWITCH_MASK) 307 { 308 case PORT_FEATURE_CON_SWITCH_1G_SWITCH: 309 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 310 " switch/1G"); 311 break; 312 case PORT_FEATURE_CON_SWITCH_10G_SWITCH: 313 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 314 " switch/10G"); 315 break; 316 case PORT_FEATURE_CON_SWITCH_AUTO_DETECT: 317 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 318 " switch/auto"); 319 break; 320 case PORT_FEATURE_CON_SWITCH_ONE_TIME_DETECT: 321 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 322 " switch/once"); 323 break; 324 default: 325 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 326 " switch/unknown"); 327 break; 328 } 329 330 switch ((uint32_t)pLM->hw_info.link_config[i] & 331 PORT_FEATURE_LINK_SPEED_MASK) 332 { 333 case PORT_FEATURE_LINK_SPEED_AUTO: 334 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 335 " speed/auto"); 336 break; 337 case PORT_FEATURE_LINK_SPEED_10M_FULL: 338 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 339 " speed/10M/full"); 340 break; 341 case PORT_FEATURE_LINK_SPEED_10M_HALF: 342 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 343 " speed/10M/half"); 344 break; 345 case PORT_FEATURE_LINK_SPEED_100M_HALF: 346 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 347 " speed/100M/half"); 348 break; 349 case PORT_FEATURE_LINK_SPEED_100M_FULL: 350 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 351 " speed/100M/full"); 352 break; 353 case PORT_FEATURE_LINK_SPEED_1G: 354 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 355 " speed/1G"); 356 break; 357 case PORT_FEATURE_LINK_SPEED_2_5G: 358 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 359 " speed/2.5G"); 360 break; 361 case PORT_FEATURE_LINK_SPEED_10G_CX4: 362 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 363 " speed/10G"); 364 break; 365 case PORT_FEATURE_LINK_SPEED_20G: 366 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 367 " speed/20G"); 368 break; 369 default: 370 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 371 " speed/unknown"); 372 break; 373 } 374 375 switch ((uint32_t)pLM->hw_info.link_config[i] & 376 PORT_FEATURE_FLOW_CONTROL_MASK) 377 { 378 case PORT_FEATURE_FLOW_CONTROL_AUTO: 379 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 380 " flow/auto"); 381 break; 382 case PORT_FEATURE_FLOW_CONTROL_TX: 383 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 384 " flow/tx"); 385 break; 386 case PORT_FEATURE_FLOW_CONTROL_RX: 387 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 388 " flow/rx"); 389 break; 390 case PORT_FEATURE_FLOW_CONTROL_BOTH: 391 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 392 " flow/both"); 393 break; 394 case PORT_FEATURE_FLOW_CONTROL_NONE: 395 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 396 " flow/none"); 397 break; 398 default: 399 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 400 " flow/unknown"); 401 break; 402 } 403 404 BnxeLogInfo(pUM, buf); 405 } 406 407 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++) 408 { 409 *buf = 0; 410 snprintf(buf, sizeof(buf), "Requesting Phy %d speed:", i); 411 412 if (pUM->curcfg.lnkcfg.param_10hdx) 413 { 414 if (((pLM->hw_info.link_config[i] & 415 PORT_FEATURE_LINK_SPEED_MASK) == 416 PORT_FEATURE_LINK_SPEED_AUTO) || 417 ((pLM->hw_info.link_config[i] & 418 PORT_FEATURE_LINK_SPEED_MASK) == 419 PORT_FEATURE_LINK_SPEED_10M_HALF)) 420 { 421 medium |= (LM_MEDIUM_SPEED_10MBPS | LM_MEDIUM_HALF_DUPLEX); 422 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 423 " 10M/half"); 424 } 425 else 426 { 427 BnxeLogWarn(pUM, "Phy 10hdx requested but not supported"); 428 } 429 } 430 431 if (pUM->curcfg.lnkcfg.param_10fdx) 432 { 433 if (((pLM->hw_info.link_config[i] & 434 PORT_FEATURE_LINK_SPEED_MASK) == 435 PORT_FEATURE_LINK_SPEED_AUTO) || 436 ((pLM->hw_info.link_config[i] & 437 PORT_FEATURE_LINK_SPEED_MASK) == 438 PORT_FEATURE_LINK_SPEED_10M_FULL)) 439 { 440 medium |= (LM_MEDIUM_SPEED_10MBPS | LM_MEDIUM_FULL_DUPLEX); 441 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 442 " 10M/full"); 443 } 444 else 445 { 446 BnxeLogWarn(pUM, "Phy 10fdx requested but not supported"); 447 } 448 } 449 450 if (pUM->curcfg.lnkcfg.param_100hdx) 451 { 452 if (((pLM->hw_info.link_config[i] & 453 PORT_FEATURE_LINK_SPEED_MASK) == 454 PORT_FEATURE_LINK_SPEED_AUTO) || 455 ((pLM->hw_info.link_config[i] & 456 PORT_FEATURE_LINK_SPEED_MASK) == 457 PORT_FEATURE_LINK_SPEED_100M_HALF)) 458 { 459 medium |= (LM_MEDIUM_SPEED_100MBPS | LM_MEDIUM_HALF_DUPLEX); 460 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 461 " 100M/half"); 462 } 463 else 464 { 465 BnxeLogWarn(pUM, "Phy 100hdx requested but not supported"); 466 } 467 } 468 469 if (pUM->curcfg.lnkcfg.param_100fdx) 470 { 471 if (((pLM->hw_info.link_config[i] & 472 PORT_FEATURE_LINK_SPEED_MASK) == 473 PORT_FEATURE_LINK_SPEED_AUTO) || 474 ((pLM->hw_info.link_config[i] & 475 PORT_FEATURE_LINK_SPEED_MASK) == 476 PORT_FEATURE_LINK_SPEED_100M_FULL)) 477 { 478 medium |= (LM_MEDIUM_SPEED_100MBPS | LM_MEDIUM_FULL_DUPLEX); 479 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 480 " 100M/full"); 481 } 482 else 483 { 484 BnxeLogWarn(pUM, "Phy 100fdx requested but not supported"); 485 } 486 } 487 488 if (pUM->curcfg.lnkcfg.param_1000fdx) 489 { 490 if (((pLM->hw_info.link_config[i] & 491 PORT_FEATURE_LINK_SPEED_MASK) == 492 PORT_FEATURE_LINK_SPEED_AUTO) || 493 ((pLM->hw_info.link_config[i] & 494 PORT_FEATURE_LINK_SPEED_MASK) == 495 PORT_FEATURE_LINK_SPEED_1G)) 496 { 497 medium |= (LM_MEDIUM_SPEED_1000MBPS | LM_MEDIUM_FULL_DUPLEX); 498 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 499 " 1G"); 500 } 501 else 502 { 503 BnxeLogWarn(pUM, "Phy 1000fdx requested but not supported"); 504 } 505 } 506 507 if (pUM->curcfg.lnkcfg.param_10000fdx) 508 { 509 if (((pLM->hw_info.link_config[i] & 510 PORT_FEATURE_LINK_SPEED_MASK) == 511 PORT_FEATURE_LINK_SPEED_AUTO) || 512 ((pLM->hw_info.link_config[i] & 513 PORT_FEATURE_LINK_SPEED_MASK) == 514 PORT_FEATURE_LINK_SPEED_10G_CX4)) 515 { 516 medium |= (LM_MEDIUM_SPEED_10GBPS | LM_MEDIUM_FULL_DUPLEX); 517 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 518 " 10G"); 519 } 520 else 521 { 522 BnxeLogWarn(pUM, "Phy 10000fdx requested but not supported"); 523 } 524 } 525 526 if (pUM->curcfg.lnkcfg.param_20000fdx) 527 { 528 if (((pLM->hw_info.link_config[i] & 529 PORT_FEATURE_LINK_SPEED_MASK) == 530 PORT_FEATURE_LINK_SPEED_AUTO) || 531 ((pLM->hw_info.link_config[i] & 532 PORT_FEATURE_LINK_SPEED_MASK) == 533 PORT_FEATURE_LINK_SPEED_20G)) 534 { 535 medium |= (LM_MEDIUM_SPEED_20GBPS | LM_MEDIUM_FULL_DUPLEX); 536 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 537 " 20G"); 538 } 539 else 540 { 541 BnxeLogWarn(pUM, "Phy 20000fdx requested but not supported"); 542 } 543 } 544 545 if (pUM->curcfg.lnkcfg.link_autoneg) 546 { 547 if ((pLM->hw_info.link_config[i] & 548 PORT_FEATURE_LINK_SPEED_MASK) == 549 PORT_FEATURE_LINK_SPEED_AUTO) 550 { 551 if (medium) 552 { 553 BnxeLogWarn(pUM, "Phy autoneg requested along with other speeds, ignoring others and forcing autoneg"); 554 } 555 556 medium = LM_MEDIUM_SPEED_AUTONEG; /* 0x0000 */ 557 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 558 " auto"); 559 } 560 else 561 { 562 BnxeLogWarn(pUM, "Phy autoneg requested but not supported"); 563 } 564 } 565 566 BnxeLogInfo(pUM, buf); 567 } 568 569 medium |= LM_MEDIUM_TYPE_XGXS; 570 571 return medium; 572 } 573 574 575 lm_flow_control_t BnxeHwReqPhyFlowSettings(um_device_t * pUM) 576 { 577 lm_device_t * pLM = &pUM->lm_dev; 578 lm_flow_control_t flowctrl; 579 char buf[128]; 580 int i; 581 582 flowctrl = LM_FLOW_CONTROL_NONE; 583 584 for (i = 0; i < pUM->hwinit.phy_cfg_size; i++) 585 { 586 *buf = 0; 587 snprintf(buf, sizeof(buf), "Requesting Phy %d flow:", i); 588 589 if (pUM->curcfg.lnkcfg.param_txpause) 590 { 591 if ((pLM->hw_info.link_config[i] & 592 PORT_FEATURE_FLOW_CONTROL_MASK) & 593 PORT_FEATURE_FLOW_CONTROL_TX) 594 { 595 flowctrl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; 596 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 597 " tx"); 598 } 599 else 600 { 601 BnxeLogWarn(pUM, "Phy TX flow requested but not supported"); 602 } 603 } 604 605 if (pUM->curcfg.lnkcfg.param_rxpause) 606 { 607 if ((pLM->hw_info.link_config[i] & 608 PORT_FEATURE_FLOW_CONTROL_MASK) & 609 PORT_FEATURE_FLOW_CONTROL_RX) 610 { 611 flowctrl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; 612 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 613 " rx"); 614 } 615 else 616 { 617 BnxeLogWarn(pUM, "Phy RX flow requested but not supported"); 618 } 619 } 620 621 if (pUM->curcfg.flow_autoneg) 622 { 623 /* 624 * This value can be or'ed with receive pause and transmit 625 * pause. If the auto-negotiation is disabled and the receive 626 * pause and transmit pause bits are set, then flow control is 627 * enabled regardless of link partner's flow control capability. 628 * Otherwise, if this bit is set, then flow is negotiated with 629 * the link partner. Values 0x80000000 and 0x80000003 are 630 * equivalent. 631 */ 632 if ((pLM->hw_info.link_config[i] & 633 PORT_FEATURE_FLOW_CONTROL_MASK) == 634 PORT_FEATURE_FLOW_CONTROL_AUTO) 635 { 636 flowctrl |= LM_FLOW_CONTROL_AUTO_PAUSE; 637 snprintf(buf + strlen(buf), (sizeof(buf) - strlen(buf)), 638 " auto"); 639 } 640 else 641 { 642 BnxeLogWarn(pUM, "Phy Auto flow requested but not supported"); 643 } 644 } 645 646 BnxeLogInfo(pUM, buf); 647 } 648 649 return flowctrl; 650 } 651 652 653 void BnxeUpdatePhy(um_device_t * pUM) 654 { 655 lm_device_t * pLM = &pUM->lm_dev; 656 int rc; 657 658 BNXE_LOCK_ENTER_PHY(pUM); 659 660 pLM->params.req_medium = BnxeHwReqPhyMediumSettings(pUM); 661 pLM->params.flow_ctrl_cap = BnxeHwReqPhyFlowSettings(pUM); 662 663 if (IS_PMF(&pUM->lm_dev)) 664 { 665 lm_reset_link(pLM); 666 } 667 668 rc = lm_init_phy(pLM, 669 pLM->params.req_medium, 670 pLM->params.flow_ctrl_cap, 671 0 /* pLM->params.selective_autoneg */, 672 0 /* pLM->params.wire_speed */, 673 0); 674 675 if (pUM->fmCapabilities && 676 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 677 { 678 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 679 } 680 681 if (rc == LM_STATUS_SUCCESS) 682 { 683 pUM->phyInitialized = B_TRUE; 684 } 685 else 686 { 687 BnxeLogWarn(pUM, "Failed to initialize the phy (%d)", rc); 688 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 689 } 690 691 #if 0 692 /* 693 * This is problematic. For non-PMF functions the lm_niv_vif_set for 694 * a link up will come very early and is queued for processing right 695 * after lm_chip_start. Thereafter setting the loopback mode brings 696 * the interface back down. Don't know if setting the loopback mode 697 * is even required when forcing it off. XXX 698 */ 699 if (IS_MF_AFEX_MODE(&pUM->lm_dev)) 700 { 701 lm_niv_set_loopback_mode(&pUM->lm_dev, FALSE); 702 } 703 #endif 704 705 BNXE_LOCK_EXIT_PHY(pUM); 706 } 707 708 709 /* 710 * (flag) TRUE = add, FALSE = remove 711 * 712 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this 713 * is shared between GLDv3 and FCoE entry points. 714 */ 715 int BnxeMacAddress(um_device_t * pUM, 716 int cliIdx, 717 boolean_t flag, 718 const uint8_t * pMacAddr) 719 { 720 int i, rc; 721 722 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE)) 723 { 724 return EINVAL; 725 } 726 727 BnxeLogDbg(pUM, "%s MAC address: %02x:%02x:%02x:%02x:%02x:%02x", 728 (flag) ? "Adding" : "Removing", 729 pMacAddr[0], pMacAddr[1], pMacAddr[2], 730 pMacAddr[3], pMacAddr[4], pMacAddr[5]); 731 732 rc = lm_set_mac_addr(&pUM->lm_dev, 733 (u8_t *)pMacAddr, 734 /* XXX */ LM_SET_CAM_NO_VLAN_FILTER, 735 LM_CLI_CID(&pUM->lm_dev, cliIdx), 736 NULL, flag, 0); 737 738 if (rc == LM_STATUS_PENDING) 739 { 740 if ((rc = lm_wait_set_mac_done(&pUM->lm_dev, 741 LM_CLI_CID(&pUM->lm_dev, cliIdx))) != 742 LM_STATUS_SUCCESS) 743 { 744 BnxeLogWarn(pUM, "Failed to %s MAC Address from pending operation (%d)", 745 (flag) ? "set" : "remove", rc); 746 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 747 return ENOMEM; 748 } 749 } 750 else if ((rc != LM_STATUS_PENDING) && (rc != LM_STATUS_EXISTING_OBJECT)) 751 { 752 BnxeLogWarn(pUM, "Failed to %s MAC Address (%d)", 753 (flag) ? "set" : "remove", rc); 754 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 755 return ENOMEM; 756 } 757 758 return 0; 759 } 760 761 762 /* 763 * This function is used to enable or disable multicast packet reception for 764 * particular multicast addresses. (flag) TRUE = add, FALSE = remove. 765 * 766 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this 767 * is shared between GLDv3 and FCoE entry points. 768 */ 769 770 void BnxeMulticastE1(um_device_t * pUM, 771 int cliIdx) 772 { 773 if ((cliIdx != LM_CLI_IDX_NDIS) || !CHIP_IS_E1(&pUM->lm_dev)) 774 { 775 return; 776 } 777 778 /* already holding BNXE_LOCK_ENTER_HWINIT */ 779 780 if (d_list_entry_cnt(&pUM->mcast_l2) > 64) 781 { 782 if (!(pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] & 783 LM_RX_MASK_ACCEPT_ALL_MULTICAST)) 784 { 785 BnxeLogInfo(pUM, "Turning ON the ALL_MCAST rx mask, number of multicast addressess is >64"); 786 787 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] |= 788 LM_RX_MASK_ACCEPT_ALL_MULTICAST; 789 790 BnxeRxMask(pUM, LM_CLI_IDX_NDIS, 791 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]); 792 } 793 } 794 else 795 { 796 if (pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] & 797 LM_RX_MASK_ACCEPT_ALL_MULTICAST) 798 { 799 BnxeLogInfo(pUM, "Turning OFF the ALL_MCAST rx mask, number of multicast addressess is <=64"); 800 801 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS] &= 802 ~LM_RX_MASK_ACCEPT_ALL_MULTICAST; 803 804 BnxeRxMask(pUM, LM_CLI_IDX_NDIS, 805 pUM->devParams.rx_filter_mask[LM_CLI_IDX_NDIS]); 806 } 807 } 808 } 809 810 int BnxeMulticast(um_device_t * pUM, 811 int cliIdx, 812 boolean_t flag, 813 const uint8_t * pMcastAddr, 814 boolean_t hwSet) 815 { 816 struct ecore_mcast_list_elem * pTmp; 817 d_list_t * mcastList; 818 int i, rc; 819 820 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE)) 821 { 822 return EINVAL; 823 } 824 825 if (!pMcastAddr) 826 { 827 BnxeLogInfo(pUM, "Removing all multicast"); 828 } 829 else 830 { 831 BnxeLogInfo(pUM, "%s multicast: %02x:%02x:%02x:%02x:%02x:%02x", 832 (flag) ? "Adding" : "Removing", 833 pMcastAddr[0], pMcastAddr[1], pMcastAddr[2], 834 pMcastAddr[3], pMcastAddr[4], pMcastAddr[5]); 835 } 836 837 mcastList = (cliIdx == LM_CLI_IDX_NDIS) ? &pUM->mcast_l2 : 838 &pUM->mcast_fcoe; 839 840 if (flag && (pMcastAddr == NULL)) 841 { 842 /* adding a new address that isn't specified...? */ 843 BnxeLogWarn(pUM, "ERROR: Multicast address not specified"); 844 return EINVAL; 845 } 846 else if (!flag && (pMcastAddr == NULL)) 847 { 848 /* clear all multicast addresses */ 849 850 while (d_list_entry_cnt(mcastList)) 851 { 852 pTmp = (struct ecore_mcast_list_elem *)d_list_pop_head(mcastList); 853 kmem_free(pTmp, (sizeof(struct ecore_mcast_list_elem) + 854 ETHERNET_ADDRESS_SIZE)); 855 } 856 857 if (!hwSet) 858 { 859 return 0; 860 } 861 862 rc = lm_set_mc_list(&pUM->lm_dev, mcastList, NULL, cliIdx); 863 864 if (rc == LM_STATUS_PENDING) 865 { 866 if ((rc = lm_wait_set_mc_done(&pUM->lm_dev, cliIdx)) != 867 LM_STATUS_SUCCESS) 868 { 869 BnxeLogWarn(pUM, "Failed to clear Multicast Address table from pending operation (%d)", rc); 870 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 871 return ENOMEM; 872 } 873 } 874 else if (rc != LM_STATUS_SUCCESS) 875 { 876 BnxeLogWarn(pUM, "Failed to clear Multicast Address table (%d)", rc); 877 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 878 return ENOMEM; 879 } 880 881 BnxeMulticastE1(pUM, cliIdx); 882 883 return 0; 884 } 885 886 /* check if this address already exists in the table */ 887 pTmp = (struct ecore_mcast_list_elem *)d_list_peek_head(mcastList); 888 while (pTmp) 889 { 890 if (IS_ETH_ADDRESS_EQUAL(pMcastAddr, pTmp->mac)) 891 { 892 break; 893 } 894 895 pTmp = (struct ecore_mcast_list_elem *)d_list_next_entry(D_LINK_CAST(pTmp)); 896 } 897 898 if (flag) 899 { 900 /* only add the address if the table is empty or address not found */ 901 if (pTmp == NULL) 902 { 903 if ((pTmp = kmem_zalloc((sizeof(struct ecore_mcast_list_elem) + 904 ETHERNET_ADDRESS_SIZE), 905 KM_NOSLEEP)) == NULL) 906 { 907 BnxeLogWarn(pUM, "Failed to alloc Multicast Address node"); 908 return ENOMEM; 909 } 910 911 pTmp->mac = (u8_t *)pTmp + sizeof(struct ecore_mcast_list_elem); 912 913 COPY_ETH_ADDRESS(pMcastAddr, pTmp->mac); 914 915 d_list_push_head(mcastList, D_LINK_CAST(pTmp)); 916 } 917 } 918 else /* (!flag) */ 919 { 920 if (pTmp == NULL) 921 { 922 /* the address isn't in the table */ 923 return ENXIO; 924 } 925 926 d_list_remove_entry(mcastList, D_LINK_CAST(pTmp)); 927 928 kmem_free(pTmp, (sizeof(struct ecore_mcast_list_elem) + 929 ETHERNET_ADDRESS_SIZE)); 930 } 931 932 if (!hwSet) 933 { 934 return 0; 935 } 936 937 rc = lm_set_mc_list(&pUM->lm_dev, mcastList, NULL, cliIdx); 938 939 if (rc == LM_STATUS_PENDING) 940 { 941 if ((rc = lm_wait_set_mc_done(&pUM->lm_dev, cliIdx)) != 942 LM_STATUS_SUCCESS) 943 { 944 BnxeLogWarn(pUM, "Failed to set Multicast Address table from pending operation (%d)", rc); 945 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 946 return ENOMEM; 947 } 948 } 949 else if (rc != LM_STATUS_SUCCESS) 950 { 951 BnxeLogWarn(pUM, "Failed to set Multicast Address table (%d)", rc); 952 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 953 return ENOMEM; 954 } 955 956 BnxeMulticastE1(pUM, cliIdx); 957 958 return 0; 959 } 960 961 962 /* 963 * This function must be called with BNXE_LOCK_ENTER_HWINIT held because this 964 * is shared between GLDv3 and FCoE entry points. 965 */ 966 int BnxeRxMask(um_device_t * pUM, 967 int cliIdx, 968 lm_rx_mask_t mask) 969 { 970 int rc; 971 972 if ((cliIdx != LM_CLI_IDX_NDIS) && (cliIdx != LM_CLI_IDX_FCOE)) 973 { 974 return EINVAL; 975 } 976 977 pUM->devParams.rx_filter_mask[cliIdx] = mask; 978 979 rc = lm_set_rx_mask(&pUM->lm_dev, 980 LM_CLI_CID(&pUM->lm_dev, cliIdx), mask, NULL); 981 982 if (rc == LM_STATUS_PENDING) 983 { 984 if ((rc = 985 lm_wait_set_rx_mask_done(&pUM->lm_dev, 986 LM_CLI_CID(&pUM->lm_dev, cliIdx))) != 987 LM_STATUS_SUCCESS) 988 { 989 BnxeLogWarn(pUM, "Failed to set Rx mask from pending operation (%d)", rc); 990 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_NO_RESPONSE); 991 return ENOMEM; 992 } 993 } 994 995 if (pUM->fmCapabilities && 996 BnxeCheckAccHandle(pUM->lm_dev.vars.reg_handle[BAR_0]) != DDI_FM_OK) 997 { 998 BnxeLogWarn(pUM, "DMA fault when setting Rx mask"); 999 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1000 return ENOMEM; 1001 } 1002 1003 if (rc != LM_STATUS_SUCCESS) 1004 { 1005 BnxeLogWarn(pUM, "Failed to set Rx mask (%d)", rc); 1006 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1007 return ENOMEM; 1008 } 1009 1010 return 0; 1011 } 1012 1013 1014 boolean_t BnxeEstablishHwConn(um_device_t * pUM, 1015 int cid) 1016 { 1017 lm_device_t * pLM = &pUM->lm_dev; 1018 lm_client_con_params_t cliParams; 1019 int sb_id; 1020 int rc; 1021 1022 sb_id = lm_sb_id_from_chain(&pUM->lm_dev, cid); 1023 1024 memset(&cliParams, 0, sizeof(cliParams)); 1025 cliParams.mtu = pUM->devParams.mtu[LM_CHAIN_IDX_CLI(pLM, cid)]; 1026 //cliParams.lah_size = pUM->devParams.mtu[LM_CHAIN_IDX_CLI(pLM, cid)]; 1027 cliParams.lah_size = 0; 1028 cliParams.num_rx_desc = pUM->devParams.numRxDesc[LM_CHAIN_IDX_CLI(pLM, cid)]; 1029 cliParams.num_tx_desc = pUM->devParams.numTxDesc[LM_CHAIN_IDX_CLI(pLM, cid)]; 1030 cliParams.attributes = (LM_CLIENT_ATTRIBUTES_RX | 1031 LM_CLIENT_ATTRIBUTES_TX | 1032 LM_CLIENT_ATTRIBUTES_REG_CLI); 1033 1034 BnxeLogDbg(pUM, "Setting up client for cid %d", cid); 1035 if (lm_setup_client_con_params(pLM, cid, &cliParams) != LM_STATUS_SUCCESS) 1036 { 1037 BnxeLogWarn(pUM, "Failed to setup client for cid %d", cid); 1038 return B_FALSE; 1039 } 1040 1041 /*********************************************************/ 1042 1043 BnxeLogDbg(pUM, "Initializing client for cid %d", cid); 1044 rc = lm_init_chain_con(pLM, cid, TRUE); 1045 1046 if (pUM->fmCapabilities && 1047 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK) 1048 { 1049 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1050 return B_FALSE; 1051 } 1052 1053 if (pUM->fmCapabilities && 1054 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1055 { 1056 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1057 return B_FALSE; 1058 } 1059 1060 if (rc != LM_STATUS_SUCCESS) 1061 { 1062 BnxeLogWarn(pUM, "Failed to initialize client for cid %d", cid); 1063 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1064 return B_FALSE; 1065 } 1066 1067 /*********************************************************/ 1068 1069 BnxeLogDbg(pUM, "Establishing client for cid %d", cid); 1070 rc = lm_establish_eth_con(pLM, cid, sb_id, 1071 pLM->params.l2_cli_con_params[cid].attributes); 1072 1073 if (pUM->fmCapabilities && 1074 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK) 1075 { 1076 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1077 return B_FALSE; 1078 } 1079 1080 if (pUM->fmCapabilities && 1081 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1082 { 1083 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1084 return B_FALSE; 1085 } 1086 1087 if (rc != LM_STATUS_SUCCESS) 1088 { 1089 BnxeLogWarn(pUM, "Failed to establish client connection"); 1090 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1091 return B_FALSE; 1092 } 1093 1094 return B_TRUE; 1095 } 1096 1097 1098 int BnxeHwStartFCOE(um_device_t * pUM) 1099 { 1100 lm_device_t * pLM = &pUM->lm_dev; 1101 int rc; 1102 1103 if (!BNXE_FCOE(pUM)) 1104 { 1105 BnxeDbgBreakMsg(pUM, "Inside BnxeHwStartFCOE and FCoE not supported!"); 1106 return -1; 1107 } 1108 1109 BNXE_LOCK_ENTER_HWINIT(pUM); 1110 1111 BnxeLogInfo(pUM, "BnxeHwStartFCOE: Starting FCoE (clients %s)", 1112 BnxeClientsHw(pUM)); 1113 1114 if (BnxeHwStartCore(pUM)) 1115 { 1116 goto BnxeHwStartFCOE_error; 1117 } 1118 1119 if (!pUM->hwInitDone) 1120 { 1121 BnxeLogWarn(pUM, "BnxeHwStartFCOE: Failed, hardware not initialized (clients %s)", 1122 BnxeClientsHw(pUM)); 1123 goto BnxeHwStartFCOE_error; 1124 } 1125 1126 /*********************************************************/ 1127 1128 BnxeLogDbg(pUM, "Allocating FCoE Resources"); 1129 1130 if (lm_fc_alloc_resc(&pUM->lm_dev) != LM_STATUS_SUCCESS) 1131 { 1132 BnxeLogWarn(pUM, "Failed to allocate FCoE resources"); 1133 goto BnxeHwStartFCOE_error; 1134 } 1135 1136 /*********************************************************/ 1137 1138 BnxeLogDbg(pUM, "Opening FCoE Ethernet Connection"); 1139 1140 pUM->lm_dev.ofld_info.state_blks[STATE_BLOCK_FCOE] = 1141 &pUM->lm_dev.fcoe_info.run_time.state_blk; 1142 1143 if (!BnxeEstablishHwConn(pUM, FCOE_CID(pLM))) 1144 { 1145 goto BnxeHwStartFCOE_error; 1146 } 1147 1148 /*********************************************************/ 1149 1150 BnxeLogDbg(pUM, "Initializing FCoE Tx Pkts"); 1151 1152 if (BnxeTxPktsInit(pUM, LM_CLI_IDX_FCOE)) 1153 { 1154 BnxeLogWarn(pUM, "Failed to allocate FCoE Tx resources"); 1155 goto BnxeHwStartFCOE_error; 1156 } 1157 1158 /*********************************************************/ 1159 1160 BnxeLogDbg(pUM, "Initializing FCoE Rx Pkts"); 1161 1162 if (BnxeRxPktsInit(pUM, LM_CLI_IDX_FCOE)) 1163 { 1164 BnxeLogWarn(pUM, "Failed to allocate FCoE Rx resources"); 1165 goto BnxeHwStartFCOE_error; 1166 } 1167 1168 if (BnxeRxPktsInitPostBuffers(pUM, LM_CLI_IDX_FCOE)) 1169 { 1170 BnxeLogWarn(pUM, "Failed to post FCoE Rx buffers"); 1171 goto BnxeHwStartFCOE_error; 1172 } 1173 1174 /*********************************************************/ 1175 1176 BnxeLogDbg(pUM, "Setting FCoE MAC Address"); 1177 1178 if (BnxeMacAddress(pUM, LM_CLI_IDX_FCOE, B_TRUE, 1179 pLM->hw_info.fcoe_mac_addr) < 0) 1180 { 1181 goto BnxeHwStartFCOE_error; 1182 } 1183 1184 /*********************************************************/ 1185 1186 BnxeLogDbg(pUM, "Setting FCoE Multicast Addresses"); 1187 1188 #define ALL_FCOE_MACS (const uint8_t *)"\x01\x10\x18\x01\x00\x00" 1189 #define ALL_ENODE_MACS (const uint8_t *)"\x01\x10\x18\x01\x00\x01" 1190 1191 if ((BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_TRUE, ALL_FCOE_MACS, B_FALSE) < 0) || 1192 (BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_TRUE, ALL_ENODE_MACS, B_TRUE) < 0)) 1193 { 1194 goto BnxeHwStartFCOE_error; 1195 } 1196 1197 /*********************************************************/ 1198 1199 BnxeLogDbg(pUM, "Turning on FCoE Rx Mask"); 1200 1201 if (BnxeRxMask(pUM, LM_CLI_IDX_FCOE, ( 1202 LM_RX_MASK_ACCEPT_UNICAST 1203 //| LM_RX_MASK_ACCEPT_ALL_MULTICAST 1204 | LM_RX_MASK_ACCEPT_MULTICAST 1205 //| LM_RX_MASK_ACCEPT_BROADCAST 1206 //| LM_RX_MASK_PROMISCUOUS_MODE 1207 )) < 0) 1208 { 1209 goto BnxeHwStartFCOE_error; 1210 } 1211 1212 /*********************************************************/ 1213 1214 CLIENT_HW_SET(pUM, LM_CLI_IDX_FCOE); 1215 1216 BnxeLogInfo(pUM, "BnxeHwStartFCOE: FCoE started (clients %s)", 1217 BnxeClientsHw(pUM)); 1218 1219 BNXE_LOCK_EXIT_HWINIT(pUM); 1220 return 0; 1221 1222 BnxeHwStartFCOE_error: 1223 1224 BNXE_LOCK_EXIT_HWINIT(pUM); 1225 return -1; 1226 } 1227 1228 1229 int BnxeHwStartL2(um_device_t * pUM) 1230 { 1231 lm_device_t * pLM = &pUM->lm_dev; 1232 int idx, rc; 1233 1234 BNXE_LOCK_ENTER_HWINIT(pUM); 1235 1236 BnxeLogInfo(pUM, "BnxeHwStartL2: Starting L2 (clients %s)", 1237 BnxeClientsHw(pUM)); 1238 1239 if (BnxeHwStartCore(pUM)) 1240 { 1241 goto BnxeHwStartL2_error; 1242 } 1243 1244 if (!pUM->hwInitDone) 1245 { 1246 BnxeLogWarn(pUM, "BnxeHwStartL2: Failed, hardware not initialized (clients %s)", 1247 BnxeClientsHw(pUM)); 1248 goto BnxeHwStartL2_error; 1249 } 1250 1251 /*********************************************************/ 1252 1253 BnxeLogDbg(pUM, "Opening L2 Ethernet Connections (%d)", 1254 pLM->params.rss_chain_cnt); 1255 1256 LM_FOREACH_RSS_IDX(pLM, idx) 1257 { 1258 if (!BnxeEstablishHwConn(pUM, idx)) 1259 { 1260 goto BnxeHwStartL2_error; 1261 } 1262 } 1263 1264 /*********************************************************/ 1265 1266 BnxeLogDbg(pUM, "Initializing Tx Pkts"); 1267 1268 if (BnxeTxPktsInit(pUM, LM_CLI_IDX_NDIS)) 1269 { 1270 BnxeLogWarn(pUM, "Failed to allocate tx resources"); 1271 goto BnxeHwStartL2_error; 1272 } 1273 1274 /*********************************************************/ 1275 1276 BnxeLogDbg(pUM, "Initializing Rx Pkts"); 1277 1278 if (BnxeRxPktsInit(pUM, LM_CLI_IDX_NDIS)) 1279 { 1280 BnxeLogWarn(pUM, "Failed to allocate L2 Rx resources"); 1281 goto BnxeHwStartL2_error; 1282 } 1283 1284 if (BnxeRxPktsInitPostBuffers(pUM, LM_CLI_IDX_NDIS)) 1285 { 1286 BnxeLogWarn(pUM, "Failed to post L2 Rx buffers"); 1287 goto BnxeHwStartL2_error; 1288 } 1289 1290 /*********************************************************/ 1291 1292 BnxeLogDbg(pUM, "Enabling RSS"); 1293 1294 if (!BnxeRssEnable(pUM)) 1295 { 1296 goto BnxeHwStartL2_error; 1297 } 1298 1299 /*********************************************************/ 1300 1301 BnxeLogDbg(pUM, "Setting L2 MAC Address"); 1302 1303 /* use the hw programmed address (GLDv3 will overwrite if needed) */ 1304 1305 { 1306 u8_t zero_mac_addr[ETHERNET_ADDRESS_SIZE]; 1307 memset(zero_mac_addr, 0, ETHERNET_ADDRESS_SIZE); 1308 1309 if (IS_ETH_ADDRESS_EQUAL(pUM->gldMac, zero_mac_addr)) 1310 { 1311 COPY_ETH_ADDRESS(pUM->lm_dev.hw_info.mac_addr, 1312 pUM->lm_dev.params.mac_addr); 1313 } 1314 else 1315 { 1316 COPY_ETH_ADDRESS(pUM->gldMac, 1317 pUM->lm_dev.params.mac_addr); 1318 } 1319 } 1320 1321 if (BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_TRUE, 1322 pUM->lm_dev.params.mac_addr) < 0) 1323 { 1324 goto BnxeHwStartL2_error; 1325 } 1326 1327 /*********************************************************/ 1328 1329 BnxeLogDbg(pUM, "Turning on L2 Rx Mask"); 1330 1331 if (BnxeRxMask(pUM, LM_CLI_IDX_NDIS, ( 1332 LM_RX_MASK_ACCEPT_UNICAST 1333 //| LM_RX_MASK_ACCEPT_ALL_MULTICAST 1334 | LM_RX_MASK_ACCEPT_MULTICAST 1335 | LM_RX_MASK_ACCEPT_BROADCAST 1336 //| LM_RX_MASK_PROMISCUOUS_MODE 1337 )) < 0) 1338 { 1339 goto BnxeHwStartL2_error; 1340 } 1341 1342 /*********************************************************/ 1343 1344 CLIENT_HW_SET(pUM, LM_CLI_IDX_NDIS); 1345 lm_mcp_indicate_client_bind(&pUM->lm_dev, LM_CLI_IDX_NDIS); 1346 1347 BNXE_LOCK_EXIT_HWINIT(pUM); 1348 1349 /*********************************************************/ 1350 1351 /* 1352 * Force a link update. Another client might already be up in which case 1353 * the link status won't change during this plumb of the L2 client. 1354 */ 1355 BnxeGldLink(pUM, (pUM->devParams.lastIndLink == LM_STATUS_LINK_ACTIVE) ? 1356 LINK_STATE_UP : LINK_STATE_DOWN); 1357 1358 BnxeLogInfo(pUM, "BnxeHwStartL2: L2 started (clients %s)", 1359 BnxeClientsHw(pUM)); 1360 1361 return 0; 1362 1363 BnxeHwStartL2_error: 1364 1365 /* XXX Need cleanup! */ 1366 1367 BNXE_LOCK_EXIT_HWINIT(pUM); 1368 return -1; 1369 } 1370 1371 1372 /* Must be called with BNXE_LOCK_ENTER_HWINIT taken! */ 1373 int BnxeHwStartCore(um_device_t * pUM) 1374 { 1375 lm_device_t * pLM = &pUM->lm_dev; 1376 int rc; 1377 1378 if (pUM->hwInitDone) 1379 { 1380 /* already initialized */ 1381 BnxeLogInfo(pUM, "BnxeHwStartCore: Hardware already initialized (clients %s)", 1382 BnxeClientsHw(pUM)); 1383 return 0; 1384 } 1385 1386 BnxeLogInfo(pUM, "BnxeHwStartCore: Starting hardware (clients %s)", 1387 BnxeClientsHw(pUM)); 1388 1389 memset(&pLM->debug_info, 0, sizeof(pLM->debug_info)); 1390 1391 /*********************************************************/ 1392 1393 /* reset the configuration to the hardware default */ 1394 BnxeCfgReset(pUM); 1395 1396 pUM->phyInitialized = B_FALSE; 1397 1398 /*********************************************************/ 1399 1400 BnxeLogDbg(pUM, "Allocating LM Resources"); 1401 1402 if (lm_alloc_resc(pLM) != LM_STATUS_SUCCESS) 1403 { 1404 BnxeLogWarn(pUM, "Failed to allocate resources"); 1405 goto BnxeHwStartCore_error; 1406 } 1407 1408 /*********************************************************/ 1409 1410 BnxeLogDbg(pUM, "Initializing BRCM Chip"); 1411 1412 rc = lm_chip_init(pLM); 1413 1414 if (pUM->fmCapabilities && 1415 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK) 1416 { 1417 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1418 goto BnxeHwStartCore_error; 1419 } 1420 1421 if (pUM->fmCapabilities && 1422 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1423 { 1424 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1425 goto BnxeHwStartCore_error; 1426 } 1427 1428 if (rc != LM_STATUS_SUCCESS) 1429 { 1430 BnxeLogWarn(pUM, "Failed to initialize chip"); 1431 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1432 goto BnxeHwStartCore_error; 1433 } 1434 1435 /*********************************************************/ 1436 1437 BnxeLogDbg(pUM, "Enabling Interrupts"); 1438 1439 if (BnxeIntrEnable(pUM)) 1440 { 1441 BnxeLogWarn(pUM, "Failed to enable interrupts"); 1442 goto BnxeHwStartCore_error; 1443 } 1444 1445 /*********************************************************/ 1446 1447 BnxeLogDbg(pUM, "Starting BRCM Chip"); 1448 1449 rc = lm_chip_start(pLM); 1450 1451 if (pUM->fmCapabilities && 1452 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1453 { 1454 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1455 goto BnxeHwStartCore_error; 1456 } 1457 1458 if (rc != LM_STATUS_SUCCESS) 1459 { 1460 BnxeLogWarn(pUM, "Failed to start chip"); 1461 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1462 goto BnxeHwStartCore_error; 1463 } 1464 1465 atomic_swap_32(&pUM->chipStarted, B_TRUE); 1466 1467 /*********************************************************/ 1468 1469 BnxeLogDbg(pUM, "Activating pending WorkQ items"); 1470 1471 BnxeWorkQueueStartPending(pUM); 1472 1473 /*********************************************************/ 1474 1475 BnxeLogDbg(pUM, "Initializing DCBX"); 1476 1477 lm_dcbx_init(pLM, B_FALSE); /* B_TRUE for hibernate */ 1478 1479 /*********************************************************/ 1480 1481 BnxeLogDbg(pUM, "Initializing Phy"); 1482 1483 BnxeUpdatePhy(pUM); 1484 1485 /*********************************************************/ 1486 1487 BnxeLogDbg(pUM, "Starting Timer"); 1488 1489 BnxeTimerStart(pUM); 1490 1491 /*********************************************************/ 1492 1493 atomic_swap_32(&pUM->hwInitDone, B_TRUE); 1494 1495 BnxeLogInfo(pUM, "BnxeHwStartCore: Hardware started (clients %s)", 1496 BnxeClientsHw(pUM)); 1497 1498 return 0; 1499 1500 BnxeHwStartCore_error: 1501 1502 return -1; 1503 } 1504 1505 1506 void BnxeHwStopFCOE(um_device_t * pUM) 1507 { 1508 lm_device_t * pLM = &pUM->lm_dev; 1509 int rc; 1510 1511 if (!BNXE_FCOE(pUM)) 1512 { 1513 BnxeDbgBreakMsg(pUM, "Inside BnxeHwStopFCOE and FCoE not supported!"); 1514 return; 1515 } 1516 1517 BNXE_LOCK_ENTER_HWINIT(pUM); 1518 1519 BnxeLogInfo(pUM, "BnxeHwStopFCOE: Stopping FCoE (clients %s)", 1520 BnxeClientsHw(pUM)); 1521 1522 CLIENT_HW_RESET(pUM, LM_CLI_IDX_FCOE); 1523 1524 /*********************************************************/ 1525 1526 BnxeLogDbg(pUM, "Turning off FCoE RX Mask"); 1527 1528 BnxeRxMask(pUM, LM_CLI_IDX_FCOE, LM_RX_MASK_ACCEPT_NONE); 1529 1530 /*********************************************************/ 1531 1532 BnxeLogDbg(pUM, "Clearing the FCoE Multicast Table"); 1533 1534 BnxeMulticast(pUM, LM_CLI_IDX_FCOE, B_FALSE, NULL, B_TRUE); 1535 1536 /*********************************************************/ 1537 1538 BnxeLogDbg(pUM, "Closing FCoE Connection"); 1539 1540 if ((rc = lm_close_eth_con(pLM, FCOE_CID(pLM), B_TRUE)) != 1541 LM_STATUS_SUCCESS) 1542 { 1543 BnxeLogWarn(pUM, "Failed to close FCoE conn %d (%d)", 1544 FCOE_CID(pLM), rc); 1545 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1546 } 1547 1548 /*********************************************************/ 1549 1550 BnxeLogDbg(pUM, "Aborting FCoE TX Chains"); 1551 1552 BnxeTxPktsAbort(pUM, LM_CLI_IDX_FCOE); 1553 1554 /*********************************************************/ 1555 1556 BnxeLogDbg(pUM, "Aborting FCoE RX Chains"); 1557 1558 BnxeRxPktsAbort(pUM, LM_CLI_IDX_FCOE); 1559 1560 /*********************************************************/ 1561 1562 BnxeLogDbg(pUM, "Cleaning up FCoE Tx Pkts"); 1563 1564 BnxeTxPktsFini(pUM, LM_CLI_IDX_FCOE); 1565 1566 /*********************************************************/ 1567 1568 BnxeLogDbg(pUM, "Cleaning up FCoE Rx Pkts"); 1569 1570 BnxeRxPktsFini(pUM, LM_CLI_IDX_FCOE); 1571 1572 /*********************************************************/ 1573 1574 BnxeLogDbg(pUM, "Clearing FCoE Resources"); 1575 1576 if ((rc = lm_fc_clear_resc(pLM)) != LM_STATUS_SUCCESS) 1577 { 1578 BnxeLogWarn(pUM, "Failed to clear FCoE resources (%d)\n", rc); 1579 } 1580 1581 lm_cid_recycled_cb_deregister(pLM, FCOE_CONNECTION_TYPE); 1582 1583 /*********************************************************/ 1584 1585 BnxeHwStopCore(pUM); 1586 1587 /*********************************************************/ 1588 1589 BnxeLogInfo(pUM, "BnxeHwStopFCOE: FCoE stopped (clients %s)", 1590 BnxeClientsHw(pUM)); 1591 1592 BNXE_LOCK_EXIT_HWINIT(pUM); 1593 } 1594 1595 1596 void BnxeHwStopL2(um_device_t * pUM) 1597 { 1598 lm_device_t * pLM = &pUM->lm_dev; 1599 int idx, rc; 1600 1601 BNXE_LOCK_ENTER_HWINIT(pUM); 1602 1603 BnxeLogInfo(pUM, "BnxeHwStopL2: Stopping L2 (clients %s)", 1604 BnxeClientsHw(pUM)); 1605 1606 lm_mcp_indicate_client_unbind(&pUM->lm_dev, LM_CLI_IDX_NDIS); 1607 CLIENT_HW_RESET(pUM, LM_CLI_IDX_NDIS); 1608 1609 /*********************************************************/ 1610 1611 BnxeLogDbg(pUM, "Turning off L2 RX Mask"); 1612 1613 BnxeRxMask(pUM, LM_CLI_IDX_NDIS, LM_RX_MASK_ACCEPT_NONE); 1614 1615 /*********************************************************/ 1616 1617 BnxeLogDbg(pUM, "Clearing the L2 MAC Address"); 1618 1619 /* 1620 * Reset the mac_addr to hw programmed default and then clear 1621 * it in the firmware. 1622 */ 1623 { 1624 u8_t mac_to_delete[ETHERNET_ADDRESS_SIZE]; 1625 COPY_ETH_ADDRESS(pUM->lm_dev.params.mac_addr, 1626 mac_to_delete); 1627 1628 COPY_ETH_ADDRESS(pUM->lm_dev.hw_info.mac_addr, 1629 pUM->lm_dev.params.mac_addr); 1630 memset(pUM->gldMac, 0, ETHERNET_ADDRESS_SIZE); 1631 1632 #if 0 1633 BnxeMacAddress(pUM, LM_CLI_IDX_NDIS, B_FALSE, mac_to_delete); 1634 #else 1635 BnxeLogInfo(pUM, "Removing all MAC addresses"); 1636 1637 if ((rc = lm_clear_all_mac_addr(pLM, 1638 LM_CLI_CID(&pUM->lm_dev, 1639 LM_CLI_IDX_NDIS))) != 1640 LM_STATUS_SUCCESS) 1641 { 1642 BnxeLogWarn(pUM, "Failed to delete all MAC addresses (%d)", rc); 1643 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1644 } 1645 #endif 1646 } 1647 1648 /*********************************************************/ 1649 1650 BnxeLogDbg(pUM, "Clearing the L2 Multicast Table"); 1651 1652 BnxeMulticast(pUM, LM_CLI_IDX_NDIS, B_FALSE, NULL, B_TRUE); 1653 1654 /*********************************************************/ 1655 1656 BnxeLogDbg(pUM, "Disabling RSS"); 1657 1658 BnxeRssDisable(pUM); 1659 1660 /*********************************************************/ 1661 1662 /* 1663 * In Solaris when RX traffic is accepted, the system might generate and 1664 * attempt to send some TX packets (from within gld_recv()!). Claiming any 1665 * TX locks before this point would create a deadlock. The ISR would be 1666 * waiting for a lock acquired here that would never be freed, since we 1667 * in-turn would be waiting for the ISR to finish here. Consequently, we 1668 * acquire the TX lock as soon as we know that no TX traffic is a result of 1669 * RX traffic. 1670 */ 1671 BNXE_LOCK_ENTER_GLDTX(pUM, RW_WRITER); 1672 1673 /*********************************************************/ 1674 1675 BnxeLogDbg(pUM, "Closing L2 Ethernet Connections (%d)", 1676 pLM->params.rss_chain_cnt); 1677 1678 LM_FOREACH_RSS_IDX(pLM, idx) 1679 { 1680 if ((rc = lm_close_eth_con(pLM, idx, B_TRUE)) != 1681 LM_STATUS_SUCCESS) 1682 { 1683 BnxeLogWarn(pUM, "Failed to close Ethernet conn on RSS %d (%d)", 1684 idx, rc); 1685 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1686 } 1687 } 1688 1689 /*********************************************************/ 1690 1691 BnxeLogDbg(pUM, "Aborting L2 Tx Chains"); 1692 1693 BnxeTxPktsAbort(pUM, LM_CLI_IDX_NDIS); 1694 1695 /*********************************************************/ 1696 1697 BnxeLogDbg(pUM, "Aborting L2 Rx Chains"); 1698 1699 BnxeRxPktsAbort(pUM, LM_CLI_IDX_NDIS); 1700 1701 /*********************************************************/ 1702 1703 BNXE_LOCK_EXIT_GLDTX(pUM); 1704 1705 /*********************************************************/ 1706 1707 BnxeLogDbg(pUM, "Cleaning up L2 Tx Pkts"); 1708 1709 BnxeTxPktsFini(pUM, LM_CLI_IDX_NDIS); 1710 1711 /*********************************************************/ 1712 1713 BnxeLogDbg(pUM, "Cleaning up L2 Rx Pkts"); 1714 1715 BnxeRxPktsFini(pUM, LM_CLI_IDX_NDIS); 1716 1717 /*********************************************************/ 1718 1719 BnxeHwStopCore(pUM); 1720 1721 /*********************************************************/ 1722 1723 BnxeLogInfo(pUM, "BnxeHwStopL2: L2 stopped (clients %s)", 1724 BnxeClientsHw(pUM)); 1725 1726 BNXE_LOCK_EXIT_HWINIT(pUM); 1727 } 1728 1729 1730 /* Must be called with BNXE_LOCK_ENTER_HWINIT taken! */ 1731 void BnxeHwStopCore(um_device_t * pUM) 1732 { 1733 lm_device_t * pLM = &pUM->lm_dev; 1734 BnxeMemBlock * pMemBlock; 1735 BnxeMemDma * pMemDma; 1736 lm_address_t physAddr; 1737 int rc; 1738 1739 physAddr.as_ptr = NULL; 1740 1741 if (!pUM->hwInitDone) 1742 { 1743 /* already finished? (should never get here) */ 1744 BnxeLogWarn(pUM, "BnxeHwStopCore: Hardware already stopped (clients %s)", 1745 BnxeClientsHw(pUM)); 1746 return; 1747 } 1748 1749 if (BnxeIsClientBound(pUM)) 1750 { 1751 BnxeLogInfo(pUM, "BnxeHwStopCore: Hardware cannot be stopped (clients %s)", 1752 BnxeClientsHw(pUM)); 1753 return; 1754 } 1755 1756 BnxeLogInfo(pUM, "BnxeHwStopCore: Stopping hardware (clients %s)", 1757 BnxeClientsHw(pUM)); 1758 1759 mm_indicate_link(pLM, LM_STATUS_LINK_DOWN, pUM->devParams.lastIndMedium); 1760 1761 /*********************************************************/ 1762 1763 BnxeLogDbg(pUM, "Stopping Timer"); 1764 1765 BnxeTimerStop(pUM); 1766 1767 /*********************************************************/ 1768 1769 BnxeLogDbg(pUM, "Stopping DCBX"); 1770 1771 lm_dcbx_free_resc(pLM); 1772 1773 /*********************************************************/ 1774 1775 BnxeLogDbg(pUM, "Stopping BRCM Chip"); 1776 1777 rc = lm_chip_stop(pLM); 1778 1779 if (pUM->fmCapabilities && 1780 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1781 { 1782 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1783 } 1784 1785 if (rc != LM_STATUS_SUCCESS) 1786 { 1787 BnxeFmErrorReport(pUM, DDI_FM_DEVICE_INVAL_STATE); 1788 } 1789 1790 atomic_swap_32(&pUM->chipStarted, B_FALSE); 1791 1792 /*********************************************************/ 1793 1794 BnxeLogDbg(pUM, "Disabling Interrupts"); 1795 1796 BnxeIntrDisable(pUM); 1797 1798 /*********************************************************/ 1799 1800 BnxeLogDbg(pUM, "Resetting BRCM Chip"); 1801 1802 lm_chip_reset(pLM, LM_REASON_DRIVER_SHUTDOWN); 1803 1804 pUM->phyInitialized = B_FALSE; 1805 1806 if (pUM->fmCapabilities && 1807 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK) 1808 { 1809 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1810 } 1811 1812 if (pUM->fmCapabilities && 1813 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1814 { 1815 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1816 } 1817 1818 /*********************************************************/ 1819 1820 while (!d_list_is_empty(&pUM->memBlockList)) 1821 { 1822 pMemBlock = (BnxeMemBlock *)d_list_peek_head(&pUM->memBlockList); 1823 mm_rt_free_mem(pLM, 1824 ((char *)pMemBlock->pBuf + BNXE_MEM_CHECK_LEN), 1825 (pMemBlock->size - (BNXE_MEM_CHECK_LEN * 2)), 1826 LM_CLI_IDX_NDIS); 1827 } 1828 1829 #ifndef BNXE_DEBUG_DMA_LIST 1830 while (!d_list_is_empty(&pUM->memDmaList)) 1831 { 1832 pMemDma = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList); 1833 mm_rt_free_phys_mem(pLM, 1834 pMemDma->size, 1835 pMemDma->pDmaVirt, 1836 physAddr, 1837 LM_CLI_IDX_NDIS); 1838 } 1839 #else 1840 { 1841 BnxeMemDma * pTmp; 1842 int i; 1843 1844 BNXE_LOCK_ENTER_MEM(pUM); 1845 1846 pTmp = (BnxeMemDma *)d_list_peek_head(&pUM->memDmaList); 1847 while (pTmp) 1848 { 1849 for (i = 0; i < pTmp->size; i++) 1850 { 1851 ((u8_t *)pTmp->pDmaVirt)[i] = 0x0; 1852 } 1853 1854 pTmp = (BnxeMemDma *)d_list_next_entry(&pTmp->link); 1855 } 1856 1857 d_list_add_head(&pUM->memDmaListSaved, &pUM->memDmaList); 1858 d_list_clear(&pUM->memDmaList); 1859 1860 BNXE_LOCK_EXIT_MEM(pUM); 1861 1862 BnxeVerifySavedDmaList(pUM); 1863 } 1864 #endif /* BNXE_DEBUG_DMA_LIST */ 1865 1866 atomic_swap_32(&pUM->hwInitDone, B_FALSE); 1867 1868 BnxeLogInfo(pUM, "BnxeHwStopCore: Hardware stopped (clients %s)", 1869 BnxeClientsHw(pUM)); 1870 } 1871 1872 1873 int BnxeHwResume(um_device_t * pUM) 1874 { 1875 lm_device_t * pLM = &pUM->lm_dev; 1876 int rc; 1877 1878 BnxeLogDbg(pUM, "Setting Power State"); 1879 lm_set_power_state(pLM, LM_POWER_STATE_D0, LM_WAKE_UP_MODE_NONE, FALSE); 1880 1881 /* XXX Do we need it? */ 1882 BnxeLogDbg(pUM, "Enabling PCI DMA"); 1883 lm_enable_pci_dma(pLM); 1884 1885 if (pUM->fmCapabilities && 1886 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1887 { 1888 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_LOST); 1889 return -1; 1890 } 1891 1892 if (!pUM->plumbed) 1893 { 1894 /* XXX 1895 * Won't work under new model with multiple clients. Need an 1896 * extra pause mechanism/layer for suspend and resume. 1897 */ 1898 if (BnxeHwStartCore(pUM)) 1899 { 1900 return -1; 1901 } 1902 1903 atomic_swap_32(&pUM->plumbed, B_TRUE); 1904 } 1905 1906 return 0; 1907 } 1908 1909 1910 int BnxeHwSuspend(um_device_t * pUM) 1911 { 1912 lm_device_t * pLM = &pUM->lm_dev; 1913 1914 lm_reset_set_inprogress(pLM); 1915 lm_reset_mask_attn(pLM); 1916 1917 disable_blocks_attention(pLM); 1918 1919 if (pUM->plumbed) 1920 { 1921 /* XXX 1922 * Won't work under new model with multiple clients. Need an 1923 * extra pause mechanism/layer for suspend and resume. 1924 */ 1925 BnxeHwStopCore(pUM); 1926 atomic_swap_32(&pUM->plumbed, B_FALSE); 1927 } 1928 1929 /* XXX proper lm_wake_up_mode_t when WOL supported */ 1930 lm_set_d3_nwuf(pLM, LM_WAKE_UP_MODE_NONE); 1931 1932 if (pUM->fmCapabilities && 1933 BnxeCheckAccHandle(pUM->pPciCfg) != DDI_FM_OK) 1934 { 1935 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1936 return LM_STATUS_FAILURE; 1937 } 1938 1939 if (pUM->fmCapabilities && 1940 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1941 { 1942 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1943 return -1; 1944 } 1945 1946 /* XXX proper lm_wake_up_mode_t when WOL supported */ 1947 lm_set_d3_mpkt(pLM, LM_WAKE_UP_MODE_NONE); 1948 1949 if (pUM->fmCapabilities && 1950 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1951 { 1952 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1953 return -1; 1954 } 1955 1956 /* XXX Do we need it? */ 1957 BnxeLogDbg(pUM, "Disabling PCI DMA"); 1958 lm_disable_pci_dma(pLM, TRUE); 1959 1960 if (pUM->fmCapabilities && 1961 BnxeCheckAccHandle(pLM->vars.reg_handle[BAR_0]) != DDI_FM_OK) 1962 { 1963 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 1964 return -1; 1965 } 1966 1967 return 0; 1968 } 1969 1970 1971 #if (DEVO_REV > 3) 1972 1973 /* 1974 * This is a non-blocking function to make sure no more interrupt and dma memory 1975 * access of this hardware. We don't have to free any resource here. 1976 */ 1977 int BnxeHwQuiesce(um_device_t * pUM) 1978 { 1979 lm_device_t * pLM = &pUM->lm_dev; 1980 1981 /* XXX temporary block until bnxef supports fast reboot... */ 1982 if (CLIENT_BOUND(pUM, LM_CLI_IDX_FCOE)) 1983 { 1984 BnxeLogWarn(pUM, "Unable to quiesce, FCoE is bound!"); 1985 return -1; 1986 } 1987 1988 #if 0 1989 lm_chip_stop(pLM); 1990 #endif 1991 1992 lm_disable_int(pLM); 1993 1994 lm_chip_reset(pLM, LM_REASON_DRIVER_SHUTDOWN); 1995 1996 BnxeRxPktsAbort(pUM, LM_CLI_IDX_NDIS); 1997 BnxeTxPktsAbort(pUM, LM_CLI_IDX_NDIS); 1998 1999 return 0; 2000 } 2001 2002 #endif 2003 2004