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, v.1,  (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://opensource.org/licenses/CDDL-1.0.
  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-2017 Cavium, Inc. 
  24 * The contents of this file are subject to the terms of the Common Development 
  25 * and Distribution License, v.1,  (the "License").
  26 
  27 * You may not use this file except in compliance with the License.
  28 
  29 * You can obtain a copy of the License at available 
  30 * at http://opensource.org/licenses/CDDL-1.0
  31 
  32 * See the License for the specific language governing permissions and 
  33 * limitations under the License.
  34 */
  35 
  36 
  37 #include "qede.h"
  38 
  39 #define FP_LOCK(ptr)    \
  40 mutex_enter(&ptr->fp_lock);
  41 #define FP_UNLOCK(ptr)  \
  42 mutex_exit(&ptr->fp_lock);
  43 
  44 int
  45 qede_ucst_find(qede_t *qede, const uint8_t *mac_addr)
  46 {
  47         int slot;
  48 
  49         for(slot = 0; slot < qede->ucst_total; slot++) {
  50                 if (bcmp(qede->ucst_mac[slot].mac_addr.ether_addr_octet,
  51                     mac_addr, ETHERADDRL) == 0) {
  52                         return (slot);
  53                 }
  54         }
  55         return (-1);
  56 
  57 }
  58 
  59 static int
  60 qede_set_mac_addr(qede_t *qede, uint8_t *mac_addr, uint8_t fl)
  61 {
  62         struct ecore_filter_ucast params;
  63 
  64         memset(&params, 0, sizeof (params));
  65 
  66         params.opcode = fl;
  67         params.type = ECORE_FILTER_MAC;
  68         params.is_rx_filter = true;
  69         params.is_tx_filter = true;
  70         COPY_ETH_ADDRESS(mac_addr, params.mac);
  71 
  72         return (ecore_filter_ucast_cmd(&qede->edev, 
  73             &params, ECORE_SPQ_MODE_EBLOCK, NULL));
  74 
  75                         
  76 }
  77 static int 
  78 qede_add_macaddr(qede_t *qede, uint8_t *mac_addr) 
  79 {
  80         int i, ret = 0;
  81 
  82         i = qede_ucst_find(qede, mac_addr);
  83         if (i != -1) {
  84                 /* LINTED E_ARGUMENT_MISMATCH */
  85                 qede_info(qede, "mac addr already added %d\n", 
  86                     qede->ucst_avail);
  87                 return (0);
  88         }
  89         if (qede->ucst_avail == 0) {
  90                 qede_info(qede, "add macaddr ignored \n");
  91                 return (ENOSPC);
  92         }
  93         for (i = 0; i < qede->ucst_total; i++) {
  94                 if (qede->ucst_mac[i].set == 0) {
  95                         break;
  96                 }
  97         }
  98         if (i >= qede->ucst_total) {
  99                 qede_info(qede, "add macaddr ignored no space");
 100                 return (ENOSPC);
 101         }
 102         ret = qede_set_mac_addr(qede, (uint8_t *)mac_addr, ECORE_FILTER_ADD);
 103         if (ret == 0) {
 104                 bcopy(mac_addr, 
 105                     qede->ucst_mac[i].mac_addr.ether_addr_octet,
 106                     ETHERADDRL);
 107                 qede->ucst_mac[i].set = 1;
 108                 qede->ucst_avail--;
 109                 /* LINTED E_ARGUMENT_MISMATCH */
 110                 qede_info(qede,  " add macaddr passed for addr "
 111                     "%02x:%02x:%02x:%02x:%02x:%02x",
 112                     mac_addr[0], mac_addr[1],
 113                     mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
 114         } else {
 115                 /* LINTED E_ARGUMENT_MISMATCH */
 116                 qede_info(qede,  "add macaddr failed for addr "
 117                     "%02x:%02x:%02x:%02x:%02x:%02x",
 118                     mac_addr[0], mac_addr[1],
 119                     mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
 120 
 121         }
 122         if (qede->ucst_avail == (qede->ucst_total -1)) {
 123                         u8 bcast_addr[] = 
 124                         { 
 125                                 0xff, 0xff, 0xff, 0xff, 0xff,
 126                                 0xff 
 127                         };
 128                         for (i = 0; i < qede->ucst_total; i++) {
 129                                 if (qede->ucst_mac[i].set == 0)
 130                                         break;
 131                         }
 132                         ret = qede_set_mac_addr(qede, 
 133                             (uint8_t *)bcast_addr, ECORE_FILTER_ADD);
 134                         if (ret == 0) {
 135                                 bcopy(bcast_addr, 
 136                                     qede->ucst_mac[i].mac_addr.ether_addr_octet,
 137                                     ETHERADDRL);
 138                                 qede->ucst_mac[i].set = 1;
 139                                 qede->ucst_avail--;
 140                         } else {
 141 
 142                         /* LINTED E_ARGUMENT_MISMATCH */
 143                         qede_info(qede,  "add macaddr failed for addr "
 144                             "%02x:%02x:%02x:%02x:%02x:%02x",
 145                             mac_addr[0], mac_addr[1],
 146                             mac_addr[2], mac_addr[3], mac_addr[4], 
 147                             mac_addr[5]);
 148                        }
 149 
 150                 }       
 151 
 152         return (ret);
 153 
 154 }
 155 
 156 #ifndef ILLUMOS
 157 static int
 158 qede_add_mac_addr(void *arg, const uint8_t *mac_addr, const uint64_t flags)
 159 #else
 160 static int
 161 qede_add_mac_addr(void *arg, const uint8_t *mac_addr)
 162 #endif
 163 {
 164         qede_mac_group_t *rx_group = (qede_mac_group_t *)arg;
 165         qede_t *qede = rx_group->qede;
 166         int ret = DDI_SUCCESS;
 167 
 168         /* LINTED E_ARGUMENT_MISMATCH */
 169         qede_info(qede, " mac addr :" MAC_STRING,  MACTOSTR(mac_addr));
 170         
 171         mutex_enter(&qede->gld_lock);
 172         if (qede->qede_state == QEDE_STATE_SUSPENDED) {
 173                 mutex_exit(&qede->gld_lock);
 174                 return (ECANCELED);
 175         }
 176         ret = qede_add_macaddr(qede, (uint8_t *)mac_addr);
 177 
 178         mutex_exit(&qede->gld_lock);
 179 
 180 
 181         return (ret);
 182 }
 183 
 184 static int
 185 qede_rem_macaddr(qede_t *qede, uint8_t *mac_addr)
 186 {
 187         int ret = 0;
 188         int i;
 189 
 190         i = qede_ucst_find(qede, mac_addr);
 191         if (i == -1) {
 192                 /* LINTED E_ARGUMENT_MISMATCH */
 193                 qede_info(qede, 
 194                     "mac addr not there to remove", 
 195                     MAC_STRING, MACTOSTR(mac_addr));
 196                 return (0);
 197         }
 198         if (qede->ucst_mac[i].set == 0) {
 199                 return (EINVAL);
 200         }       
 201         ret = qede_set_mac_addr(qede, (uint8_t *)mac_addr, ECORE_FILTER_REMOVE);
 202         if (ret == 0) {
 203                 bzero(qede->ucst_mac[i].mac_addr.ether_addr_octet,ETHERADDRL);
 204                 qede->ucst_mac[i].set = 0;
 205                 qede->ucst_avail++;
 206         } else {
 207                 /* LINTED E_ARGUMENT_MISMATCH */
 208                 qede_info(qede, "mac addr remove failed", 
 209                     MAC_STRING, MACTOSTR(mac_addr));
 210         }
 211         return (ret);
 212 
 213 }
 214 
 215 
 216 static int
 217 qede_rem_mac_addr(void *arg, const uint8_t *mac_addr)
 218 {
 219         qede_mac_group_t *rx_group = (qede_mac_group_t *)arg;
 220         qede_t *qede = rx_group->qede;
 221         int ret = DDI_SUCCESS;
 222 
 223         /* LINTED E_ARGUMENT_MISMATCH */
 224         qede_info(qede, "mac addr remove:" MAC_STRING, MACTOSTR(mac_addr));
 225         mutex_enter(&qede->gld_lock);
 226         if (qede->qede_state == QEDE_STATE_SUSPENDED) {
 227                 mutex_exit(&qede->gld_lock);
 228                 return (ECANCELED);
 229         }
 230         ret = qede_rem_macaddr(qede, (uint8_t *)mac_addr);
 231         mutex_exit(&qede->gld_lock);
 232         return (ret);
 233 }
 234 
 235 
 236 static int
 237 qede_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
 238 {
 239         int ret = 0;
 240 
 241         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 242         qede_tx_ring_t *tx_ring = fp->tx_ring[0];
 243         qede_t *qede = fp->qede;
 244 
 245 
 246         if (qede->qede_state == QEDE_STATE_SUSPENDED)
 247                 return (ECANCELED);
 248 
 249         switch (stat) {
 250         case MAC_STAT_OBYTES:
 251                 *val = tx_ring->tx_byte_count;
 252                 break;
 253 
 254         case MAC_STAT_OPACKETS:
 255                 *val = tx_ring->tx_pkt_count;
 256                 break;
 257 
 258         default:
 259                 *val = 0;
 260                 ret = ENOTSUP;
 261         }
 262 
 263         return (ret);
 264 }
 265 
 266 #ifndef ILLUMOS
 267 static mblk_t *
 268 qede_rx_ring_poll(void *arg, int poll_bytes, int poll_pkts)
 269 {
 270 #else
 271 static mblk_t *
 272 qede_rx_ring_poll(void *arg, int poll_bytes)
 273 {
 274         /* XXX pick a value at the moment */
 275         int poll_pkts = 100;
 276 #endif
 277         qede_fastpath_t *fp = (qede_fastpath_t *)arg;
 278         mblk_t *mp = NULL;
 279         int work_done = 0;
 280         qede_t *qede = fp->qede;
 281 
 282         if (poll_bytes == 0) {
 283                 return (NULL);
 284         }
 285 
 286         mutex_enter(&fp->fp_lock);
 287         qede->intrSbPollCnt[fp->vect_info->vect_index]++;
 288 
 289         mp = qede_process_fastpath(fp, poll_bytes, poll_pkts, &work_done);
 290         if (mp != NULL) {
 291                 fp->rx_ring->rx_poll_cnt++;
 292         } else if ((mp == NULL) && (work_done == 0)) {
 293                 qede->intrSbPollNoChangeCnt[fp->vect_info->vect_index]++;
 294         }
 295 
 296         mutex_exit(&fp->fp_lock);
 297         return (mp);
 298 }
 299 
 300 #ifndef ILLUMOS
 301 static int
 302 qede_rx_ring_intr_enable(mac_ring_driver_t rh)
 303 #else
 304 static int
 305 qede_rx_ring_intr_enable(mac_intr_handle_t rh)
 306 #endif
 307 {
 308         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 309 
 310         mutex_enter(&fp->qede->drv_lock);
 311         if (!fp->sb_phys && (fp->sb_dma_handle == NULL)) {
 312                 mutex_exit(&fp->qede->drv_lock);
 313                 return (DDI_FAILURE);
 314         }
 315 
 316         fp->rx_ring->intrEnableCnt++;
 317         qede_enable_hw_intr(fp);
 318         fp->disabled_by_poll = 0;
 319         mutex_exit(&fp->qede->drv_lock);
 320 
 321         return (DDI_SUCCESS);
 322 }
 323 
 324 #ifndef ILLUMOS
 325 static int
 326 qede_rx_ring_intr_disable(mac_ring_driver_t rh)
 327 #else
 328 static int
 329 qede_rx_ring_intr_disable(mac_intr_handle_t rh)
 330 #endif
 331 {
 332         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 333 
 334         mutex_enter(&fp->qede->drv_lock);
 335         if (!fp->sb_phys && (fp->sb_dma_handle == NULL)) {
 336                 mutex_exit(&fp->qede->drv_lock);
 337                 return (DDI_FAILURE);
 338         }
 339         fp->rx_ring->intrDisableCnt++;
 340         qede_disable_hw_intr(fp);
 341         fp->disabled_by_poll = 1;
 342         mutex_exit(&fp->qede->drv_lock);
 343         return (DDI_SUCCESS);
 344 }
 345 
 346 static int
 347 qede_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
 348 {
 349 
 350         int ret = 0;
 351 
 352         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 353         qede_t *qede = fp->qede;
 354         qede_rx_ring_t *rx_ring = fp->rx_ring;
 355 
 356         if (qede->qede_state == QEDE_STATE_SUSPENDED) {
 357                 return (ECANCELED);
 358         }
 359 
 360         switch (stat) {
 361         case MAC_STAT_RBYTES:
 362                 *val = rx_ring->rx_byte_cnt;
 363                 break;
 364         case MAC_STAT_IPACKETS:
 365                 *val = rx_ring->rx_pkt_cnt;
 366                 break;
 367         default:
 368                 *val = 0;
 369                 ret = ENOTSUP;
 370                 break;  
 371         }
 372 
 373         return (ret);
 374 }
 375 
 376 static int
 377 qede_get_global_ring_index(qede_t *qede, int gindex, int rindex)
 378 {
 379         qede_fastpath_t *fp;
 380         qede_rx_ring_t *rx_ring;
 381         int i = 0;
 382 
 383         for (i = 0; i < qede->num_fp; i++) {
 384                 fp = &qede->fp_array[i];
 385                 rx_ring = fp->rx_ring;
 386 
 387                 if (rx_ring->group_index == gindex) {
 388                         rindex--;
 389                 }
 390                 if (rindex < 0) {
 391                         return (i);
 392                 }
 393         }
 394 
 395         return (-1);
 396 }
 397 
 398 static void
 399 qede_rx_ring_stop(mac_ring_driver_t rh)
 400 {
 401         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 402         qede_rx_ring_t *rx_ring = fp->rx_ring;
 403 
 404         qede_print("!%s(%d): called", __func__,fp->qede->instance);
 405         mutex_enter(&fp->fp_lock);
 406         rx_ring->mac_ring_started = B_FALSE;
 407         mutex_exit(&fp->fp_lock);
 408 }
 409 
 410 static int
 411 qede_rx_ring_start(mac_ring_driver_t rh, u64 mr_gen_num)
 412 {
 413         qede_fastpath_t *fp = (qede_fastpath_t *)rh;
 414         qede_rx_ring_t *rx_ring = fp->rx_ring;
 415 
 416         qede_print("!%s(%d): called", __func__,fp->qede->instance);
 417         mutex_enter(&fp->fp_lock);
 418         rx_ring->mr_gen_num = mr_gen_num;
 419         rx_ring->mac_ring_started = B_TRUE;
 420         rx_ring->intrDisableCnt = 0;
 421         rx_ring->intrEnableCnt  = 0;
 422         fp->disabled_by_poll = 0;
 423 
 424         mutex_exit(&fp->fp_lock);
 425 
 426         return (DDI_SUCCESS);
 427 }
 428 
 429 /* Callback function from mac layer to register rings */
 430 void
 431 qede_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
 432     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
 433 {
 434         qede_t *qede = (qede_t *)arg;
 435         mac_intr_t *mintr = &infop->mri_intr;
 436 
 437         switch (rtype) {
 438         case MAC_RING_TYPE_RX: {
 439                 /*
 440                  * Index passed as a param is the ring index within the
 441                  * given group index. If multiple groups are supported
 442                  * then need to search into all groups to find out the
 443                  * global ring index for the passed group relative
 444                  * ring index
 445                  */
 446                 int global_ring_index = qede_get_global_ring_index(qede,
 447                     group_index, ring_index);
 448                 qede_fastpath_t *fp;
 449                 qede_rx_ring_t *rx_ring;
 450                 int i;
 451 
 452                 /* 
 453                  * global_ring_index < 0 means group index passed
 454                  * was registered by our driver
 455                  */
 456                 ASSERT(global_ring_index >= 0);
 457 
 458                 if (rh == NULL) {
 459                         cmn_err(CE_WARN, "!rx ring(%d) ring handle NULL",
 460                             global_ring_index);
 461                 }
 462 
 463                 fp = &qede->fp_array[global_ring_index];
 464                 rx_ring = fp->rx_ring;
 465                 fp->qede = qede;
 466 
 467                 rx_ring->mac_ring_handle = rh;
 468 
 469                 qede_info(qede, "rx_ring %d mac_ring_handle %p",
 470                     rx_ring->rss_id, rh);
 471 
 472                 /* mri_driver passed as arg to mac_ring* callbacks */
 473                 infop->mri_driver = (mac_ring_driver_t)fp;
 474                 /*
 475                  * mri_start callback will supply a mac rings generation
 476                  * number which is needed while indicating packets
 477                  * upstream via mac_ring_rx() call
 478                  */
 479                 infop->mri_start = qede_rx_ring_start;
 480                 infop->mri_stop = qede_rx_ring_stop;
 481                 infop->mri_poll = qede_rx_ring_poll;
 482                 infop->mri_stat = qede_rx_ring_stat;
 483 
 484                 mintr->mi_handle = (mac_intr_handle_t)fp;
 485                 mintr->mi_enable = qede_rx_ring_intr_enable;
 486                 mintr->mi_disable = qede_rx_ring_intr_disable;
 487                 if (qede->intr_ctx.intr_type_in_use &
 488                     (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
 489                         mintr->mi_ddi_handle =
 490                             qede->intr_ctx.
 491                             intr_hdl_array[global_ring_index + qede->num_hwfns];
 492                 }
 493                 break;
 494         }
 495         case MAC_RING_TYPE_TX: {
 496                 qede_fastpath_t *fp;
 497                 qede_tx_ring_t *tx_ring;
 498                 int i, tc;
 499 
 500                 ASSERT(ring_index < qede->num_fp);
 501                 
 502                 fp = &qede->fp_array[ring_index];
 503                 fp->qede = qede;
 504                 tx_ring = fp->tx_ring[0];
 505                 tx_ring->mac_ring_handle = rh;
 506                 qede_info(qede, "tx_ring %d mac_ring_handle %p",
 507                     tx_ring->tx_queue_index, rh);
 508                 infop->mri_driver = (mac_ring_driver_t)fp;
 509                 infop->mri_start = NULL;
 510                 infop->mri_stop = NULL;
 511                 infop->mri_tx = qede_ring_tx;
 512                 infop->mri_stat = qede_tx_ring_stat;
 513                 if (qede->intr_ctx.intr_type_in_use &
 514                     (DDI_INTR_TYPE_MSIX | DDI_INTR_TYPE_MSI)) {
 515                         mintr->mi_ddi_handle =
 516                             qede->intr_ctx.
 517                             intr_hdl_array[ring_index + qede->num_hwfns]; 
 518                 }
 519                 break;
 520         }
 521         default:
 522                 break;
 523         }
 524 }
 525 
 526 /*
 527  * Callback function from mac layer to register group
 528  */
 529 void
 530 qede_fill_group(void *arg, mac_ring_type_t rtype, const int index,
 531     mac_group_info_t *infop, mac_group_handle_t gh)
 532 {
 533         qede_t *qede = (qede_t *)arg;
 534 
 535         switch (rtype) {
 536         case MAC_RING_TYPE_RX: {
 537                 qede_mac_group_t *rx_group;
 538 
 539                 rx_group = &qede->rx_groups[index];
 540                 rx_group->group_handle = gh;
 541                 rx_group->group_index = index;
 542                 rx_group->qede = qede;
 543                 infop->mgi_driver = (mac_group_driver_t)rx_group;
 544                 infop->mgi_start = NULL;
 545                 infop->mgi_stop = NULL;
 546 #ifndef ILLUMOS
 547                 infop->mgi_addvlan = NULL;
 548                 infop->mgi_remvlan = NULL;
 549                 infop->mgi_getsriov_info = NULL;
 550                 infop->mgi_setmtu = NULL;
 551 #endif
 552                 infop->mgi_addmac = qede_add_mac_addr;
 553                 infop->mgi_remmac = qede_rem_mac_addr;
 554                 infop->mgi_count =  qede->num_fp;
 555 #ifndef ILLUMOS
 556                 if (index == 0) {
 557                         infop->mgi_flags = MAC_GROUP_DEFAULT;
 558                 }
 559 #endif
 560 
 561                 break;
 562         }
 563         case MAC_RING_TYPE_TX: {
 564                 qede_mac_group_t *tx_group;
 565 
 566                 tx_group = &qede->tx_groups[index];
 567                 tx_group->group_handle = gh;
 568                 tx_group->group_index = index;
 569                 tx_group->qede = qede;
 570 
 571                 infop->mgi_driver = (mac_group_driver_t)tx_group;
 572                 infop->mgi_start = NULL;
 573                 infop->mgi_stop = NULL;
 574                 infop->mgi_addmac = NULL;
 575                 infop->mgi_remmac = NULL;
 576 #ifndef ILLUMOS
 577                 infop->mgi_addvlan = NULL;
 578                 infop->mgi_remvlan = NULL;
 579                 infop->mgi_setmtu = NULL;
 580                 infop->mgi_getsriov_info = NULL;
 581 #endif
 582 
 583                 infop->mgi_count = qede->num_fp;
 584 
 585 #ifndef ILLUMOS
 586                 if (index == 0) {
 587                         infop->mgi_flags = MAC_GROUP_DEFAULT;
 588                 }
 589 #endif
 590                 break;
 591         }
 592         default:
 593                 break;
 594         }
 595 }
 596 
 597 #ifdef ILLUMOS
 598 static int
 599 qede_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
 600 {
 601         qede_t *qede = arg;
 602         struct ecore_dev *edev = &qede->edev;
 603         struct ecore_hwfn *hwfn;
 604         struct ecore_ptt *ptt;
 605         uint32_t transceiver_state;
 606 
 607         if (id >= edev->num_hwfns || arg == NULL || infop == NULL)
 608                 return (EINVAL);
 609 
 610         hwfn = &edev->hwfns[id];
 611         ptt = ecore_ptt_acquire(hwfn);
 612         if (ptt == NULL) {
 613                 return (EIO);
 614         }
 615         /*
 616          * Use the underlying raw API to get this information. While the
 617          * ecore_phy routines have some ways of getting to this information, it
 618          * ends up writing the raw data as ASCII characters which doesn't help
 619          * us one bit.
 620          */
 621         transceiver_state = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
 622             OFFSETOF(struct public_port, transceiver_data));
 623         transceiver_state = GET_FIELD(transceiver_state, ETH_TRANSCEIVER_STATE);
 624         ecore_ptt_release(hwfn, ptt);
 625 
 626         if ((transceiver_state & ETH_TRANSCEIVER_STATE_PRESENT) != 0) {
 627                 mac_transceiver_info_set_present(infop, B_TRUE);
 628                 /*
 629                  * Based on our testing, the ETH_TRANSCEIVER_STATE_VALID flag is
 630                  * not set, so we cannot rely on it. Instead, we have found that
 631                  * the ETH_TRANSCEIVER_STATE_UPDATING will be set when we cannot
 632                  * use the transceiver.
 633                  */
 634                 if ((transceiver_state & ETH_TRANSCEIVER_STATE_UPDATING) != 0) {
 635                         mac_transceiver_info_set_usable(infop, B_FALSE);
 636                 } else {
 637                         mac_transceiver_info_set_usable(infop, B_TRUE);
 638                 }
 639         } else {
 640                 mac_transceiver_info_set_present(infop, B_FALSE);
 641                 mac_transceiver_info_set_usable(infop, B_FALSE);
 642         }
 643 
 644         return (0);
 645 }
 646 
 647 static int
 648 qede_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
 649     size_t nbytes, off_t offset, size_t *nread)
 650 {
 651         qede_t *qede = arg;
 652         struct ecore_dev *edev = &qede->edev;
 653         struct ecore_hwfn *hwfn;
 654         uint32_t port, lane;
 655         struct ecore_ptt *ptt;
 656         enum _ecore_status_t ret;
 657 
 658         if (id >= edev->num_hwfns || buf == NULL || nbytes == 0 || nread == NULL ||
 659             (page != 0xa0 && page != 0xa2) || offset < 0)
 660                 return (EINVAL);
 661 
 662         /*
 663          * Both supported pages have a length of 256 bytes, ensure nothing asks
 664          * us to go beyond that.
 665          */
 666         if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
 667                return (EINVAL);
 668         }
 669 
 670         hwfn = &edev->hwfns[id];
 671         ptt = ecore_ptt_acquire(hwfn);
 672         if (ptt == NULL) {
 673                 return (EIO);
 674         }
 675 
 676         ret = ecore_mcp_phy_sfp_read(hwfn, ptt, hwfn->port_id, page, offset,
 677             nbytes, buf);
 678         ecore_ptt_release(hwfn, ptt);
 679         if (ret != ECORE_SUCCESS) {
 680                 return (EIO);
 681         }
 682         *nread = nbytes;
 683         return (0);
 684 }
 685 #endif /* ILLUMOS */
 686 
 687 
 688 static int
 689 qede_mac_stats(void *     arg,
 690                         uint_t     stat,
 691                         uint64_t * value)
 692 {
 693         qede_t * qede = (qede_t *)arg;
 694         struct ecore_eth_stats vstats;
 695         struct ecore_dev *edev = &qede->edev;
 696         struct qede_link_cfg lnkcfg;
 697         int rc = 0;
 698         qede_fastpath_t *fp = &qede->fp_array[0];
 699         qede_rx_ring_t *rx_ring;
 700         qede_tx_ring_t *tx_ring;
 701 
 702         if ((qede == NULL) || (value == NULL)) {
 703                 return EINVAL;
 704         }
 705 
 706 
 707         mutex_enter(&qede->gld_lock);
 708 
 709         if(qede->qede_state != QEDE_STATE_STARTED) {
 710                 mutex_exit(&qede->gld_lock);
 711                 return EAGAIN;
 712         }
 713 
 714         *value = 0;
 715         
 716         memset(&vstats, 0, sizeof(struct ecore_eth_stats));
 717         ecore_get_vport_stats(edev, &vstats);
 718         
 719 
 720         memset(&qede->curcfg, 0, sizeof(struct qede_link_cfg));
 721         qede_get_link_info(&edev->hwfns[0], &qede->curcfg);
 722 
 723 
 724 
 725         switch (stat)
 726         {
 727         case MAC_STAT_IFSPEED:
 728                 *value = (qede->props.link_speed * 1000000ULL);
 729                 break;
 730         case MAC_STAT_MULTIRCV:
 731                 *value = vstats.common.rx_mcast_pkts;
 732                 break;
 733         case MAC_STAT_BRDCSTRCV:
 734                 *value = vstats.common.rx_bcast_pkts;
 735                 break;
 736         case MAC_STAT_MULTIXMT:
 737                 *value = vstats.common.tx_mcast_pkts;
 738                 break;
 739         case MAC_STAT_BRDCSTXMT:
 740                 *value = vstats.common.tx_bcast_pkts;
 741                 break;
 742         case MAC_STAT_NORCVBUF:
 743                 *value = vstats.common.no_buff_discards;
 744                 break;
 745         case MAC_STAT_NOXMTBUF:
 746                 *value = 0;
 747                 break;
 748         case MAC_STAT_IERRORS:
 749         case ETHER_STAT_MACRCV_ERRORS:
 750                 *value = vstats.common.mac_filter_discards + 
 751                     vstats.common.packet_too_big_discard + 
 752                     vstats.common.rx_crc_errors;        
 753                 break;
 754         
 755         case MAC_STAT_OERRORS:
 756                 break;
 757 
 758         case MAC_STAT_COLLISIONS:
 759                 *value = vstats.bb.tx_total_collisions;
 760                 break;
 761 
 762         case MAC_STAT_RBYTES:
 763                 *value = vstats.common.rx_ucast_bytes + 
 764                     vstats.common.rx_mcast_bytes + 
 765                     vstats.common.rx_bcast_bytes;
 766                 break;
 767 
 768         case MAC_STAT_IPACKETS:
 769                 *value = vstats.common.rx_ucast_pkts + 
 770                     vstats.common.rx_mcast_pkts + 
 771                     vstats.common.rx_bcast_pkts; 
 772                 break;
 773 
 774         case MAC_STAT_OBYTES:
 775                 *value = vstats.common.tx_ucast_bytes + 
 776                     vstats.common.tx_mcast_bytes + 
 777                     vstats.common.tx_bcast_bytes;
 778                 break;
 779 
 780         case MAC_STAT_OPACKETS:
 781                 *value = vstats.common.tx_ucast_pkts + 
 782                     vstats.common.tx_mcast_pkts + 
 783                     vstats.common.tx_bcast_pkts;
 784                 break;
 785 
 786         case ETHER_STAT_ALIGN_ERRORS:
 787                 *value = vstats.common.rx_align_errors;
 788                 break;
 789         
 790         case ETHER_STAT_FCS_ERRORS:
 791                 *value = vstats.common.rx_crc_errors;
 792                 break;
 793 
 794         case ETHER_STAT_FIRST_COLLISIONS:
 795                 break;
 796 
 797         case ETHER_STAT_MULTI_COLLISIONS:
 798                 break;
 799 
 800         case ETHER_STAT_DEFER_XMTS:
 801                 break;
 802 
 803         case ETHER_STAT_TX_LATE_COLLISIONS:
 804                 break;
 805 
 806         case ETHER_STAT_EX_COLLISIONS:
 807                 break;
 808 
 809         case ETHER_STAT_MACXMT_ERRORS:
 810                 *value = 0;
 811                 break;
 812 
 813         case ETHER_STAT_CARRIER_ERRORS:
 814                 break;
 815 
 816         case ETHER_STAT_TOOLONG_ERRORS:
 817                 *value = vstats.common.rx_oversize_packets;
 818                 break;
 819 
 820 #if (MAC_VERSION > 1)
 821         case ETHER_STAT_TOOSHORT_ERRORS:
 822                 *value = vstats.common.rx_undersize_packets;
 823                 break;
 824 #endif
 825 
 826         case ETHER_STAT_XCVR_ADDR:
 827                 *value = 0;
 828                 break;
 829 
 830         case ETHER_STAT_XCVR_ID:
 831                 *value = 0;
 832                 break;
 833 
 834         case ETHER_STAT_XCVR_INUSE:
 835                 switch (qede->props.link_speed) {
 836                 default:
 837                         *value = XCVR_UNDEFINED;
 838                 }
 839                 break;
 840 #if (MAC_VERSION > 1)
 841         case ETHER_STAT_CAP_10GFDX:
 842                 *value = 0;
 843                 break;
 844 #endif
 845         case ETHER_STAT_CAP_100FDX:
 846                 *value = 0;
 847                 break;  
 848         case ETHER_STAT_CAP_100HDX:
 849                 *value = 0;
 850                 break;  
 851         case ETHER_STAT_CAP_ASMPAUSE:
 852                 *value = 1;
 853                 break;
 854         case ETHER_STAT_CAP_PAUSE:      
 855                 *value = 1;
 856                 break;
 857         case ETHER_STAT_CAP_AUTONEG:
 858                 *value = 1;
 859                 break;
 860         
 861 #if (MAC_VERSION > 1)
 862         case ETHER_STAT_CAP_REMFAULT:
 863                 *value = 0;
 864                 break;
 865 #endif
 866 
 867 #if (MAC_VERSION > 1)
 868         case ETHER_STAT_ADV_CAP_10GFDX:
 869                 *value = 0; 
 870                 break;
 871 #endif
 872     case ETHER_STAT_ADV_CAP_ASMPAUSE:
 873                 *value = 1;
 874                 break;
 875 
 876         case ETHER_STAT_ADV_CAP_PAUSE:
 877                 *value = 1;
 878                 break;
 879 
 880         case ETHER_STAT_ADV_CAP_AUTONEG:
 881                 *value = qede->curcfg.adv_capab.autoneg;
 882                 break;
 883 
 884 #if (MAC_VERSION > 1)
 885         case ETHER_STAT_ADV_REMFAULT:
 886                 *value = 0;
 887                 break;
 888 #endif  
 889 
 890         case ETHER_STAT_LINK_AUTONEG:
 891                 *value  = qede->curcfg.autoneg;
 892                 break;
 893 
 894         case ETHER_STAT_LINK_DUPLEX:
 895                 *value = (qede->props.link_duplex == DUPLEX_FULL) ?
 896                                     LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
 897                 break;
 898         /*
 899          * Supported speeds. These indicate what hardware is capable of.
 900          */
 901         case ETHER_STAT_CAP_1000HDX:
 902                 *value = qede->curcfg.supp_capab.param_1000hdx;
 903                 break;
 904 
 905         case ETHER_STAT_CAP_1000FDX:
 906                 *value = qede->curcfg.supp_capab.param_1000fdx;
 907                 break;
 908 
 909         case ETHER_STAT_CAP_10GFDX:
 910                 *value = qede->curcfg.supp_capab.param_10000fdx;
 911                 break;
 912 
 913         case ETHER_STAT_CAP_25GFDX:
 914                 *value = qede->curcfg.supp_capab.param_25000fdx;
 915                 break;
 916 
 917         case ETHER_STAT_CAP_40GFDX:
 918                 *value = qede->curcfg.supp_capab.param_40000fdx;
 919                 break;
 920 
 921         case ETHER_STAT_CAP_50GFDX:
 922                 *value = qede->curcfg.supp_capab.param_50000fdx;
 923                 break;
 924 
 925         case ETHER_STAT_CAP_100GFDX:
 926                 *value = qede->curcfg.supp_capab.param_100000fdx;
 927                 break;
 928 
 929         /*
 930          * Advertised speeds. These indicate what hardware is currently sending.
 931          */
 932         case ETHER_STAT_ADV_CAP_1000HDX:
 933                 *value = qede->curcfg.adv_capab.param_1000hdx;
 934                 break;
 935 
 936         case ETHER_STAT_ADV_CAP_1000FDX:
 937                 *value = qede->curcfg.adv_capab.param_1000fdx;
 938                 break;
 939 
 940         case ETHER_STAT_ADV_CAP_10GFDX:
 941                 *value = qede->curcfg.adv_capab.param_10000fdx;
 942                 break;
 943 
 944         case ETHER_STAT_ADV_CAP_25GFDX:
 945                 *value = qede->curcfg.adv_capab.param_25000fdx;
 946                 break;
 947 
 948         case ETHER_STAT_ADV_CAP_40GFDX:
 949                 *value = qede->curcfg.adv_capab.param_40000fdx;
 950                 break;
 951 
 952         case ETHER_STAT_ADV_CAP_50GFDX:
 953                 *value = qede->curcfg.adv_capab.param_50000fdx;
 954                 break;
 955 
 956         case ETHER_STAT_ADV_CAP_100GFDX:
 957                 *value = qede->curcfg.adv_capab.param_100000fdx;
 958                 break;
 959 
 960         default:
 961                 rc = ENOTSUP;
 962         }
 963 
 964         mutex_exit(&qede->gld_lock);
 965         return (rc);
 966 }
 967 
 968 /* (flag) TRUE = on, FALSE = off */
 969 static int
 970 qede_mac_promiscuous(void *arg,
 971     boolean_t on)
 972 {
 973         qede_t *qede = (qede_t *)arg;
 974         qede_print("!%s(%d): called", __func__,qede->instance);
 975         int ret = DDI_SUCCESS;
 976         enum qede_filter_rx_mode_type mode;
 977         
 978         mutex_enter(&qede->drv_lock);
 979         
 980         if (qede->qede_state == QEDE_STATE_SUSPENDED) {
 981                 ret = ECANCELED;
 982                 goto exit;
 983         }
 984 
 985         if (on) {
 986                 qede_info(qede, "Entering promiscuous mode");
 987                 mode = QEDE_FILTER_RX_MODE_PROMISC;
 988                 qede->params.promisc_fl = B_TRUE;
 989         } else {
 990                 qede_info(qede, "Leaving promiscuous mode");
 991                 if(qede->params.multi_promisc_fl == B_TRUE) {
 992                         mode = QEDE_FILTER_RX_MODE_MULTI_PROMISC;
 993                 } else {        
 994                          mode = QEDE_FILTER_RX_MODE_REGULAR;
 995                 }
 996                 qede->params.promisc_fl = B_FALSE;
 997         }
 998 
 999         ret = qede_set_filter_rx_mode(qede, mode);
1000 
1001 exit:
1002         mutex_exit(&qede->drv_lock);
1003         return (ret);
1004 }
1005 
1006 int qede_set_rx_mac_mcast(qede_t *qede, enum ecore_filter_opcode opcode, 
1007                           uint8_t *mac, int mc_cnt) 
1008 {
1009         struct ecore_filter_mcast cmd;
1010         int i;
1011         memset(&cmd, 0, sizeof(cmd));
1012         cmd.opcode = opcode;
1013         cmd.num_mc_addrs = mc_cnt;
1014 
1015         for (i = 0; i < mc_cnt; i++, mac += ETH_ALLEN) {
1016                 COPY_ETH_ADDRESS(mac, cmd.mac[i]);
1017         }
1018 
1019 
1020         return (ecore_filter_mcast_cmd(&qede->edev, &cmd, 
1021             ECORE_SPQ_MODE_CB, NULL));
1022                 
1023 }
1024 
1025 int
1026 qede_set_filter_rx_mode(qede_t * qede, enum qede_filter_rx_mode_type type) 
1027 {
1028         struct ecore_filter_accept_flags flg;
1029 
1030         memset(&flg, 0, sizeof(flg));
1031 
1032         flg.update_rx_mode_config      = 1;
1033         flg.update_tx_mode_config      = 1;
1034         flg.rx_accept_filter           = ECORE_ACCEPT_UCAST_MATCHED | 
1035             ECORE_ACCEPT_MCAST_MATCHED | ECORE_ACCEPT_BCAST;
1036         flg.tx_accept_filter = ECORE_ACCEPT_UCAST_MATCHED | 
1037             ECORE_ACCEPT_MCAST_MATCHED | ECORE_ACCEPT_BCAST;
1038 
1039         if (type == QEDE_FILTER_RX_MODE_PROMISC)
1040                 flg.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED | 
1041                     ECORE_ACCEPT_MCAST_UNMATCHED;
1042         else if (type == QEDE_FILTER_RX_MODE_MULTI_PROMISC)
1043                 flg.rx_accept_filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
1044         qede_info(qede, "rx_mode rx_filter=0x%x tx_filter=0x%x type=0x%x\n", 
1045             flg.rx_accept_filter, flg.tx_accept_filter, type);
1046         return (ecore_filter_accept_cmd(&qede->edev, 0, flg,
1047                         0, /* update_accept_any_vlan */
1048                         0, /* accept_any_vlan */
1049                         ECORE_SPQ_MODE_CB, NULL));
1050 }
1051 
1052 int 
1053 qede_multicast(qede_t *qede, boolean_t flag, const uint8_t *ptr_mcaddr)
1054 {
1055         int i, ret = DDI_SUCCESS;
1056         qede_mcast_list_entry_t *ptr_mlist;
1057         qede_mcast_list_entry_t *ptr_entry;
1058         int mc_cnt;
1059         unsigned char *mc_macs, *tmpmc;
1060         size_t size;
1061         boolean_t mcmac_exists = B_FALSE;
1062         enum qede_filter_rx_mode_type mode;
1063 
1064         if (!ptr_mcaddr)  {
1065                 cmn_err(CE_NOTE, "Removing all multicast");
1066         } else  {
1067                 cmn_err(CE_NOTE,
1068                     "qede=%p %s multicast: %02x:%02x:%02x:%02x:%02x:%02x",
1069                     qede, (flag) ? "Adding" : "Removing", ptr_mcaddr[0], 
1070                     ptr_mcaddr[1],ptr_mcaddr[2],ptr_mcaddr[3],ptr_mcaddr[4],
1071                     ptr_mcaddr[5]);
1072         }
1073 
1074 
1075         if (flag && (ptr_mcaddr == NULL)) {
1076                 cmn_err(CE_WARN, "ERROR: Multicast address not specified");
1077                 return EINVAL;
1078         }
1079 
1080 
1081         /* exceeds addition of mcaddr above limit */
1082         if (flag && (qede->mc_cnt >= MAX_MC_SOFT_LIMIT)) {
1083                 qede_info(qede, "Cannot add more than MAX_MC_SOFT_LIMIT");
1084                 return ENOENT;
1085         }
1086 
1087         size = MAX_MC_SOFT_LIMIT * ETH_ALLEN;
1088 
1089         mc_macs = kmem_zalloc(size, KM_NOSLEEP);
1090         if (!mc_macs) { 
1091                 cmn_err(CE_WARN, "ERROR: Failed to allocate for mc_macs");
1092                 return EINVAL;
1093         }
1094 
1095         tmpmc = mc_macs;
1096 
1097         /* remove all multicast - as flag not set and mcaddr not specified*/
1098         if (!flag && (ptr_mcaddr == NULL)) {
1099                 QEDE_LIST_FOR_EACH_ENTRY(ptr_entry, 
1100                     &qede->mclist.head, qede_mcast_list_entry_t, mclist_entry)
1101                 {
1102                         if (ptr_entry != NULL) {
1103                         QEDE_LIST_REMOVE(&ptr_entry->mclist_entry, 
1104                             &qede->mclist.head);
1105                         kmem_free(ptr_entry, 
1106                             sizeof (qede_mcast_list_entry_t) + ETH_ALLEN);
1107                         }
1108                 }
1109 
1110                 ret = qede_set_rx_mac_mcast(qede, 
1111                     ECORE_FILTER_REMOVE, mc_macs, 1);
1112                 qede->mc_cnt = 0;
1113                 goto exit;
1114         }
1115 
1116         QEDE_LIST_FOR_EACH_ENTRY(ptr_entry, 
1117             &qede->mclist.head, qede_mcast_list_entry_t, mclist_entry)
1118         {
1119                 if ((ptr_entry != NULL) && 
1120                     IS_ETH_ADDRESS_EQUAL(ptr_mcaddr, ptr_entry->mac)) {
1121                         mcmac_exists = B_TRUE;
1122                         break;
1123                 }
1124         }
1125         if (flag && mcmac_exists) {
1126                 ret = DDI_SUCCESS;
1127                 goto exit;
1128         } else if (!flag && !mcmac_exists) {
1129                 ret = DDI_SUCCESS;
1130                 goto exit;
1131         }
1132 
1133        if (flag) {
1134                 ptr_entry = kmem_zalloc((sizeof (qede_mcast_list_entry_t) + 
1135                     ETH_ALLEN), KM_NOSLEEP);
1136                 ptr_entry->mac = (uint8_t *)ptr_entry + 
1137                     sizeof (qede_mcast_list_entry_t);
1138                 COPY_ETH_ADDRESS(ptr_mcaddr, ptr_entry->mac);
1139                 QEDE_LIST_ADD(&ptr_entry->mclist_entry, &qede->mclist.head);
1140         } else {
1141                 QEDE_LIST_REMOVE(&ptr_entry->mclist_entry, &qede->mclist.head);
1142                 kmem_free(ptr_entry, sizeof(qede_mcast_list_entry_t) + 
1143                     ETH_ALLEN);
1144         }
1145 
1146         mc_cnt = 0;
1147         QEDE_LIST_FOR_EACH_ENTRY(ptr_entry, &qede->mclist.head, 
1148             qede_mcast_list_entry_t, mclist_entry) {
1149                 COPY_ETH_ADDRESS(ptr_entry->mac, tmpmc);
1150                 tmpmc += ETH_ALLEN;
1151                 mc_cnt++;
1152         }
1153         qede->mc_cnt = mc_cnt;
1154         if (mc_cnt <=64) {
1155                 ret = qede_set_rx_mac_mcast(qede, ECORE_FILTER_ADD, 
1156                     (unsigned char *)mc_macs, mc_cnt);
1157                 if ((qede->params.multi_promisc_fl == B_TRUE) && 
1158                     (qede->params.promisc_fl == B_FALSE)) {
1159                         mode = QEDE_FILTER_RX_MODE_REGULAR;
1160                         ret = qede_set_filter_rx_mode(qede, mode);
1161                 }
1162                 qede->params.multi_promisc_fl = B_FALSE;
1163         } else {
1164                 if ((qede->params.multi_promisc_fl == B_FALSE) && 
1165                     (qede->params.promisc_fl = B_FALSE)) {
1166                         ret = qede_set_filter_rx_mode(qede, 
1167                             QEDE_FILTER_RX_MODE_MULTI_PROMISC);
1168                 }
1169                 qede->params.multi_promisc_fl = B_TRUE;
1170                 qede_info(qede, "mode is MULTI_PROMISC");
1171         }
1172 exit:
1173 kmem_free(mc_macs, size);
1174 qede_info(qede, "multicast ret %d mc_cnt %d\n", ret, qede->mc_cnt);
1175 return (ret);
1176 }
1177 
1178 /*
1179  * This function is used to enable or disable multicast packet reception for
1180  * particular multicast addresses.
1181  * (flag) TRUE = add, FALSE = remove
1182  */
1183 static int
1184 qede_mac_multicast(void *arg,
1185     boolean_t       flag,
1186     const uint8_t * mcast_addr)
1187 {
1188         qede_t *qede = (qede_t *)arg;
1189         int ret = DDI_SUCCESS;
1190 
1191 
1192         mutex_enter(&qede->gld_lock);
1193         if(qede->qede_state != QEDE_STATE_STARTED) {
1194                 mutex_exit(&qede->gld_lock);
1195                 return (EAGAIN);
1196         }
1197         ret = qede_multicast(qede, flag, mcast_addr);
1198                 
1199         mutex_exit(&qede->gld_lock);
1200 
1201     return (ret);
1202 }
1203 int 
1204 qede_clear_filters(qede_t *qede)
1205 {
1206         int ret = 0;
1207         int i;
1208         if ((qede->params.promisc_fl == B_TRUE) || 
1209             (qede->params.multi_promisc_fl == B_TRUE)) {
1210                 ret = qede_set_filter_rx_mode(qede, 
1211                     QEDE_FILTER_RX_MODE_REGULAR);
1212                 if (ret) {
1213                         qede_info(qede, 
1214                             "qede_clear_filters failed to set rx_mode");
1215                 }
1216         }
1217         for (i=0; i < qede->ucst_total; i++)
1218         {
1219                 if (qede->ucst_mac[i].set) {
1220                         qede_rem_macaddr(qede, 
1221                             qede->ucst_mac[i].mac_addr.ether_addr_octet);
1222                 }
1223         }
1224         qede_multicast(qede, B_FALSE, NULL);
1225         return (ret);
1226 }
1227 
1228 
1229 #ifdef  NO_CROSSBOW
1230 static int
1231 qede_mac_unicast(void *arg,
1232     const uint8_t * mac_addr)
1233 {
1234     qede_t *qede = (qede_t *)arg;
1235     return 0;
1236 }
1237 
1238 
1239 static mblk_t *
1240 qede_mac_tx(void *arg,
1241     mblk_t * mblk)
1242 {
1243     qede_t *qede = (qede_t *)arg;
1244     qede_fastpath_t *fp = &qede->fp_array[0];
1245 
1246     mblk = qede_ring_tx((void *)fp, mblk);
1247 
1248     return (mblk);
1249 }
1250 #endif  /* NO_CROSSBOW */
1251 
1252 
1253 static lb_property_t loopmodes[] = {
1254         { normal,       "normal",       QEDE_LOOP_NONE                },
1255         { internal,     "internal",     QEDE_LOOP_INTERNAL            },
1256         { external,     "external",     QEDE_LOOP_EXTERNAL            },
1257 };
1258 
1259 /* 
1260  * Set Loopback mode 
1261  */
1262 
1263 static enum ioc_reply
1264 qede_set_loopback_mode(qede_t *qede, uint32_t mode)
1265 {
1266         int ret, i = 0;
1267         struct ecore_dev *edev = &qede->edev;
1268         struct ecore_hwfn *hwfn;
1269         struct ecore_ptt *ptt = NULL;
1270         struct ecore_mcp_link_params *link_params;
1271 
1272         hwfn = &edev->hwfns[0];
1273         link_params = ecore_mcp_get_link_params(hwfn);
1274         ptt = ecore_ptt_acquire(hwfn);
1275 
1276         switch(mode) {
1277         default:
1278                 qede_info(qede, "unknown loopback mode !!");
1279                 ecore_ptt_release(hwfn, ptt);
1280                 return IOC_INVAL;
1281 
1282         case QEDE_LOOP_NONE:
1283                 ecore_mcp_set_link(hwfn, ptt, 0);
1284 
1285                 while (qede->params.link_state && i < 5000) {
1286                         OSAL_MSLEEP(1);
1287                         i++;
1288                 }
1289                 i = 0;
1290 
1291                 link_params->loopback_mode = ETH_LOOPBACK_NONE;
1292                 qede->loop_back_mode = QEDE_LOOP_NONE;
1293                 ret = ecore_mcp_set_link(hwfn, ptt, 1);
1294                 ecore_ptt_release(hwfn, ptt);
1295 
1296                 while (!qede->params.link_state && i < 5000) {
1297                         OSAL_MSLEEP(1);
1298                         i++;
1299                 }
1300                 return IOC_REPLY;
1301 
1302         case QEDE_LOOP_INTERNAL:
1303                 qede_print("!%s(%d) : loopback mode (INTERNAL) is set!",
1304                     __func__, qede->instance);
1305                     ecore_mcp_set_link(hwfn, ptt, 0);
1306 
1307                 while(qede->params.link_state && i < 5000) {
1308                         OSAL_MSLEEP(1);
1309                         i++;
1310                 }
1311                 i = 0;
1312                 link_params->loopback_mode = ETH_LOOPBACK_INT_PHY;
1313                 qede->loop_back_mode = QEDE_LOOP_INTERNAL;
1314                 ret = ecore_mcp_set_link(hwfn, ptt, 1);
1315                 ecore_ptt_release(hwfn, ptt);
1316 
1317                 while(!qede->params.link_state && i < 5000) {
1318                         OSAL_MSLEEP(1);
1319                         i++;
1320                 }
1321                 return IOC_REPLY;
1322 
1323         case QEDE_LOOP_EXTERNAL:
1324                 qede_print("!%s(%d) : External loopback mode is not supported",
1325                     __func__, qede->instance);
1326                 ecore_ptt_release(hwfn, ptt);
1327                 return IOC_INVAL;
1328         }
1329 }
1330 
1331 static int
1332 qede_ioctl_pcicfg_rd(qede_t *qede, u32 addr, void *data,
1333     int len)
1334 {
1335         u32 crb, actual_crb; 
1336         uint32_t ret = 0;
1337         int cap_offset = 0, cap_id = 0, next_cap = 0;
1338         ddi_acc_handle_t pci_cfg_handle  = qede->pci_cfg_handle;
1339         qede_ioctl_data_t * data1 = (qede_ioctl_data_t *) data;
1340         
1341         cap_offset = pci_config_get8(pci_cfg_handle, PCI_CONF_CAP_PTR);
1342         while (cap_offset != 0) {
1343                 /* Check for an invalid PCI read. */
1344                 if (cap_offset == PCI_EINVAL8) {
1345                         return DDI_FAILURE;
1346                 }
1347                 cap_id = pci_config_get8(pci_cfg_handle, cap_offset);
1348                 if (cap_id == PCI_CAP_ID_PCI_E) {
1349                         /* PCIe expr capab struct found */
1350                         break;
1351                 } else {
1352                         next_cap = pci_config_get8(pci_cfg_handle,
1353                             cap_offset + 1);
1354                         cap_offset = next_cap;
1355                 }
1356         }
1357 
1358         switch (len) {
1359         case 1:
1360                 ret = pci_config_get8(qede->pci_cfg_handle, addr);
1361                 (void) memcpy(data, &ret, sizeof(uint8_t));
1362                 break;
1363         case 2:
1364                 ret = pci_config_get16(qede->pci_cfg_handle, addr);
1365                 (void) memcpy(data, &ret, sizeof(uint16_t));
1366                 break;
1367         case 4:
1368                 ret = pci_config_get32(qede->pci_cfg_handle, addr);
1369                 (void) memcpy(data, &ret, sizeof(uint32_t));
1370                 break;
1371         default:
1372                 cmn_err(CE_WARN, "bad length for pci config read\n");
1373                 return (1);
1374         }
1375         return (0);
1376 }
1377 
1378 static int
1379 qede_ioctl_pcicfg_wr(qede_t *qede, u32 addr, void *data,
1380     int len)
1381 {
1382         uint16_t ret = 0;
1383         int cap_offset = 0, cap_id = 0, next_cap = 0;
1384         qede_ioctl_data_t * data1 = (qede_ioctl_data_t *) data;
1385         ddi_acc_handle_t pci_cfg_handle  = qede->pci_cfg_handle;
1386 #if 1
1387         cap_offset = pci_config_get8(pci_cfg_handle, PCI_CONF_CAP_PTR);
1388         while (cap_offset != 0) {
1389                 cap_id = pci_config_get8(pci_cfg_handle, cap_offset);
1390                 if (cap_id == PCI_CAP_ID_PCI_E) {
1391                         /* PCIe expr capab struct found */
1392                         break;
1393                 } else {
1394                         next_cap = pci_config_get8(pci_cfg_handle, 
1395                             cap_offset + 1);
1396                         cap_offset = next_cap;
1397                 }
1398         }
1399 #endif
1400 
1401         switch(len) {
1402         case 1:
1403                 pci_config_put8(qede->pci_cfg_handle, addr, 
1404                     *(char *)&(data));
1405                 break;
1406         case 2:
1407                 ret = pci_config_get16(qede->pci_cfg_handle, addr);
1408                 ret = ret | *(uint16_t *)data1->uabc;
1409 
1410                 pci_config_put16(qede->pci_cfg_handle, addr, 
1411                     ret);
1412                 break;
1413         case 4:
1414                 pci_config_put32(qede->pci_cfg_handle, addr, *(uint32_t *)data1->uabc);
1415                 break;
1416                 
1417         default:
1418                 return (1);
1419         }
1420         return (0);
1421 }
1422 
1423 static int
1424 qede_ioctl_rd_wr_reg(qede_t *qede, void *data)
1425 {
1426         struct ecore_hwfn *p_hwfn;
1427         struct ecore_dev *edev = &qede->edev;
1428         struct ecore_ptt *ptt;
1429         qede_ioctl_data_t *data1 = (qede_ioctl_data_t *)data;
1430         uint32_t ret = 0;
1431         uint8_t cmd = (uint8_t) data1->unused1;
1432         uint32_t addr = data1->off;
1433         uint32_t val = *(uint32_t *)&data1->uabc[1];
1434         uint32_t hwfn_index = *(uint32_t *)&data1->uabc[5];      
1435         uint32_t *reg_addr;
1436 
1437         if (hwfn_index > qede->num_hwfns) {
1438                 cmn_err(CE_WARN, "invalid hwfn index from application\n");
1439                 return (EINVAL);
1440         }
1441         p_hwfn = &edev->hwfns[hwfn_index];
1442         
1443         switch(cmd) {
1444         case QEDE_REG_READ:
1445                 ret = ecore_rd(p_hwfn, p_hwfn->p_main_ptt, addr);
1446                 (void) memcpy(data1->uabc, &ret, sizeof(uint32_t));
1447                 break;
1448                 
1449         case QEDE_REG_WRITE:
1450                 ecore_wr(p_hwfn, p_hwfn->p_main_ptt, addr, val);
1451                 break;
1452 
1453         default:
1454                 cmn_err(CE_WARN, 
1455                     "wrong command in register read/write from application\n");
1456                 break;
1457         }
1458         return (ret);
1459 }
1460 
1461 static int
1462 qede_ioctl_rd_wr_nvram(qede_t *qede, mblk_t *mp)
1463 {
1464         qede_nvram_data_t *data1 = (qede_nvram_data_t *)(mp->b_cont->b_rptr); 
1465         qede_nvram_data_t *data2, *next_data;
1466         struct ecore_dev *edev = &qede->edev;
1467         uint32_t ret = 0, hdr_size = 24, bytes_to_copy, copy_len = 0;
1468         uint32_t copy_len1 = 0;
1469         uint32_t addr = data1->off;
1470         uint32_t size = data1->size, i, buf_size;
1471         uint8_t cmd, cmd2;
1472         uint8_t *buf, *tmp_buf;
1473         mblk_t *mp1;
1474 
1475         cmd = (uint8_t)data1->unused1;
1476 
1477         switch(cmd) {
1478         case QEDE_NVRAM_CMD_READ:
1479                 buf = kmem_zalloc(size, GFP_KERNEL);
1480                 if(buf == NULL) {
1481                         cmn_err(CE_WARN, "memory allocation failed" 
1482                         " in nvram read ioctl\n");
1483                         return (DDI_FAILURE);
1484                 }
1485                 ret = ecore_mcp_nvm_read(edev, addr, buf, data1->size);
1486 
1487                 copy_len = (MBLKL(mp->b_cont)) - hdr_size;
1488                 if(copy_len > size) {
1489                         (void) memcpy(data1->uabc, buf, size);
1490                         kmem_free(buf, size);
1491                         //OSAL_FREE(edev, buf);
1492                         ret = 0;
1493                         break;
1494                 }
1495                 (void) memcpy(data1->uabc, buf, copy_len);
1496                 bytes_to_copy = size - copy_len;
1497                 tmp_buf = ((uint8_t *)buf) + copy_len;
1498                 copy_len1 = copy_len;
1499                 mp1 = mp->b_cont;
1500                 mp1 = mp1->b_cont;
1501 
1502                 while (mp1) {
1503                         copy_len = MBLKL(mp1);
1504                         if(mp1->b_cont == NULL) {
1505                                 copy_len = MBLKL(mp1) - 4;
1506                         }
1507                         data2 = (qede_nvram_data_t *)mp1->b_rptr;
1508                         if (copy_len > bytes_to_copy) {
1509                                 (void) memcpy(data2->uabc, tmp_buf, 
1510                                     bytes_to_copy);
1511                                 kmem_free(buf, size);
1512                                 //OSAL_FREE(edev, buf);
1513                                 break;
1514                         }
1515                         (void) memcpy(data2->uabc, tmp_buf, copy_len);
1516                         tmp_buf = tmp_buf + copy_len;
1517                         copy_len += copy_len;
1518                         mp1 = mp1->b_cont;
1519                         bytes_to_copy = bytes_to_copy - copy_len;
1520                 }
1521                         
1522                 kmem_free(buf, size);
1523                 //OSAL_FREE(edev, buf);
1524                 break;
1525         
1526         case QEDE_NVRAM_CMD_WRITE:
1527                 cmd2 = (uint8_t )data1->cmd2;
1528                 size = data1->size;
1529                 addr = data1->off;
1530                 buf_size =  size; //data1->buf_size;
1531                 //buf_size =  data1->buf_size;
1532                 ret = 0;
1533 
1534                 switch(cmd2){
1535                 case START_NVM_WRITE:
1536                         buf = kmem_zalloc(size, GFP_KERNEL);
1537                         //buf = qede->reserved_buf;
1538                         qede->nvm_buf_size = data1->size;
1539                         if(buf == NULL) {
1540                                 cmn_err(CE_WARN, 
1541                                 "memory allocation failed in START_NVM_WRITE\n");
1542                                 return DDI_FAILURE;
1543                         }
1544                         qede->nvm_buf_start = buf;
1545                         cmn_err(CE_NOTE, 
1546                             "buf = %p, size = %x\n", qede->nvm_buf_start, size);
1547                         qede->nvm_buf = buf;
1548                         qede->copy_len = 0;
1549                         //tmp_buf = buf + addr;
1550                         ret = 0;
1551                         break;
1552                         
1553                 case ACCUMULATE_NVM_BUF:
1554                         tmp_buf = qede->nvm_buf;
1555                         copy_len = MBLKL(mp->b_cont) - hdr_size;
1556                         if(copy_len > buf_size) {
1557                                 if (buf_size < qede->nvm_buf_size) {
1558                                 (void) memcpy(tmp_buf, data1->uabc, buf_size);
1559                                         qede->copy_len = qede->copy_len + 
1560                                             buf_size;
1561                                 } else {
1562                                         (void) memcpy(tmp_buf, 
1563                                             data1->uabc, qede->nvm_buf_size);
1564                                         qede->copy_len = 
1565                                             qede->copy_len + qede->nvm_buf_size;
1566                                 }
1567                                 tmp_buf = tmp_buf + buf_size;
1568                                 qede->nvm_buf = tmp_buf;
1569                                 //qede->copy_len = qede->copy_len + buf_size;
1570                                 cmn_err(CE_NOTE, 
1571                                     "buf_size from app = %x\n", copy_len);
1572                                 ret = 0;
1573                                 break;
1574                         }
1575                         (void) memcpy(tmp_buf, data1->uabc, copy_len);
1576                         tmp_buf = tmp_buf + copy_len;
1577                         bytes_to_copy = buf_size - copy_len;
1578                         mp1 = mp->b_cont;
1579                         mp1 = mp1->b_cont;
1580                         copy_len1 = copy_len;
1581                         
1582                         while (mp1) {
1583                                 copy_len = MBLKL(mp1);
1584                                 if (mp1->b_cont == NULL) {
1585                                         copy_len = MBLKL(mp1) - 4;
1586                                 }
1587                                 next_data = (qede_nvram_data_t *) mp1->b_rptr;
1588                                 if (copy_len > bytes_to_copy){
1589                                         (void) memcpy(tmp_buf, next_data->uabc,
1590                                             bytes_to_copy);
1591                                         qede->copy_len = qede->copy_len + 
1592                                             bytes_to_copy;
1593                                         ret = 0;
1594                                         break;
1595                                 }
1596                                 (void) memcpy(tmp_buf, next_data->uabc, 
1597                                     copy_len);
1598                                 qede->copy_len = qede->copy_len + copy_len;
1599                                 tmp_buf = tmp_buf + copy_len;
1600                                 copy_len = copy_len1 + copy_len;
1601                                 bytes_to_copy = bytes_to_copy - copy_len;
1602                                 mp1 = mp1->b_cont;
1603                         }
1604                         qede->nvm_buf = tmp_buf;
1605                         ret = 0;
1606                         break;
1607 
1608                 case STOP_NVM_WRITE:
1609                         //qede->nvm_buf = tmp_buf;
1610                         ret = 0;
1611                         break;
1612                 case READ_BUF:
1613                         tmp_buf = (uint8_t *)qede->nvm_buf_start;
1614                         for(i = 0; i < size ; i++){
1615                                 cmn_err(CE_NOTE, 
1616                                     "buff (%d) : %d\n", i, *tmp_buf);
1617                                 tmp_buf ++;
1618                         }
1619                         ret = 0;
1620                         break;
1621                 }
1622                 break;
1623         case QEDE_NVRAM_CMD_PUT_FILE_DATA:
1624                 tmp_buf = qede->nvm_buf_start;       
1625                 ret = ecore_mcp_nvm_write(edev, ECORE_PUT_FILE_DATA,
1626                           addr, tmp_buf, size);
1627                 kmem_free(qede->nvm_buf_start, size);
1628                 //OSAL_FREE(edev, tmp_buf);
1629                 cmn_err(CE_NOTE, "total size = %x, copied size = %x\n",
1630                     qede->nvm_buf_size, qede->copy_len);
1631                 tmp_buf = NULL;
1632                 qede->nvm_buf = NULL;
1633                 qede->nvm_buf_start = NULL;
1634                 ret = 0;
1635                 break;
1636 
1637         case QEDE_NVRAM_CMD_SET_SECURE_MODE:
1638                 ret = ecore_mcp_nvm_set_secure_mode(edev, addr);
1639                 break;
1640 
1641         case QEDE_NVRAM_CMD_DEL_FILE:
1642                 ret = ecore_mcp_nvm_del_file(edev, addr);
1643                 break;
1644 
1645         case QEDE_NVRAM_CMD_PUT_FILE_BEGIN:
1646                 ret = ecore_mcp_nvm_put_file_begin(edev, addr);
1647                 break;
1648 
1649         case QEDE_NVRAM_CMD_GET_NVRAM_RESP:
1650                 buf = kmem_zalloc(size, KM_SLEEP);
1651                 ret = ecore_mcp_nvm_resp(edev, buf);
1652                 (void)memcpy(data1->uabc, buf, size);
1653                 kmem_free(buf, size);
1654                 break;
1655 
1656         default:
1657                 cmn_err(CE_WARN, 
1658                     "wrong command in NVRAM read/write from application\n");
1659                 break;
1660         }
1661         return (DDI_SUCCESS);   
1662 }
1663 
1664 static int
1665 qede_get_func_info(qede_t *qede, void *data)
1666 {
1667         qede_link_output_t link_op;
1668         qede_func_info_t func_info;
1669         qede_ioctl_data_t *data1 = (qede_ioctl_data_t *)data;
1670         struct ecore_dev *edev = &qede->edev;
1671         struct ecore_hwfn *hwfn;
1672         struct ecore_mcp_link_params params;
1673         struct ecore_mcp_link_state link;
1674         
1675         hwfn = &edev->hwfns[0];
1676 
1677         if(hwfn == NULL){
1678                 cmn_err(CE_WARN, "(%s) : cannot acquire hwfn\n",
1679                     __func__);
1680                 return (DDI_FAILURE);
1681         }
1682         memcpy(&params, &hwfn->mcp_info->link_input, sizeof(params));
1683         memcpy(&link, &hwfn->mcp_info->link_output, sizeof(link));
1684 
1685         if(link.link_up) {
1686                 link_op.link_up = true;
1687         }
1688 
1689         link_op.supported_caps = SUPPORTED_FIBRE;
1690         if(params.speed.autoneg) {
1691                 link_op.supported_caps |= SUPPORTED_Autoneg;
1692         }
1693         
1694         if(params.pause.autoneg ||
1695             (params.pause.forced_rx && params.pause.forced_tx)) {
1696                 link_op.supported_caps |= SUPPORTED_Asym_Pause;
1697         }
1698 
1699         if (params.pause.autoneg || params.pause.forced_rx ||
1700              params.pause.forced_tx) {
1701                 link_op.supported_caps |= SUPPORTED_Pause;
1702         }
1703         
1704         if (params.speed.advertised_speeds &
1705             NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_1G) {
1706                 link_op.supported_caps |= SUPPORTED_1000baseT_Half |
1707                     SUPPORTED_1000baseT_Full;
1708         }
1709 
1710         if (params.speed.advertised_speeds &
1711             NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G) {
1712                 link_op.supported_caps |= SUPPORTED_10000baseKR_Full;
1713         }
1714         
1715         if (params.speed.advertised_speeds &
1716             NVM_CFG1_PORT_DRV_LINK_SPEED_40G) {
1717                 link_op.supported_caps |= SUPPORTED_40000baseLR4_Full;
1718         }
1719         
1720         link_op.advertised_caps = link_op.supported_caps;
1721 
1722         if(link.link_up) {
1723                 link_op.speed = link.speed;
1724         } else {
1725                 link_op.speed = 0;
1726         }
1727 
1728         link_op.duplex = DUPLEX_FULL;
1729         link_op.port = PORT_FIBRE;
1730         
1731         link_op.autoneg = params.speed.autoneg;
1732 
1733         /* Link partner capabilities */
1734         if (link.partner_adv_speed &
1735             ECORE_LINK_PARTNER_SPEED_1G_HD) {
1736                 link_op.lp_caps |= SUPPORTED_1000baseT_Half;
1737         }
1738         
1739         if (link.partner_adv_speed &
1740             ECORE_LINK_PARTNER_SPEED_1G_FD) {
1741                 link_op.lp_caps |= SUPPORTED_1000baseT_Full;
1742         }
1743         
1744         if (link.partner_adv_speed &
1745             ECORE_LINK_PARTNER_SPEED_10G) {
1746                 link_op.lp_caps |= SUPPORTED_10000baseKR_Full;
1747         }
1748         
1749         if (link.partner_adv_speed &
1750             ECORE_LINK_PARTNER_SPEED_20G) {
1751                 link_op.lp_caps |= SUPPORTED_20000baseKR2_Full;
1752         }
1753         
1754         if (link.partner_adv_speed &
1755             ECORE_LINK_PARTNER_SPEED_40G) {
1756                 link_op.lp_caps |= SUPPORTED_40000baseLR4_Full;
1757         }
1758         
1759         if (link.an_complete) {
1760                 link_op.lp_caps |= SUPPORTED_Autoneg;
1761         }
1762         
1763         if (link.partner_adv_pause) {
1764                 link_op.lp_caps |= SUPPORTED_Pause;
1765         }
1766         
1767         if (link.partner_adv_pause == ECORE_LINK_PARTNER_ASYMMETRIC_PAUSE ||
1768             link.partner_adv_pause == ECORE_LINK_PARTNER_BOTH_PAUSE) {
1769                 link_op.lp_caps |= SUPPORTED_Asym_Pause;
1770         }
1771 
1772         func_info.supported = link_op.supported_caps;
1773         func_info.advertising = link_op.advertised_caps;
1774         func_info.speed = link_op.speed;
1775         func_info.duplex = link_op.duplex;
1776         func_info.port = qede->pci_func & 0x1;
1777         func_info.autoneg = link_op.autoneg;    
1778         
1779         (void) memcpy(data1->uabc, &func_info, sizeof(qede_func_info_t));
1780         
1781         return (0);
1782 }
1783 
1784 static int 
1785 qede_do_ioctl(qede_t *qede, queue_t *q, mblk_t *mp)
1786 {
1787         qede_ioctl_data_t *up_data;
1788         qede_driver_info_t driver_info;
1789         struct ecore_dev *edev = &qede->edev;
1790         struct ecore_hwfn *hwfn;
1791         struct ecore_ptt *ptt = NULL;
1792         struct mcp_file_att attrib;
1793         uint32_t flash_size;
1794         uint32_t mcp_resp, mcp_param, txn_size;
1795         uint32_t cmd, size, ret = 0;
1796         uint64_t off;
1797         int * up_data1;
1798         void * ptr;
1799         mblk_t *mp1 = mp;
1800         char mac_addr[32];
1801         
1802         up_data = (qede_ioctl_data_t *)(mp->b_cont->b_rptr);
1803         
1804         cmd = up_data->cmd;
1805         off = up_data->off;
1806         size = up_data->size;
1807         
1808         switch (cmd) {
1809         case QEDE_DRV_INFO:
1810                 hwfn = &edev->hwfns[0]; 
1811                 ptt = ecore_ptt_acquire(hwfn);
1812         
1813                 snprintf(driver_info.drv_name, MAX_QEDE_NAME_LEN, "%s", "qede");
1814                 snprintf(driver_info.drv_version, QEDE_STR_SIZE, 
1815                     "v:%s", qede->version);
1816                 snprintf(driver_info.mfw_version, QEDE_STR_SIZE, 
1817                     "%s", qede->versionMFW);
1818                 snprintf(driver_info.stormfw_version, QEDE_STR_SIZE, 
1819                     "%s", qede->versionFW);
1820                 snprintf(driver_info.bus_info, QEDE_STR_SIZE, 
1821                     "%s", qede->bus_dev_func);
1822 
1823 
1824                 /* 
1825                  * calling ecore_mcp_nvm_rd_cmd to find the flash length, i
1826                  * 0x08 is equivalent of NVM_TYPE_MFW_TRACE1
1827                  */
1828                 ecore_mcp_get_flash_size(hwfn, ptt, &flash_size);
1829                 driver_info.eeprom_dump_len = flash_size;       
1830                 (void) memcpy(up_data->uabc, &driver_info, 
1831                     sizeof (qede_driver_info_t));
1832                 up_data->size = sizeof (qede_driver_info_t);
1833 
1834                 ecore_ptt_release(hwfn, ptt);
1835                 break;
1836 
1837         case QEDE_RD_PCICFG:
1838                 ret = qede_ioctl_pcicfg_rd(qede, off, up_data->uabc, size);
1839                 break;
1840 
1841         case QEDE_WR_PCICFG:
1842                 ret = qede_ioctl_pcicfg_wr(qede, off, up_data, size);
1843                 break;
1844         
1845         case QEDE_RW_REG:
1846                 ret = qede_ioctl_rd_wr_reg(qede, (void *)up_data);
1847                 break;
1848 
1849         case QEDE_RW_NVRAM:
1850                 ret = qede_ioctl_rd_wr_nvram(qede, mp1);
1851                 break;
1852 
1853         case QEDE_FUNC_INFO:
1854                 ret = qede_get_func_info(qede, (void *)up_data);
1855                 break;
1856 
1857         case QEDE_MAC_ADDR:
1858                 snprintf(mac_addr, sizeof(mac_addr),
1859                         "%02x:%02x:%02x:%02x:%02x:%02x", 
1860                         qede->ether_addr[0], qede->ether_addr[1],
1861                         qede->ether_addr[2], qede->ether_addr[3],
1862                         qede->ether_addr[4], qede->ether_addr[5]);
1863                 (void) memcpy(up_data->uabc, &mac_addr, sizeof(mac_addr));
1864                 break;
1865 
1866         }
1867         //if (cmd == QEDE_RW_NVRAM) {
1868         //      miocack (q, mp, (sizeof(qede_ioctl_data_t)), 0);
1869         //      return IOC_REPLY;
1870         //}
1871         miocack (q, mp, (sizeof(qede_ioctl_data_t)), ret);
1872         //miocack (q, mp, 0, ret);
1873         return (IOC_REPLY);
1874 }
1875 
1876 static void
1877 qede_ioctl(qede_t *qede, int cmd, queue_t *q, mblk_t *mp)
1878 {
1879         void *ptr;
1880 
1881         switch(cmd) {
1882         case QEDE_CMD:
1883                 (void) qede_do_ioctl(qede, q, mp);
1884                 break;
1885         default :
1886                 cmn_err(CE_WARN, "qede ioctl command %x not supported\n", cmd);
1887                 break;
1888         }
1889         return;
1890 }
1891 enum ioc_reply
1892 qede_loopback_ioctl(qede_t *qede, queue_t *wq, mblk_t *mp,
1893     struct iocblk *iocp)
1894 {
1895         lb_info_sz_t *lb_info_size;
1896         lb_property_t *lb_prop;
1897         uint32_t *lb_mode;
1898         int cmd;
1899 
1900         /*
1901          * Validate format of ioctl
1902          */
1903         if(mp->b_cont == NULL) {
1904                 return IOC_INVAL;
1905         }
1906         
1907         cmd = iocp->ioc_cmd;
1908 
1909         switch(cmd) {
1910         default:
1911                 qede_print("!%s(%d): unknown ioctl command %x\n",
1912                     __func__, qede->instance, cmd);
1913                 return IOC_INVAL;
1914         case LB_GET_INFO_SIZE:
1915                 if (iocp->ioc_count != sizeof(lb_info_sz_t)) {
1916                         qede_info(qede, "error: ioc_count %d, sizeof %d",
1917                             iocp->ioc_count,  sizeof(lb_info_sz_t));
1918                         return IOC_INVAL;
1919                 }
1920                 lb_info_size = (void *)mp->b_cont->b_rptr;
1921                 *lb_info_size = sizeof(loopmodes);
1922                 return IOC_REPLY;
1923         case LB_GET_INFO:
1924                 if (iocp->ioc_count != sizeof (loopmodes)) {
1925                         qede_info(qede, "error: iocp->ioc_count %d, sizepof %d",
1926                             iocp->ioc_count,  sizeof (loopmodes));
1927                         return (IOC_INVAL);
1928                 }
1929                 lb_prop = (void *)mp->b_cont->b_rptr;
1930                 bcopy(loopmodes, lb_prop, sizeof (loopmodes));
1931                 return IOC_REPLY;
1932         case LB_GET_MODE:
1933                 if (iocp->ioc_count != sizeof (uint32_t)) {
1934                         qede_info(qede, "iocp->ioc_count %d, sizeof : %d\n",
1935                             iocp->ioc_count, sizeof (uint32_t));
1936                         return (IOC_INVAL);
1937                 }
1938                 lb_mode = (void *)mp->b_cont->b_rptr;
1939                 *lb_mode = qede->loop_back_mode;
1940                 return IOC_REPLY;
1941         case LB_SET_MODE:
1942                 if (iocp->ioc_count != sizeof (uint32_t)) {
1943                         qede_info(qede, "iocp->ioc_count %d, sizeof : %d\n",
1944                             iocp->ioc_count, sizeof (uint32_t));
1945                         return (IOC_INVAL);
1946                 }
1947                 lb_mode = (void *)mp->b_cont->b_rptr;
1948                 return (qede_set_loopback_mode(qede,*lb_mode));
1949         }
1950 }
1951 
1952 static void
1953 qede_mac_ioctl(void *    arg,
1954                queue_t * wq,
1955                mblk_t *  mp)
1956 {
1957         int err, cmd;
1958         qede_t * qede = (qede_t *)arg;
1959         struct iocblk *iocp = (struct iocblk *) (uintptr_t)mp->b_rptr;
1960         enum ioc_reply status = IOC_DONE;
1961         boolean_t need_privilege = B_TRUE;
1962 
1963         iocp->ioc_error = 0;
1964         cmd = iocp->ioc_cmd;
1965 
1966         mutex_enter(&qede->drv_lock);
1967         if ((qede->qede_state == QEDE_STATE_SUSPENDING) ||
1968            (qede->qede_state == QEDE_STATE_SUSPENDED)) {
1969                 mutex_exit(&qede->drv_lock);
1970                 miocnak(wq, mp, 0, EINVAL);
1971                 return;
1972         }
1973 
1974         switch(cmd) {
1975                 case QEDE_CMD:
1976                         break;
1977                 case LB_GET_INFO_SIZE:
1978                 case LB_GET_INFO:
1979                 case LB_GET_MODE:
1980                         need_privilege = B_FALSE;
1981                 case LB_SET_MODE:
1982                         break;
1983                 default:
1984                         qede_print("!%s(%d) unknown ioctl command %x\n",
1985                             __func__, qede->instance, cmd);
1986                         miocnak(wq, mp, 0, EINVAL);
1987                         mutex_exit(&qede->drv_lock);
1988                         return;
1989         }
1990         
1991         if(need_privilege) {
1992                 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
1993                 if(err){
1994                         qede_info(qede, "secpolicy() failed");
1995                         miocnak(wq, mp, 0, err);
1996                         mutex_exit(&qede->drv_lock);
1997                         return;
1998                 }
1999         }
2000 
2001         switch (cmd) {
2002                 default:
2003                         qede_print("!%s(%d) : unknown ioctl command %x\n", 
2004                             __func__, qede->instance, cmd);
2005                         status = IOC_INVAL;
2006                         mutex_exit(&qede->drv_lock);
2007                         return;
2008                 case LB_GET_INFO_SIZE:
2009                 case LB_GET_INFO:
2010                 case LB_GET_MODE:
2011                 case LB_SET_MODE:
2012                         status = qede_loopback_ioctl(qede, wq, mp, iocp);
2013                         break;
2014                 case QEDE_CMD:
2015                         qede_ioctl(qede, cmd, wq, mp);
2016                         status = IOC_DONE; 
2017                         break;
2018         }
2019 
2020         switch(status){
2021                 default:
2022                         qede_print("!%s(%d) : invalid status from ioctl",
2023                             __func__,qede->instance);
2024                         break;
2025                 case IOC_DONE:
2026                         /*
2027                          * OK, Reply already sent
2028                          */
2029                         
2030                         break;
2031                 case IOC_REPLY:
2032                         mp->b_datap->db_type = iocp->ioc_error == 0 ?
2033                                 M_IOCACK : M_IOCNAK;
2034                         qreply(wq, mp);
2035                         break;
2036                 case IOC_INVAL:
2037                         mutex_exit(&qede->drv_lock);
2038                         //miocack(wq, mp, 0, 0);
2039                         miocnak(wq, mp, 0, iocp->ioc_error == 0 ?
2040                             EINVAL : iocp->ioc_error); 
2041                         return; 
2042         }
2043         mutex_exit(&qede->drv_lock);
2044 }
2045 
2046 extern ddi_dma_attr_t qede_buf2k_dma_attr_txbuf;
2047 extern ddi_dma_attr_t qede_dma_attr_rxbuf;
2048 extern ddi_dma_attr_t qede_dma_attr_desc;
2049 
2050 static boolean_t
2051 qede_mac_get_capability(void *arg,
2052         mac_capab_t capability,
2053         void *      cap_data)
2054 {
2055         qede_t * qede = (qede_t *)arg;
2056         uint32_t *txflags = cap_data;
2057         boolean_t ret = B_FALSE;
2058 
2059         switch (capability) {
2060         case MAC_CAPAB_HCKSUM: {
2061                 u32 *tx_flags = cap_data;
2062                 /*
2063                  * Check if checksum is enabled on
2064                  * tx and advertise the cksum capab
2065                  * to mac layer accordingly. On Rx
2066                  * side checksummed packets are
2067                  * reveiced anyway
2068                  */
2069                 qede_info(qede, "%s tx checksum offload",
2070                     (qede->checksum == DEFAULT_CKSUM_OFFLOAD) ?
2071                     "Enabling":
2072                     "Disabling");
2073 
2074                 if (qede->checksum != DEFAULT_CKSUM_OFFLOAD) {
2075                         ret = B_FALSE;
2076                         break;
2077                 }
2078                 /*
2079                  * Hardware does not support ICMPv6 checksumming. Right now the
2080                  * GLDv3 doesn't provide us a way to specify that we don't
2081                  * support that. As such, we cannot indicate
2082                  * HCKSUM_INET_FULL_V6.
2083                  */
2084 
2085                 *tx_flags = HCKSUM_INET_FULL_V4 |
2086                     HCKSUM_IPHDRCKSUM;
2087                 ret = B_TRUE;
2088                 break;
2089         }
2090         case MAC_CAPAB_LSO: {
2091                 mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
2092 
2093                 qede_info(qede, "%s large segmentation offload",
2094                     qede->lso_enable ? "Enabling": "Disabling");
2095                 if (qede->lso_enable) {
2096                         cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
2097                         cap_lso->lso_basic_tcp_ipv4.lso_max = QEDE_LSO_MAXLEN;
2098                         ret = B_TRUE;
2099                 }
2100                 break;
2101         }
2102         case MAC_CAPAB_RINGS: {
2103 #ifndef NO_CROSSBOW
2104                 mac_capab_rings_t *cap_rings = cap_data;
2105 #ifndef ILLUMOS
2106                 cap_rings->mr_version = MAC_RINGS_VERSION_1;
2107 #endif
2108 
2109                 switch (cap_rings->mr_type) {
2110                 case MAC_RING_TYPE_RX:
2111 #ifndef ILLUMOS
2112                         cap_rings->mr_flags = MAC_RINGS_VLAN_TRANSPARENT;
2113 #endif
2114                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
2115                         //cap_rings->mr_rnum = 1; /* qede variable */
2116                         cap_rings->mr_rnum = qede->num_fp; /* qede variable */
2117                         cap_rings->mr_gnum = 1;
2118                         cap_rings->mr_rget = qede_fill_ring;
2119                         cap_rings->mr_gget = qede_fill_group;
2120                         cap_rings->mr_gaddring = NULL;
2121                         cap_rings->mr_gremring = NULL;
2122 #ifndef ILLUMOS
2123                         cap_rings->mr_ggetringtc = NULL;
2124 #endif
2125                         ret = B_TRUE;
2126                         break;
2127                 case MAC_RING_TYPE_TX:
2128 #ifndef ILLUMOS
2129                         cap_rings->mr_flags = MAC_RINGS_VLAN_TRANSPARENT;
2130 #endif
2131                         cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
2132                         //cap_rings->mr_rnum = 1;
2133                         cap_rings->mr_rnum = qede->num_fp;
2134                         cap_rings->mr_gnum = 0;
2135                         cap_rings->mr_rget = qede_fill_ring;
2136                         cap_rings->mr_gget = qede_fill_group;
2137                         cap_rings->mr_gaddring = NULL;
2138                         cap_rings->mr_gremring = NULL;
2139 #ifndef ILLUMOS
2140                         cap_rings->mr_ggetringtc = NULL;
2141 #endif
2142                         ret = B_TRUE;
2143                         break;
2144                 default:
2145                         ret = B_FALSE;
2146                         break;
2147                 }
2148 #endif
2149                 break; /* CASE MAC_CAPAB_RINGS */
2150         }
2151 #ifdef ILLUMOS
2152         case MAC_CAPAB_TRANSCEIVER: {
2153                 mac_capab_transceiver_t *mct = cap_data;
2154 
2155                 mct->mct_flags = 0;
2156                 mct->mct_ntransceivers = qede->edev.num_hwfns;
2157                 mct->mct_info = qede_transceiver_info;
2158                 mct->mct_read = qede_transceiver_read;
2159 
2160                 ret = B_TRUE;
2161                 break;
2162         }
2163 #endif
2164         default:
2165                 break;
2166         }
2167 
2168     return (ret);
2169 }
2170 
2171 int
2172 qede_configure_link(qede_t *qede, bool op);
2173 
2174 static int
2175 qede_mac_set_property(void *        arg,
2176                               const char *  pr_name,
2177                               mac_prop_id_t pr_num,
2178                               uint_t        pr_valsize,
2179                               const void *  pr_val)
2180 {
2181         qede_t * qede = (qede_t *)arg;
2182         struct ecore_mcp_link_params *link_params;
2183         struct ecore_dev *edev = &qede->edev;
2184         struct ecore_hwfn *hwfn;
2185         int ret_val = 0, i;
2186         uint32_t option;
2187 
2188         mutex_enter(&qede->gld_lock);
2189         switch (pr_num)
2190         {
2191         case MAC_PROP_MTU:
2192                 bcopy(pr_val, &option, sizeof (option));
2193 
2194                 if(option == qede->mtu) {
2195                         ret_val = 0;
2196                         break;
2197                 }
2198                 if ((option != DEFAULT_JUMBO_MTU) &&
2199                    (option != DEFAULT_MTU)) {
2200                         ret_val = EINVAL;
2201                         break;
2202                 }
2203                 if(qede->qede_state == QEDE_STATE_STARTED) {
2204                         ret_val = EBUSY;
2205                         break;
2206                 }
2207 
2208                 ret_val = mac_maxsdu_update(qede->mac_handle, qede->mtu);
2209                 if (ret_val == 0) {
2210 
2211                         qede->mtu = option;
2212                         if (option == DEFAULT_JUMBO_MTU) {
2213                                 qede->jumbo_enable = B_TRUE;
2214                         } else {
2215                                 qede->jumbo_enable = B_FALSE;
2216                         }
2217 
2218                         hwfn = ECORE_LEADING_HWFN(edev);
2219                         hwfn->hw_info.mtu = qede->mtu;
2220                         ret_val = ecore_mcp_ov_update_mtu(hwfn, 
2221                             hwfn->p_main_ptt,
2222                             hwfn->hw_info.mtu);
2223                         if (ret_val != ECORE_SUCCESS) {
2224                                 qede_print("!%s(%d): MTU change %d option %d"
2225                                     "FAILED",
2226                                     __func__,qede->instance, qede->mtu, option);
2227                                 break;
2228                         }
2229                         qede_print("!%s(%d): MTU changed  %d MTU option"
2230                             " %d hwfn %d",
2231                             __func__,qede->instance, qede->mtu, 
2232                             option, hwfn->hw_info.mtu);
2233                 }
2234                 break;
2235 
2236         case MAC_PROP_EN_10GFDX_CAP:
2237                 hwfn = &edev->hwfns[0];
2238                 link_params = ecore_mcp_get_link_params(hwfn);
2239                 if (*(uint8_t *) pr_val) {
2240                         link_params->speed.autoneg = 0;
2241                         link_params->speed.forced_speed = 10000;
2242                         link_params->speed.advertised_speeds = 
2243                             NVM_CFG1_PORT_DRV_SPEED_CAPABILITY_MASK_10G;
2244                         qede->forced_speed_10G = *(uint8_t *)pr_val;
2245                 }
2246                 else {
2247                         memcpy(link_params, 
2248                             &qede->link_input_params.default_link_params, 
2249                             sizeof (struct ecore_mcp_link_params));
2250                         qede->forced_speed_10G = *(uint8_t *)pr_val;
2251                 }
2252                 if (qede->qede_state == QEDE_STATE_STARTED) {
2253                         qede_configure_link(qede,1);
2254                 } else {
2255                         mutex_exit(&qede->gld_lock);
2256                         return (0);
2257                 }
2258                 break;
2259         default:
2260                 ret_val = ENOTSUP;
2261                 break;
2262         }
2263         mutex_exit(&qede->gld_lock);
2264         return (ret_val); 
2265 }
2266 
2267 static void
2268 qede_mac_stop(void *arg)
2269 {
2270     qede_t *qede = (qede_t *)arg;
2271         int status;
2272 
2273         qede_print("!%s(%d): called",
2274             __func__,qede->instance);
2275         mutex_enter(&qede->drv_lock);
2276         status = qede_stop(qede);
2277         if (status != DDI_SUCCESS) {
2278                 qede_print("!%s(%d): qede_stop "
2279                     "FAILED",
2280                 __func__,qede->instance);
2281         }
2282 
2283         mac_link_update(qede->mac_handle, LINK_STATE_UNKNOWN);
2284         mutex_exit(&qede->drv_lock);
2285 }
2286 
2287 static int
2288 qede_mac_start(void *arg)
2289 {
2290         qede_t *qede = (qede_t *)arg;
2291         int status;
2292 
2293         qede_print("!%s(%d): called", __func__,qede->instance);
2294         if (!mutex_tryenter(&qede->drv_lock)) {
2295                 return (EAGAIN);
2296         }
2297 
2298         if (qede->qede_state == QEDE_STATE_SUSPENDED) {
2299                 mutex_exit(&qede->drv_lock);
2300                 return (ECANCELED);
2301         }
2302 
2303         status = qede_start(qede);
2304         if (status != DDI_SUCCESS) {
2305                 mutex_exit(&qede->drv_lock);
2306                 return (EIO);
2307         }
2308 
2309         mutex_exit(&qede->drv_lock);
2310 
2311 #ifdef  DBLK_DMA_PREMAP
2312         qede->pm_handle = mac_pmh_tx_get(qede->mac_handle);
2313 #endif
2314         return (0);
2315 }
2316 
2317 static int
2318 qede_mac_get_property(void *arg,
2319     const char *pr_name,
2320     mac_prop_id_t pr_num,
2321     uint_t        pr_valsize,
2322     void *pr_val)
2323 {
2324         qede_t *qede = (qede_t *)arg;
2325         struct ecore_dev *edev = &qede->edev;
2326         link_state_t    link_state;
2327         link_duplex_t   link_duplex;
2328         uint64_t        link_speed;
2329         link_flowctrl_t link_flowctrl;
2330         struct qede_link_cfg link_cfg;
2331         qede_link_cfg_t  *hw_cfg  = &qede->hwinit;
2332         int ret_val = 0;
2333 
2334         memset(&link_cfg, 0, sizeof (struct qede_link_cfg));
2335         qede_get_link_info(&edev->hwfns[0], &link_cfg);
2336 
2337         
2338 
2339         switch (pr_num)
2340         {
2341         case MAC_PROP_MTU:
2342 
2343                 ASSERT(pr_valsize >= sizeof(uint32_t));
2344                 bcopy(&qede->mtu, pr_val, sizeof(uint32_t));
2345                 break;
2346 
2347         case MAC_PROP_DUPLEX:
2348 
2349                 ASSERT(pr_valsize >= sizeof(link_duplex_t));
2350                 link_duplex = (qede->props.link_duplex) ?
2351                                           LINK_DUPLEX_FULL : LINK_DUPLEX_HALF;
2352                 bcopy(&link_duplex, pr_val, sizeof(link_duplex_t));
2353                 break;
2354 
2355         case MAC_PROP_SPEED:
2356 
2357                 ASSERT(pr_valsize >= sizeof(link_speed));
2358 
2359                 link_speed = (qede->props.link_speed * 1000000ULL);
2360                 bcopy(&link_speed, pr_val, sizeof(link_speed));
2361                 break;
2362 
2363         case MAC_PROP_STATUS:
2364 
2365                 ASSERT(pr_valsize >= sizeof(link_state_t));
2366 
2367                 link_state = (qede->params.link_state) ?
2368                                         LINK_STATE_UP : LINK_STATE_DOWN;
2369                 bcopy(&link_state, pr_val, sizeof(link_state_t));
2370                 qede_info(qede, "mac_prop_status %d\n", link_state);
2371                 break;  
2372 
2373         case MAC_PROP_AUTONEG:
2374 
2375                 *(uint8_t *)pr_val = link_cfg.autoneg;
2376                 break;
2377 
2378         case MAC_PROP_FLOWCTRL:
2379 
2380                 ASSERT(pr_valsize >= sizeof(link_flowctrl_t));
2381 
2382 /*
2383  * illumos does not have the notion of LINK_FLOWCTRL_AUTO at this time.
2384  */
2385 #ifndef ILLUMOS
2386                 if (link_cfg.pause_cfg & QEDE_LINK_PAUSE_AUTONEG_ENABLE)  {
2387                     link_flowctrl = LINK_FLOWCTRL_AUTO;
2388                 }
2389 #endif
2390 
2391                 if (!(link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) && 
2392                     !(link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2393                     link_flowctrl = LINK_FLOWCTRL_NONE;
2394                 }
2395                 if ((link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) && 
2396                     !(link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2397                     link_flowctrl = LINK_FLOWCTRL_RX;
2398                 }
2399                 if (!(link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) && 
2400                     (link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2401                     link_flowctrl = LINK_FLOWCTRL_TX;
2402                 }
2403                 if ((link_cfg.pause_cfg & QEDE_LINK_PAUSE_RX_ENABLE) && 
2404                     (link_cfg.pause_cfg & QEDE_LINK_PAUSE_TX_ENABLE)) {
2405                     link_flowctrl = LINK_FLOWCTRL_BI;
2406                 }
2407 
2408                 bcopy(&link_flowctrl, pr_val, sizeof (link_flowctrl_t));
2409                 break;
2410 
2411         case MAC_PROP_ADV_10GFDX_CAP:
2412                 *(uint8_t *)pr_val = link_cfg.adv_capab.param_10000fdx;
2413                 break;
2414 
2415         case MAC_PROP_EN_10GFDX_CAP:
2416                 *(uint8_t *)pr_val = qede->forced_speed_10G;
2417                 break;
2418 
2419         case MAC_PROP_PRIVATE:
2420         default:
2421                 return (ENOTSUP);
2422 
2423         }
2424                 
2425         return (0);
2426 }
2427 
2428 static void
2429 qede_mac_property_info(void *arg,
2430     const char *pr_name,
2431     mac_prop_id_t  pr_num, 
2432     mac_prop_info_handle_t prh)
2433 {
2434         qede_t *qede = (qede_t *)arg;
2435         qede_link_props_t *def_cfg = &qede_def_link_props;
2436         link_flowctrl_t link_flowctrl;
2437 
2438 
2439         switch (pr_num)
2440         {
2441 
2442         case MAC_PROP_STATUS:
2443         case MAC_PROP_SPEED:
2444         case MAC_PROP_DUPLEX:
2445                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2446                 break;
2447 
2448         case MAC_PROP_MTU:
2449 
2450                 mac_prop_info_set_range_uint32(prh,
2451                     MIN_MTU,
2452                     MAX_MTU);
2453                 break;
2454 
2455         case MAC_PROP_AUTONEG:
2456 
2457                 mac_prop_info_set_default_uint8(prh, def_cfg->autoneg);
2458                 break;
2459  
2460         case MAC_PROP_FLOWCTRL:
2461 
2462                 if (!def_cfg->pause) {
2463                         link_flowctrl = LINK_FLOWCTRL_NONE;
2464                 } else {
2465                         link_flowctrl = LINK_FLOWCTRL_BI;
2466                 }
2467 
2468                 mac_prop_info_set_default_link_flowctrl(prh, link_flowctrl);
2469                 break;
2470 
2471         case MAC_PROP_EN_10GFDX_CAP:
2472                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
2473                 break;
2474 
2475         case MAC_PROP_ADV_10GFDX_CAP:
2476                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2477                 break;
2478 
2479         default:
2480                 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
2481                 break;
2482 
2483     }
2484 }
2485 
2486 static mac_callbacks_t qede_callbacks =
2487 {
2488     (
2489       MC_IOCTL
2490 /*    | MC_RESOURCES */
2491     | MC_SETPROP
2492     | MC_GETPROP
2493     | MC_PROPINFO
2494     | MC_GETCAPAB
2495     ),
2496     qede_mac_stats,
2497     qede_mac_start,
2498     qede_mac_stop,
2499     qede_mac_promiscuous,
2500     qede_mac_multicast,
2501     NULL,
2502 #ifndef NO_CROSSBOW
2503     NULL,
2504 #else
2505     qede_mac_tx,
2506 #endif
2507     NULL,       /* qede_mac_resources, */
2508     qede_mac_ioctl,
2509     qede_mac_get_capability,
2510     NULL,
2511     NULL,
2512     qede_mac_set_property,
2513     qede_mac_get_property,
2514 #ifdef MC_PROPINFO
2515     qede_mac_property_info
2516 #endif
2517 };
2518 
2519 boolean_t
2520 qede_gld_init(qede_t *qede)
2521 {
2522         int status, ret;
2523         mac_register_t *macp;
2524 
2525         macp = mac_alloc(MAC_VERSION);
2526         if (macp == NULL) {
2527                 cmn_err(CE_NOTE, "%s: mac_alloc() failed\n", __func__);
2528                 return (B_FALSE);
2529         }
2530 
2531         macp->m_driver = qede;
2532         macp->m_dip = qede->dip;
2533         macp->m_instance = qede->instance;
2534         macp->m_priv_props = NULL;
2535         macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
2536         macp->m_src_addr = qede->ether_addr;
2537         macp->m_callbacks = &qede_callbacks;
2538         macp->m_min_sdu = 0;
2539         macp->m_max_sdu = qede->mtu;
2540         macp->m_margin = VLAN_TAGSZ;
2541 #ifdef  ILLUMOS
2542         macp->m_v12n = MAC_VIRT_LEVEL1;
2543 #endif
2544 
2545         status = mac_register(macp, &qede->mac_handle);
2546         if (status != 0) {
2547                 cmn_err(CE_NOTE, "%s: mac_register() failed\n", __func__);
2548         }
2549 
2550         mac_free(macp);
2551         if (status == 0) {
2552                 return (B_TRUE);
2553         }
2554         return (B_FALSE);
2555 }
2556 
2557 boolean_t qede_gld_fini(qede_t * qede)
2558 {
2559     return (B_TRUE);
2560 }
2561 
2562 
2563 void qede_link_update(qede_t * qede,
2564                  link_state_t  state)
2565 {
2566     mac_link_update(qede->mac_handle, state);
2567 }
2568