1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2010 QLogic Corporation. All rights reserved. 24 */ 25 26 #include <sys/note.h> 27 #include <qlge.h> 28 #include <sys/strsubr.h> 29 #include <netinet/in.h> 30 #include <netinet/ip.h> 31 #include <netinet/ip6.h> 32 #include <inet/ip.h> 33 34 /* 35 * GLDv3 functions prototypes 36 */ 37 static int ql_m_getstat(void *, uint_t, uint64_t *); 38 static int ql_m_start(void *); 39 static void ql_m_stop(void *); 40 static int ql_m_setpromiscuous(void *, boolean_t); 41 static int ql_m_multicst(void *, boolean_t, const uint8_t *); 42 static int ql_m_unicst(void *, const uint8_t *); 43 static mblk_t *ql_m_tx(void *, mblk_t *); 44 static void ql_m_ioctl(void *, queue_t *, mblk_t *); 45 static boolean_t ql_m_getcapab(void *, mac_capab_t, void *); 46 47 static int ql_m_setprop(void *, const char *, mac_prop_id_t, uint_t, 48 const void *); 49 static int ql_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *); 50 static void ql_m_propinfo(void *, const char *, mac_prop_id_t, 51 mac_prop_info_handle_t); 52 53 #define QL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | \ 54 MC_GETPROP | MC_PROPINFO) 55 static mac_callbacks_t ql_m_callbacks = { 56 QL_M_CALLBACK_FLAGS, 57 ql_m_getstat, 58 ql_m_start, 59 ql_m_stop, 60 ql_m_setpromiscuous, 61 ql_m_multicst, 62 NULL, 63 NULL, 64 NULL, 65 ql_m_ioctl, 66 ql_m_getcapab, 67 NULL, 68 NULL, 69 ql_m_setprop, 70 ql_m_getprop, 71 ql_m_propinfo 72 }; 73 74 char *qlge_priv_prop[] = { 75 "_adv_pause_mode", 76 "_fm_enable", 77 NULL 78 }; 79 80 /* 81 * This function starts the driver 82 */ 83 static int 84 ql_m_start(void *arg) 85 { 86 qlge_t *qlge = (qlge_t *)arg; 87 88 /* 89 * reset chip, re-initialize everything but do not 90 * re-allocate memory 91 */ 92 mutex_enter(&qlge->gen_mutex); 93 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 94 mutex_exit(&qlge->gen_mutex); 95 return (ECANCELED); 96 } 97 mutex_enter(&qlge->hw_mutex); 98 qlge->mac_flags = QL_MAC_INIT; 99 /* 100 * Write default ethernet address to chip register Mac 101 * Address slot 0 and Enable Primary Mac Function. 102 */ 103 (void) ql_unicst_set(qlge, 104 (uint8_t *)qlge->unicst_addr[0].addr.ether_addr_octet, 0); 105 qlge->stats.rpackets = 0; 106 qlge->stats.rbytes = 0; 107 qlge->stats.opackets = 0; 108 qlge->stats.obytes = 0; 109 mutex_exit(&qlge->hw_mutex); 110 111 (void) ql_do_start(qlge); 112 mutex_exit(&qlge->gen_mutex); 113 114 mutex_enter(&qlge->mbx_mutex); 115 (void) ql_get_firmware_version(qlge, NULL); 116 mutex_exit(&qlge->mbx_mutex); 117 118 return (0); 119 } 120 121 /* 122 * This function stops the driver 123 */ 124 static void 125 ql_m_stop(void *arg) 126 { 127 qlge_t *qlge = (qlge_t *)arg; 128 129 mutex_enter(&qlge->gen_mutex); 130 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 131 mutex_exit(&qlge->gen_mutex); 132 return; 133 } 134 (void) ql_do_stop(qlge); 135 mutex_exit(&qlge->gen_mutex); 136 qlge->mac_flags = QL_MAC_STOPPED; 137 } 138 139 /* 140 * Add or remove a multicast address 141 */ 142 static int 143 ql_m_multicst(void *arg, boolean_t add, const uint8_t *ep) 144 { 145 qlge_t *qlge = (qlge_t *)arg; 146 int ret = DDI_SUCCESS; 147 148 mutex_enter(&qlge->gen_mutex); 149 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 150 mutex_exit(&qlge->gen_mutex); 151 return (ECANCELED); 152 } 153 154 if (qlge->mac_flags == QL_MAC_DETACH) { 155 mutex_exit(&qlge->gen_mutex); 156 return (ECANCELED); 157 } 158 if (add) { 159 QL_DUMP(DBG_GLD, "add to multicast list:\n", 160 (uint8_t *)ep, 8, ETHERADDRL); 161 ret = ql_add_to_multicast_list(qlge, (uint8_t *)ep); 162 } else { 163 QL_DUMP(DBG_GLD, "remove from multicast list:\n", 164 (uint8_t *)ep, 8, ETHERADDRL); 165 ret = ql_remove_from_multicast_list(qlge, (uint8_t *)ep); 166 } 167 mutex_exit(&qlge->gen_mutex); 168 169 if (ret != DDI_SUCCESS) { 170 ret = EIO; 171 if (qlge->fm_enable) { 172 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED); 173 } 174 } else { 175 ret = 0; 176 } 177 return (ret); 178 } 179 180 /* 181 * Enable or disable promiscuous mode 182 */ 183 static int 184 ql_m_setpromiscuous(void* arg, boolean_t on) 185 { 186 qlge_t *qlge = (qlge_t *)arg; 187 int mode; 188 189 mutex_enter(&qlge->gen_mutex); 190 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 191 mutex_exit(&qlge->gen_mutex); 192 return (ECANCELED); 193 } 194 195 /* enable reception of all packets on the medium, */ 196 if (on) { 197 mode = 1; 198 QL_PRINT(DBG_GLD, ("%s(%d) enable promiscuous mode\n", 199 __func__, qlge->instance)); 200 } else { 201 mode = 0; 202 QL_PRINT(DBG_GLD, ("%s(%d) disable promiscuous mode\n", 203 __func__, qlge->instance)); 204 } 205 206 mutex_enter(&qlge->hw_mutex); 207 ql_set_promiscuous(qlge, mode); 208 mutex_exit(&qlge->hw_mutex); 209 mutex_exit(&qlge->gen_mutex); 210 return (DDI_SUCCESS); 211 } 212 213 214 static int 215 ql_m_getstat(void *arg, uint_t stat, uint64_t *valp) 216 { 217 qlge_t *qlge = (qlge_t *)arg; 218 struct ql_stats *cur_stats; 219 uint64_t val = 0; 220 int i; 221 uint32_t val32; 222 struct rx_ring *rx_ring; 223 struct tx_ring *tx_ring; 224 225 ASSERT(qlge != NULL); 226 mutex_enter(&qlge->gen_mutex); 227 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 228 mutex_exit(&qlge->gen_mutex); 229 return (ECANCELED); 230 } 231 232 cur_stats = &qlge->stats; 233 /* these stats are maintained in software */ 234 switch (stat) { 235 236 case MAC_STAT_IFSPEED /* 1000 */ : 237 if (CFG_IST(qlge, CFG_CHIP_8100) != 0) { 238 qlge->speed = SPEED_10G; 239 } 240 val = qlge->speed * 1000000ull; 241 break; 242 243 case MAC_STAT_MULTIRCV: 244 val = cur_stats->multircv; 245 break; 246 247 case MAC_STAT_BRDCSTRCV: 248 val = cur_stats->brdcstrcv; 249 break; 250 251 case MAC_STAT_MULTIXMT: 252 cur_stats->multixmt = 0; 253 for (i = 0; i < qlge->tx_ring_count; i++) { 254 tx_ring = &qlge->tx_ring[i]; 255 cur_stats->multixmt += tx_ring->multixmt; 256 } 257 val = cur_stats->multixmt; 258 break; 259 260 case MAC_STAT_BRDCSTXMT: 261 cur_stats->brdcstxmt = 0; 262 for (i = 0; i < qlge->tx_ring_count; i++) { 263 tx_ring = &qlge->tx_ring[i]; 264 cur_stats->brdcstxmt += tx_ring->brdcstxmt; 265 } 266 val = cur_stats->brdcstxmt; 267 break; 268 269 case MAC_STAT_NORCVBUF: 270 val = cur_stats->norcvbuf; 271 break; 272 273 case MAC_STAT_IERRORS: 274 val = cur_stats->errrcv; 275 break; 276 277 case MAC_STAT_OBYTES: 278 cur_stats->obytes = 0; 279 for (i = 0; i < qlge->tx_ring_count; i++) { 280 tx_ring = &qlge->tx_ring[i]; 281 cur_stats->obytes += tx_ring->obytes; 282 } 283 val = cur_stats->obytes; 284 break; 285 286 case MAC_STAT_OPACKETS: 287 cur_stats->opackets = 0; 288 for (i = 0; i < qlge->tx_ring_count; i++) { 289 tx_ring = &qlge->tx_ring[i]; 290 cur_stats->opackets += tx_ring->opackets; 291 } 292 val = cur_stats->opackets; 293 break; 294 295 case ETHER_STAT_DEFER_XMTS: 296 cur_stats->defer = 0; 297 for (i = 0; i < qlge->tx_ring_count; i++) { 298 tx_ring = &qlge->tx_ring[i]; 299 cur_stats->defer += (tx_ring->defer); 300 } 301 val = cur_stats->defer; 302 break; 303 304 case MAC_STAT_OERRORS: 305 cur_stats->errxmt = 0; 306 for (i = 0; i < qlge->tx_ring_count; i++) { 307 tx_ring = &qlge->tx_ring[i]; 308 cur_stats->errxmt += tx_ring->errxmt; 309 } 310 val = cur_stats->errxmt; 311 break; 312 313 case MAC_STAT_RBYTES: 314 cur_stats->rbytes = 0; 315 for (i = 0; i < qlge->rx_ring_count; i++) { 316 rx_ring = &qlge->rx_ring[i]; 317 cur_stats->rbytes += rx_ring->rx_bytes; 318 } 319 val = cur_stats->rbytes; 320 break; 321 322 case MAC_STAT_IPACKETS: 323 cur_stats->rpackets = 0; 324 for (i = 0; i < qlge->rx_ring_count; i++) { 325 rx_ring = &qlge->rx_ring[i]; 326 cur_stats->rpackets += rx_ring->rx_packets; 327 } 328 val = cur_stats->rpackets; 329 break; 330 331 case ETHER_STAT_FCS_ERRORS: 332 cur_stats->crc = 0; 333 for (i = 0; i < qlge->rx_ring_count; i++) { 334 rx_ring = &qlge->rx_ring[i]; 335 cur_stats->crc += rx_ring->fcs_err; 336 } 337 val = cur_stats->crc; 338 break; 339 340 case ETHER_STAT_TOOLONG_ERRORS: 341 cur_stats->frame_too_long = 0; 342 for (i = 0; i < qlge->rx_ring_count; i++) { 343 rx_ring = &qlge->rx_ring[i]; 344 cur_stats->frame_too_long += 345 rx_ring->frame_too_long; 346 } 347 val = cur_stats->frame_too_long; 348 break; 349 350 case ETHER_STAT_XCVR_INUSE: 351 val = XCVR_1000X; 352 break; 353 case ETHER_STAT_JABBER_ERRORS: 354 if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) != 355 DDI_SUCCESS) { 356 break; 357 } 358 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS, 359 &val32); 360 val = val32; 361 ql_sem_unlock(qlge, qlge->xgmac_sem_mask); 362 QL_PRINT(DBG_STATS, ("%s(%d) MAC_STAT_JABBER_ERRORS " 363 "status %d\n", __func__, qlge->instance, val)); 364 break; 365 case ETHER_STAT_LINK_DUPLEX: 366 if (qlge->duplex == 1) 367 val = LINK_DUPLEX_FULL; 368 else 369 val = LINK_DUPLEX_HALF; 370 break; 371 372 /* statics saved in hw */ 373 case ETHER_STAT_MACRCV_ERRORS: 374 val = 0; 375 if (ql_sem_spinlock(qlge, qlge->xgmac_sem_mask) != 376 DDI_SUCCESS) { 377 break; 378 } 379 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_ALIGN_ERR, 380 &val32); 381 val += val32; 382 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_FCS_ERR, &val32); 383 val += val32; 384 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_JABBER_PKTS, 385 &val32); 386 val += val32; 387 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_SYM_ERR, 388 &val32); 389 val += val32; 390 (void) ql_read_xgmac_reg(qlge, REG_XGMAC_MAC_RX_INT_ERR, 391 &val32); 392 val += val32; 393 ql_sem_unlock(qlge, qlge->xgmac_sem_mask); 394 break; 395 396 default: 397 mutex_exit(&qlge->gen_mutex); 398 return (ENOTSUP); 399 } 400 *valp = val; 401 mutex_exit(&qlge->gen_mutex); 402 403 return (0); 404 405 } 406 407 /* 408 * Set the physical network address 409 */ 410 int 411 ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot) 412 { 413 int ret; 414 415 ret = ql_sem_spinlock(qlge, SEM_MAC_ADDR_MASK); 416 if (ret != DDI_SUCCESS) 417 goto exit; 418 ret = ql_set_mac_addr_reg(qlge, (uint8_t *)macaddr, 419 MAC_ADDR_TYPE_CAM_MAC, 420 (uint16_t)(qlge->func_number * MAX_CQ + slot)); 421 ql_sem_unlock(qlge, SEM_MAC_ADDR_MASK); 422 423 exit: 424 if (ret != DDI_SUCCESS) { 425 ret = EIO; 426 if (qlge->fm_enable) { 427 ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED); 428 } 429 } else { 430 ret = 0; 431 } 432 return (ret); 433 } 434 435 /* 436 * Set default MAC address 437 * Each function has a total of 128 mac address, function0: 0~127, 438 * function1 128~254 etc or func_number *128 + n (0~127), but 439 * we only support one MAC address, so its address is 440 * func_number*128+0 441 */ 442 static int 443 ql_m_unicst(void *arg, const uint8_t *mac) 444 { 445 qlge_t *qlge = (qlge_t *)arg; 446 int status; 447 448 ASSERT(qlge->mac_flags != QL_MAC_DETACH); 449 mutex_enter(&qlge->gen_mutex); 450 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 451 mutex_exit(&qlge->gen_mutex); 452 return (ECANCELED); 453 } 454 455 mutex_enter(&qlge->hw_mutex); 456 bcopy(mac, qlge->unicst_addr[0].addr.ether_addr_octet, ETHERADDRL); 457 /* Set Mac Address to slot 0 and Enable Primary Mac Function */ 458 status = ql_unicst_set(qlge, mac, 0); 459 mutex_exit(&qlge->hw_mutex); 460 mutex_exit(&qlge->gen_mutex); 461 462 return (status); 463 } 464 465 /* 466 * ql_m_tx is used only for sending data packets into ethernet wire. 467 */ 468 static mblk_t * 469 ql_m_tx(void *arg, mblk_t *mp) 470 { 471 qlge_t *qlge = (qlge_t *)arg; 472 struct tx_ring *tx_ring; 473 mblk_t *next; 474 int rval; 475 uint32_t tx_count = 0; 476 caddr_t bp; 477 uint8_t selected_ring = 0; 478 479 if ((qlge->port_link_state == LS_DOWN) || 480 (qlge->mac_flags != QL_MAC_STARTED)) { 481 482 cmn_err(CE_WARN, "!%s(%d): exit due to link down", 483 __func__, qlge->instance); 484 freemsgchain(mp); 485 mp = NULL; 486 goto tx_exit; 487 } 488 489 /* 490 * Calculate which tx ring to send this packet 491 */ 492 bp = (caddr_t)mp->b_rptr; 493 selected_ring = ql_tx_hashing(qlge, bp); 494 tx_ring = &qlge->tx_ring[selected_ring]; 495 mutex_enter(&tx_ring->tx_lock); 496 if (tx_ring->mac_flags != QL_MAC_STARTED) { 497 mutex_exit(&tx_ring->tx_lock); 498 goto tx_exit; 499 } 500 501 /* we must try to send all */ 502 while (mp != NULL) { 503 /* 504 * if number of available slots is less than a threshold, 505 * then quit 506 */ 507 if (tx_ring->tx_free_count <= TX_STOP_THRESHOLD) { 508 tx_ring->queue_stopped = 1; 509 rval = DDI_FAILURE; 510 /* 511 * If we return the buffer back we are expected to 512 * call mac_tx_ring_update() when 513 * resources are available 514 */ 515 tx_ring->defer++; 516 break; 517 } 518 next = mp->b_next; 519 mp->b_next = NULL; 520 521 rval = ql_send_common(tx_ring, mp); 522 523 if (rval != DDI_SUCCESS) { 524 mp->b_next = next; 525 break; 526 } 527 tx_count++; 528 mp = next; 529 } 530 /* 531 * After all msg blocks are mapped or copied to tx buffer, 532 * trigger the hardware to send the msg! 533 */ 534 if (tx_count > 0) { 535 ql_write_doorbell_reg(tx_ring->qlge, tx_ring->prod_idx_db_reg, 536 tx_ring->prod_idx); 537 } 538 mutex_exit(&tx_ring->tx_lock); 539 tx_exit: 540 return (mp); 541 } 542 543 static void 544 ql_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 545 { 546 qlge_t *qlge = (qlge_t *)arg; 547 struct iocblk *iocp; 548 boolean_t need_privilege = B_TRUE; 549 int err, cmd; 550 enum ioc_reply status; 551 552 /* 553 * Validate the command before bothering with the mutex... 554 */ 555 iocp = (struct iocblk *)(void *)mp->b_rptr; 556 iocp->ioc_error = 0; 557 cmd = iocp->ioc_cmd; 558 559 mutex_enter(&qlge->gen_mutex); 560 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 561 mutex_exit(&qlge->gen_mutex); 562 miocnak(wq, mp, 0, EINVAL); 563 return; 564 } 565 switch (cmd) { 566 default: 567 QL_PRINT(DBG_GLD, ("unknown ioctl cmd \n")); 568 miocnak(wq, mp, 0, EINVAL); 569 mutex_exit(&qlge->gen_mutex); 570 return; 571 case QLA_PCI_STATUS: 572 case QLA_WRITE_REG: 573 case QLA_READ_PCI_REG: 574 case QLA_WRITE_PCI_REG: 575 case QLA_GET_DBGLEAVEL: 576 case QLA_SET_DBGLEAVEL: 577 case QLA_READ_CONTRL_REGISTERS: 578 case QLA_MANUAL_READ_FLASH: 579 case QLA_MANUAL_WRITE_FLASH: 580 case QLA_GET_BINARY_CORE_DUMP: 581 case QLA_SUPPORTED_DUMP_TYPES: 582 case QLA_TRIGGER_SYS_ERROR_EVENT: 583 case QLA_READ_FLASH: 584 case QLA_WRITE_FLASH: 585 case QLA_READ_VPD: 586 case QLA_GET_PROP: 587 case QLA_SHOW_REGION: 588 case QLA_LIST_ADAPTER_INFO: 589 case QLA_READ_FW_IMAGE: 590 case QLA_WRITE_FW_IMAGE_HEADERS: 591 case QLA_CONTINUE_COPY_IN: 592 case QLA_CONTINUE_COPY_OUT: 593 case QLA_SOFT_RESET: 594 break; 595 case LB_GET_INFO_SIZE: 596 case LB_GET_INFO: 597 case LB_GET_MODE: 598 need_privilege = B_FALSE; 599 /* FALLTHRU */ 600 case LB_SET_MODE: 601 break; 602 } 603 604 if (need_privilege) { 605 /* 606 * Check for specific net_config privilege 607 */ 608 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 609 if (err != 0) { 610 miocnak(wq, mp, 0, err); 611 mutex_exit(&qlge->gen_mutex); 612 return; 613 } 614 } 615 /* 616 * Implement ioctl 617 */ 618 switch (cmd) { 619 case QLA_PCI_STATUS: 620 case QLA_WRITE_REG: 621 case QLA_READ_PCI_REG: 622 case QLA_WRITE_PCI_REG: 623 case QLA_GET_DBGLEAVEL: 624 case QLA_SET_DBGLEAVEL: 625 case QLA_READ_CONTRL_REGISTERS: 626 case QLA_MANUAL_READ_FLASH: 627 case QLA_MANUAL_WRITE_FLASH: 628 case QLA_GET_BINARY_CORE_DUMP: 629 case QLA_SUPPORTED_DUMP_TYPES: 630 case QLA_TRIGGER_SYS_ERROR_EVENT: 631 case QLA_READ_FLASH: 632 case QLA_WRITE_FLASH: 633 case QLA_READ_VPD: 634 case QLA_GET_PROP: 635 case QLA_SHOW_REGION: 636 case QLA_LIST_ADAPTER_INFO: 637 case QLA_READ_FW_IMAGE: 638 case QLA_WRITE_FW_IMAGE_HEADERS: 639 case QLA_CONTINUE_COPY_IN: 640 case QLA_CONTINUE_COPY_OUT: 641 case QLA_SOFT_RESET: 642 status = ql_chip_ioctl(qlge, wq, mp); 643 break; 644 case LB_GET_INFO_SIZE: 645 case LB_GET_INFO: 646 case LB_GET_MODE: 647 case LB_SET_MODE: 648 status = ql_loop_ioctl(qlge, wq, mp, iocp); 649 break; 650 default: 651 status = IOC_INVAL; 652 break; 653 } 654 655 /* 656 * Decide how to reply 657 */ 658 switch (status) { 659 default: 660 case IOC_INVAL: 661 /* 662 * Error, reply with a NAK and EINVAL or the specified error 663 */ 664 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 665 EINVAL : iocp->ioc_error); 666 break; 667 668 case IOC_DONE: 669 /* 670 * OK, reply already sent 671 */ 672 break; 673 674 case IOC_ACK: 675 /* 676 * OK, reply with an ACK 677 */ 678 miocack(wq, mp, 0, 0); 679 break; 680 681 case IOC_REPLY: 682 /* 683 * OK, send prepared reply as ACK or NAK 684 */ 685 mp->b_datap->db_type = (uint8_t)(iocp->ioc_error == 0 ? 686 M_IOCACK : M_IOCNAK); 687 qreply(wq, mp); 688 break; 689 } 690 mutex_exit(&qlge->gen_mutex); 691 } 692 /* ARGSUSED */ 693 static int 694 qlge_set_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize, 695 const void *pr_val) 696 { 697 int err = 0; 698 long result; 699 700 if (strcmp(pr_name, "_adv_pause_mode") == 0) { 701 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 702 if (result > PAUSE_MODE_PER_PRIORITY || 703 result < PAUSE_MODE_DISABLED) { 704 err = EINVAL; 705 } else if (qlge->pause != (uint32_t)result) { 706 qlge->pause = (uint32_t)result; 707 if (qlge->flags & INTERRUPTS_ENABLED) { 708 mutex_enter(&qlge->mbx_mutex); 709 if (ql_set_pause_mode(qlge) == DDI_FAILURE) 710 err = EINVAL; 711 mutex_exit(&qlge->mbx_mutex); 712 } 713 } 714 return (err); 715 } else if (strcmp(pr_name, "_fm_enable") == 0) { 716 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 717 if ((result != 0) && (result != 1)) { 718 err = EINVAL; 719 } else if (qlge->fm_enable != (boolean_t)result) { 720 qlge->fm_enable = (boolean_t)result; 721 } 722 return (err); 723 } 724 return (ENOTSUP); 725 } 726 727 /* 728 * callback functions for set/get of properties 729 */ 730 /* ARGSUSED */ 731 static int 732 ql_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 733 uint_t pr_valsize, const void *pr_val) 734 { 735 qlge_t *qlge = barg; 736 int err = 0; 737 uint32_t cur_mtu, new_mtu; 738 739 mutex_enter(&qlge->gen_mutex); 740 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 741 mutex_exit(&qlge->gen_mutex); 742 return (ECANCELED); 743 } 744 745 switch (pr_num) { 746 case MAC_PROP_MTU: 747 cur_mtu = qlge->mtu; 748 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 749 750 QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d \n", 751 __func__, qlge->instance, new_mtu)); 752 if (new_mtu == cur_mtu) { 753 err = 0; 754 break; 755 } 756 if ((new_mtu != ETHERMTU) && (new_mtu != JUMBO_MTU)) { 757 err = EINVAL; 758 break; 759 } 760 /* 761 * do not change on the fly, allow only before 762 * driver is started or stopped 763 */ 764 if ((qlge->mac_flags == QL_MAC_STARTED) || 765 (qlge->mac_flags == QL_MAC_DETACH)) { 766 err = EBUSY; 767 cmn_err(CE_WARN, "%s(%d) new mtu %d ignored, " 768 "driver busy, mac_flags %d", __func__, 769 qlge->instance, new_mtu, qlge->mac_flags); 770 break; 771 } 772 qlge->mtu = new_mtu; 773 err = mac_maxsdu_update(qlge->mh, qlge->mtu); 774 if (err == 0) { 775 /* EMPTY */ 776 QL_PRINT(DBG_GLD, ("%s(%d) new mtu %d set success\n", 777 __func__, qlge->instance, 778 new_mtu)); 779 } 780 break; 781 case MAC_PROP_PRIVATE: 782 mutex_exit(&qlge->gen_mutex); 783 err = qlge_set_priv_prop(qlge, pr_name, pr_valsize, 784 pr_val); 785 mutex_enter(&qlge->gen_mutex); 786 break; 787 default: 788 err = ENOTSUP; 789 break; 790 } 791 mutex_exit(&qlge->gen_mutex); 792 return (err); 793 } 794 795 static int 796 qlge_get_priv_prop(qlge_t *qlge, const char *pr_name, uint_t pr_valsize, 797 void *pr_val) 798 { 799 int err = ENOTSUP; 800 uint32_t value; 801 802 if (strcmp(pr_name, "_adv_pause_mode") == 0) { 803 value = qlge->pause; 804 err = 0; 805 } else if (strcmp(pr_name, "_fm_enable") == 0) { 806 value = qlge->fm_enable; 807 err = 0; 808 } 809 810 if (err == 0) { 811 (void) snprintf(pr_val, pr_valsize, "%d", value); 812 } 813 return (err); 814 } 815 816 /* ARGSUSED */ 817 static int 818 ql_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 819 uint_t pr_valsize, void *pr_val) 820 { 821 qlge_t *qlge = barg; 822 uint64_t speed; 823 link_state_t link_state; 824 link_duplex_t link_duplex; 825 int err = 0; 826 827 mutex_enter(&qlge->gen_mutex); 828 if (qlge->mac_flags == QL_MAC_SUSPENDED) { 829 err = ECANCELED; 830 goto out; 831 } 832 833 switch (pr_num) { 834 case MAC_PROP_DUPLEX: 835 ASSERT(pr_valsize >= sizeof (link_duplex_t)); 836 if (qlge->duplex) 837 link_duplex = LINK_DUPLEX_FULL; 838 else 839 link_duplex = LINK_DUPLEX_HALF; 840 841 bcopy(&link_duplex, pr_val, 842 sizeof (link_duplex_t)); 843 break; 844 case MAC_PROP_SPEED: 845 ASSERT(pr_valsize >= sizeof (speed)); 846 speed = qlge->speed * 1000000ull; 847 bcopy(&speed, pr_val, sizeof (speed)); 848 break; 849 case MAC_PROP_STATUS: 850 ASSERT(pr_valsize >= sizeof (link_state_t)); 851 if (qlge->port_link_state == LS_DOWN) 852 link_state = LINK_STATE_DOWN; 853 else 854 link_state = LINK_STATE_UP; 855 bcopy(&link_state, pr_val, 856 sizeof (link_state_t)); 857 break; 858 859 case MAC_PROP_PRIVATE: 860 err = qlge_get_priv_prop(qlge, pr_name, pr_valsize, pr_val); 861 break; 862 863 default: 864 err = ENOTSUP; 865 } 866 out: 867 mutex_exit(&qlge->gen_mutex); 868 return (err); 869 } 870 871 /* ARGSUSED */ 872 static void 873 ql_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num, 874 mac_prop_info_handle_t prh) 875 { 876 _NOTE(ARGUNUSED(barg)); 877 878 switch (pr_num) { 879 case MAC_PROP_DUPLEX: 880 case MAC_PROP_SPEED: 881 case MAC_PROP_STATUS: 882 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 883 break; 884 885 case MAC_PROP_PRIVATE: { 886 char val_str[64]; 887 int default_val; 888 889 if (strcmp(pr_name, "_adv_pause_mode") == 0) 890 default_val = 2; 891 else if (strcmp(pr_name, "_fm_enable") == 0) 892 default_val = 1; 893 else 894 return; 895 896 (void) snprintf(val_str, sizeof (val_str), "%d", default_val); 897 mac_prop_info_set_default_str(prh, val_str); 898 break; 899 } 900 } 901 } 902 903 /* ARGSUSED */ 904 static boolean_t 905 ql_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 906 { 907 int ret = B_FALSE; 908 uint32_t cksum = 0; 909 qlge_t *qlge = (qlge_t *)arg; 910 911 switch (cap) { 912 case MAC_CAPAB_HCKSUM: 913 if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv4) != 0) { 914 cksum |= HCKSUM_INET_FULL_V4; 915 } 916 if ((qlge->cfg_flags & CFG_CKSUM_FULL_IPv6) != 0) { 917 cksum |= HCKSUM_INET_FULL_V6; 918 } 919 if ((qlge->cfg_flags & CFG_CKSUM_HEADER_IPv4) != 0) { 920 cksum |= HCKSUM_IPHDRCKSUM; 921 } 922 if ((qlge->cfg_flags & CFG_CKSUM_PARTIAL) != 0) { 923 cksum |= HCKSUM_INET_PARTIAL; 924 } 925 qlge->chksum_cap = cksum; 926 *(uint32_t *)cap_data = cksum; 927 ret = B_TRUE; 928 break; 929 930 case MAC_CAPAB_LSO: { 931 mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data; 932 uint32_t page_size; 933 uint32_t lso_max; 934 935 if ((qlge->cfg_flags & CFG_LSO)&& 936 (qlge->cfg_flags & CFG_SUPPORT_SCATTER_GATHER)) { 937 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 938 page_size = ddi_ptob(qlge->dip, (ulong_t)1); 939 lso_max = page_size * (QL_MAX_TX_DMA_HANDLES-1); 940 cap_lso->lso_basic_tcp_ipv4.lso_max = 941 min(lso_max, QL_LSO_MAX); 942 ret = B_TRUE; 943 } 944 break; 945 } 946 947 default: 948 return (B_FALSE); 949 } 950 return (ret); 951 } 952 953 void 954 ql_gld3_init(qlge_t *qlge, mac_register_t *macp) 955 { 956 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 957 macp->m_driver = qlge; 958 macp->m_dip = qlge->dip; 959 /* This is the mac address from flash to be used by the port */ 960 macp->m_src_addr = qlge->dev_addr.ether_addr_octet; 961 macp->m_min_sdu = 0; 962 macp->m_max_sdu = qlge->mtu; 963 macp->m_margin = VLAN_TAGSZ; 964 macp->m_priv_props = qlge_priv_prop; 965 macp->m_v12n = 0; 966 ql_m_callbacks.mc_unicst = ql_m_unicst; 967 ql_m_callbacks.mc_tx = ql_m_tx; 968 macp->m_callbacks = &ql_m_callbacks; 969 } 970