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