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 /* Copyright © 2003-2011 Emulex. All rights reserved. */ 23 24 /* 25 * Source file containing the implementation of the Hardware specific 26 * functions 27 */ 28 29 #include <oce_impl.h> 30 #include <oce_stat.h> 31 #include <oce_ioctl.h> 32 33 static ddi_device_acc_attr_t reg_accattr = { 34 DDI_DEVICE_ATTR_V1, 35 DDI_STRUCTURE_LE_ACC, 36 DDI_STRICTORDER_ACC, 37 DDI_FLAGERR_ACC 38 }; 39 40 extern int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx, 41 size_t req_size, enum qtype qtype); 42 43 static int 44 oce_map_regs(struct oce_dev *dev) 45 { 46 int ret = 0; 47 off_t bar_size = 0; 48 49 ASSERT(NULL != dev); 50 ASSERT(NULL != dev->dip); 51 52 /* get number of supported bars */ 53 ret = ddi_dev_nregs(dev->dip, &dev->num_bars); 54 if (ret != DDI_SUCCESS) { 55 oce_log(dev, CE_WARN, MOD_CONFIG, 56 "%d: could not retrieve num_bars", MOD_CONFIG); 57 return (DDI_FAILURE); 58 } 59 60 /* verify each bar and map it accordingly */ 61 /* PCI CFG */ 62 ret = ddi_dev_regsize(dev->dip, OCE_DEV_CFG_BAR, &bar_size); 63 if (ret != DDI_SUCCESS) { 64 oce_log(dev, CE_WARN, MOD_CONFIG, 65 "Could not get sizeof BAR %d", 66 OCE_DEV_CFG_BAR); 67 return (DDI_FAILURE); 68 } 69 70 ret = ddi_regs_map_setup(dev->dip, OCE_DEV_CFG_BAR, &dev->dev_cfg_addr, 71 0, bar_size, ®_accattr, &dev->dev_cfg_handle); 72 73 if (ret != DDI_SUCCESS) { 74 oce_log(dev, CE_WARN, MOD_CONFIG, 75 "Could not map bar %d", 76 OCE_DEV_CFG_BAR); 77 return (DDI_FAILURE); 78 } 79 80 /* CSR */ 81 ret = ddi_dev_regsize(dev->dip, OCE_PCI_CSR_BAR, &bar_size); 82 83 if (ret != DDI_SUCCESS) { 84 oce_log(dev, CE_WARN, MOD_CONFIG, 85 "Could not get sizeof BAR %d", 86 OCE_PCI_CSR_BAR); 87 return (DDI_FAILURE); 88 } 89 90 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_CSR_BAR, &dev->csr_addr, 91 0, bar_size, ®_accattr, &dev->csr_handle); 92 if (ret != DDI_SUCCESS) { 93 oce_log(dev, CE_WARN, MOD_CONFIG, 94 "Could not map bar %d", 95 OCE_PCI_CSR_BAR); 96 ddi_regs_map_free(&dev->dev_cfg_handle); 97 return (DDI_FAILURE); 98 } 99 100 /* Doorbells */ 101 ret = ddi_dev_regsize(dev->dip, OCE_PCI_DB_BAR, &bar_size); 102 if (ret != DDI_SUCCESS) { 103 oce_log(dev, CE_WARN, MOD_CONFIG, 104 "%d Could not get sizeof BAR %d", 105 ret, OCE_PCI_DB_BAR); 106 ddi_regs_map_free(&dev->csr_handle); 107 ddi_regs_map_free(&dev->dev_cfg_handle); 108 return (DDI_FAILURE); 109 } 110 111 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr, 112 0, 0, ®_accattr, &dev->db_handle); 113 if (ret != DDI_SUCCESS) { 114 oce_log(dev, CE_WARN, MOD_CONFIG, 115 "Could not map bar %d", OCE_PCI_DB_BAR); 116 ddi_regs_map_free(&dev->csr_handle); 117 ddi_regs_map_free(&dev->dev_cfg_handle); 118 return (DDI_FAILURE); 119 } 120 return (DDI_SUCCESS); 121 } 122 static void 123 oce_unmap_regs(struct oce_dev *dev) 124 { 125 126 ASSERT(NULL != dev); 127 ASSERT(NULL != dev->dip); 128 129 ddi_regs_map_free(&dev->db_handle); 130 ddi_regs_map_free(&dev->csr_handle); 131 ddi_regs_map_free(&dev->dev_cfg_handle); 132 133 } 134 135 136 137 138 139 /* 140 * function to map the device memory 141 * 142 * dev - handle to device private data structure 143 * 144 */ 145 int 146 oce_pci_init(struct oce_dev *dev) 147 { 148 int ret = 0; 149 150 ret = oce_map_regs(dev); 151 152 if (ret != DDI_SUCCESS) { 153 return (DDI_FAILURE); 154 } 155 dev->fn = OCE_PCI_FUNC(dev); 156 if (oce_fm_check_acc_handle(dev, dev->dev_cfg_handle) != DDI_FM_OK) { 157 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 158 } 159 160 if (ret != DDI_FM_OK) { 161 oce_pci_fini(dev); 162 return (DDI_FAILURE); 163 } 164 165 return (DDI_SUCCESS); 166 } /* oce_pci_init */ 167 168 /* 169 * function to free device memory mapping mapped using 170 * oce_pci_init 171 * 172 * dev - handle to device private data 173 */ 174 void 175 oce_pci_fini(struct oce_dev *dev) 176 { 177 oce_unmap_regs(dev); 178 } /* oce_pci_fini */ 179 180 /* 181 * function to read the PCI Bus, Device, and function numbers for the 182 * device instance. 183 * 184 * dev - handle to device private data 185 */ 186 int 187 oce_get_bdf(struct oce_dev *dev) 188 { 189 pci_regspec_t *pci_rp; 190 uint32_t length; 191 int rc; 192 193 /* Get "reg" property */ 194 rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dev->dip, 195 0, "reg", (int **)&pci_rp, (uint_t *)&length); 196 197 if ((rc != DDI_SUCCESS) || 198 (length < (sizeof (pci_regspec_t) / sizeof (int)))) { 199 oce_log(dev, CE_WARN, MOD_CONFIG, 200 "Failed to read \"reg\" property, Status = 0x%x", rc); 201 return (rc); 202 } 203 204 dev->pci_bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi); 205 dev->pci_device = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 206 dev->pci_function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 207 208 oce_log(dev, CE_NOTE, MOD_CONFIG, 209 "\"reg\" property num=%d, Bus=%d, Device=%d, Function=%d", 210 length, dev->pci_bus, dev->pci_device, dev->pci_function); 211 212 /* Free the memory allocated by ddi_prop_lookup_int_array() */ 213 ddi_prop_free(pci_rp); 214 return (rc); 215 } 216 217 int 218 oce_identify_hw(struct oce_dev *dev) 219 { 220 int ret = DDI_SUCCESS; 221 222 dev->vendor_id = pci_config_get16(dev->pci_cfg_handle, 223 PCI_CONF_VENID); 224 dev->device_id = pci_config_get16(dev->pci_cfg_handle, 225 PCI_CONF_DEVID); 226 dev->subsys_id = pci_config_get16(dev->pci_cfg_handle, 227 PCI_CONF_SUBSYSID); 228 dev->subvendor_id = pci_config_get16(dev->pci_cfg_handle, 229 PCI_CONF_SUBVENID); 230 231 switch (dev->device_id) { 232 233 case DEVID_TIGERSHARK: 234 dev->chip_rev = OC_CNA_GEN2; 235 break; 236 case DEVID_TOMCAT: 237 dev->chip_rev = OC_CNA_GEN3; 238 break; 239 default: 240 dev->chip_rev = 0; 241 ret = DDI_FAILURE; 242 break; 243 } 244 return (ret); 245 } 246 247 248 /* 249 * function to check if a reset is required 250 * 251 * dev - software handle to the device 252 * 253 */ 254 boolean_t 255 oce_is_reset_pci(struct oce_dev *dev) 256 { 257 mpu_ep_semaphore_t post_status; 258 259 ASSERT(dev != NULL); 260 ASSERT(dev->dip != NULL); 261 262 post_status.dw0 = 0; 263 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 264 265 if (post_status.bits.stage == POST_STAGE_ARMFW_READY) { 266 return (B_FALSE); 267 } 268 return (B_TRUE); 269 } /* oce_is_reset_pci */ 270 271 /* 272 * function to do a soft reset on the device 273 * 274 * dev - software handle to the device 275 * 276 */ 277 int 278 oce_pci_soft_reset(struct oce_dev *dev) 279 { 280 pcicfg_soft_reset_t soft_rst; 281 /* struct mpu_ep_control ep_control; */ 282 /* struct pcicfg_online1 online1; */ 283 clock_t tmo; 284 clock_t earlier = ddi_get_lbolt(); 285 286 ASSERT(dev != NULL); 287 288 /* issue soft reset */ 289 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET); 290 soft_rst.bits.soft_reset = 0x01; 291 OCE_CFG_WRITE32(dev, PCICFG_SOFT_RESET, soft_rst.dw0); 292 293 /* wait till soft reset bit deasserts */ 294 tmo = drv_usectohz(60000000); /* 1.0min */ 295 do { 296 if ((ddi_get_lbolt() - earlier) > tmo) { 297 tmo = 0; 298 break; 299 } 300 301 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET); 302 if (soft_rst.bits.soft_reset) 303 drv_usecwait(100); 304 } while (soft_rst.bits.soft_reset); 305 306 if (soft_rst.bits.soft_reset) { 307 oce_log(dev, CE_WARN, MOD_CONFIG, 308 "0x%x soft_reset" 309 "bit asserted[1]. Reset failed", 310 soft_rst.dw0); 311 return (DDI_FAILURE); 312 } 313 314 return (oce_POST(dev)); 315 } /* oce_pci_soft_reset */ 316 /* 317 * function to trigger a POST on the device 318 * 319 * dev - software handle to the device 320 * 321 */ 322 int 323 oce_POST(struct oce_dev *dev) 324 { 325 mpu_ep_semaphore_t post_status; 326 clock_t tmo; 327 clock_t earlier = ddi_get_lbolt(); 328 329 /* read semaphore CSR */ 330 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 331 if (oce_fm_check_acc_handle(dev, dev->csr_handle) != DDI_FM_OK) { 332 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 333 return (DDI_FAILURE); 334 } 335 /* if host is ready then wait for fw ready else send POST */ 336 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { 337 post_status.bits.stage = POST_STAGE_CHIP_RESET; 338 OCE_CSR_WRITE32(dev, MPU_EP_SEMAPHORE, post_status.dw0); 339 if (oce_fm_check_acc_handle(dev, dev->csr_handle) != 340 DDI_FM_OK) { 341 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 342 return (DDI_FAILURE); 343 } 344 } 345 346 /* wait for FW ready */ 347 tmo = drv_usectohz(60000000); /* 1.0min */ 348 for (;;) { 349 if ((ddi_get_lbolt() - earlier) > tmo) { 350 tmo = 0; 351 break; 352 } 353 354 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 355 if (oce_fm_check_acc_handle(dev, dev->csr_handle) != 356 DDI_FM_OK) { 357 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED); 358 return (DDI_FAILURE); 359 } 360 if (post_status.bits.error) { 361 oce_log(dev, CE_WARN, MOD_CONFIG, 362 "0x%x POST ERROR!!", post_status.dw0); 363 return (DDI_FAILURE); 364 } 365 if (post_status.bits.stage == POST_STAGE_ARMFW_READY) 366 return (DDI_SUCCESS); 367 368 drv_usecwait(100); 369 } 370 return (DDI_FAILURE); 371 } /* oce_POST */ 372 /* 373 * function to modify register access attributes corresponding to the 374 * FM capabilities configured by the user 375 * 376 * fm_caps - fm capability configured by the user and accepted by the driver 377 */ 378 void 379 oce_set_reg_fma_flags(int fm_caps) 380 { 381 if (fm_caps == DDI_FM_NOT_CAPABLE) { 382 return; 383 } 384 if (DDI_FM_ACC_ERR_CAP(fm_caps)) { 385 reg_accattr.devacc_attr_access = DDI_FLAGERR_ACC; 386 } else { 387 reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC; 388 } 389 } /* oce_set_fma_flags */ 390 391 392 int 393 oce_create_nw_interface(struct oce_dev *dev) 394 { 395 int ret; 396 uint32_t capab_flags = OCE_CAPAB_FLAGS; 397 uint32_t capab_en_flags = OCE_CAPAB_ENABLE; 398 399 if (dev->rss_enable) { 400 capab_flags |= MBX_RX_IFACE_FLAGS_RSS; 401 capab_en_flags |= MBX_RX_IFACE_FLAGS_RSS; 402 } 403 404 /* create an interface for the device with out mac */ 405 ret = oce_if_create(dev, capab_flags, capab_en_flags, 406 0, &dev->mac_addr[0], (uint32_t *)&dev->if_id); 407 if (ret != 0) { 408 oce_log(dev, CE_WARN, MOD_CONFIG, 409 "Interface creation failed: 0x%x", ret); 410 return (ret); 411 } 412 atomic_inc_32(&dev->nifs); 413 414 dev->if_cap_flags = capab_en_flags; 415 416 /* Enable VLAN Promisc on HW */ 417 ret = oce_config_vlan(dev, (uint8_t)dev->if_id, NULL, 0, 418 B_TRUE, B_TRUE); 419 if (ret != 0) { 420 oce_log(dev, CE_WARN, MOD_CONFIG, 421 "Config vlan failed: %d", ret); 422 oce_delete_nw_interface(dev); 423 return (ret); 424 425 } 426 427 /* set default flow control */ 428 ret = oce_set_flow_control(dev, dev->flow_control); 429 if (ret != 0) { 430 oce_log(dev, CE_NOTE, MOD_CONFIG, 431 "Set flow control failed: %d", ret); 432 } 433 ret = oce_set_promiscuous(dev, dev->promisc); 434 435 if (ret != 0) { 436 oce_log(dev, CE_NOTE, MOD_CONFIG, 437 "Set Promisc failed: %d", ret); 438 } 439 440 return (0); 441 } 442 443 void 444 oce_delete_nw_interface(struct oce_dev *dev) { 445 446 /* currently only single interface is implmeneted */ 447 if (dev->nifs > 0) { 448 (void) oce_if_del(dev, dev->if_id); 449 atomic_dec_32(&dev->nifs); 450 } 451 } 452 453 static void 454 oce_create_itbl(struct oce_dev *dev, char *itbl) 455 { 456 int i; 457 struct oce_rq **rss_queuep = &dev->rq[1]; 458 int nrss = dev->nrqs - 1; 459 /* fill the indirection table rq 0 is default queue */ 460 for (i = 0; i < OCE_ITBL_SIZE; i++) { 461 itbl[i] = rss_queuep[i % nrss]->rss_cpuid; 462 } 463 } 464 465 int 466 oce_setup_adapter(struct oce_dev *dev) 467 { 468 int ret; 469 char itbl[OCE_ITBL_SIZE]; 470 char hkey[OCE_HKEY_SIZE]; 471 472 /* disable the interrupts here and enable in start */ 473 oce_chip_di(dev); 474 475 ret = oce_create_nw_interface(dev); 476 if (ret != DDI_SUCCESS) { 477 return (DDI_FAILURE); 478 } 479 ret = oce_create_queues(dev); 480 if (ret != DDI_SUCCESS) { 481 oce_delete_nw_interface(dev); 482 return (DDI_FAILURE); 483 } 484 if (dev->rss_enable) { 485 (void) oce_create_itbl(dev, itbl); 486 (void) oce_gen_hkey(hkey, OCE_HKEY_SIZE); 487 ret = oce_config_rss(dev, dev->if_id, hkey, itbl, OCE_ITBL_SIZE, 488 OCE_DEFAULT_RSS_TYPE, B_TRUE); 489 if (ret != DDI_SUCCESS) { 490 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", 491 "Failed to Configure RSS"); 492 oce_delete_queues(dev); 493 oce_delete_nw_interface(dev); 494 return (ret); 495 } 496 } 497 ret = oce_setup_handlers(dev); 498 if (ret != DDI_SUCCESS) { 499 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", 500 "Failed to Setup handlers"); 501 oce_delete_queues(dev); 502 oce_delete_nw_interface(dev); 503 return (ret); 504 } 505 return (DDI_SUCCESS); 506 } 507 508 void 509 oce_unsetup_adapter(struct oce_dev *dev) 510 { 511 oce_remove_handler(dev); 512 if (dev->rss_enable) { 513 char itbl[OCE_ITBL_SIZE] = {0}; 514 char hkey[OCE_HKEY_SIZE] = {0}; 515 int ret = 0; 516 517 ret = oce_config_rss(dev, dev->if_id, hkey, itbl, OCE_ITBL_SIZE, 518 RSS_ENABLE_NONE, B_TRUE); 519 520 if (ret != DDI_SUCCESS) { 521 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s", 522 "Failed to Disable RSS"); 523 } 524 } 525 oce_delete_queues(dev); 526 oce_delete_nw_interface(dev); 527 } 528 529 int 530 oce_hw_init(struct oce_dev *dev) 531 { 532 int ret; 533 struct mac_address_format mac_addr; 534 535 ret = oce_POST(dev); 536 if (ret != DDI_SUCCESS) { 537 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 538 "!!!HW POST1 FAILED"); 539 /* ADD FM FAULT */ 540 return (DDI_FAILURE); 541 } 542 /* create bootstrap mailbox */ 543 dev->bmbx = oce_alloc_dma_buffer(dev, 544 sizeof (struct oce_bmbx), NULL, DDI_DMA_CONSISTENT); 545 if (dev->bmbx == NULL) { 546 oce_log(dev, CE_WARN, MOD_CONFIG, 547 "Failed to allocate bmbx: size = %u", 548 (uint32_t)sizeof (struct oce_bmbx)); 549 return (DDI_FAILURE); 550 } 551 552 ret = oce_reset_fun(dev); 553 if (ret != 0) { 554 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 555 "!!!FUNCTION RESET FAILED"); 556 goto init_fail; 557 } 558 559 /* reset the Endianess of BMBX */ 560 ret = oce_mbox_init(dev); 561 if (ret != 0) { 562 oce_log(dev, CE_WARN, MOD_CONFIG, 563 "Mailbox initialization2 Failed with %d", ret); 564 goto init_fail; 565 } 566 567 /* read the firmware version */ 568 ret = oce_get_fw_version(dev); 569 if (ret != 0) { 570 oce_log(dev, CE_WARN, MOD_CONFIG, 571 "Firmaware version read failed with %d", ret); 572 goto init_fail; 573 } 574 575 /* read the fw config */ 576 ret = oce_get_fw_config(dev); 577 if (ret != 0) { 578 oce_log(dev, CE_WARN, MOD_CONFIG, 579 "Firmware configuration read failed with %d", ret); 580 goto init_fail; 581 } 582 583 /* read the Factory MAC address */ 584 ret = oce_read_mac_addr(dev, 0, 1, 585 MAC_ADDRESS_TYPE_NETWORK, &mac_addr); 586 if (ret != 0) { 587 oce_log(dev, CE_WARN, MOD_CONFIG, 588 "MAC address read failed with %d", ret); 589 goto init_fail; 590 } 591 bcopy(&mac_addr.mac_addr[0], &dev->mac_addr[0], ETHERADDRL); 592 return (DDI_SUCCESS); 593 init_fail: 594 oce_hw_fini(dev); 595 return (DDI_FAILURE); 596 } 597 void 598 oce_hw_fini(struct oce_dev *dev) 599 { 600 if (dev->bmbx != NULL) { 601 oce_free_dma_buffer(dev, dev->bmbx); 602 dev->bmbx = NULL; 603 } 604 } 605