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 2009 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Source file containing the implementation of the Hardware specific 29 * functions 30 */ 31 32 #include <oce_impl.h> 33 #include <oce_stat.h> 34 #include <oce_ioctl.h> 35 36 static ddi_device_acc_attr_t reg_accattr = { 37 DDI_DEVICE_ATTR_V0, 38 DDI_STRUCTURE_LE_ACC, 39 DDI_STRICTORDER_ACC, 40 DDI_FLAGERR_ACC 41 }; 42 43 extern int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx, 44 size_t req_size, enum qtype qtype); 45 46 static int 47 oce_map_regs(struct oce_dev *dev) 48 { 49 int ret = 0; 50 off_t bar_size = 0; 51 52 ASSERT(NULL != dev); 53 ASSERT(NULL != dev->dip); 54 55 /* get number of supported bars */ 56 ret = ddi_dev_nregs(dev->dip, &dev->num_bars); 57 if (ret != DDI_SUCCESS) { 58 oce_log(dev, CE_WARN, MOD_CONFIG, 59 "%d: could not retrieve num_bars", MOD_CONFIG); 60 return (DDI_FAILURE); 61 } 62 63 /* verify each bar and map it accordingly */ 64 /* PCI CFG */ 65 ret = ddi_dev_regsize(dev->dip, OCE_DEV_CFG_BAR, &bar_size); 66 if (ret != DDI_SUCCESS) { 67 oce_log(dev, CE_WARN, MOD_CONFIG, 68 "Could not get sizeof BAR %d", 69 OCE_DEV_CFG_BAR); 70 return (DDI_FAILURE); 71 } 72 73 ret = ddi_regs_map_setup(dev->dip, OCE_DEV_CFG_BAR, &dev->dev_cfg_addr, 74 0, bar_size, ®_accattr, &dev->dev_cfg_handle); 75 76 if (ret != DDI_SUCCESS) { 77 oce_log(dev, CE_WARN, MOD_CONFIG, 78 "Could not map bar %d", 79 OCE_DEV_CFG_BAR); 80 return (DDI_FAILURE); 81 } 82 83 /* CSR */ 84 ret = ddi_dev_regsize(dev->dip, OCE_PCI_CSR_BAR, &bar_size); 85 86 if (ret != DDI_SUCCESS) { 87 oce_log(dev, CE_WARN, MOD_CONFIG, 88 "Could not get sizeof BAR %d", 89 OCE_PCI_CSR_BAR); 90 return (DDI_FAILURE); 91 } 92 93 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_CSR_BAR, &dev->csr_addr, 94 0, bar_size, ®_accattr, &dev->csr_handle); 95 if (ret != DDI_SUCCESS) { 96 oce_log(dev, CE_WARN, MOD_CONFIG, 97 "Could not map bar %d", 98 OCE_PCI_CSR_BAR); 99 ddi_regs_map_free(&dev->dev_cfg_handle); 100 return (DDI_FAILURE); 101 } 102 103 /* Doorbells */ 104 ret = ddi_dev_regsize(dev->dip, OCE_PCI_DB_BAR, &bar_size); 105 if (ret != DDI_SUCCESS) { 106 oce_log(dev, CE_WARN, MOD_CONFIG, 107 "%d Could not get sizeof BAR %d", 108 ret, OCE_PCI_DB_BAR); 109 ddi_regs_map_free(&dev->csr_handle); 110 ddi_regs_map_free(&dev->dev_cfg_handle); 111 return (DDI_FAILURE); 112 } 113 114 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr, 115 0, 0, ®_accattr, &dev->db_handle); 116 if (ret != DDI_SUCCESS) { 117 oce_log(dev, CE_WARN, MOD_CONFIG, 118 "Could not map bar %d", OCE_PCI_DB_BAR); 119 ddi_regs_map_free(&dev->csr_handle); 120 ddi_regs_map_free(&dev->dev_cfg_handle); 121 return (DDI_FAILURE); 122 } 123 return (DDI_SUCCESS); 124 } 125 static void 126 oce_unmap_regs(struct oce_dev *dev) 127 { 128 129 ASSERT(NULL != dev); 130 ASSERT(NULL != dev->dip); 131 132 ddi_regs_map_free(&dev->db_handle); 133 ddi_regs_map_free(&dev->csr_handle); 134 ddi_regs_map_free(&dev->dev_cfg_handle); 135 136 } 137 138 139 140 141 142 /* 143 * function to map the device memory 144 * 145 * dev - handle to device private data structure 146 * 147 */ 148 int 149 oce_pci_init(struct oce_dev *dev) 150 { 151 int ret = 0; 152 153 ret = pci_config_setup(dev->dip, &dev->pci_cfg_handle); 154 if (ret != DDI_SUCCESS) { 155 return (DDI_FAILURE); 156 } 157 158 ret = oce_map_regs(dev); 159 160 if (ret != DDI_SUCCESS) { 161 return (DDI_FAILURE); 162 } 163 dev->fn = OCE_PCI_FUNC(dev); 164 ret = oce_fm_check_acc_handle(dev, dev->dev_cfg_handle); 165 166 if (ret != DDI_FM_OK) { 167 oce_pci_fini(dev); 168 return (DDI_FAILURE); 169 } 170 171 return (DDI_SUCCESS); 172 } /* oce_pci_init */ 173 174 /* 175 * function to free device memory mapping mapped using 176 * oce_pci_init 177 * 178 * dev - handle to device private data 179 */ 180 void 181 oce_pci_fini(struct oce_dev *dev) 182 { 183 oce_unmap_regs(dev); 184 pci_config_teardown(&dev->pci_cfg_handle); 185 } /* oce_pci_fini */ 186 187 188 /* 189 * function to check if a reset is required 190 * 191 * dev - software handle to the device 192 * 193 */ 194 boolean_t 195 oce_is_reset_pci(struct oce_dev *dev) 196 { 197 mpu_ep_semaphore_t post_status; 198 199 ASSERT(dev != NULL); 200 ASSERT(dev->dip != NULL); 201 202 post_status.dw0 = 0; 203 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 204 205 if (post_status.bits.stage == POST_STAGE_ARMFW_READY) { 206 return (B_FALSE); 207 } 208 return (B_TRUE); 209 } /* oce_is_reset_pci */ 210 211 /* 212 * function to do a soft reset on the device 213 * 214 * dev - software handle to the device 215 * 216 */ 217 int 218 oce_pci_soft_reset(struct oce_dev *dev) 219 { 220 pcicfg_soft_reset_t soft_rst; 221 /* struct mpu_ep_control ep_control; */ 222 /* struct pcicfg_online1 online1; */ 223 clock_t tmo; 224 clock_t earlier = ddi_get_lbolt(); 225 226 ASSERT(dev != NULL); 227 228 /* issue soft reset */ 229 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET); 230 soft_rst.bits.soft_reset = 0x01; 231 OCE_CFG_WRITE32(dev, PCICFG_SOFT_RESET, soft_rst.dw0); 232 233 /* wait till soft reset bit deasserts */ 234 tmo = drv_usectohz(60000000); /* 1.0min */ 235 do { 236 if ((ddi_get_lbolt() - earlier) > tmo) { 237 tmo = 0; 238 break; 239 } 240 241 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET); 242 if (soft_rst.bits.soft_reset) 243 drv_usecwait(100); 244 } while (soft_rst.bits.soft_reset); 245 246 if (soft_rst.bits.soft_reset) { 247 oce_log(dev, CE_WARN, MOD_CONFIG, 248 "0x%x soft_reset" 249 "bit asserted[1]. Reset failed", 250 soft_rst.dw0); 251 return (DDI_FAILURE); 252 } 253 254 return (oce_POST(dev)); 255 } /* oce_pci_soft_reset */ 256 /* 257 * function to trigger a POST on the device 258 * 259 * dev - software handle to the device 260 * 261 */ 262 int 263 oce_POST(struct oce_dev *dev) 264 { 265 mpu_ep_semaphore_t post_status; 266 clock_t tmo; 267 clock_t earlier = ddi_get_lbolt(); 268 269 /* read semaphore CSR */ 270 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 271 272 /* if host is ready then wait for fw ready else send POST */ 273 if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) { 274 post_status.bits.stage = POST_STAGE_CHIP_RESET; 275 OCE_CSR_WRITE32(dev, MPU_EP_SEMAPHORE, post_status.dw0); 276 } 277 278 /* wait for FW ready */ 279 tmo = drv_usectohz(60000000); /* 1.0min */ 280 for (;;) { 281 if ((ddi_get_lbolt() - earlier) > tmo) { 282 tmo = 0; 283 break; 284 } 285 286 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE); 287 if (post_status.bits.error) { 288 oce_log(dev, CE_WARN, MOD_CONFIG, 289 "0x%x POST ERROR!!", post_status.dw0); 290 return (DDI_FAILURE); 291 } 292 if (post_status.bits.stage == POST_STAGE_ARMFW_READY) 293 return (DDI_SUCCESS); 294 295 drv_usecwait(100); 296 } 297 return (DDI_FAILURE); 298 } /* oce_POST */ 299 /* 300 * function to modify register access attributes corresponding to the 301 * FM capabilities configured by the user 302 * 303 * fm_caps - fm capability configured by the user and accepted by the driver 304 */ 305 void 306 oce_set_reg_fma_flags(int fm_caps) 307 { 308 if (fm_caps == DDI_FM_NOT_CAPABLE) { 309 return; 310 } 311 if (DDI_FM_ACC_ERR_CAP(fm_caps)) { 312 reg_accattr.devacc_attr_access = DDI_FLAGERR_ACC; 313 } else { 314 reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC; 315 } 316 } /* oce_set_fma_flags */ 317 318 319 int 320 oce_create_nw_interface(struct oce_dev *dev) 321 { 322 int ret; 323 324 /* create an interface for the device with out mac */ 325 ret = oce_if_create(dev, OCE_DEFAULT_IF_CAP, OCE_DEFAULT_IF_CAP_EN, 326 0, &dev->mac_addr[0], (uint32_t *)&dev->if_id); 327 if (ret != 0) { 328 oce_log(dev, CE_WARN, MOD_CONFIG, 329 "Interface creation failed: 0x%x", ret); 330 return (ret); 331 } 332 atomic_inc_32(&dev->nifs); 333 334 dev->if_cap_flags = OCE_DEFAULT_IF_CAP_EN; 335 336 /* Enable VLAN Promisc on HW */ 337 ret = oce_config_vlan(dev, (uint8_t)dev->if_id, NULL, 0, 338 B_TRUE, B_TRUE); 339 if (ret != 0) { 340 oce_log(dev, CE_WARN, MOD_CONFIG, 341 "Config vlan failed: %d", ret); 342 oce_delete_nw_interface(dev); 343 return (ret); 344 345 } 346 347 /* set default flow control */ 348 ret = oce_set_flow_control(dev, dev->flow_control); 349 if (ret != 0) { 350 oce_log(dev, CE_NOTE, MOD_CONFIG, 351 "Set flow control failed: %d", ret); 352 } 353 ret = oce_set_promiscuous(dev, dev->promisc); 354 355 if (ret != 0) { 356 oce_log(dev, CE_NOTE, MOD_CONFIG, 357 "Set Promisc failed: %d", ret); 358 } 359 #if 0 360 /* this could happen if the driver is resuming after suspend */ 361 if (dev->num_mca > 0) { 362 ret = oce_set_multicast_table(dev, dev->multi_cast, 363 dev->num_mca); 364 if (ret != 0) { 365 oce_log(dev, CE_NOTE, MOD_CONFIG, 366 "Set Multicast failed: %d", ret); 367 } 368 } 369 #endif 370 371 return (0); 372 } 373 374 void 375 oce_delete_nw_interface(struct oce_dev *dev) { 376 377 /* currently only single interface is implmeneted */ 378 if (dev->nifs > 0) { 379 (void) oce_if_del(dev, dev->if_id); 380 atomic_dec_32(&dev->nifs); 381 } 382 } 383 384 385 int 386 oce_setup_adapter(struct oce_dev *dev) 387 { 388 int ret; 389 ret = oce_create_nw_interface(dev); 390 if (ret != DDI_SUCCESS) { 391 return (DDI_FAILURE); 392 } 393 ret = oce_create_queues(dev); 394 if (ret != DDI_SUCCESS) { 395 oce_delete_nw_interface(dev); 396 return (DDI_FAILURE); 397 } 398 return (DDI_SUCCESS); 399 } 400 401 void 402 oce_unsetup_adapter(struct oce_dev *dev) 403 { 404 oce_delete_queues(dev); 405 oce_delete_nw_interface(dev); 406 } 407 408 int 409 oce_hw_init(struct oce_dev *dev) 410 { 411 int ret; 412 struct mac_address_format mac_addr; 413 414 ret = oce_POST(dev); 415 if (ret != DDI_SUCCESS) { 416 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 417 "!!!HW POST1 FAILED"); 418 /* ADD FM FAULT */ 419 return (DDI_FAILURE); 420 } 421 /* create bootstrap mailbox */ 422 dev->bmbx = oce_alloc_dma_buffer(dev, 423 sizeof (struct oce_bmbx), DDI_DMA_CONSISTENT); 424 if (dev->bmbx == NULL) { 425 oce_log(dev, CE_WARN, MOD_CONFIG, 426 "Failed to allocate bmbx: size = %u", 427 (uint32_t)sizeof (struct oce_bmbx)); 428 return (DDI_FAILURE); 429 } 430 431 ret = oce_reset_fun(dev); 432 if (ret != 0) { 433 oce_log(dev, CE_WARN, MOD_CONFIG, "%s", 434 "!!!FUNCTION RESET FAILED"); 435 goto init_fail; 436 } 437 438 /* reset the Endianess of BMBX */ 439 ret = oce_mbox_init(dev); 440 if (ret != 0) { 441 oce_log(dev, CE_WARN, MOD_CONFIG, 442 "Mailbox initialization2 Failed with %d", ret); 443 goto init_fail; 444 } 445 446 /* read the firmware version */ 447 ret = oce_get_fw_version(dev); 448 if (ret != 0) { 449 oce_log(dev, CE_WARN, MOD_CONFIG, 450 "Firmaware version read failed with %d", ret); 451 goto init_fail; 452 } 453 454 /* read the fw config */ 455 ret = oce_get_fw_config(dev); 456 if (ret != 0) { 457 oce_log(dev, CE_WARN, MOD_CONFIG, 458 "Firmware configuration read failed with %d", ret); 459 goto init_fail; 460 } 461 462 /* read the Factory MAC address */ 463 ret = oce_read_mac_addr(dev, 0, 1, 464 MAC_ADDRESS_TYPE_NETWORK, &mac_addr); 465 if (ret != 0) { 466 oce_log(dev, CE_WARN, MOD_CONFIG, 467 "MAC address read failed with %d", ret); 468 goto init_fail; 469 } 470 bcopy(&mac_addr.mac_addr[0], &dev->mac_addr[0], ETHERADDRL); 471 return (DDI_SUCCESS); 472 init_fail: 473 oce_hw_fini(dev); 474 return (DDI_FAILURE); 475 } 476 void 477 oce_hw_fini(struct oce_dev *dev) 478 { 479 if (dev->bmbx != NULL) { 480 oce_free_dma_buffer(dev, dev->bmbx); 481 dev->bmbx = NULL; 482 } 483 } 484