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