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