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 /*
  26  * Source file containing the implementation of the driver entry points
  27  * and related helper functions
  28  */
  29 
  30 #include <oce_impl.h>
  31 #include <oce_stat.h>
  32 #include <oce_ioctl.h>
  33 
  34 #define ATTACH_DEV_INIT         0x1
  35 #define ATTACH_FM_INIT          0x2
  36 #define ATTACH_PCI_CFG          0x4
  37 #define ATTACH_LOCK_INIT        0x8
  38 #define ATTACH_PCI_INIT         0x10
  39 #define ATTACH_HW_INIT          0x20
  40 #define ATTACH_SETUP_TXRX       0x40
  41 #define ATTACH_SETUP_ADAP       0x80
  42 #define ATTACH_SETUP_INTR       0x100
  43 #define ATTACH_STAT_INIT        0x200
  44 #define ATTACH_MAC_REG          0x400
  45 
  46 /* ---[ globals and externs ]-------------------------------------------- */
  47 const char oce_ident_string[] = OCE_IDENT_STRING;
  48 const char oce_mod_name[] = OCE_MOD_NAME;
  49 struct oce_dev *oce_dev_list[MAX_DEVS + 1];     /* Last entry is invalid */
  50 
  51 /* driver properties */
  52 static const char flow_control[]         = "flow_control";
  53 static const char mtu_prop_name[]        = "oce_default_mtu";
  54 static const char tx_ring_size_name[]    = "tx_ring_size";
  55 static const char tx_bcopy_limit_name[]  = "tx_bcopy_limit";
  56 static const char rx_bcopy_limit_name[]  = "rx_bcopy_limit";
  57 static const char rx_frag_size_name[]    = "rx_frag_size";
  58 static const char rx_max_bufs_name[]     = "rx_max_bufs";
  59 static const char fm_cap_name[]          = "oce_fm_capability";
  60 static const char log_level_name[]       = "oce_log_level";
  61 static const char lso_capable_name[]     = "lso_capable";
  62 static const char rx_pkt_per_intr_name[] = "rx_pkts_per_intr";
  63 static const char tx_reclaim_threshold_name[] = "tx_reclaim_threshold";
  64 static const char rx_rings_name[]        = "max_rx_rings";
  65 static const char tx_rings_name[]        = "max_tx_rings";
  66 
  67 /* --[ static function prototypes here ]------------------------------- */
  68 static int oce_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd);
  69 static int oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
  70 static int oce_quiesce(dev_info_t *dip);
  71 static int oce_suspend(dev_info_t *dip);
  72 static int oce_resume(dev_info_t *dip);
  73 static void oce_unconfigure(struct oce_dev *dev);
  74 static void oce_init_locks(struct oce_dev *dev);
  75 static void oce_destroy_locks(struct oce_dev *dev);
  76 static void oce_get_params(struct oce_dev *dev);
  77 static int oce_get_prop(struct oce_dev *dev, char *propname, int minval,
  78     int maxval, int defval, uint32_t *values);
  79 
  80 static struct cb_ops oce_cb_ops = {
  81         nulldev,                /* cb_open */
  82         nulldev,                /* cb_close */
  83         nodev,                  /* cb_strategy */
  84         nodev,                  /* cb_print */
  85         nodev,                  /* cb_dump */
  86         nodev,                  /* cb_read */
  87         nodev,                  /* cb_write */
  88         nodev,                  /* cb_ioctl */
  89         nodev,                  /* cb_devmap */
  90         nodev,                  /* cb_mmap */
  91         nodev,                  /* cb_segmap */
  92         nochpoll,               /* cb_chpoll */
  93         ddi_prop_op,    /* cb_prop_op */
  94         NULL,                   /* cb_stream */
  95         D_MP,                   /* cb_flag */
  96         CB_REV,                 /* cb_rev */
  97         nodev,                  /* cb_aread */
  98         nodev                   /* cb_awrite */
  99 };
 100 
 101 static struct dev_ops oce_dev_ops = {
 102         DEVO_REV,       /* devo_rev */
 103         0,              /* devo_refcnt */
 104         NULL,           /* devo_getinfo */
 105         NULL,           /* devo_identify */
 106         nulldev,        /* devo_probe */
 107         oce_attach,     /* devo_attach */
 108         oce_detach,     /* devo_detach */
 109         nodev,          /* devo_reset */
 110         &oce_cb_ops,        /* devo_cb_ops */
 111         NULL,           /* devo_bus_ops */
 112         nodev,          /* devo_power */
 113         oce_quiesce     /* devo_quiesce */
 114 };
 115 
 116 static struct modldrv oce_drv = {
 117         &mod_driverops,     /* Type of module.  This one is a driver */
 118         (char *)oce_ident_string, /* Description string */
 119         &oce_dev_ops,       /* driver ops */
 120 };
 121 
 122 static struct modlinkage oce_mod_linkage = {
 123         MODREV_1, &oce_drv, NULL
 124 };
 125 
 126 #define OCE_M_CB_FLAGS  (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | \
 127     MC_PROPINFO)
 128 static mac_callbacks_t oce_mac_cb = {
 129         OCE_M_CB_FLAGS,         /* mc_callbacks */
 130         oce_m_stat,             /* mc_getstat */
 131         oce_m_start,            /* mc_start */
 132         oce_m_stop,             /* mc_stop */
 133         oce_m_promiscuous,      /* mc_setpromisc */
 134         oce_m_multicast,        /* mc_multicast */
 135         oce_m_unicast,          /* mc_unicast */
 136         oce_m_send,             /* mc_tx */
 137         NULL,                   /* mc_reserve */
 138         oce_m_ioctl,            /* mc_ioctl */
 139         oce_m_getcap,           /* mc_getcapab */
 140         NULL,                   /* open */
 141         NULL,                   /* close */
 142         oce_m_setprop,          /* set properties */
 143         oce_m_getprop,          /* get properties */
 144         oce_m_propinfo          /* properties info */
 145 };
 146 
 147 extern char *oce_priv_props[];
 148 
 149 /* Module Init */
 150 int
 151 _info(struct modinfo *modinfop)
 152 {
 153         return (mod_info(&oce_mod_linkage, modinfop));
 154 } /* _info */
 155 
 156 int
 157 _init(void)
 158 {
 159         int ret = 0;
 160 
 161         /* install the module */
 162         mac_init_ops(&oce_dev_ops, "oce");
 163 
 164         ret = mod_install(&oce_mod_linkage);
 165         if (ret) {
 166                 cmn_err(CE_WARN, "mod_install failed  rval=%x", ret);
 167         }
 168 
 169         return (ret);
 170 } /* _init */
 171 
 172 
 173 int
 174 _fini(void)
 175 {
 176         int ret = 0;
 177         /* remove the module */
 178         ret = mod_remove(&oce_mod_linkage);
 179         if (ret != 0) {
 180                 return (ret);
 181         }
 182 
 183         mac_fini_ops(&oce_dev_ops);
 184 
 185         return (ret);
 186 } /* _fini */
 187 
 188 
 189 static int
 190 oce_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 191 {
 192         int ret = 0;
 193         struct oce_dev *dev = NULL;
 194         mac_register_t *mac;
 195         uint8_t dev_index = 0;
 196 
 197         switch (cmd) {
 198         case DDI_RESUME:
 199                 return (oce_resume(dip));
 200         default:
 201                 return (DDI_FAILURE);
 202 
 203         case DDI_ATTACH:
 204                 break;
 205         }
 206 
 207         /* allocate dev */
 208         dev = kmem_zalloc(sizeof (struct oce_dev), KM_SLEEP);
 209 
 210         /* populate the dev structure */
 211         dev->dip = dip;
 212         dev->dev_id = ddi_get_instance(dip);
 213         dev->suspended = B_FALSE;
 214 
 215         dev->dev_list_index = MAX_DEVS;
 216         while (dev_index < MAX_DEVS) {
 217                 (void) atomic_cas_ptr(&oce_dev_list[dev_index], NULL, dev);
 218                 if (oce_dev_list[dev_index] == dev) {
 219                         break;
 220                 }
 221                 dev_index++;
 222         }
 223         if (dev_index == MAX_DEVS) {
 224                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 225                     "Too many oce devices on the system. Failed to attach.");
 226                 goto attach_fail;
 227         }
 228         dev->dev_list_index = dev_index;
 229 
 230         /* get the parameters */
 231         oce_get_params(dev);
 232 
 233         /*
 234          * set the ddi driver private data pointer. This is
 235          * sent to all mac callback entry points
 236          */
 237         ddi_set_driver_private(dip, dev);
 238 
 239         dev->attach_state |= ATTACH_DEV_INIT;
 240 
 241         oce_fm_init(dev);
 242         dev->attach_state |= ATTACH_FM_INIT;
 243 
 244         ret = pci_config_setup(dev->dip, &dev->pci_cfg_handle);
 245         if (ret != DDI_SUCCESS) {
 246                 oce_log(dev, CE_WARN, MOD_CONFIG,
 247                     "Map PCI config failed with  %d", ret);
 248                 goto attach_fail;
 249         }
 250         dev->attach_state |= ATTACH_PCI_CFG;
 251 
 252         ret = oce_identify_hw(dev);
 253 
 254         if (ret != DDI_SUCCESS) {
 255                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 256                     "Device Unknown");
 257                 goto attach_fail;
 258         }
 259 
 260         ret = oce_get_bdf(dev);
 261         if (ret != DDI_SUCCESS) {
 262                 oce_log(dev, CE_WARN, MOD_CONFIG,
 263                     "Failed to read BDF, status = 0x%x", ret);
 264                 goto attach_fail;
 265         }
 266         /* Update the dev->rss */
 267         oce_dev_rss_ready(dev);
 268 
 269         /* setup PCI bars */
 270         ret = oce_pci_init(dev);
 271         if (ret != DDI_SUCCESS) {
 272                 oce_log(dev, CE_WARN, MOD_CONFIG,
 273                     "PCI initialization failed with %d", ret);
 274                 goto attach_fail;
 275         }
 276         dev->attach_state |= ATTACH_PCI_INIT;
 277 
 278         ret = oce_setup_intr(dev);
 279         if (ret != DDI_SUCCESS) {
 280                 oce_log(dev, CE_WARN, MOD_CONFIG,
 281                     "Interrupt setup failed with %d", ret);
 282                 goto attach_fail;
 283 
 284         }
 285         dev->attach_state |= ATTACH_SETUP_INTR;
 286 
 287         /* initialize locks */
 288         oce_init_locks(dev);
 289         dev->attach_state |= ATTACH_LOCK_INIT;
 290 
 291 
 292         /* HW init */
 293         ret = oce_hw_init(dev);
 294         if (ret != DDI_SUCCESS) {
 295                 oce_log(dev, CE_WARN, MOD_CONFIG,
 296                     "HW initialization failed with %d", ret);
 297                 goto attach_fail;
 298         }
 299         dev->attach_state |= ATTACH_HW_INIT;
 300 
 301         ret = oce_init_txrx(dev);
 302         if (ret  != DDI_SUCCESS) {
 303                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 304                     "Failed to init rings");
 305                 goto attach_fail;
 306         }
 307         dev->attach_state |= ATTACH_SETUP_TXRX;
 308 
 309         ret = oce_setup_adapter(dev);
 310         if (ret != DDI_SUCCESS) {
 311                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 312                     "Failed to setup adapter");
 313                 goto attach_fail;
 314         }
 315         dev->attach_state |=  ATTACH_SETUP_ADAP;
 316 
 317 
 318         ret = oce_stat_init(dev);
 319         if (ret != DDI_SUCCESS) {
 320                 oce_log(dev, CE_WARN, MOD_CONFIG,
 321                     "kstat setup Failed with %d", ret);
 322                 goto attach_fail;
 323         }
 324         dev->attach_state |= ATTACH_STAT_INIT;
 325 
 326         /* mac_register_t */
 327         oce_log(dev, CE_NOTE, MOD_CONFIG,
 328             "MAC_VERSION = 0x%x", MAC_VERSION);
 329         mac = mac_alloc(MAC_VERSION);
 330         if (mac == NULL) {
 331                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 332                     "MAC allocation Failed");
 333                 goto attach_fail;
 334         }
 335         /*
 336          * fill the mac structure before calling mac_register
 337          */
 338         mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
 339         mac->m_driver = dev;
 340         mac->m_dip = dip;
 341         mac->m_src_addr = dev->mac_addr;
 342         mac->m_callbacks = &oce_mac_cb;
 343         mac->m_min_sdu = 0;
 344         mac->m_max_sdu = dev->mtu;
 345         mac->m_margin = VTAG_SIZE;
 346         mac->m_priv_props = oce_priv_props;
 347 
 348         oce_log(dev, CE_NOTE, MOD_CONFIG,
 349             "Driver Private structure = 0x%p", (void *)dev);
 350 
 351         /* now register with GLDv3 */
 352         ret = mac_register(mac, (mac_handle_t *)&dev->mac_handle);
 353         /* regardless of the status, free mac_register */
 354         mac_free(mac);
 355         mac = NULL;
 356         if (ret != DDI_SUCCESS) {
 357                 oce_log(dev, CE_WARN, MOD_CONFIG,
 358                     "MAC registration failed :0x%x", ret);
 359                 goto attach_fail;
 360 
 361         }
 362 
 363         /* correct link status only after start */
 364         dev->link_status = LINK_STATE_UNKNOWN;
 365         mac_link_update(dev->mac_handle, dev->link_status);
 366 
 367         dev->attach_state |= ATTACH_MAC_REG;
 368         dev->state |= STATE_INIT;
 369 
 370         oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
 371             "ATTACH SUCCESS");
 372 
 373         return (DDI_SUCCESS);
 374 
 375 attach_fail:
 376         oce_unconfigure(dev);
 377         return (DDI_FAILURE);
 378 } /* oce_attach */
 379 
 380 static int
 381 oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 382 {
 383         struct oce_dev *dev;
 384         int pcnt = 0;
 385         int qid;
 386 
 387         dev = ddi_get_driver_private(dip);
 388         if (dev == NULL) {
 389                 return (DDI_FAILURE);
 390         }
 391         oce_log(dev, CE_NOTE, MOD_CONFIG,
 392             "Detaching driver: cmd = 0x%x", cmd);
 393 
 394         switch (cmd) {
 395         default:
 396                 return (DDI_FAILURE);
 397         case DDI_SUSPEND:
 398                 return (oce_suspend(dip));
 399         case DDI_DETACH:
 400                 break;
 401         } /* switch cmd */
 402 
 403         /* Fail detach if MAC unregister is unsuccessfule */
 404         if (mac_unregister(dev->mac_handle) != 0) {
 405                 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
 406                     "Failed to unregister MAC ");
 407         }
 408         dev->attach_state &= ~ATTACH_MAC_REG;
 409 
 410         /* check if the detach is called with out stopping */
 411         DEV_LOCK(dev);
 412         if (dev->state & STATE_MAC_STARTED) {
 413                 dev->state &= ~STATE_MAC_STARTED;
 414                 oce_stop(dev);
 415                 DEV_UNLOCK(dev);
 416         } else
 417                 DEV_UNLOCK(dev);
 418 
 419         /*
 420          * Wait for Packets sent up to be freed
 421          */
 422         for (qid = 0; qid < dev->rx_rings; qid++) {
 423                 pcnt = oce_rx_pending(dev, dev->rq[qid], DEFAULT_DRAIN_TIME);
 424                 if (pcnt != 0) {
 425                         oce_log(dev, CE_WARN, MOD_CONFIG,
 426                             "%d Pending Buffers Detach failed", pcnt);
 427                         return (DDI_FAILURE);
 428                 }
 429         }
 430         oce_unconfigure(dev);
 431 
 432         return (DDI_SUCCESS);
 433 } /* oce_detach */
 434 
 435 static int
 436 oce_quiesce(dev_info_t *dip)
 437 {
 438         int ret = DDI_SUCCESS;
 439         struct oce_dev *dev = ddi_get_driver_private(dip);
 440 
 441         if (dev == NULL) {
 442                 return (DDI_FAILURE);
 443         }
 444         if (dev->suspended) {
 445                 return (DDI_SUCCESS);
 446         }
 447 
 448         oce_chip_di(dev);
 449 
 450         ret = oce_reset_fun(dev);
 451 
 452         return (ret);
 453 }
 454 
 455 static int
 456 oce_suspend(dev_info_t *dip)
 457 {
 458         struct oce_dev *dev = ddi_get_driver_private(dip);
 459 
 460         mutex_enter(&dev->dev_lock);
 461         /* Suspend the card */
 462         dev->suspended = B_TRUE;
 463         /* stop the adapter */
 464         if (dev->state & STATE_MAC_STARTED) {
 465                 oce_stop(dev);
 466                 oce_unsetup_adapter(dev);
 467         }
 468         dev->state &= ~STATE_MAC_STARTED;
 469         mutex_exit(&dev->dev_lock);
 470         return (DDI_SUCCESS);
 471 } /* oce_suspend */
 472 
 473 static int
 474 oce_resume(dev_info_t *dip)
 475 {
 476         struct oce_dev *dev;
 477         int ret;
 478 
 479         /* get the dev pointer from dip */
 480         dev = ddi_get_driver_private(dip);
 481         mutex_enter(&dev->dev_lock);
 482         if (!dev->suspended) {
 483                 mutex_exit(&dev->dev_lock);
 484                 return (DDI_SUCCESS);
 485         }
 486         if (!(dev->state & STATE_MAC_STARTED)) {
 487                 ret = oce_setup_adapter(dev);
 488                 if (ret != DDI_SUCCESS) {
 489                         mutex_exit(&dev->dev_lock);
 490                         return (DDI_FAILURE);
 491                 }
 492                 ret = oce_start(dev);
 493                 if (ret != DDI_SUCCESS) {
 494                         mutex_exit(&dev->dev_lock);
 495                         return (DDI_FAILURE);
 496                 }
 497         }
 498         dev->suspended = B_FALSE;
 499         dev->state |= STATE_MAC_STARTED;
 500         mutex_exit(&dev->dev_lock);
 501         return (ret);
 502 } /* oce_resume */
 503 
 504 static void
 505 oce_init_locks(struct oce_dev *dev)
 506 {
 507         /* initialize locks */
 508         mutex_init(&dev->dev_lock, NULL, MUTEX_DRIVER,
 509             DDI_INTR_PRI(dev->intr_pri));
 510         mutex_init(&dev->bmbx_lock, NULL, MUTEX_DRIVER,
 511             DDI_INTR_PRI(dev->intr_pri));
 512 } /* oce_init_locks */
 513 
 514 static void
 515 oce_destroy_locks(struct oce_dev *dev)
 516 {
 517         mutex_destroy(&dev->dev_lock);
 518         mutex_destroy(&dev->bmbx_lock);
 519 } /* oce_destroy_locks */
 520 
 521 static void
 522 oce_unconfigure(struct oce_dev *dev)
 523 {
 524         uint32_t state = dev->attach_state;
 525 
 526         if (state & ATTACH_MAC_REG) {
 527                 (void) mac_unregister(dev->mac_handle);
 528         }
 529         if (state & ATTACH_STAT_INIT) {
 530                 oce_stat_fini(dev);
 531         }
 532         if (state & ATTACH_SETUP_ADAP) {
 533                 oce_unsetup_adapter(dev);
 534         }
 535         if (state & ATTACH_SETUP_TXRX) {
 536                 oce_fini_txrx(dev);
 537         }
 538         if (state & ATTACH_HW_INIT) {
 539                 oce_hw_fini(dev);
 540         }
 541         if (state & ATTACH_LOCK_INIT) {
 542                 oce_destroy_locks(dev);
 543         }
 544         if (state & ATTACH_SETUP_INTR) {
 545                 (void) oce_teardown_intr(dev);
 546         }
 547         if (state & ATTACH_PCI_INIT) {
 548                 oce_pci_fini(dev);
 549         }
 550         if (state & ATTACH_PCI_CFG) {
 551                 pci_config_teardown(&dev->pci_cfg_handle);
 552         }
 553         if (state & ATTACH_FM_INIT) {
 554                 oce_fm_fini(dev);
 555         }
 556         if (state & ATTACH_DEV_INIT) {
 557                 ddi_set_driver_private(dev->dip, NULL);
 558                 oce_dev_list[dev->dev_list_index] = NULL;
 559                 kmem_free(dev, sizeof (struct oce_dev));
 560         }
 561 } /* oce_unconfigure */
 562 
 563 static void
 564 oce_get_params(struct oce_dev *dev)
 565 {
 566         uint32_t log_level;
 567         uint16_t mod_mask;
 568         uint16_t severity;
 569         /*
 570          * Allowed values for the driver parameters. If all values in a range
 571          * is allowed, the the array has only one value.
 572          */
 573         uint32_t fc_values[] = {OCE_FC_NONE, OCE_FC_TX, OCE_FC_RX,
 574             OCE_DEFAULT_FLOW_CONTROL, END};
 575         uint32_t mtu_values[] = {OCE_MIN_MTU, OCE_MAX_MTU, END};
 576         uint32_t tx_rs_values[] = {SIZE_256, SIZE_512, SIZE_1K, SIZE_2K, END};
 577         uint32_t tx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
 578             SIZE_2K, END};
 579         uint32_t rx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
 580             SIZE_2K, END};
 581         uint32_t rq_fs_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
 582         uint32_t rq_mb_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
 583         uint32_t lso_capable_values[] = {0, 1, END};
 584         uint32_t fm_caps_values[] = {DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY,
 585             END};
 586         uint32_t tx_rt_values[] = {END};
 587         uint32_t rx_ppi_values[] = {END};
 588         uint32_t rx_rings_values[] = {END};
 589         uint32_t tx_rings_values[] = {END};
 590         uint32_t log_level_values[] = {END};
 591 
 592         /* non tunables  */
 593         dev->rx_ring_size = OCE_DEFAULT_RX_RING_SIZE;
 594 
 595         /* configurable parameters */
 596         dev->flow_control = oce_get_prop(dev, (char *)flow_control, OCE_FC_NONE,
 597             OCE_DEFAULT_FLOW_CONTROL, OCE_DEFAULT_FLOW_CONTROL, fc_values);
 598 
 599         dev->mtu = oce_get_prop(dev, (char *)mtu_prop_name, OCE_MIN_MTU,
 600             OCE_MAX_MTU, OCE_MIN_MTU, mtu_values);
 601 
 602         dev->tx_ring_size = oce_get_prop(dev, (char *)tx_ring_size_name,
 603             SIZE_256, SIZE_2K, OCE_DEFAULT_TX_RING_SIZE, tx_rs_values);
 604 
 605         dev->tx_bcopy_limit = oce_get_prop(dev, (char *)tx_bcopy_limit_name,
 606             SIZE_128, SIZE_2K, OCE_DEFAULT_TX_BCOPY_LIMIT, tx_bcl_values);
 607 
 608         dev->rx_bcopy_limit = oce_get_prop(dev, (char *)rx_bcopy_limit_name,
 609             SIZE_128, SIZE_2K, OCE_DEFAULT_RX_BCOPY_LIMIT, rx_bcl_values);
 610 
 611         dev->rq_frag_size = oce_get_prop(dev, (char *)rx_frag_size_name,
 612             SIZE_2K, SIZE_8K, OCE_RQ_BUF_SIZE, rq_fs_values);
 613 
 614         dev->rq_max_bufs = oce_get_prop(dev, (char *)rx_max_bufs_name, SIZE_2K,
 615             SIZE_8K, OCE_RQ_NUM_BUFFERS, rq_mb_values);
 616 
 617         dev->lso_capable = oce_get_prop(dev, (char *)lso_capable_name, 0,
 618             1, 1, lso_capable_values);
 619 
 620         dev->fm_caps = oce_get_prop(dev, (char *)fm_cap_name,
 621             DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY, OCE_FM_CAPABILITY,
 622             fm_caps_values);
 623 
 624         dev->tx_reclaim_threshold = oce_get_prop(dev,
 625             (char *)tx_reclaim_threshold_name, 0, dev->tx_ring_size/2,
 626             OCE_DEFAULT_TX_RECLAIM_THRESHOLD, tx_rt_values);
 627 
 628         dev->rx_pkt_per_intr = oce_get_prop(dev, (char *)rx_pkt_per_intr_name,
 629             0, dev->rx_ring_size/2, OCE_DEFAULT_RX_PKT_PER_INTR, rx_ppi_values);
 630 
 631         dev->rx_rings = oce_get_prop(dev, (char *)rx_rings_name,
 632             OCE_MIN_RQ, OCE_MAX_RQ, OCE_DEFAULT_RQS, rx_rings_values);
 633 
 634         dev->tx_rings = oce_get_prop(dev, (char *)tx_rings_name,
 635             OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, tx_rings_values);
 636 
 637         log_level = oce_get_prop(dev, (char *)log_level_name, 0,
 638             OCE_MAX_LOG_SETTINGS, OCE_DEFAULT_LOG_SETTINGS, log_level_values);
 639 
 640         severity = (uint16_t)(log_level & 0xffff);
 641         mod_mask = (uint16_t)(log_level >> 16);
 642         if (mod_mask > MOD_ISR) {
 643                 mod_mask = 0;
 644         }
 645         if (severity > CE_IGNORE) {
 646                 severity = 0;
 647         }
 648 
 649         dev->mod_mask = mod_mask;
 650         dev->severity = severity;
 651 } /* oce_get_params */
 652 
 653 static int
 654 oce_get_prop(struct oce_dev *dev, char *propname, int minval, int maxval,
 655     int defval, uint32_t *values)
 656 {
 657         int value = 0;
 658         int i = 0;
 659 
 660         value = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
 661             DDI_PROP_DONTPASS, propname, defval);
 662 
 663         if (value > maxval)
 664                 value = maxval;
 665 
 666         if (value < minval)
 667                 value = minval;
 668 
 669         while (values[i] != 0xdeadface) {
 670                 if (values[i] == value) {
 671                         break;
 672                 }
 673                 i++;
 674         }
 675 
 676         if ((i != 0) && (values[i] == 0xdeadface)) {
 677                 value = defval;
 678         }
 679 
 680         return (value);
 681 }