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 (c) 2009-2012 Emulex. All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 
  28 
  29 /*
  30  * Source file containing the implementation of the Hardware specific
  31  * functions
  32  */
  33 
  34 #include <oce_impl.h>
  35 #include <oce_stat.h>
  36 #include <oce_ioctl.h>
  37 
  38 static ddi_device_acc_attr_t reg_accattr = {
  39         DDI_DEVICE_ATTR_V1,
  40         DDI_STRUCTURE_LE_ACC,
  41         DDI_STRICTORDER_ACC,
  42         DDI_FLAGERR_ACC
  43 };
  44 
  45 extern int oce_destroy_q(struct oce_dev *dev, struct oce_mbx *mbx,
  46     size_t req_size, enum qtype qtype, uint32_t mode);
  47 
  48 static int
  49 oce_map_regs(struct oce_dev *dev)
  50 {
  51         int ret = 0;
  52         off_t bar_size = 0;
  53 
  54         ASSERT(NULL != dev);
  55         ASSERT(NULL != dev->dip);
  56 
  57         /* get number of supported bars */
  58         ret = ddi_dev_nregs(dev->dip, &dev->num_bars);
  59         if (ret != DDI_SUCCESS) {
  60                 oce_log(dev, CE_WARN, MOD_CONFIG,
  61                     "Could not retrieve num_bars, ret =0x%x", ret);
  62                 return (DDI_FAILURE);
  63         }
  64 
  65         if (LANCER_CHIP(dev)) {
  66                 /* Doorbells */
  67                 ret = ddi_dev_regsize(dev->dip, OCE_PCI_LANCER_DB_BAR,
  68                     &bar_size);
  69                 if (ret != DDI_SUCCESS) {
  70                         oce_log(dev, CE_WARN, MOD_CONFIG,
  71                             "%d Could not get sizeof BAR %d",
  72                             ret, OCE_PCI_LANCER_DB_BAR);
  73                         return (DDI_FAILURE);
  74                 }
  75 
  76                 ret = ddi_regs_map_setup(dev->dip, OCE_PCI_LANCER_DB_BAR,
  77                     &dev->db_addr, 0, 0, ®_accattr, &dev->db_handle);
  78                 if (ret != DDI_SUCCESS) {
  79                         oce_log(dev, CE_WARN, MOD_CONFIG,
  80                             "Could not map bar %d", OCE_PCI_LANCER_DB_BAR);
  81                         return (DDI_FAILURE);
  82                 }
  83                 return (DDI_SUCCESS);
  84         }
  85 
  86         /* verify each bar and map it accordingly */
  87         /* PCI CFG */
  88         ret = ddi_dev_regsize(dev->dip, OCE_DEV_CFG_BAR, &bar_size);
  89         if (ret != DDI_SUCCESS) {
  90                 oce_log(dev, CE_WARN, MOD_CONFIG,
  91                     "Could not get sizeof BAR %d",
  92                     OCE_DEV_CFG_BAR);
  93                 return (DDI_FAILURE);
  94         }
  95 
  96         ret = ddi_regs_map_setup(dev->dip, OCE_DEV_CFG_BAR, &dev->dev_cfg_addr,
  97             0, bar_size, ®_accattr, &dev->dev_cfg_handle);
  98 
  99         if (ret != DDI_SUCCESS) {
 100                 oce_log(dev, CE_WARN, MOD_CONFIG,
 101                     "Could not map bar %d",
 102                     OCE_DEV_CFG_BAR);
 103                 return (DDI_FAILURE);
 104         }
 105 
 106         /* CSR */
 107         ret = ddi_dev_regsize(dev->dip, OCE_PCI_CSR_BAR, &bar_size);
 108 
 109         if (ret != DDI_SUCCESS) {
 110                 oce_log(dev, CE_WARN, MOD_CONFIG,
 111                     "Could not get sizeof BAR %d",
 112                     OCE_PCI_CSR_BAR);
 113                 return (DDI_FAILURE);
 114         }
 115 
 116         ret = ddi_regs_map_setup(dev->dip, OCE_PCI_CSR_BAR, &dev->csr_addr,
 117             0, bar_size, ®_accattr, &dev->csr_handle);
 118         if (ret != DDI_SUCCESS) {
 119                 oce_log(dev, CE_WARN, MOD_CONFIG,
 120                     "Could not map bar %d",
 121                     OCE_PCI_CSR_BAR);
 122                 ddi_regs_map_free(&dev->dev_cfg_handle);
 123                 return (DDI_FAILURE);
 124         }
 125 
 126         /* Doorbells */
 127         ret = ddi_dev_regsize(dev->dip, OCE_PCI_DB_BAR, &bar_size);
 128         if (ret != DDI_SUCCESS) {
 129                 oce_log(dev, CE_WARN, MOD_CONFIG,
 130                     "%d Could not get sizeof BAR %d",
 131                     ret, OCE_PCI_DB_BAR);
 132                 ddi_regs_map_free(&dev->csr_handle);
 133                 ddi_regs_map_free(&dev->dev_cfg_handle);
 134                 return (DDI_FAILURE);
 135         }
 136 
 137         ret = ddi_regs_map_setup(dev->dip, OCE_PCI_DB_BAR, &dev->db_addr,
 138             0, 0, ®_accattr, &dev->db_handle);
 139         if (ret != DDI_SUCCESS) {
 140                 oce_log(dev, CE_WARN, MOD_CONFIG,
 141                     "Could not map bar %d", OCE_PCI_DB_BAR);
 142                 ddi_regs_map_free(&dev->csr_handle);
 143                 ddi_regs_map_free(&dev->dev_cfg_handle);
 144                 return (DDI_FAILURE);
 145         }
 146         return (DDI_SUCCESS);
 147 }
 148 static void
 149 oce_unmap_regs(struct oce_dev *dev)
 150 {
 151 
 152         ASSERT(NULL != dev);
 153         ASSERT(NULL != dev->dip);
 154 
 155         ddi_regs_map_free(&dev->db_handle);
 156         if (!LANCER_CHIP(dev)) {
 157                 ddi_regs_map_free(&dev->csr_handle);
 158                 ddi_regs_map_free(&dev->dev_cfg_handle);
 159         }
 160 
 161 }
 162 
 163 
 164 static void
 165 oce_check_slot(struct oce_dev *dev)
 166 {
 167         uint32_t curr = 0;
 168         uint32_t max = 0;
 169         uint32_t width = 0;
 170         uint32_t max_width = 0;
 171         uint32_t speed = 0;
 172         uint32_t max_speed = 0;
 173 
 174         curr = OCE_CFG_READ32(dev, PCICFG_PCIE_LINK_STATUS_OFFSET);
 175 
 176         width = (curr >> PCIE_LINK_STATUS_NEG_WIDTH_SHIFT) &
 177             PCIE_LINK_STATUS_NEG_WIDTH_MASK;
 178         speed = (curr >> PCIE_LINK_STATUS_SPEED_SHIFT) &
 179             PCIE_LINK_STATUS_SPEED_MASK;
 180 
 181         oce_log(dev, CE_NOTE, MOD_CONFIG, "Reg value %x"
 182             " width %d speed %d\n", curr, width,  speed);
 183         max = OCE_CFG_READ32(dev, PCICFG_PCIE_LINK_CAP_OFFSET);
 184 
 185         max_width = (max >> PCIE_LINK_CAP_MAX_WIDTH_SHIFT) &
 186             PCIE_LINK_CAP_MAX_WIDTH_MASK;
 187         max_speed = (max >> PCIE_LINK_CAP_MAX_SPEED_SHIFT) &
 188             PCIE_LINK_CAP_MAX_SPEED_MASK;
 189         oce_log(dev, CE_NOTE, MOD_CONFIG, "Reg value %x"
 190             " max_width %d max_speed %d\n",
 191             max, max_width,  max_speed);
 192 
 193         if (width < max_width || speed < max_speed) {
 194                         oce_log(dev, CE_NOTE, MOD_CONFIG,
 195                             "Found CNA device in a Gen%s x%d PCIe Slot."
 196                             "It is recommended to be in a Gen2 x%d slot"
 197                             "for best performance\n",
 198                             speed < max_speed ? "1" : "2",
 199                             width, max_width);
 200         }
 201 }
 202 
 203 
 204 /*
 205  * function to map the device memory
 206  *
 207  * dev - handle to device private data structure
 208  *
 209  */
 210 int
 211 oce_pci_init(struct oce_dev *dev)
 212 {
 213         int ret = 0;
 214 
 215         ret = oce_map_regs(dev);
 216 
 217         if (ret != DDI_SUCCESS) {
 218                 return (DDI_FAILURE);
 219         }
 220 
 221         if (!LANCER_CHIP(dev)) {
 222                 dev->fn =  OCE_PCI_FUNC(dev);
 223                 if (oce_fm_check_acc_handle(dev, dev->dev_cfg_handle) !=
 224                     DDI_FM_OK) {
 225                         ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 226                 }
 227         }
 228 
 229         if (ret != DDI_FM_OK) {
 230                 oce_pci_fini(dev);
 231                 return (DDI_FAILURE);
 232         }
 233 
 234         if (!LANCER_CHIP(dev))
 235                 oce_check_slot(dev);
 236 
 237         return (DDI_SUCCESS);
 238 } /* oce_pci_init */
 239 
 240 /*
 241  * function to free device memory mapping mapped using
 242  * oce_pci_init
 243  *
 244  * dev - handle to device private data
 245  */
 246 void
 247 oce_pci_fini(struct oce_dev *dev)
 248 {
 249         oce_unmap_regs(dev);
 250 } /* oce_pci_fini */
 251 
 252 
 253 int
 254 oce_identify_hw(struct oce_dev *dev)
 255 {
 256         int ret = DDI_SUCCESS;
 257         uint32_t if_type = 0, sli_intf = 0;
 258 
 259         dev->vendor_id = pci_config_get16(dev->pci_cfg_handle,
 260             PCI_CONF_VENID);
 261         dev->device_id = pci_config_get16(dev->pci_cfg_handle,
 262             PCI_CONF_DEVID);
 263         dev->subsys_id = pci_config_get16(dev->pci_cfg_handle,
 264             PCI_CONF_SUBSYSID);
 265         dev->subvendor_id = pci_config_get16(dev->pci_cfg_handle,
 266             PCI_CONF_SUBVENID);
 267 
 268         switch (dev->device_id) {
 269 
 270         case DEVID_TIGERSHARK:
 271                 dev->chip_rev = OC_CNA_GEN2;
 272                 /* BE2 hardware properly supports single tx ring */
 273                 dev->tx_rings = 1;
 274                 break;
 275         case DEVID_TOMCAT:
 276                 dev->chip_rev = OC_CNA_GEN3;
 277                 break;
 278         case DEVID_LANCER:
 279                 sli_intf = pci_config_get32(dev->pci_cfg_handle,
 280                     SLI_INTF_REG_OFFSET);
 281 
 282                 if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
 283                     SLI_INTF_IF_TYPE_SHIFT;
 284 
 285                 if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
 286                     if_type != 0x02) {
 287                         oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 288                             "SLI I/F not Valid or different interface type\n");
 289                         ret = DDI_FAILURE;
 290                         break;
 291                 }
 292                 dev->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
 293                     SLI_INTF_FAMILY_SHIFT);
 294 
 295                 dev->chip_rev = 0;
 296                 break;
 297 
 298         default:
 299                 dev->chip_rev = 0;
 300                 ret = DDI_FAILURE;
 301                 break;
 302         }
 303         return (ret);
 304 }
 305 
 306 
 307 /*
 308  * function to check if a reset is required
 309  *
 310  * dev - software handle to the device
 311  *
 312  */
 313 boolean_t
 314 oce_is_reset_pci(struct oce_dev *dev)
 315 {
 316         mpu_ep_semaphore_t post_status;
 317 
 318         ASSERT(dev != NULL);
 319         ASSERT(dev->dip != NULL);
 320 
 321         post_status.dw0 = 0;
 322         post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
 323 
 324         if (post_status.bits.stage == POST_STAGE_ARMFW_READY) {
 325                 return (B_FALSE);
 326         }
 327         return (B_TRUE);
 328 } /* oce_is_reset_pci */
 329 
 330 /*
 331  * function to do a soft reset on the device
 332  *
 333  * dev - software handle to the device
 334  *
 335  */
 336 int
 337 oce_pci_soft_reset(struct oce_dev *dev)
 338 {
 339         pcicfg_soft_reset_t soft_rst;
 340         /* struct mpu_ep_control ep_control; */
 341         /* struct pcicfg_online1 online1; */
 342         clock_t tmo;
 343         clock_t earlier = ddi_get_lbolt();
 344 
 345         ASSERT(dev != NULL);
 346 
 347         /* issue soft reset */
 348         soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET);
 349         soft_rst.bits.soft_reset = 0x01;
 350         OCE_CFG_WRITE32(dev, PCICFG_SOFT_RESET, soft_rst.dw0);
 351 
 352         /* wait till soft reset bit deasserts */
 353         tmo = drv_usectohz(60000000); /* 1.0min */
 354         do {
 355                 if ((ddi_get_lbolt() - earlier) > tmo) {
 356                         tmo = 0;
 357                         break;
 358                 }
 359 
 360                 soft_rst.dw0 = OCE_CFG_READ32(dev, PCICFG_SOFT_RESET);
 361                 if (soft_rst.bits.soft_reset)
 362                         drv_usecwait(100);
 363         } while (soft_rst.bits.soft_reset);
 364 
 365         if (soft_rst.bits.soft_reset) {
 366                 oce_log(dev, CE_WARN, MOD_CONFIG,
 367                     "0x%x soft_reset"
 368                     "bit asserted[1]. Reset failed",
 369                     soft_rst.dw0);
 370                 return (DDI_FAILURE);
 371         }
 372 
 373         return (oce_POST(dev));
 374 } /* oce_pci_soft_reset */
 375 
 376 
 377 static int lancer_wait_ready(struct oce_dev *dev)
 378 {
 379         uint32_t sliport_status;
 380         int status = 0, i;
 381 
 382         for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
 383                 sliport_status = OCE_DB_READ32(dev, SLIPORT_STATUS_OFFSET);
 384                         if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
 385                             DDI_FM_OK) {
 386                                 ddi_fm_service_impact(dev->dip,
 387                                     DDI_SERVICE_DEGRADED);
 388                                 return (EIO);
 389                         }
 390                 if (sliport_status & SLIPORT_STATUS_RDY_MASK)
 391                         break;
 392                 drv_usecwait(20000);
 393         }
 394 
 395         if (i == SLIPORT_READY_TIMEOUT)
 396                 status = DDI_FAILURE;
 397 
 398         return (status);
 399 }
 400 
 401 static int lancer_test_and_set_rdy_state(struct oce_dev *dev)
 402 {
 403         int status;
 404         uint32_t sliport_status, err, reset_needed;
 405         status = lancer_wait_ready(dev);
 406         if (!status) {
 407                 sliport_status = OCE_DB_READ32(dev, SLIPORT_STATUS_OFFSET);
 408                 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
 409                         ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 410                         return (EIO);
 411                 }
 412                 err = sliport_status & SLIPORT_STATUS_ERR_MASK;
 413                 reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK;
 414                 if (err && reset_needed) {
 415                         OCE_DB_WRITE32(dev, SLIPORT_CONTROL_OFFSET,
 416                             SLI_PORT_CONTROL_IP_MASK);
 417                         if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
 418                             DDI_FM_OK) {
 419                                 ddi_fm_service_impact(dev->dip,
 420                                     DDI_SERVICE_DEGRADED);
 421                                 return (EIO);
 422                         }
 423                         /* check adapter has corrected the error */
 424                         status = lancer_wait_ready(dev);
 425                         sliport_status = OCE_DB_READ32(dev,
 426                             SLIPORT_STATUS_OFFSET);
 427                         if (oce_fm_check_acc_handle(dev, dev->db_handle) !=
 428                             DDI_FM_OK) {
 429                                 ddi_fm_service_impact(dev->dip,
 430                                     DDI_SERVICE_DEGRADED);
 431                                 return (EIO);
 432                         }
 433                         sliport_status &= (SLIPORT_STATUS_ERR_MASK |
 434                             SLIPORT_STATUS_RN_MASK);
 435                         if (status || sliport_status)
 436                                 status = -1;
 437                 } else if (err || reset_needed) {
 438                         status = DDI_FAILURE;
 439                 }
 440         }
 441         return (status);
 442 }
 443 
 444 /*
 445  * function to trigger a POST on the Lancer device
 446  *
 447  * dev - software handle to the device
 448  *
 449  */
 450 int
 451 oce_lancer_POST(struct oce_dev *dev)
 452 {
 453         int status = 0;
 454         int sem = 0;
 455         int stage = 0;
 456         int timeout = 0;
 457 
 458         status = lancer_test_and_set_rdy_state(dev);
 459         if (status != 0)
 460                 return (DDI_FAILURE);
 461 
 462         do {
 463                 sem = OCE_DB_READ32(dev, MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
 464                 if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
 465                         ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 466                         return (EIO);
 467                 }
 468                 stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
 469 
 470                 if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) &
 471                     EP_SEMAPHORE_POST_ERR_MASK) {
 472                         oce_log(dev, CE_WARN, MOD_CONFIG,
 473                             "POST error; stage=0x%x\n", stage);
 474                         return (DDI_FAILURE);
 475                 } else if (stage != POST_STAGE_ARMFW_READY) {
 476                         drv_usecwait(1000);
 477                 } else {
 478                         return (0);
 479                 }
 480         } while (timeout++ < 1000);
 481         oce_log(dev, CE_WARN, MOD_CONFIG,
 482             "POST timeout; stage=0x%x\n", stage);
 483         return (DDI_FAILURE);
 484 
 485 } /* oce_lancer_POST */
 486 
 487 /*
 488  * function to trigger a POST on the BE device
 489  *
 490  * dev - software handle to the device
 491  *
 492  */
 493 int
 494 oce_be_POST(struct oce_dev *dev)
 495 {
 496         mpu_ep_semaphore_t post_status;
 497         clock_t tmo;
 498         clock_t earlier = ddi_get_lbolt();
 499 
 500         /* read semaphore CSR */
 501         post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
 502         if (oce_fm_check_acc_handle(dev, dev->csr_handle) != DDI_FM_OK) {
 503                 ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 504                 return (DDI_FAILURE);
 505         }
 506         /* if host is ready then wait for fw ready else send POST */
 507         if (post_status.bits.stage <= POST_STAGE_AWAITING_HOST_RDY) {
 508                 post_status.bits.stage = POST_STAGE_CHIP_RESET;
 509                 OCE_CSR_WRITE32(dev, MPU_EP_SEMAPHORE, post_status.dw0);
 510                 if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
 511                     DDI_FM_OK) {
 512                         ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 513                         return (DDI_FAILURE);
 514                 }
 515         }
 516 
 517         /* wait for FW ready */
 518         tmo = drv_usectohz(60000000); /* 1.0min */
 519         for (;;) {
 520                 if ((ddi_get_lbolt() - earlier) > tmo) {
 521                         tmo = 0;
 522                         break;
 523                 }
 524 
 525                 post_status.dw0 = OCE_CSR_READ32(dev, MPU_EP_SEMAPHORE);
 526                 if (oce_fm_check_acc_handle(dev, dev->csr_handle) !=
 527                     DDI_FM_OK) {
 528                         ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
 529                         return (DDI_FAILURE);
 530                 }
 531                 if (post_status.bits.error) {
 532                         oce_log(dev, CE_WARN, MOD_CONFIG,
 533                             "0x%x POST ERROR!!", post_status.dw0);
 534                         return (DDI_FAILURE);
 535                 }
 536                 if (post_status.bits.stage == POST_STAGE_ARMFW_READY)
 537                         return (DDI_SUCCESS);
 538 
 539                 drv_usecwait(100);
 540         }
 541         return (DDI_FAILURE);
 542 } /* oce_be_POST */
 543 
 544 /*
 545  * function to trigger a POST on the device
 546  *
 547  * dev - software handle to the device
 548  *
 549  */
 550 int
 551 oce_POST(struct oce_dev *dev)
 552 {
 553         int ret = 0;
 554 
 555         if (LANCER_CHIP(dev)) {
 556                 ret = oce_lancer_POST(dev);
 557         } else {
 558                 ret = oce_be_POST(dev);
 559         }
 560 
 561         return (ret);
 562 }
 563 
 564 /*
 565  * function to modify register access attributes corresponding to the
 566  * FM capabilities configured by the user
 567  *
 568  * fm_caps - fm capability configured by the user and accepted by the driver
 569  */
 570 void
 571 oce_set_reg_fma_flags(int fm_caps)
 572 {
 573         if (fm_caps == DDI_FM_NOT_CAPABLE) {
 574                 return;
 575         }
 576         if (DDI_FM_ACC_ERR_CAP(fm_caps)) {
 577                 reg_accattr.devacc_attr_access = DDI_FLAGERR_ACC;
 578         } else {
 579                 reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC;
 580         }
 581 } /* oce_set_fma_flags */
 582 
 583 
 584 int
 585 oce_create_nw_interface(struct oce_dev *dev, oce_group_t *grp, uint32_t mode)
 586 {
 587         int ret;
 588         uint32_t cap_flags, en_flags;
 589 
 590         cap_flags = MBX_RX_IFACE_FLAGS_UNTAGGED;
 591         en_flags = MBX_RX_IFACE_FLAGS_UNTAGGED;
 592 
 593         /* first/default group receives broadcast and mcast pkts */
 594         if (grp->grp_num == 0) {
 595                 cap_flags |= MBX_RX_IFACE_FLAGS_BROADCAST |
 596                     MBX_RX_IFACE_FLAGS_MCAST_PROMISCUOUS |
 597                     MBX_RX_IFACE_FLAGS_PROMISCUOUS |
 598                     MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS |
 599                     MBX_RX_IFACE_FLAGS_MCAST;
 600 
 601                 en_flags |= MBX_RX_IFACE_FLAGS_BROADCAST |
 602                     MBX_RX_IFACE_FLAGS_MCAST;
 603 
 604 
 605                 cap_flags |= MBX_RX_IFACE_FLAGS_PASS_L3L4;
 606                 en_flags  |= MBX_RX_IFACE_FLAGS_PASS_L3L4;
 607                 if (grp->rss_enable) {
 608                         cap_flags |= MBX_RX_IFACE_FLAGS_RSS;
 609                         en_flags |= MBX_RX_IFACE_FLAGS_RSS;
 610                 }
 611         }
 612 
 613         if (grp->grp_num == 0) {
 614                 ret = oce_if_create(dev, cap_flags, en_flags,
 615                     0, NULL,
 616                     (uint32_t *)&grp->if_id, mode);
 617                 /* copy default if_id into dev */
 618                 dev->if_id = grp->if_id;
 619 
 620         } else {
 621                 ret = oce_if_create(dev, cap_flags, en_flags,
 622                     0, NULL, (uint32_t *)&grp->if_id, mode);
 623         }
 624         if (ret != 0) {
 625                 oce_log(dev, CE_WARN, MOD_CONFIG,
 626                     "Interface creation failed for group "
 627                     "instance %d: 0x%x", grp->grp_num, ret);
 628                 return (ret);
 629         }
 630 
 631         /* Enable VLAN Promisc on HW */
 632         ret = oce_config_vlan(dev, (uint8_t)grp->if_id,
 633             NULL, 0, B_TRUE, B_TRUE, mode);
 634         if (ret != 0) {
 635                 oce_log(dev, CE_WARN, MOD_CONFIG,
 636                     "Config vlan failed: 0x%x", ret);
 637                 oce_delete_nw_interface(dev, grp, mode);
 638                 return (ret);
 639         }
 640         return (0);
 641 }
 642 
 643 void
 644 oce_delete_nw_interface(struct oce_dev *dev, oce_group_t *grp, uint32_t mode)
 645 {
 646         char itbl[OCE_ITBL_SIZE] = {0};
 647         char hkey[OCE_HKEY_SIZE] = {0};
 648         int ret = 0;
 649 
 650         if (grp->rss_enable) {
 651                 ret = oce_config_rss(dev, grp->if_id, hkey,
 652                     itbl, OCE_ITBL_SIZE, RSS_ENABLE_NONE, B_FALSE, mode);
 653 
 654                 if (ret != DDI_SUCCESS) {
 655                         oce_log(dev, CE_NOTE, MOD_CONFIG,
 656                             "Failed to Disable RSS if_id=%d, ret=0x%x",
 657                             grp->if_id, ret);
 658                 }
 659         }
 660         ret = oce_if_del(dev, (uint8_t)grp->if_id, mode);
 661         if (ret != DDI_SUCCESS)
 662                 oce_log(dev, CE_NOTE, MOD_CONFIG,
 663                     "Failed to delete nw i/f gidx =%d if_id = 0x%x ret=0x%x",
 664                     grp->grp_num, grp->if_id, ret);
 665 }
 666 
 667 void
 668 oce_group_create_itbl(oce_group_t *grp, char *itbl)
 669 {
 670         int i;
 671         oce_ring_t *rss_queuep = &grp->ring[1];
 672         /* fill the indirection table rq 0 is default queue */
 673         for (i = 0; i < OCE_ITBL_SIZE; i++) {
 674                 itbl[i] = rss_queuep[i % (grp->num_rings - 1)].rx->rss_cpuid;
 675         }
 676 }
 677 
 678 
 679 int
 680 oce_hw_init(struct oce_dev *dev)
 681 {
 682         int  ret;
 683         struct mac_address_format mac_addr;
 684 
 685         ret = oce_POST(dev);
 686         if (ret != DDI_SUCCESS) {
 687                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 688                     "!!!HW POST1 FAILED");
 689                 /* ADD FM FAULT */
 690                 return (DDI_FAILURE);
 691         }
 692         /* create bootstrap mailbox */
 693         ret = oce_alloc_dma_buffer(dev, &dev->bmbx,
 694             sizeof (struct oce_bmbx), NULL, DDI_DMA_CONSISTENT|DDI_DMA_RDWR);
 695         if (ret != DDI_SUCCESS) {
 696                 oce_log(dev, CE_WARN, MOD_CONFIG,
 697                     "Failed to allocate bmbx: 0x%x", ret);
 698                 return (DDI_FAILURE);
 699         }
 700 
 701         ret = oce_reset_fun(dev);
 702         if (ret != 0) {
 703                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 704                     "!!!FUNCTION RESET FAILED");
 705                 goto init_fail;
 706         }
 707 
 708         /* reset the Endianess of BMBX */
 709         ret = oce_mbox_init(dev);
 710         if (ret != 0) {
 711                 oce_log(dev, CE_WARN, MOD_CONFIG,
 712                     "Mailbox initialization failed with 0x%x", ret);
 713                 goto init_fail;
 714         }
 715 
 716         /* read the firmware version */
 717         ret = oce_get_fw_version(dev, MBX_BOOTSTRAP);
 718         if (ret != 0) {
 719                 oce_log(dev, CE_WARN, MOD_CONFIG,
 720                     "Firmaware version read failed with 0x%x", ret);
 721                 goto init_fail;
 722         }
 723 
 724         /* read the fw config */
 725         ret = oce_get_fw_config(dev, MBX_BOOTSTRAP);
 726         if (ret != 0) {
 727                 oce_log(dev, CE_WARN, MOD_CONFIG,
 728                     "Firmware configuration read failed with %d", ret);
 729                 goto init_fail;
 730         }
 731 
 732         /* read the Factory MAC address */
 733         ret = oce_read_mac_addr(dev, 0, 1,
 734             MAC_ADDRESS_TYPE_NETWORK, &mac_addr, MBX_BOOTSTRAP);
 735         if (ret != 0) {
 736                 oce_log(dev, CE_WARN, MOD_CONFIG,
 737                     "MAC address read failed with 0x%x", ret);
 738                 goto init_fail;
 739         }
 740         bcopy(&mac_addr.mac_addr[0], &dev->mac_addr[0], ETHERADDRL);
 741 
 742         if (!LANCER_CHIP(dev)) {
 743                 /* cache the ue mask registers for ue detection */
 744                 dev->ue_mask_lo = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_LO_MASK);
 745                 dev->ue_mask_hi = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_HI_MASK);
 746         }
 747 
 748         return (DDI_SUCCESS);
 749 init_fail:
 750         oce_hw_fini(dev);
 751         return (DDI_FAILURE);
 752 }
 753 void
 754 oce_hw_fini(struct oce_dev *dev)
 755 {
 756         (void) oce_mbox_fini(dev);
 757         oce_free_dma_buffer(dev, &dev->bmbx);
 758 }
 759 
 760 boolean_t
 761 oce_check_ue(struct oce_dev *dev)
 762 {
 763         uint32_t ue_lo;
 764         uint32_t ue_hi;
 765 
 766         /* check for  the Hardware unexpected error */
 767         ue_lo = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_LO);
 768         ue_hi = OCE_CFG_READ32(dev, PCICFG_UE_STATUS_HI);
 769 
 770         if ((~dev->ue_mask_lo & ue_lo) ||
 771             (~dev->ue_mask_hi & ue_hi)) {
 772                 /* Unrecoverable error detected */
 773                 oce_log(dev, CE_WARN, MOD_CONFIG,
 774                     "Hardware UE Detected: "
 775                     "UE_LOW:%08x"
 776                     "UE_HI:%08x "
 777                     "UE_MASK_LO:%08x "
 778                     "UE_MASK_HI:%08x",
 779                     ue_lo, ue_hi,
 780                     dev->ue_mask_lo,
 781                     dev->ue_mask_hi);
 782                 return (B_TRUE);
 783         }
 784         return (B_FALSE);
 785 }