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 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2002-2009 Neterion, Inc. 29 * All right Reserved. 30 * 31 * FileName : xgell.c 32 * 33 * Description: Xge Link Layer data path implementation 34 * 35 */ 36 37 #include "xgell.h" 38 39 #include <netinet/ip.h> 40 #include <netinet/tcp.h> 41 #include <netinet/udp.h> 42 43 #define XGELL_MAX_FRAME_SIZE(hldev) ((hldev)->config.mtu + \ 44 sizeof (struct ether_vlan_header)) 45 46 #define HEADROOM 2 /* for DIX-only packets */ 47 48 void header_free_func(void *arg) { } 49 frtn_t header_frtn = {header_free_func, NULL}; 50 51 /* DMA attributes used for Tx side */ 52 static struct ddi_dma_attr tx_dma_attr = { 53 DMA_ATTR_V0, /* dma_attr_version */ 54 0x0ULL, /* dma_attr_addr_lo */ 55 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_addr_hi */ 56 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_count_max */ 57 #if defined(__sparc) 58 0x2000, /* dma_attr_align */ 59 #else 60 0x1000, /* dma_attr_align */ 61 #endif 62 0xFC00FC, /* dma_attr_burstsizes */ 63 0x1, /* dma_attr_minxfer */ 64 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_maxxfer */ 65 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_seg */ 66 18, /* dma_attr_sgllen */ 67 (unsigned int)1, /* dma_attr_granular */ 68 0 /* dma_attr_flags */ 69 }; 70 71 /* 72 * DMA attributes used when using ddi_dma_mem_alloc to 73 * allocat HAL descriptors and Rx buffers during replenish 74 */ 75 static struct ddi_dma_attr hal_dma_attr = { 76 DMA_ATTR_V0, /* dma_attr_version */ 77 0x0ULL, /* dma_attr_addr_lo */ 78 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_addr_hi */ 79 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_count_max */ 80 #if defined(__sparc) 81 0x2000, /* dma_attr_align */ 82 #else 83 0x1000, /* dma_attr_align */ 84 #endif 85 0xFC00FC, /* dma_attr_burstsizes */ 86 0x1, /* dma_attr_minxfer */ 87 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_maxxfer */ 88 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_seg */ 89 1, /* dma_attr_sgllen */ 90 (unsigned int)1, /* dma_attr_sgllen */ 91 DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */ 92 }; 93 94 struct ddi_dma_attr *p_hal_dma_attr = &hal_dma_attr; 95 96 static int xgell_m_stat(void *, uint_t, uint64_t *); 97 static int xgell_m_start(void *); 98 static void xgell_m_stop(void *); 99 static int xgell_m_promisc(void *, boolean_t); 100 static int xgell_m_multicst(void *, boolean_t, const uint8_t *); 101 static void xgell_m_ioctl(void *, queue_t *, mblk_t *); 102 static boolean_t xgell_m_getcapab(void *, mac_capab_t, void *); 103 104 #define XGELL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB) 105 106 static mac_callbacks_t xgell_m_callbacks = { 107 XGELL_M_CALLBACK_FLAGS, 108 xgell_m_stat, 109 xgell_m_start, 110 xgell_m_stop, 111 xgell_m_promisc, 112 xgell_m_multicst, 113 NULL, 114 NULL, 115 NULL, 116 xgell_m_ioctl, 117 xgell_m_getcapab 118 }; 119 120 /* 121 * xge_device_poll 122 * 123 * Timeout should call me every 1s. xge_callback_event_queued should call me 124 * when HAL hope event was rescheduled. 125 */ 126 /*ARGSUSED*/ 127 void 128 xge_device_poll(void *data) 129 { 130 xgelldev_t *lldev = xge_hal_device_private(data); 131 132 mutex_enter(&lldev->genlock); 133 if (lldev->is_initialized) { 134 xge_hal_device_poll(data); 135 lldev->timeout_id = timeout(xge_device_poll, data, 136 XGE_DEV_POLL_TICKS); 137 } else if (lldev->in_reset == 1) { 138 lldev->timeout_id = timeout(xge_device_poll, data, 139 XGE_DEV_POLL_TICKS); 140 } else { 141 lldev->timeout_id = 0; 142 } 143 mutex_exit(&lldev->genlock); 144 } 145 146 /* 147 * xge_device_poll_now 148 * 149 * Will call xge_device_poll() immediately 150 */ 151 void 152 xge_device_poll_now(void *data) 153 { 154 xgelldev_t *lldev = xge_hal_device_private(data); 155 156 mutex_enter(&lldev->genlock); 157 if (lldev->is_initialized) { 158 xge_hal_device_poll(data); 159 } 160 mutex_exit(&lldev->genlock); 161 } 162 163 /* 164 * xgell_callback_link_up 165 * 166 * This function called by HAL to notify HW link up state change. 167 */ 168 void 169 xgell_callback_link_up(void *userdata) 170 { 171 xgelldev_t *lldev = (xgelldev_t *)userdata; 172 173 mac_link_update(lldev->mh, LINK_STATE_UP); 174 } 175 176 /* 177 * xgell_callback_link_down 178 * 179 * This function called by HAL to notify HW link down state change. 180 */ 181 void 182 xgell_callback_link_down(void *userdata) 183 { 184 xgelldev_t *lldev = (xgelldev_t *)userdata; 185 186 mac_link_update(lldev->mh, LINK_STATE_DOWN); 187 } 188 189 /* 190 * xgell_rx_buffer_replenish_all 191 * 192 * To replenish all freed dtr(s) with buffers in free pool. It's called by 193 * xgell_rx_buffer_recycle() or xgell_rx_1b_callback(). 194 * Must be called with pool_lock held. 195 */ 196 static void 197 xgell_rx_buffer_replenish_all(xgell_rx_ring_t *ring) 198 { 199 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 200 xge_hal_dtr_h dtr; 201 xgell_rx_buffer_t *rx_buffer; 202 xgell_rxd_priv_t *rxd_priv; 203 204 xge_assert(mutex_owned(&bf_pool->pool_lock)); 205 206 while ((bf_pool->free > 0) && 207 (xge_hal_ring_dtr_reserve(ring->channelh, &dtr) == XGE_HAL_OK)) { 208 xge_assert(bf_pool->head); 209 210 rx_buffer = bf_pool->head; 211 212 bf_pool->head = rx_buffer->next; 213 bf_pool->free--; 214 215 xge_assert(rx_buffer->dma_addr); 216 217 rxd_priv = (xgell_rxd_priv_t *) 218 xge_hal_ring_dtr_private(ring->channelh, dtr); 219 xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr, 220 bf_pool->size); 221 222 rxd_priv->rx_buffer = rx_buffer; 223 xge_hal_ring_dtr_post(ring->channelh, dtr); 224 } 225 } 226 227 /* 228 * xgell_rx_buffer_release 229 * 230 * The only thing done here is to put the buffer back to the pool. 231 * Calling this function need be protected by mutex, bf_pool.pool_lock. 232 */ 233 static void 234 xgell_rx_buffer_release(xgell_rx_buffer_t *rx_buffer) 235 { 236 xgell_rx_ring_t *ring = rx_buffer->ring; 237 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 238 239 xge_assert(mutex_owned(&bf_pool->pool_lock)); 240 241 /* Put the buffer back to pool */ 242 rx_buffer->next = bf_pool->head; 243 bf_pool->head = rx_buffer; 244 245 bf_pool->free++; 246 } 247 248 /* 249 * xgell_rx_buffer_recycle 250 * 251 * Called by desballoc() to "free" the resource. 252 * We will try to replenish all descripters. 253 */ 254 255 /* 256 * Previously there were much lock contention between xgell_rx_1b_compl() and 257 * xgell_rx_buffer_recycle(), which consumed a lot of CPU resources and had bad 258 * effect on rx performance. A separate recycle list is introduced to overcome 259 * this. The recycle list is used to record the rx buffer that has been recycled 260 * and these buffers will be retuned back to the free list in bulk instead of 261 * one-by-one. 262 */ 263 264 static void 265 xgell_rx_buffer_recycle(char *arg) 266 { 267 xgell_rx_buffer_t *rx_buffer = (xgell_rx_buffer_t *)arg; 268 xgell_rx_ring_t *ring = rx_buffer->ring; 269 xgelldev_t *lldev = ring->lldev; 270 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 271 272 mutex_enter(&bf_pool->recycle_lock); 273 274 rx_buffer->next = bf_pool->recycle_head; 275 bf_pool->recycle_head = rx_buffer; 276 if (bf_pool->recycle_tail == NULL) 277 bf_pool->recycle_tail = rx_buffer; 278 bf_pool->recycle++; 279 280 /* 281 * Before finding a good way to set this hiwat, just always call to 282 * replenish_all. *TODO* 283 */ 284 if ((lldev->is_initialized != 0) && (ring->live) && 285 (bf_pool->recycle >= XGELL_RX_BUFFER_RECYCLE_CACHE)) { 286 mutex_enter(&bf_pool->pool_lock); 287 bf_pool->recycle_tail->next = bf_pool->head; 288 bf_pool->head = bf_pool->recycle_head; 289 bf_pool->recycle_head = bf_pool->recycle_tail = NULL; 290 bf_pool->post -= bf_pool->recycle; 291 bf_pool->free += bf_pool->recycle; 292 bf_pool->recycle = 0; 293 xgell_rx_buffer_replenish_all(ring); 294 mutex_exit(&bf_pool->pool_lock); 295 } 296 297 mutex_exit(&bf_pool->recycle_lock); 298 } 299 300 /* 301 * xgell_rx_buffer_alloc 302 * 303 * Allocate one rx buffer and return with the pointer to the buffer. 304 * Return NULL if failed. 305 */ 306 static xgell_rx_buffer_t * 307 xgell_rx_buffer_alloc(xgell_rx_ring_t *ring) 308 { 309 xgelldev_t *lldev = ring->lldev; 310 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 311 xge_hal_device_t *hldev; 312 void *vaddr; 313 ddi_dma_handle_t dma_handle; 314 ddi_acc_handle_t dma_acch; 315 dma_addr_t dma_addr; 316 uint_t ncookies; 317 ddi_dma_cookie_t dma_cookie; 318 size_t real_size; 319 extern ddi_device_acc_attr_t *p_xge_dev_attr; 320 xgell_rx_buffer_t *rx_buffer; 321 322 hldev = (xge_hal_device_t *)lldev->devh; 323 324 if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP, 325 0, &dma_handle) != DDI_SUCCESS) { 326 xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA handle", 327 XGELL_IFNAME, lldev->instance); 328 goto handle_failed; 329 } 330 331 /* reserve some space at the end of the buffer for recycling */ 332 if (ddi_dma_mem_alloc(dma_handle, HEADROOM + bf_pool->size + 333 sizeof (xgell_rx_buffer_t), p_xge_dev_attr, DDI_DMA_STREAMING, 334 DDI_DMA_SLEEP, 0, (caddr_t *)&vaddr, &real_size, &dma_acch) != 335 DDI_SUCCESS) { 336 xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory", 337 XGELL_IFNAME, lldev->instance); 338 goto mem_failed; 339 } 340 341 if (HEADROOM + bf_pool->size + sizeof (xgell_rx_buffer_t) > 342 real_size) { 343 xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory", 344 XGELL_IFNAME, lldev->instance); 345 goto bind_failed; 346 } 347 348 if (ddi_dma_addr_bind_handle(dma_handle, NULL, (char *)vaddr + HEADROOM, 349 bf_pool->size, DDI_DMA_READ | DDI_DMA_STREAMING, 350 DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_SUCCESS) { 351 xge_debug_ll(XGE_ERR, "%s%d: out of mapping for mblk", 352 XGELL_IFNAME, lldev->instance); 353 goto bind_failed; 354 } 355 356 if (ncookies != 1 || dma_cookie.dmac_size < bf_pool->size) { 357 xge_debug_ll(XGE_ERR, "%s%d: can not handle partial DMA", 358 XGELL_IFNAME, lldev->instance); 359 goto check_failed; 360 } 361 362 dma_addr = dma_cookie.dmac_laddress; 363 364 rx_buffer = (xgell_rx_buffer_t *)((char *)vaddr + real_size - 365 sizeof (xgell_rx_buffer_t)); 366 rx_buffer->next = NULL; 367 rx_buffer->vaddr = vaddr; 368 rx_buffer->dma_addr = dma_addr; 369 rx_buffer->dma_handle = dma_handle; 370 rx_buffer->dma_acch = dma_acch; 371 rx_buffer->ring = ring; 372 rx_buffer->frtn.free_func = xgell_rx_buffer_recycle; 373 rx_buffer->frtn.free_arg = (void *)rx_buffer; 374 375 return (rx_buffer); 376 377 check_failed: 378 (void) ddi_dma_unbind_handle(dma_handle); 379 bind_failed: 380 XGE_OS_MEMORY_CHECK_FREE(vaddr, 0); 381 ddi_dma_mem_free(&dma_acch); 382 mem_failed: 383 ddi_dma_free_handle(&dma_handle); 384 handle_failed: 385 386 return (NULL); 387 } 388 389 /* 390 * xgell_rx_destroy_buffer_pool 391 * 392 * Destroy buffer pool. If there is still any buffer hold by upper layer, 393 * recorded by bf_pool.post, return DDI_FAILURE to reject to be unloaded. 394 */ 395 static boolean_t 396 xgell_rx_destroy_buffer_pool(xgell_rx_ring_t *ring) 397 { 398 xgelldev_t *lldev = ring->lldev; 399 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 400 xgell_rx_buffer_t *rx_buffer; 401 ddi_dma_handle_t dma_handle; 402 ddi_acc_handle_t dma_acch; 403 int i; 404 405 /* 406 * If the pool has been destroied, just return B_TRUE 407 */ 408 if (!bf_pool->live) 409 return (B_TRUE); 410 411 mutex_enter(&bf_pool->recycle_lock); 412 if (bf_pool->recycle > 0) { 413 mutex_enter(&bf_pool->pool_lock); 414 bf_pool->recycle_tail->next = bf_pool->head; 415 bf_pool->head = bf_pool->recycle_head; 416 bf_pool->recycle_tail = bf_pool->recycle_head = NULL; 417 bf_pool->post -= bf_pool->recycle; 418 bf_pool->free += bf_pool->recycle; 419 bf_pool->recycle = 0; 420 mutex_exit(&bf_pool->pool_lock); 421 } 422 mutex_exit(&bf_pool->recycle_lock); 423 424 /* 425 * If there is any posted buffer, the driver should reject to be 426 * detached. Need notice upper layer to release them. 427 */ 428 if (bf_pool->post != 0) { 429 xge_debug_ll(XGE_ERR, 430 "%s%d has some buffers not be recycled, try later!", 431 XGELL_IFNAME, lldev->instance); 432 return (B_FALSE); 433 } 434 435 /* 436 * Release buffers one by one. 437 */ 438 for (i = bf_pool->total; i > 0; i--) { 439 rx_buffer = bf_pool->head; 440 xge_assert(rx_buffer != NULL); 441 442 bf_pool->head = rx_buffer->next; 443 444 dma_handle = rx_buffer->dma_handle; 445 dma_acch = rx_buffer->dma_acch; 446 447 if (ddi_dma_unbind_handle(dma_handle) != DDI_SUCCESS) { 448 xge_debug_ll(XGE_ERR, "failed to unbind DMA handle!"); 449 bf_pool->head = rx_buffer; 450 return (B_FALSE); 451 } 452 ddi_dma_mem_free(&dma_acch); 453 ddi_dma_free_handle(&dma_handle); 454 455 bf_pool->total--; 456 bf_pool->free--; 457 } 458 459 xge_assert(!mutex_owned(&bf_pool->pool_lock)); 460 461 mutex_destroy(&bf_pool->recycle_lock); 462 mutex_destroy(&bf_pool->pool_lock); 463 bf_pool->live = B_FALSE; 464 465 return (B_TRUE); 466 } 467 468 /* 469 * xgell_rx_create_buffer_pool 470 * 471 * Initialize RX buffer pool for all RX rings. Refer to rx_buffer_pool_t. 472 */ 473 static boolean_t 474 xgell_rx_create_buffer_pool(xgell_rx_ring_t *ring) 475 { 476 xgelldev_t *lldev = ring->lldev; 477 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 478 xge_hal_device_t *hldev; 479 xgell_rx_buffer_t *rx_buffer; 480 int i; 481 482 if (bf_pool->live) 483 return (B_TRUE); 484 485 hldev = (xge_hal_device_t *)lldev->devh; 486 487 bf_pool->total = 0; 488 bf_pool->size = XGELL_MAX_FRAME_SIZE(hldev); 489 bf_pool->head = NULL; 490 bf_pool->free = 0; 491 bf_pool->post = 0; 492 bf_pool->post_hiwat = lldev->config.rx_buffer_post_hiwat; 493 bf_pool->recycle = 0; 494 bf_pool->recycle_head = NULL; 495 bf_pool->recycle_tail = NULL; 496 bf_pool->live = B_TRUE; 497 498 mutex_init(&bf_pool->pool_lock, NULL, MUTEX_DRIVER, 499 DDI_INTR_PRI(hldev->irqh)); 500 mutex_init(&bf_pool->recycle_lock, NULL, MUTEX_DRIVER, 501 DDI_INTR_PRI(hldev->irqh)); 502 503 /* 504 * Allocate buffers one by one. If failed, destroy whole pool by 505 * call to xgell_rx_destroy_buffer_pool(). 506 */ 507 508 for (i = 0; i < lldev->config.rx_buffer_total; i++) { 509 if ((rx_buffer = xgell_rx_buffer_alloc(ring)) == NULL) { 510 (void) xgell_rx_destroy_buffer_pool(ring); 511 return (B_FALSE); 512 } 513 514 rx_buffer->next = bf_pool->head; 515 bf_pool->head = rx_buffer; 516 517 bf_pool->total++; 518 bf_pool->free++; 519 } 520 521 return (B_TRUE); 522 } 523 524 /* 525 * xgell_rx_dtr_replenish 526 * 527 * Replenish descriptor with rx_buffer in RX buffer pool. 528 * The dtr should be post right away. 529 */ 530 xge_hal_status_e 531 xgell_rx_dtr_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, int index, 532 void *userdata, xge_hal_channel_reopen_e reopen) 533 { 534 xgell_rx_ring_t *ring = userdata; 535 xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool; 536 xgell_rx_buffer_t *rx_buffer; 537 xgell_rxd_priv_t *rxd_priv; 538 539 mutex_enter(&bf_pool->pool_lock); 540 if (bf_pool->head == NULL) { 541 xge_debug_ll(XGE_ERR, "no more available rx DMA buffer!"); 542 return (XGE_HAL_FAIL); 543 } 544 rx_buffer = bf_pool->head; 545 xge_assert(rx_buffer); 546 xge_assert(rx_buffer->dma_addr); 547 548 bf_pool->head = rx_buffer->next; 549 bf_pool->free--; 550 mutex_exit(&bf_pool->pool_lock); 551 552 rxd_priv = (xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtr); 553 xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr, bf_pool->size); 554 555 rxd_priv->rx_buffer = rx_buffer; 556 557 return (XGE_HAL_OK); 558 } 559 560 /* 561 * xgell_get_ip_offset 562 * 563 * Calculate the offset to IP header. 564 */ 565 static inline int 566 xgell_get_ip_offset(xge_hal_dtr_info_t *ext_info) 567 { 568 int ip_off; 569 570 /* get IP-header offset */ 571 switch (ext_info->frame) { 572 case XGE_HAL_FRAME_TYPE_DIX: 573 ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE; 574 break; 575 case XGE_HAL_FRAME_TYPE_IPX: 576 ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + 577 XGE_HAL_HEADER_802_2_SIZE + 578 XGE_HAL_HEADER_SNAP_SIZE); 579 break; 580 case XGE_HAL_FRAME_TYPE_LLC: 581 ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + 582 XGE_HAL_HEADER_802_2_SIZE); 583 break; 584 case XGE_HAL_FRAME_TYPE_SNAP: 585 ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE + 586 XGE_HAL_HEADER_SNAP_SIZE); 587 break; 588 default: 589 ip_off = 0; 590 break; 591 } 592 593 if ((ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 || 594 ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6) && 595 (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED)) { 596 ip_off += XGE_HAL_HEADER_VLAN_SIZE; 597 } 598 599 return (ip_off); 600 } 601 602 /* 603 * xgell_rx_hcksum_assoc 604 * 605 * Judge the packet type and then call to hcksum_assoc() to associate 606 * h/w checksum information. 607 */ 608 static inline void 609 xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length, 610 xge_hal_dtr_info_t *ext_info) 611 { 612 int cksum_flags = 0; 613 614 if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED)) { 615 if (ext_info->proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) { 616 if (ext_info->l3_cksum == XGE_HAL_L3_CKSUM_OK) { 617 cksum_flags |= HCK_IPV4_HDRCKSUM_OK; 618 } 619 if (ext_info->l4_cksum == XGE_HAL_L4_CKSUM_OK) { 620 cksum_flags |= HCK_FULLCKSUM_OK; 621 } 622 if (cksum_flags != 0) { 623 mac_hcksum_set(mp, 0, 0, 0, 0, cksum_flags); 624 } 625 } 626 } else if (ext_info->proto & 627 (XGE_HAL_FRAME_PROTO_IPV4 | XGE_HAL_FRAME_PROTO_IPV6)) { 628 /* 629 * Just pass the partial cksum up to IP. 630 */ 631 int ip_off = xgell_get_ip_offset(ext_info); 632 int start, end = pkt_length - ip_off; 633 634 if (ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4) { 635 struct ip *ip = 636 (struct ip *)(vaddr + ip_off); 637 start = ip->ip_hl * 4; 638 } else { 639 start = 40; 640 } 641 cksum_flags |= HCK_PARTIALCKSUM; 642 mac_hcksum_set(mp, start, 0, end, 643 ntohs(ext_info->l4_cksum), cksum_flags); 644 } 645 } 646 647 /* 648 * xgell_rx_1b_msg_alloc 649 * 650 * Allocate message header for data buffer, and decide if copy the packet to 651 * new data buffer to release big rx_buffer to save memory. 652 * 653 * If the pkt_length <= XGELL_RX_DMA_LOWAT, call allocb() to allocate 654 * new message and copy the payload in. 655 */ 656 static mblk_t * 657 xgell_rx_1b_msg_alloc(xgell_rx_ring_t *ring, xgell_rx_buffer_t *rx_buffer, 658 int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit) 659 { 660 xgelldev_t *lldev = ring->lldev; 661 mblk_t *mp; 662 char *vaddr; 663 664 vaddr = (char *)rx_buffer->vaddr + HEADROOM; 665 /* 666 * Copy packet into new allocated message buffer, if pkt_length 667 * is less than XGELL_RX_DMA_LOWAT 668 */ 669 if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) { 670 if ((mp = allocb(pkt_length + HEADROOM, 0)) == NULL) { 671 return (NULL); 672 } 673 mp->b_rptr += HEADROOM; 674 bcopy(vaddr, mp->b_rptr, pkt_length); 675 mp->b_wptr = mp->b_rptr + pkt_length; 676 *copyit = B_TRUE; 677 return (mp); 678 } 679 680 /* 681 * Just allocate mblk for current data buffer 682 */ 683 if ((mp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0, 684 &rx_buffer->frtn)) == NULL) { 685 /* Drop it */ 686 return (NULL); 687 } 688 /* 689 * Adjust the b_rptr/b_wptr in the mblk_t structure. 690 */ 691 mp->b_wptr += pkt_length; 692 693 return (mp); 694 } 695 696 /* 697 * xgell_rx_1b_callback 698 * 699 * If the interrupt is because of a received frame or if the receive ring 700 * contains fresh as yet un-processed frames, this function is called. 701 */ 702 static xge_hal_status_e 703 xgell_rx_1b_callback(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, 704 void *userdata) 705 { 706 xgell_rx_ring_t *ring = (xgell_rx_ring_t *)userdata; 707 xgelldev_t *lldev = ring->lldev; 708 xgell_rx_buffer_t *rx_buffer; 709 mblk_t *mp_head = NULL; 710 mblk_t *mp_end = NULL; 711 int pkt_burst = 0; 712 713 xge_debug_ll(XGE_TRACE, "xgell_rx_1b_callback on ring %d", ring->index); 714 715 mutex_enter(&ring->bf_pool.pool_lock); 716 do { 717 int pkt_length; 718 dma_addr_t dma_data; 719 mblk_t *mp; 720 boolean_t copyit = B_FALSE; 721 722 xgell_rxd_priv_t *rxd_priv = ((xgell_rxd_priv_t *) 723 xge_hal_ring_dtr_private(channelh, dtr)); 724 xge_hal_dtr_info_t ext_info; 725 726 rx_buffer = rxd_priv->rx_buffer; 727 728 xge_hal_ring_dtr_1b_get(channelh, dtr, &dma_data, &pkt_length); 729 xge_hal_ring_dtr_info_get(channelh, dtr, &ext_info); 730 731 xge_assert(dma_data == rx_buffer->dma_addr); 732 733 if (t_code != 0) { 734 xge_debug_ll(XGE_ERR, "%s%d: rx: dtr 0x%"PRIx64 735 " completed due to error t_code %01x", XGELL_IFNAME, 736 lldev->instance, (uint64_t)(uintptr_t)dtr, t_code); 737 738 (void) xge_hal_device_handle_tcode(channelh, dtr, 739 t_code); 740 xge_hal_ring_dtr_free(channelh, dtr); /* drop it */ 741 xgell_rx_buffer_release(rx_buffer); 742 continue; 743 } 744 745 /* 746 * Sync the DMA memory 747 */ 748 if (ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length, 749 DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) { 750 xge_debug_ll(XGE_ERR, "%s%d: rx: can not do DMA sync", 751 XGELL_IFNAME, lldev->instance); 752 xge_hal_ring_dtr_free(channelh, dtr); /* drop it */ 753 xgell_rx_buffer_release(rx_buffer); 754 continue; 755 } 756 757 /* 758 * Allocate message for the packet. 759 */ 760 if (ring->bf_pool.post > ring->bf_pool.post_hiwat) { 761 copyit = B_TRUE; 762 } else { 763 copyit = B_FALSE; 764 } 765 766 mp = xgell_rx_1b_msg_alloc(ring, rx_buffer, pkt_length, 767 &ext_info, ©it); 768 769 xge_hal_ring_dtr_free(channelh, dtr); 770 771 /* 772 * Release the buffer and recycle it later 773 */ 774 if ((mp == NULL) || copyit) { 775 xgell_rx_buffer_release(rx_buffer); 776 } else { 777 /* 778 * Count it since the buffer should be loaned up. 779 */ 780 ring->bf_pool.post++; 781 } 782 if (mp == NULL) { 783 xge_debug_ll(XGE_ERR, 784 "%s%d: rx: can not allocate mp mblk", 785 XGELL_IFNAME, lldev->instance); 786 continue; 787 } 788 789 /* 790 * Associate cksum_flags per packet type and h/w 791 * cksum flags. 792 */ 793 xgell_rx_hcksum_assoc(mp, (char *)rx_buffer->vaddr + HEADROOM, 794 pkt_length, &ext_info); 795 796 ring->rx_pkts++; 797 ring->rx_bytes += pkt_length; 798 799 if (mp_head == NULL) { 800 mp_head = mp; 801 mp_end = mp; 802 } else { 803 mp_end->b_next = mp; 804 mp_end = mp; 805 } 806 807 /* 808 * Inlined implemented polling function. 809 */ 810 if ((ring->poll_mp == NULL) && (ring->poll_bytes > 0)) { 811 ring->poll_mp = mp_head; 812 } 813 if (ring->poll_mp != NULL) { 814 if ((ring->poll_bytes -= pkt_length) <= 0) { 815 /* have polled enough packets. */ 816 break; 817 } else { 818 /* continue polling packets. */ 819 continue; 820 } 821 } 822 823 /* 824 * We're not in polling mode, so try to chain more messages 825 * or send the chain up according to pkt_burst. 826 */ 827 if (++pkt_burst < lldev->config.rx_pkt_burst) 828 continue; 829 830 if (ring->bf_pool.post > ring->bf_pool.post_hiwat) { 831 /* Replenish rx buffers */ 832 xgell_rx_buffer_replenish_all(ring); 833 } 834 mutex_exit(&ring->bf_pool.pool_lock); 835 if (mp_head != NULL) { 836 mac_rx_ring(lldev->mh, ring->ring_handle, mp_head, 837 ring->ring_gen_num); 838 } 839 mp_head = mp_end = NULL; 840 pkt_burst = 0; 841 mutex_enter(&ring->bf_pool.pool_lock); 842 843 } while (xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) == 844 XGE_HAL_OK); 845 846 /* 847 * Always call replenish_all to recycle rx_buffers. 848 */ 849 xgell_rx_buffer_replenish_all(ring); 850 mutex_exit(&ring->bf_pool.pool_lock); 851 852 /* 853 * If we're not in polling cycle, call mac_rx(), otherwise 854 * just return while leaving packets chained to ring->poll_mp. 855 */ 856 if ((ring->poll_mp == NULL) && (mp_head != NULL)) { 857 mac_rx_ring(lldev->mh, ring->ring_handle, mp_head, 858 ring->ring_gen_num); 859 } 860 861 return (XGE_HAL_OK); 862 } 863 864 mblk_t * 865 xgell_rx_poll(void *arg, int bytes_to_pickup) 866 { 867 xgell_rx_ring_t *ring = (xgell_rx_ring_t *)arg; 868 int got_rx = 0; 869 mblk_t *mp; 870 871 xge_debug_ll(XGE_TRACE, "xgell_rx_poll on ring %d", ring->index); 872 873 ring->poll_mp = NULL; 874 ring->poll_bytes = bytes_to_pickup; 875 (void) xge_hal_device_poll_rx_channel(ring->channelh, &got_rx); 876 877 mp = ring->poll_mp; 878 ring->poll_bytes = -1; 879 ring->polled_bytes += got_rx; 880 ring->poll_mp = NULL; 881 882 return (mp); 883 } 884 885 /* 886 * xgell_xmit_compl 887 * 888 * If an interrupt was raised to indicate DMA complete of the Tx packet, 889 * this function is called. It identifies the last TxD whose buffer was 890 * freed and frees all skbs whose data have already DMA'ed into the NICs 891 * internal memory. 892 */ 893 static xge_hal_status_e 894 xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, 895 void *userdata) 896 { 897 xgell_tx_ring_t *ring = userdata; 898 xgelldev_t *lldev = ring->lldev; 899 900 do { 901 xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *) 902 xge_hal_fifo_dtr_private(dtr)); 903 int i; 904 905 if (t_code) { 906 xge_debug_ll(XGE_TRACE, "%s%d: tx: dtr 0x%"PRIx64 907 " completed due to error t_code %01x", XGELL_IFNAME, 908 lldev->instance, (uint64_t)(uintptr_t)dtr, t_code); 909 910 (void) xge_hal_device_handle_tcode(channelh, dtr, 911 t_code); 912 } 913 914 for (i = 0; i < txd_priv->handle_cnt; i++) { 915 if (txd_priv->dma_handles[i] != NULL) { 916 xge_assert(txd_priv->dma_handles[i]); 917 (void) ddi_dma_unbind_handle( 918 txd_priv->dma_handles[i]); 919 ddi_dma_free_handle(&txd_priv->dma_handles[i]); 920 txd_priv->dma_handles[i] = 0; 921 } 922 } 923 txd_priv->handle_cnt = 0; 924 925 xge_hal_fifo_dtr_free(channelh, dtr); 926 927 if (txd_priv->mblk != NULL) { 928 freemsg(txd_priv->mblk); 929 txd_priv->mblk = NULL; 930 } 931 932 } while (xge_hal_fifo_dtr_next_completed(channelh, &dtr, &t_code) == 933 XGE_HAL_OK); 934 935 if (ring->need_resched) 936 mac_tx_ring_update(lldev->mh, ring->ring_handle); 937 938 return (XGE_HAL_OK); 939 } 940 941 mblk_t * 942 xgell_ring_tx(void *arg, mblk_t *mp) 943 { 944 xgell_tx_ring_t *ring = (xgell_tx_ring_t *)arg; 945 mblk_t *bp; 946 xgelldev_t *lldev = ring->lldev; 947 xge_hal_device_t *hldev = lldev->devh; 948 xge_hal_status_e status; 949 xge_hal_dtr_h dtr; 950 xgell_txd_priv_t *txd_priv; 951 uint32_t hckflags; 952 uint32_t lsoflags; 953 uint32_t mss; 954 int handle_cnt, frag_cnt, ret, i, copied; 955 boolean_t used_copy; 956 uint64_t sent_bytes; 957 958 handle_cnt = frag_cnt = 0; 959 sent_bytes = 0; 960 961 if (!lldev->is_initialized || lldev->in_reset) 962 return (mp); 963 964 /* 965 * If the free Tx dtrs count reaches the lower threshold, 966 * inform the gld to stop sending more packets till the free 967 * dtrs count exceeds higher threshold. Driver informs the 968 * gld through gld_sched call, when the free dtrs count exceeds 969 * the higher threshold. 970 */ 971 if (xge_hal_channel_dtr_count(ring->channelh) 972 <= XGELL_TX_LEVEL_LOW) { 973 xge_debug_ll(XGE_TRACE, "%s%d: queue %d: err on xmit," 974 "free descriptors count at low threshold %d", 975 XGELL_IFNAME, lldev->instance, 976 ((xge_hal_channel_t *)ring->channelh)->post_qid, 977 XGELL_TX_LEVEL_LOW); 978 goto _exit; 979 } 980 981 status = xge_hal_fifo_dtr_reserve(ring->channelh, &dtr); 982 if (status != XGE_HAL_OK) { 983 switch (status) { 984 case XGE_HAL_INF_CHANNEL_IS_NOT_READY: 985 xge_debug_ll(XGE_ERR, 986 "%s%d: channel %d is not ready.", XGELL_IFNAME, 987 lldev->instance, 988 ((xge_hal_channel_t *) 989 ring->channelh)->post_qid); 990 goto _exit; 991 case XGE_HAL_INF_OUT_OF_DESCRIPTORS: 992 xge_debug_ll(XGE_TRACE, "%s%d: queue %d: error in xmit," 993 " out of descriptors.", XGELL_IFNAME, 994 lldev->instance, 995 ((xge_hal_channel_t *) 996 ring->channelh)->post_qid); 997 goto _exit; 998 default: 999 return (mp); 1000 } 1001 } 1002 1003 txd_priv = xge_hal_fifo_dtr_private(dtr); 1004 txd_priv->mblk = mp; 1005 1006 /* 1007 * VLAN tag should be passed down along with MAC header, so h/w needn't 1008 * do insertion. 1009 * 1010 * For NIC driver that has to strip and re-insert VLAN tag, the example 1011 * is the other implementation for xge. The driver can simple bcopy() 1012 * ether_vlan_header to overwrite VLAN tag and let h/w insert the tag 1013 * automatically, since it's impossible that GLD sends down mp(s) with 1014 * splited ether_vlan_header. 1015 * 1016 * struct ether_vlan_header *evhp; 1017 * uint16_t tci; 1018 * 1019 * evhp = (struct ether_vlan_header *)mp->b_rptr; 1020 * if (evhp->ether_tpid == htons(VLAN_TPID)) { 1021 * tci = ntohs(evhp->ether_tci); 1022 * (void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, 1023 * 2 * ETHERADDRL); 1024 * mp->b_rptr += VLAN_TAGSZ; 1025 * 1026 * xge_hal_fifo_dtr_vlan_set(dtr, tci); 1027 * } 1028 */ 1029 1030 copied = 0; 1031 used_copy = B_FALSE; 1032 for (bp = mp; bp != NULL; bp = bp->b_cont) { 1033 int mblen; 1034 uint_t ncookies; 1035 ddi_dma_cookie_t dma_cookie; 1036 ddi_dma_handle_t dma_handle; 1037 1038 /* skip zero-length message blocks */ 1039 mblen = MBLKL(bp); 1040 if (mblen == 0) { 1041 continue; 1042 } 1043 1044 sent_bytes += mblen; 1045 1046 /* 1047 * Check the message length to decide to DMA or bcopy() data 1048 * to tx descriptor(s). 1049 */ 1050 if (mblen < lldev->config.tx_dma_lowat && 1051 (copied + mblen) < lldev->tx_copied_max) { 1052 xge_hal_status_e rc; 1053 rc = xge_hal_fifo_dtr_buffer_append(ring->channelh, 1054 dtr, bp->b_rptr, mblen); 1055 if (rc == XGE_HAL_OK) { 1056 used_copy = B_TRUE; 1057 copied += mblen; 1058 continue; 1059 } else if (used_copy) { 1060 xge_hal_fifo_dtr_buffer_finalize( 1061 ring->channelh, dtr, frag_cnt++); 1062 used_copy = B_FALSE; 1063 } 1064 } else if (used_copy) { 1065 xge_hal_fifo_dtr_buffer_finalize(ring->channelh, 1066 dtr, frag_cnt++); 1067 used_copy = B_FALSE; 1068 } 1069 1070 ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr, 1071 DDI_DMA_DONTWAIT, 0, &dma_handle); 1072 if (ret != DDI_SUCCESS) { 1073 xge_debug_ll(XGE_ERR, 1074 "%s%d: can not allocate dma handle", XGELL_IFNAME, 1075 lldev->instance); 1076 goto _exit_cleanup; 1077 } 1078 1079 ret = ddi_dma_addr_bind_handle(dma_handle, NULL, 1080 (caddr_t)bp->b_rptr, mblen, 1081 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0, 1082 &dma_cookie, &ncookies); 1083 1084 switch (ret) { 1085 case DDI_DMA_MAPPED: 1086 /* everything's fine */ 1087 break; 1088 1089 case DDI_DMA_NORESOURCES: 1090 xge_debug_ll(XGE_ERR, 1091 "%s%d: can not bind dma address", 1092 XGELL_IFNAME, lldev->instance); 1093 ddi_dma_free_handle(&dma_handle); 1094 goto _exit_cleanup; 1095 1096 case DDI_DMA_NOMAPPING: 1097 case DDI_DMA_INUSE: 1098 case DDI_DMA_TOOBIG: 1099 default: 1100 /* drop packet, don't retry */ 1101 xge_debug_ll(XGE_ERR, 1102 "%s%d: can not map message buffer", 1103 XGELL_IFNAME, lldev->instance); 1104 ddi_dma_free_handle(&dma_handle); 1105 goto _exit_cleanup; 1106 } 1107 1108 if (ncookies + frag_cnt > hldev->config.fifo.max_frags) { 1109 xge_debug_ll(XGE_ERR, "%s%d: too many fragments, " 1110 "requested c:%d+f:%d", XGELL_IFNAME, 1111 lldev->instance, ncookies, frag_cnt); 1112 (void) ddi_dma_unbind_handle(dma_handle); 1113 ddi_dma_free_handle(&dma_handle); 1114 goto _exit_cleanup; 1115 } 1116 1117 /* setup the descriptors for this data buffer */ 1118 while (ncookies) { 1119 xge_hal_fifo_dtr_buffer_set(ring->channelh, dtr, 1120 frag_cnt++, dma_cookie.dmac_laddress, 1121 dma_cookie.dmac_size); 1122 if (--ncookies) { 1123 ddi_dma_nextcookie(dma_handle, &dma_cookie); 1124 } 1125 1126 } 1127 1128 txd_priv->dma_handles[handle_cnt++] = dma_handle; 1129 1130 if (bp->b_cont && 1131 (frag_cnt + XGE_HAL_DEFAULT_FIFO_FRAGS_THRESHOLD >= 1132 hldev->config.fifo.max_frags)) { 1133 mblk_t *nmp; 1134 1135 xge_debug_ll(XGE_TRACE, 1136 "too many FRAGs [%d], pull up them", frag_cnt); 1137 1138 if ((nmp = msgpullup(bp->b_cont, -1)) == NULL) { 1139 /* Drop packet, don't retry */ 1140 xge_debug_ll(XGE_ERR, 1141 "%s%d: can not pullup message buffer", 1142 XGELL_IFNAME, lldev->instance); 1143 goto _exit_cleanup; 1144 } 1145 freemsg(bp->b_cont); 1146 bp->b_cont = nmp; 1147 } 1148 } 1149 1150 /* finalize unfinished copies */ 1151 if (used_copy) { 1152 xge_hal_fifo_dtr_buffer_finalize(ring->channelh, dtr, 1153 frag_cnt++); 1154 } 1155 1156 txd_priv->handle_cnt = handle_cnt; 1157 1158 /* 1159 * If LSO is required, just call xge_hal_fifo_dtr_mss_set(dtr, mss) to 1160 * do all necessary work. 1161 */ 1162 mac_lso_get(mp, &mss, &lsoflags); 1163 1164 if (lsoflags & HW_LSO) { 1165 xge_assert((mss != 0) && (mss <= XGE_HAL_DEFAULT_MTU)); 1166 xge_hal_fifo_dtr_mss_set(dtr, mss); 1167 } 1168 1169 mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &hckflags); 1170 if (hckflags & HCK_IPV4_HDRCKSUM) { 1171 xge_hal_fifo_dtr_cksum_set_bits(dtr, 1172 XGE_HAL_TXD_TX_CKO_IPV4_EN); 1173 } 1174 if (hckflags & HCK_FULLCKSUM) { 1175 xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_TCP_EN | 1176 XGE_HAL_TXD_TX_CKO_UDP_EN); 1177 } 1178 1179 xge_hal_fifo_dtr_post(ring->channelh, dtr); 1180 1181 /* Update per-ring tx statistics */ 1182 atomic_inc_64(&ring->tx_pkts); 1183 atomic_add_64(&ring->tx_bytes, sent_bytes); 1184 1185 return (NULL); 1186 1187 _exit_cleanup: 1188 /* 1189 * Could not successfully transmit but have changed the message, 1190 * so just free it and return NULL 1191 */ 1192 for (i = 0; i < handle_cnt; i++) { 1193 (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]); 1194 ddi_dma_free_handle(&txd_priv->dma_handles[i]); 1195 txd_priv->dma_handles[i] = 0; 1196 } 1197 1198 xge_hal_fifo_dtr_free(ring->channelh, dtr); 1199 1200 freemsg(mp); 1201 return (NULL); 1202 1203 _exit: 1204 ring->need_resched = B_TRUE; 1205 return (mp); 1206 } 1207 1208 /* 1209 * xgell_ring_macaddr_init 1210 */ 1211 static void 1212 xgell_rx_ring_maddr_init(xgell_rx_ring_t *ring) 1213 { 1214 int i; 1215 xgelldev_t *lldev = ring->lldev; 1216 xge_hal_device_t *hldev = lldev->devh; 1217 int slot_start; 1218 1219 xge_debug_ll(XGE_TRACE, "%s", "xgell_rx_ring_maddr_init"); 1220 1221 ring->mmac.naddr = XGE_RX_MULTI_MAC_ADDRESSES_MAX; 1222 ring->mmac.naddrfree = ring->mmac.naddr; 1223 1224 /* 1225 * For the default rx ring, the first MAC address is the factory one. 1226 * This will be set by the framework, so need to clear it for now. 1227 */ 1228 (void) xge_hal_device_macaddr_clear(hldev, 0); 1229 1230 /* 1231 * Read the MAC address Configuration Memory from HAL. 1232 * The first slot will hold a factory MAC address, contents in other 1233 * slots will be FF:FF:FF:FF:FF:FF. 1234 */ 1235 slot_start = ring->index * 32; 1236 for (i = 0; i < ring->mmac.naddr; i++) { 1237 (void) xge_hal_device_macaddr_get(hldev, slot_start + i, 1238 ring->mmac.mac_addr + i); 1239 ring->mmac.mac_addr_set[i] = B_FALSE; 1240 } 1241 } 1242 1243 static int xgell_maddr_set(xgelldev_t *, int, uint8_t *); 1244 1245 static int 1246 xgell_addmac(void *arg, const uint8_t *mac_addr) 1247 { 1248 xgell_rx_ring_t *ring = arg; 1249 xgelldev_t *lldev = ring->lldev; 1250 xge_hal_device_t *hldev = lldev->devh; 1251 int slot; 1252 int slot_start; 1253 1254 xge_debug_ll(XGE_TRACE, "%s", "xgell_addmac"); 1255 1256 mutex_enter(&lldev->genlock); 1257 1258 if (ring->mmac.naddrfree == 0) { 1259 mutex_exit(&lldev->genlock); 1260 return (ENOSPC); 1261 } 1262 1263 /* First slot is for factory MAC address */ 1264 for (slot = 0; slot < ring->mmac.naddr; slot++) { 1265 if (ring->mmac.mac_addr_set[slot] == B_FALSE) { 1266 break; 1267 } 1268 } 1269 1270 ASSERT(slot < ring->mmac.naddr); 1271 1272 slot_start = ring->index * 32; 1273 1274 if (xgell_maddr_set(lldev, slot_start + slot, (uint8_t *)mac_addr) != 1275 0) { 1276 mutex_exit(&lldev->genlock); 1277 return (EIO); 1278 } 1279 1280 /* Simply enable RTS for the whole section. */ 1281 (void) xge_hal_device_rts_section_enable(hldev, slot_start + slot); 1282 1283 /* 1284 * Read back the MAC address from HAL to keep the array up to date. 1285 */ 1286 if (xge_hal_device_macaddr_get(hldev, slot_start + slot, 1287 ring->mmac.mac_addr + slot) != XGE_HAL_OK) { 1288 (void) xge_hal_device_macaddr_clear(hldev, slot_start + slot); 1289 return (EIO); 1290 } 1291 1292 ring->mmac.mac_addr_set[slot] = B_TRUE; 1293 ring->mmac.naddrfree--; 1294 1295 mutex_exit(&lldev->genlock); 1296 1297 return (0); 1298 } 1299 1300 static int 1301 xgell_remmac(void *arg, const uint8_t *mac_addr) 1302 { 1303 xgell_rx_ring_t *ring = arg; 1304 xgelldev_t *lldev = ring->lldev; 1305 xge_hal_device_t *hldev = lldev->devh; 1306 xge_hal_status_e status; 1307 int slot; 1308 int slot_start; 1309 1310 xge_debug_ll(XGE_TRACE, "%s", "xgell_remmac"); 1311 1312 slot = xge_hal_device_macaddr_find(hldev, (uint8_t *)mac_addr); 1313 if (slot == -1) 1314 return (EINVAL); 1315 1316 slot_start = ring->index * 32; 1317 1318 /* 1319 * Adjust slot to the offset in the MAC array of this ring (group). 1320 */ 1321 slot -= slot_start; 1322 1323 /* 1324 * Only can remove a pre-set MAC address for this ring (group). 1325 */ 1326 if (slot < 0 || slot >= ring->mmac.naddr) 1327 return (EINVAL); 1328 1329 1330 xge_assert(ring->mmac.mac_addr_set[slot]); 1331 1332 mutex_enter(&lldev->genlock); 1333 if (!ring->mmac.mac_addr_set[slot]) { 1334 mutex_exit(&lldev->genlock); 1335 /* 1336 * The result will be unexpected when reach here. WARNING! 1337 */ 1338 xge_debug_ll(XGE_ERR, 1339 "%s%d: caller is trying to remove an unset MAC address", 1340 XGELL_IFNAME, lldev->instance); 1341 return (ENXIO); 1342 } 1343 1344 status = xge_hal_device_macaddr_clear(hldev, slot_start + slot); 1345 if (status != XGE_HAL_OK) { 1346 mutex_exit(&lldev->genlock); 1347 return (EIO); 1348 } 1349 1350 ring->mmac.mac_addr_set[slot] = B_FALSE; 1351 ring->mmac.naddrfree++; 1352 1353 /* 1354 * TODO: Disable MAC RTS if all addresses have been cleared. 1355 */ 1356 1357 /* 1358 * Read back the MAC address from HAL to keep the array up to date. 1359 */ 1360 (void) xge_hal_device_macaddr_get(hldev, slot_start + slot, 1361 ring->mmac.mac_addr + slot); 1362 mutex_exit(&lldev->genlock); 1363 1364 return (0); 1365 } 1366 1367 /* 1368 * Temporarily calling hal function. 1369 * 1370 * With MSI-X implementation, no lock is needed, so that the interrupt 1371 * handling could be faster. 1372 */ 1373 int 1374 xgell_rx_ring_intr_enable(mac_intr_handle_t ih) 1375 { 1376 xgell_rx_ring_t *ring = (xgell_rx_ring_t *)ih; 1377 1378 mutex_enter(&ring->ring_lock); 1379 xge_hal_device_rx_channel_disable_polling(ring->channelh); 1380 mutex_exit(&ring->ring_lock); 1381 1382 return (0); 1383 } 1384 1385 int 1386 xgell_rx_ring_intr_disable(mac_intr_handle_t ih) 1387 { 1388 xgell_rx_ring_t *ring = (xgell_rx_ring_t *)ih; 1389 1390 mutex_enter(&ring->ring_lock); 1391 xge_hal_device_rx_channel_enable_polling(ring->channelh); 1392 mutex_exit(&ring->ring_lock); 1393 1394 return (0); 1395 } 1396 1397 static int 1398 xgell_rx_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 1399 { 1400 xgell_rx_ring_t *rx_ring = (xgell_rx_ring_t *)rh; 1401 1402 rx_ring->ring_gen_num = mr_gen_num; 1403 1404 return (0); 1405 } 1406 1407 /*ARGSUSED*/ 1408 static void 1409 xgell_rx_ring_stop(mac_ring_driver_t rh) 1410 { 1411 } 1412 1413 /*ARGSUSED*/ 1414 static int 1415 xgell_tx_ring_start(mac_ring_driver_t rh, uint64_t useless) 1416 { 1417 return (0); 1418 } 1419 1420 /*ARGSUSED*/ 1421 static void 1422 xgell_tx_ring_stop(mac_ring_driver_t rh) 1423 { 1424 } 1425 1426 /* 1427 * Callback funtion for MAC layer to register all rings. 1428 * 1429 * Xframe hardware doesn't support grouping explicitly, so the driver needs 1430 * to pretend having resource groups. We may also optionally group all 8 rx 1431 * rings into a single group for increased scalability on CMT architectures, 1432 * or group one rx ring per group for maximum virtualization. 1433 * 1434 * TX grouping is actually done by framework, so, just register all TX 1435 * resources without grouping them. 1436 */ 1437 void 1438 xgell_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 1439 const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 1440 { 1441 xgelldev_t *lldev = (xgelldev_t *)arg; 1442 mac_intr_t *mintr; 1443 1444 switch (rtype) { 1445 case MAC_RING_TYPE_RX: { 1446 xgell_rx_ring_t *rx_ring; 1447 1448 xge_assert(index < lldev->init_rx_rings); 1449 xge_assert(rg_index < lldev->init_rx_groups); 1450 1451 /* 1452 * Performance vs. Virtualization 1453 */ 1454 if (lldev->init_rx_rings == lldev->init_rx_groups) 1455 rx_ring = lldev->rx_ring + rg_index; 1456 else 1457 rx_ring = lldev->rx_ring + index; 1458 1459 rx_ring->ring_handle = rh; 1460 1461 infop->mri_driver = (mac_ring_driver_t)rx_ring; 1462 infop->mri_start = xgell_rx_ring_start; 1463 infop->mri_stop = xgell_rx_ring_stop; 1464 infop->mri_poll = xgell_rx_poll; 1465 infop->mri_stat = xgell_rx_ring_stat; 1466 1467 mintr = &infop->mri_intr; 1468 mintr->mi_handle = (mac_intr_handle_t)rx_ring; 1469 mintr->mi_enable = xgell_rx_ring_intr_enable; 1470 mintr->mi_disable = xgell_rx_ring_intr_disable; 1471 1472 break; 1473 } 1474 case MAC_RING_TYPE_TX: { 1475 xgell_tx_ring_t *tx_ring; 1476 1477 xge_assert(rg_index == -1); 1478 1479 xge_assert((index >= 0) && (index < lldev->init_tx_rings)); 1480 1481 tx_ring = lldev->tx_ring + index; 1482 tx_ring->ring_handle = rh; 1483 1484 infop->mri_driver = (mac_ring_driver_t)tx_ring; 1485 infop->mri_start = xgell_tx_ring_start; 1486 infop->mri_stop = xgell_tx_ring_stop; 1487 infop->mri_tx = xgell_ring_tx; 1488 infop->mri_stat = xgell_tx_ring_stat; 1489 1490 break; 1491 } 1492 default: 1493 break; 1494 } 1495 } 1496 1497 void 1498 xgell_fill_group(void *arg, mac_ring_type_t rtype, const int index, 1499 mac_group_info_t *infop, mac_group_handle_t gh) 1500 { 1501 xgelldev_t *lldev = (xgelldev_t *)arg; 1502 1503 switch (rtype) { 1504 case MAC_RING_TYPE_RX: { 1505 xgell_rx_ring_t *rx_ring; 1506 1507 xge_assert(index < lldev->init_rx_groups); 1508 1509 rx_ring = lldev->rx_ring + index; 1510 1511 rx_ring->group_handle = gh; 1512 1513 infop->mgi_driver = (mac_group_driver_t)rx_ring; 1514 infop->mgi_start = NULL; 1515 infop->mgi_stop = NULL; 1516 infop->mgi_addmac = xgell_addmac; 1517 infop->mgi_remmac = xgell_remmac; 1518 infop->mgi_count = lldev->init_rx_rings / lldev->init_rx_groups; 1519 1520 break; 1521 } 1522 case MAC_RING_TYPE_TX: 1523 xge_assert(0); 1524 break; 1525 default: 1526 break; 1527 } 1528 } 1529 1530 /* 1531 * xgell_macaddr_set 1532 */ 1533 static int 1534 xgell_maddr_set(xgelldev_t *lldev, int index, uint8_t *macaddr) 1535 { 1536 xge_hal_device_t *hldev = lldev->devh; 1537 xge_hal_status_e status; 1538 1539 xge_debug_ll(XGE_TRACE, "%s", "xgell_maddr_set"); 1540 1541 xge_debug_ll(XGE_TRACE, 1542 "setting macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x", 1543 macaddr[0], macaddr[1], macaddr[2], 1544 macaddr[3], macaddr[4], macaddr[5]); 1545 1546 status = xge_hal_device_macaddr_set(hldev, index, (uchar_t *)macaddr); 1547 1548 if (status != XGE_HAL_OK) { 1549 xge_debug_ll(XGE_ERR, "%s%d: can not set mac address", 1550 XGELL_IFNAME, lldev->instance); 1551 return (EIO); 1552 } 1553 1554 return (0); 1555 } 1556 1557 /* 1558 * xgell_rx_dtr_term 1559 * 1560 * Function will be called by HAL to terminate all DTRs for 1561 * Ring(s) type of channels. 1562 */ 1563 static void 1564 xgell_rx_dtr_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, 1565 xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen) 1566 { 1567 xgell_rxd_priv_t *rxd_priv = 1568 ((xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtrh)); 1569 xgell_rx_buffer_t *rx_buffer = rxd_priv->rx_buffer; 1570 1571 if (state == XGE_HAL_DTR_STATE_POSTED) { 1572 xgell_rx_ring_t *ring = rx_buffer->ring; 1573 1574 mutex_enter(&ring->bf_pool.pool_lock); 1575 xge_hal_ring_dtr_free(channelh, dtrh); 1576 xgell_rx_buffer_release(rx_buffer); 1577 mutex_exit(&ring->bf_pool.pool_lock); 1578 } 1579 } 1580 1581 /* 1582 * To open a rx ring. 1583 */ 1584 static boolean_t 1585 xgell_rx_ring_open(xgell_rx_ring_t *rx_ring) 1586 { 1587 xge_hal_status_e status; 1588 xge_hal_channel_attr_t attr; 1589 xgelldev_t *lldev = rx_ring->lldev; 1590 xge_hal_device_t *hldev = lldev->devh; 1591 1592 if (rx_ring->live) 1593 return (B_TRUE); 1594 1595 /* Create the buffer pool first */ 1596 if (!xgell_rx_create_buffer_pool(rx_ring)) { 1597 xge_debug_ll(XGE_ERR, "can not create buffer pool for ring: %d", 1598 rx_ring->index); 1599 return (B_FALSE); 1600 } 1601 1602 /* Default ring initialization */ 1603 attr.post_qid = rx_ring->index; 1604 attr.compl_qid = 0; 1605 attr.callback = xgell_rx_1b_callback; 1606 attr.per_dtr_space = sizeof (xgell_rxd_priv_t); 1607 attr.flags = 0; 1608 attr.type = XGE_HAL_CHANNEL_TYPE_RING; 1609 attr.dtr_init = xgell_rx_dtr_replenish; 1610 attr.dtr_term = xgell_rx_dtr_term; 1611 attr.userdata = rx_ring; 1612 1613 status = xge_hal_channel_open(lldev->devh, &attr, &rx_ring->channelh, 1614 XGE_HAL_CHANNEL_OC_NORMAL); 1615 if (status != XGE_HAL_OK) { 1616 xge_debug_ll(XGE_ERR, "%s%d: cannot open Rx channel got status " 1617 " code %d", XGELL_IFNAME, lldev->instance, status); 1618 (void) xgell_rx_destroy_buffer_pool(rx_ring); 1619 return (B_FALSE); 1620 } 1621 1622 xgell_rx_ring_maddr_init(rx_ring); 1623 1624 mutex_init(&rx_ring->ring_lock, NULL, MUTEX_DRIVER, 1625 DDI_INTR_PRI(hldev->irqh)); 1626 1627 rx_ring->poll_bytes = -1; 1628 rx_ring->polled_bytes = 0; 1629 rx_ring->poll_mp = NULL; 1630 rx_ring->live = B_TRUE; 1631 1632 xge_debug_ll(XGE_TRACE, "RX ring [%d] is opened successfully", 1633 rx_ring->index); 1634 1635 return (B_TRUE); 1636 } 1637 1638 static void 1639 xgell_rx_ring_close(xgell_rx_ring_t *rx_ring) 1640 { 1641 if (!rx_ring->live) 1642 return; 1643 xge_hal_channel_close(rx_ring->channelh, XGE_HAL_CHANNEL_OC_NORMAL); 1644 rx_ring->channelh = NULL; 1645 /* This may not clean up all used buffers, driver will handle it */ 1646 if (xgell_rx_destroy_buffer_pool(rx_ring)) 1647 rx_ring->live = B_FALSE; 1648 1649 mutex_destroy(&rx_ring->ring_lock); 1650 } 1651 1652 /* 1653 * xgell_rx_open 1654 * @lldev: the link layer object 1655 * 1656 * Initialize and open all RX channels. 1657 */ 1658 static boolean_t 1659 xgell_rx_open(xgelldev_t *lldev) 1660 { 1661 xgell_rx_ring_t *rx_ring; 1662 int i; 1663 1664 if (lldev->live_rx_rings != 0) 1665 return (B_TRUE); 1666 1667 lldev->live_rx_rings = 0; 1668 1669 /* 1670 * Initialize all rings 1671 */ 1672 for (i = 0; i < lldev->init_rx_rings; i++) { 1673 rx_ring = &lldev->rx_ring[i]; 1674 rx_ring->index = i; 1675 rx_ring->lldev = lldev; 1676 rx_ring->live = B_FALSE; 1677 1678 if (!xgell_rx_ring_open(rx_ring)) 1679 return (B_FALSE); 1680 1681 lldev->live_rx_rings++; 1682 } 1683 1684 return (B_TRUE); 1685 } 1686 1687 static void 1688 xgell_rx_close(xgelldev_t *lldev) 1689 { 1690 xgell_rx_ring_t *rx_ring; 1691 int i; 1692 1693 if (lldev->live_rx_rings == 0) 1694 return; 1695 1696 /* 1697 * Close all rx rings 1698 */ 1699 for (i = 0; i < lldev->init_rx_rings; i++) { 1700 rx_ring = &lldev->rx_ring[i]; 1701 1702 if (rx_ring->live) { 1703 xgell_rx_ring_close(rx_ring); 1704 lldev->live_rx_rings--; 1705 } 1706 } 1707 1708 xge_assert(lldev->live_rx_rings == 0); 1709 } 1710 1711 /* 1712 * xgell_tx_term 1713 * 1714 * Function will be called by HAL to terminate all DTRs for 1715 * Fifo(s) type of channels. 1716 */ 1717 static void 1718 xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, 1719 xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen) 1720 { 1721 xgell_txd_priv_t *txd_priv = 1722 ((xgell_txd_priv_t *)xge_hal_fifo_dtr_private(dtrh)); 1723 mblk_t *mp = txd_priv->mblk; 1724 int i; 1725 1726 /* 1727 * for Tx we must clean up the DTR *only* if it has been 1728 * posted! 1729 */ 1730 if (state != XGE_HAL_DTR_STATE_POSTED) { 1731 return; 1732 } 1733 1734 for (i = 0; i < txd_priv->handle_cnt; i++) { 1735 xge_assert(txd_priv->dma_handles[i]); 1736 (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]); 1737 ddi_dma_free_handle(&txd_priv->dma_handles[i]); 1738 txd_priv->dma_handles[i] = 0; 1739 } 1740 1741 xge_hal_fifo_dtr_free(channelh, dtrh); 1742 1743 if (mp) { 1744 txd_priv->mblk = NULL; 1745 freemsg(mp); 1746 } 1747 } 1748 1749 static boolean_t 1750 xgell_tx_ring_open(xgell_tx_ring_t *tx_ring) 1751 { 1752 xge_hal_status_e status; 1753 xge_hal_channel_attr_t attr; 1754 xgelldev_t *lldev = tx_ring->lldev; 1755 1756 if (tx_ring->live) 1757 return (B_TRUE); 1758 1759 attr.post_qid = tx_ring->index; 1760 attr.compl_qid = 0; 1761 attr.callback = xgell_xmit_compl; 1762 attr.per_dtr_space = sizeof (xgell_txd_priv_t); 1763 attr.flags = 0; 1764 attr.type = XGE_HAL_CHANNEL_TYPE_FIFO; 1765 attr.dtr_init = NULL; 1766 attr.dtr_term = xgell_tx_term; 1767 attr.userdata = tx_ring; 1768 1769 status = xge_hal_channel_open(lldev->devh, &attr, &tx_ring->channelh, 1770 XGE_HAL_CHANNEL_OC_NORMAL); 1771 if (status != XGE_HAL_OK) { 1772 xge_debug_ll(XGE_ERR, "%s%d: cannot open Tx channel got status " 1773 "code %d", XGELL_IFNAME, lldev->instance, status); 1774 return (B_FALSE); 1775 } 1776 1777 tx_ring->live = B_TRUE; 1778 1779 return (B_TRUE); 1780 } 1781 1782 static void 1783 xgell_tx_ring_close(xgell_tx_ring_t *tx_ring) 1784 { 1785 if (!tx_ring->live) 1786 return; 1787 xge_hal_channel_close(tx_ring->channelh, XGE_HAL_CHANNEL_OC_NORMAL); 1788 tx_ring->live = B_FALSE; 1789 } 1790 1791 /* 1792 * xgell_tx_open 1793 * @lldev: the link layer object 1794 * 1795 * Initialize and open all TX channels. 1796 */ 1797 static boolean_t 1798 xgell_tx_open(xgelldev_t *lldev) 1799 { 1800 xgell_tx_ring_t *tx_ring; 1801 int i; 1802 1803 if (lldev->live_tx_rings != 0) 1804 return (B_TRUE); 1805 1806 lldev->live_tx_rings = 0; 1807 1808 /* 1809 * Enable rings by reserve sequence to match the h/w sequences. 1810 */ 1811 for (i = 0; i < lldev->init_tx_rings; i++) { 1812 tx_ring = &lldev->tx_ring[i]; 1813 tx_ring->index = i; 1814 tx_ring->lldev = lldev; 1815 tx_ring->live = B_FALSE; 1816 1817 if (!xgell_tx_ring_open(tx_ring)) 1818 return (B_FALSE); 1819 1820 lldev->live_tx_rings++; 1821 } 1822 1823 return (B_TRUE); 1824 } 1825 1826 static void 1827 xgell_tx_close(xgelldev_t *lldev) 1828 { 1829 xgell_tx_ring_t *tx_ring; 1830 int i; 1831 1832 if (lldev->live_tx_rings == 0) 1833 return; 1834 1835 /* 1836 * Enable rings by reserve sequence to match the h/w sequences. 1837 */ 1838 for (i = 0; i < lldev->init_tx_rings; i++) { 1839 tx_ring = &lldev->tx_ring[i]; 1840 if (tx_ring->live) { 1841 xgell_tx_ring_close(tx_ring); 1842 lldev->live_tx_rings--; 1843 } 1844 } 1845 } 1846 1847 static int 1848 xgell_initiate_start(xgelldev_t *lldev) 1849 { 1850 xge_hal_status_e status; 1851 xge_hal_device_t *hldev = lldev->devh; 1852 int maxpkt = hldev->config.mtu; 1853 1854 /* check initial mtu before enabling the device */ 1855 status = xge_hal_device_mtu_check(lldev->devh, maxpkt); 1856 if (status != XGE_HAL_OK) { 1857 xge_debug_ll(XGE_ERR, "%s%d: MTU size %d is invalid", 1858 XGELL_IFNAME, lldev->instance, maxpkt); 1859 return (EINVAL); 1860 } 1861 1862 /* set initial mtu before enabling the device */ 1863 status = xge_hal_device_mtu_set(lldev->devh, maxpkt); 1864 if (status != XGE_HAL_OK) { 1865 xge_debug_ll(XGE_ERR, "%s%d: can not set new MTU %d", 1866 XGELL_IFNAME, lldev->instance, maxpkt); 1867 return (EIO); 1868 } 1869 1870 /* tune jumbo/normal frame UFC counters */ 1871 hldev->config.ring.queue[XGELL_RX_RING_MAIN].rti.ufc_b = 1872 (maxpkt > XGE_HAL_DEFAULT_MTU) ? 1873 XGE_HAL_DEFAULT_RX_UFC_B_J : 1874 XGE_HAL_DEFAULT_RX_UFC_B_N; 1875 1876 hldev->config.ring.queue[XGELL_RX_RING_MAIN].rti.ufc_c = 1877 (maxpkt > XGE_HAL_DEFAULT_MTU) ? 1878 XGE_HAL_DEFAULT_RX_UFC_C_J : 1879 XGE_HAL_DEFAULT_RX_UFC_C_N; 1880 1881 /* now, enable the device */ 1882 status = xge_hal_device_enable(lldev->devh); 1883 if (status != XGE_HAL_OK) { 1884 xge_debug_ll(XGE_ERR, "%s%d: can not enable the device", 1885 XGELL_IFNAME, lldev->instance); 1886 return (EIO); 1887 } 1888 1889 if (!xgell_rx_open(lldev)) { 1890 status = xge_hal_device_disable(lldev->devh); 1891 if (status != XGE_HAL_OK) { 1892 u64 adapter_status; 1893 (void) xge_hal_device_status(lldev->devh, 1894 &adapter_status); 1895 xge_debug_ll(XGE_ERR, "%s%d: can not safely disable " 1896 "the device. adaper status 0x%"PRIx64 1897 " returned status %d", 1898 XGELL_IFNAME, lldev->instance, 1899 (uint64_t)adapter_status, status); 1900 } 1901 xgell_rx_close(lldev); 1902 xge_os_mdelay(1500); 1903 return (ENOMEM); 1904 } 1905 1906 if (!xgell_tx_open(lldev)) { 1907 status = xge_hal_device_disable(lldev->devh); 1908 if (status != XGE_HAL_OK) { 1909 u64 adapter_status; 1910 (void) xge_hal_device_status(lldev->devh, 1911 &adapter_status); 1912 xge_debug_ll(XGE_ERR, "%s%d: can not safely disable " 1913 "the device. adaper status 0x%"PRIx64 1914 " returned status %d", 1915 XGELL_IFNAME, lldev->instance, 1916 (uint64_t)adapter_status, status); 1917 } 1918 xgell_tx_close(lldev); 1919 xgell_rx_close(lldev); 1920 xge_os_mdelay(1500); 1921 return (ENOMEM); 1922 } 1923 1924 /* time to enable interrupts */ 1925 (void) xge_enable_intrs(lldev); 1926 xge_hal_device_intr_enable(lldev->devh); 1927 1928 lldev->is_initialized = 1; 1929 1930 return (0); 1931 } 1932 1933 static void 1934 xgell_initiate_stop(xgelldev_t *lldev) 1935 { 1936 xge_hal_status_e status; 1937 1938 lldev->is_initialized = 0; 1939 1940 status = xge_hal_device_disable(lldev->devh); 1941 if (status != XGE_HAL_OK) { 1942 u64 adapter_status; 1943 (void) xge_hal_device_status(lldev->devh, &adapter_status); 1944 xge_debug_ll(XGE_ERR, "%s%d: can not safely disable " 1945 "the device. adaper status 0x%"PRIx64" returned status %d", 1946 XGELL_IFNAME, lldev->instance, 1947 (uint64_t)adapter_status, status); 1948 } 1949 xge_hal_device_intr_disable(lldev->devh); 1950 /* disable OS ISR's */ 1951 xge_disable_intrs(lldev); 1952 1953 xge_debug_ll(XGE_TRACE, "%s", 1954 "waiting for device irq to become quiescent..."); 1955 xge_os_mdelay(1500); 1956 1957 xge_queue_flush(xge_hal_device_queue(lldev->devh)); 1958 1959 xgell_rx_close(lldev); 1960 xgell_tx_close(lldev); 1961 } 1962 1963 /* 1964 * xgell_m_start 1965 * @arg: pointer to device private strucutre(hldev) 1966 * 1967 * This function is called by MAC Layer to enable the XFRAME 1968 * firmware to generate interrupts and also prepare the 1969 * driver to call mac_rx for delivering receive packets 1970 * to MAC Layer. 1971 */ 1972 static int 1973 xgell_m_start(void *arg) 1974 { 1975 xgelldev_t *lldev = arg; 1976 xge_hal_device_t *hldev = lldev->devh; 1977 int ret; 1978 1979 xge_debug_ll(XGE_TRACE, "%s%d: M_START", XGELL_IFNAME, 1980 lldev->instance); 1981 1982 mutex_enter(&lldev->genlock); 1983 1984 if (lldev->is_initialized) { 1985 xge_debug_ll(XGE_ERR, "%s%d: device is already initialized", 1986 XGELL_IFNAME, lldev->instance); 1987 mutex_exit(&lldev->genlock); 1988 return (EINVAL); 1989 } 1990 1991 hldev->terminating = 0; 1992 if (ret = xgell_initiate_start(lldev)) { 1993 mutex_exit(&lldev->genlock); 1994 return (ret); 1995 } 1996 1997 lldev->timeout_id = timeout(xge_device_poll, hldev, XGE_DEV_POLL_TICKS); 1998 1999 mutex_exit(&lldev->genlock); 2000 2001 return (0); 2002 } 2003 2004 /* 2005 * xgell_m_stop 2006 * @arg: pointer to device private data (hldev) 2007 * 2008 * This function is called by the MAC Layer to disable 2009 * the XFRAME firmware for generating any interrupts and 2010 * also stop the driver from calling mac_rx() for 2011 * delivering data packets to the MAC Layer. 2012 */ 2013 static void 2014 xgell_m_stop(void *arg) 2015 { 2016 xgelldev_t *lldev = arg; 2017 xge_hal_device_t *hldev = lldev->devh; 2018 2019 xge_debug_ll(XGE_TRACE, "%s", "MAC_STOP"); 2020 2021 mutex_enter(&lldev->genlock); 2022 if (!lldev->is_initialized) { 2023 xge_debug_ll(XGE_ERR, "%s", "device is not initialized..."); 2024 mutex_exit(&lldev->genlock); 2025 return; 2026 } 2027 2028 xge_hal_device_terminating(hldev); 2029 xgell_initiate_stop(lldev); 2030 2031 /* reset device */ 2032 (void) xge_hal_device_reset(lldev->devh); 2033 2034 mutex_exit(&lldev->genlock); 2035 2036 if (lldev->timeout_id != 0) { 2037 (void) untimeout(lldev->timeout_id); 2038 } 2039 2040 xge_debug_ll(XGE_TRACE, "%s", "returning back to MAC Layer..."); 2041 } 2042 2043 /* 2044 * xgell_onerr_reset 2045 * @lldev: pointer to xgelldev_t structure 2046 * 2047 * This function is called by HAL Event framework to reset the HW 2048 * This function is must be called with genlock taken. 2049 */ 2050 int 2051 xgell_onerr_reset(xgelldev_t *lldev) 2052 { 2053 int rc = 0; 2054 2055 if (!lldev->is_initialized) { 2056 xge_debug_ll(XGE_ERR, "%s%d: can not reset", 2057 XGELL_IFNAME, lldev->instance); 2058 return (rc); 2059 } 2060 2061 lldev->in_reset = 1; 2062 xgell_initiate_stop(lldev); 2063 2064 /* reset device */ 2065 (void) xge_hal_device_reset(lldev->devh); 2066 2067 rc = xgell_initiate_start(lldev); 2068 lldev->in_reset = 0; 2069 2070 return (rc); 2071 } 2072 2073 /* 2074 * xgell_m_multicst 2075 * @arg: pointer to device private strucutre(hldev) 2076 * @add: 2077 * @mc_addr: 2078 * 2079 * This function is called by MAC Layer to enable or 2080 * disable device-level reception of specific multicast addresses. 2081 */ 2082 static int 2083 xgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr) 2084 { 2085 xge_hal_status_e status; 2086 xgelldev_t *lldev = (xgelldev_t *)arg; 2087 xge_hal_device_t *hldev = lldev->devh; 2088 2089 xge_debug_ll(XGE_TRACE, "M_MULTICAST add %d", add); 2090 2091 mutex_enter(&lldev->genlock); 2092 2093 if (!lldev->is_initialized) { 2094 xge_debug_ll(XGE_ERR, "%s%d: can not set multicast", 2095 XGELL_IFNAME, lldev->instance); 2096 mutex_exit(&lldev->genlock); 2097 return (EIO); 2098 } 2099 2100 /* FIXME: missing HAL functionality: enable_one() */ 2101 2102 status = (add) ? 2103 xge_hal_device_mcast_enable(hldev) : 2104 xge_hal_device_mcast_disable(hldev); 2105 2106 if (status != XGE_HAL_OK) { 2107 xge_debug_ll(XGE_ERR, "failed to %s multicast, status %d", 2108 add ? "enable" : "disable", status); 2109 mutex_exit(&lldev->genlock); 2110 return (EIO); 2111 } 2112 2113 mutex_exit(&lldev->genlock); 2114 2115 return (0); 2116 } 2117 2118 2119 /* 2120 * xgell_m_promisc 2121 * @arg: pointer to device private strucutre(hldev) 2122 * @on: 2123 * 2124 * This function is called by MAC Layer to enable or 2125 * disable the reception of all the packets on the medium 2126 */ 2127 static int 2128 xgell_m_promisc(void *arg, boolean_t on) 2129 { 2130 xgelldev_t *lldev = (xgelldev_t *)arg; 2131 xge_hal_device_t *hldev = lldev->devh; 2132 2133 mutex_enter(&lldev->genlock); 2134 2135 xge_debug_ll(XGE_TRACE, "%s", "MAC_PROMISC_SET"); 2136 2137 if (!lldev->is_initialized) { 2138 xge_debug_ll(XGE_ERR, "%s%d: can not set promiscuous", 2139 XGELL_IFNAME, lldev->instance); 2140 mutex_exit(&lldev->genlock); 2141 return (EIO); 2142 } 2143 2144 if (on) { 2145 xge_hal_device_promisc_enable(hldev); 2146 } else { 2147 xge_hal_device_promisc_disable(hldev); 2148 } 2149 2150 mutex_exit(&lldev->genlock); 2151 2152 return (0); 2153 } 2154 2155 /* 2156 * xgell_m_stat 2157 * @arg: pointer to device private strucutre(hldev) 2158 * 2159 * This function is called by MAC Layer to get network statistics 2160 * from the driver. 2161 */ 2162 static int 2163 xgell_m_stat(void *arg, uint_t stat, uint64_t *val) 2164 { 2165 xge_hal_stats_hw_info_t *hw_info; 2166 xgelldev_t *lldev = (xgelldev_t *)arg; 2167 xge_hal_device_t *hldev = lldev->devh; 2168 2169 xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET"); 2170 2171 mutex_enter(&lldev->genlock); 2172 2173 if (!lldev->is_initialized) { 2174 mutex_exit(&lldev->genlock); 2175 return (EAGAIN); 2176 } 2177 2178 if (xge_hal_stats_hw(hldev, &hw_info) != XGE_HAL_OK) { 2179 mutex_exit(&lldev->genlock); 2180 return (EAGAIN); 2181 } 2182 2183 switch (stat) { 2184 case MAC_STAT_IFSPEED: 2185 *val = 10000000000ull; /* 10G */ 2186 break; 2187 2188 case MAC_STAT_MULTIRCV: 2189 *val = ((u64) hw_info->rmac_vld_mcst_frms_oflow << 32) | 2190 hw_info->rmac_vld_mcst_frms; 2191 break; 2192 2193 case MAC_STAT_BRDCSTRCV: 2194 *val = ((u64) hw_info->rmac_vld_bcst_frms_oflow << 32) | 2195 hw_info->rmac_vld_bcst_frms; 2196 break; 2197 2198 case MAC_STAT_MULTIXMT: 2199 *val = ((u64) hw_info->tmac_mcst_frms_oflow << 32) | 2200 hw_info->tmac_mcst_frms; 2201 break; 2202 2203 case MAC_STAT_BRDCSTXMT: 2204 *val = ((u64) hw_info->tmac_bcst_frms_oflow << 32) | 2205 hw_info->tmac_bcst_frms; 2206 break; 2207 2208 case MAC_STAT_RBYTES: 2209 *val = ((u64) hw_info->rmac_ttl_octets_oflow << 32) | 2210 hw_info->rmac_ttl_octets; 2211 break; 2212 2213 case MAC_STAT_NORCVBUF: 2214 *val = hw_info->rmac_drop_frms; 2215 break; 2216 2217 case MAC_STAT_IERRORS: 2218 *val = ((u64) hw_info->rmac_discarded_frms_oflow << 32) | 2219 hw_info->rmac_discarded_frms; 2220 break; 2221 2222 case MAC_STAT_OBYTES: 2223 *val = ((u64) hw_info->tmac_ttl_octets_oflow << 32) | 2224 hw_info->tmac_ttl_octets; 2225 break; 2226 2227 case MAC_STAT_NOXMTBUF: 2228 *val = hw_info->tmac_drop_frms; 2229 break; 2230 2231 case MAC_STAT_OERRORS: 2232 *val = ((u64) hw_info->tmac_any_err_frms_oflow << 32) | 2233 hw_info->tmac_any_err_frms; 2234 break; 2235 2236 case MAC_STAT_IPACKETS: 2237 *val = ((u64) hw_info->rmac_vld_frms_oflow << 32) | 2238 hw_info->rmac_vld_frms; 2239 break; 2240 2241 case MAC_STAT_OPACKETS: 2242 *val = ((u64) hw_info->tmac_frms_oflow << 32) | 2243 hw_info->tmac_frms; 2244 break; 2245 2246 case ETHER_STAT_FCS_ERRORS: 2247 *val = hw_info->rmac_fcs_err_frms; 2248 break; 2249 2250 case ETHER_STAT_TOOLONG_ERRORS: 2251 *val = hw_info->rmac_long_frms; 2252 break; 2253 2254 case ETHER_STAT_LINK_DUPLEX: 2255 *val = LINK_DUPLEX_FULL; 2256 break; 2257 2258 default: 2259 mutex_exit(&lldev->genlock); 2260 return (ENOTSUP); 2261 } 2262 2263 mutex_exit(&lldev->genlock); 2264 2265 return (0); 2266 } 2267 2268 /* 2269 * Retrieve a value for one of the statistics for a particular rx ring 2270 */ 2271 int 2272 xgell_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 2273 { 2274 xgell_rx_ring_t *rx_ring = (xgell_rx_ring_t *)rh; 2275 2276 switch (stat) { 2277 case MAC_STAT_RBYTES: 2278 *val = rx_ring->rx_bytes; 2279 break; 2280 2281 case MAC_STAT_IPACKETS: 2282 *val = rx_ring->rx_pkts; 2283 break; 2284 2285 default: 2286 *val = 0; 2287 return (ENOTSUP); 2288 } 2289 2290 return (0); 2291 } 2292 2293 /* 2294 * Retrieve a value for one of the statistics for a particular tx ring 2295 */ 2296 int 2297 xgell_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 2298 { 2299 xgell_tx_ring_t *tx_ring = (xgell_tx_ring_t *)rh; 2300 2301 switch (stat) { 2302 case MAC_STAT_OBYTES: 2303 *val = tx_ring->tx_bytes; 2304 break; 2305 2306 case MAC_STAT_OPACKETS: 2307 *val = tx_ring->tx_pkts; 2308 break; 2309 2310 default: 2311 *val = 0; 2312 return (ENOTSUP); 2313 } 2314 2315 return (0); 2316 } 2317 2318 /* 2319 * xgell_device_alloc - Allocate new LL device 2320 */ 2321 int 2322 xgell_device_alloc(xge_hal_device_h devh, 2323 dev_info_t *dev_info, xgelldev_t **lldev_out) 2324 { 2325 xgelldev_t *lldev; 2326 xge_hal_device_t *hldev = (xge_hal_device_t *)devh; 2327 int instance = ddi_get_instance(dev_info); 2328 2329 *lldev_out = NULL; 2330 2331 xge_debug_ll(XGE_TRACE, "trying to register etherenet device %s%d...", 2332 XGELL_IFNAME, instance); 2333 2334 lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP); 2335 2336 lldev->devh = hldev; 2337 lldev->instance = instance; 2338 lldev->dev_info = dev_info; 2339 2340 *lldev_out = lldev; 2341 2342 ddi_set_driver_private(dev_info, (caddr_t)hldev); 2343 2344 return (DDI_SUCCESS); 2345 } 2346 2347 /* 2348 * xgell_device_free 2349 */ 2350 void 2351 xgell_device_free(xgelldev_t *lldev) 2352 { 2353 xge_debug_ll(XGE_TRACE, "freeing device %s%d", 2354 XGELL_IFNAME, lldev->instance); 2355 2356 kmem_free(lldev, sizeof (xgelldev_t)); 2357 } 2358 2359 /* 2360 * xgell_ioctl 2361 */ 2362 static void 2363 xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 2364 { 2365 xgelldev_t *lldev = arg; 2366 struct iocblk *iocp; 2367 int err = 0; 2368 int cmd; 2369 int need_privilege = 1; 2370 int ret = 0; 2371 2372 2373 iocp = (struct iocblk *)mp->b_rptr; 2374 iocp->ioc_error = 0; 2375 cmd = iocp->ioc_cmd; 2376 xge_debug_ll(XGE_TRACE, "MAC_IOCTL cmd 0x%x", cmd); 2377 switch (cmd) { 2378 case ND_GET: 2379 need_privilege = 0; 2380 /* FALLTHRU */ 2381 case ND_SET: 2382 break; 2383 default: 2384 xge_debug_ll(XGE_TRACE, "unknown cmd 0x%x", cmd); 2385 miocnak(wq, mp, 0, EINVAL); 2386 return; 2387 } 2388 2389 if (need_privilege) { 2390 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 2391 if (err != 0) { 2392 xge_debug_ll(XGE_ERR, 2393 "drv_priv(): rejected cmd 0x%x, err %d", 2394 cmd, err); 2395 miocnak(wq, mp, 0, err); 2396 return; 2397 } 2398 } 2399 2400 switch (cmd) { 2401 case ND_GET: 2402 /* 2403 * If nd_getset() returns B_FALSE, the command was 2404 * not valid (e.g. unknown name), so we just tell the 2405 * top-level ioctl code to send a NAK (with code EINVAL). 2406 * 2407 * Otherwise, nd_getset() will have built the reply to 2408 * be sent (but not actually sent it), so we tell the 2409 * caller to send the prepared reply. 2410 */ 2411 ret = nd_getset(wq, lldev->ndp, mp); 2412 xge_debug_ll(XGE_TRACE, "%s", "got ndd get ioctl"); 2413 break; 2414 2415 case ND_SET: 2416 ret = nd_getset(wq, lldev->ndp, mp); 2417 xge_debug_ll(XGE_TRACE, "%s", "got ndd set ioctl"); 2418 break; 2419 2420 default: 2421 break; 2422 } 2423 2424 if (ret == B_FALSE) { 2425 xge_debug_ll(XGE_ERR, 2426 "nd_getset(): rejected cmd 0x%x, err %d", 2427 cmd, err); 2428 miocnak(wq, mp, 0, EINVAL); 2429 } else { 2430 mp->b_datap->db_type = iocp->ioc_error == 0 ? 2431 M_IOCACK : M_IOCNAK; 2432 qreply(wq, mp); 2433 } 2434 } 2435 2436 2437 static boolean_t 2438 xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 2439 { 2440 xgelldev_t *lldev = arg; 2441 2442 xge_debug_ll(XGE_TRACE, "xgell_m_getcapab: %x", cap); 2443 2444 switch (cap) { 2445 case MAC_CAPAB_HCKSUM: { 2446 uint32_t *hcksum_txflags = cap_data; 2447 *hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 | 2448 HCKSUM_IPHDRCKSUM; 2449 break; 2450 } 2451 case MAC_CAPAB_LSO: { 2452 mac_capab_lso_t *cap_lso = cap_data; 2453 2454 if (lldev->config.lso_enable) { 2455 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 2456 cap_lso->lso_basic_tcp_ipv4.lso_max = XGELL_LSO_MAXLEN; 2457 break; 2458 } else { 2459 return (B_FALSE); 2460 } 2461 } 2462 case MAC_CAPAB_RINGS: { 2463 mac_capab_rings_t *cap_rings = cap_data; 2464 2465 switch (cap_rings->mr_type) { 2466 case MAC_RING_TYPE_RX: 2467 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 2468 cap_rings->mr_rnum = lldev->init_rx_rings; 2469 cap_rings->mr_gnum = lldev->init_rx_groups; 2470 cap_rings->mr_rget = xgell_fill_ring; 2471 cap_rings->mr_gget = xgell_fill_group; 2472 break; 2473 case MAC_RING_TYPE_TX: 2474 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 2475 cap_rings->mr_rnum = lldev->init_tx_rings; 2476 cap_rings->mr_gnum = 0; 2477 cap_rings->mr_rget = xgell_fill_ring; 2478 cap_rings->mr_gget = NULL; 2479 break; 2480 default: 2481 break; 2482 } 2483 break; 2484 } 2485 default: 2486 return (B_FALSE); 2487 } 2488 return (B_TRUE); 2489 } 2490 2491 static int 2492 xgell_stats_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2493 { 2494 xgelldev_t *lldev = (xgelldev_t *)cp; 2495 xge_hal_status_e status; 2496 int count = 0, retsize; 2497 char *buf; 2498 2499 buf = kmem_alloc(XGELL_STATS_BUFSIZE, KM_SLEEP); 2500 if (buf == NULL) { 2501 return (ENOSPC); 2502 } 2503 2504 status = xge_hal_aux_stats_tmac_read(lldev->devh, XGELL_STATS_BUFSIZE, 2505 buf, &retsize); 2506 if (status != XGE_HAL_OK) { 2507 kmem_free(buf, XGELL_STATS_BUFSIZE); 2508 xge_debug_ll(XGE_ERR, "tmac_read(): status %d", status); 2509 return (EINVAL); 2510 } 2511 count += retsize; 2512 2513 status = xge_hal_aux_stats_rmac_read(lldev->devh, 2514 XGELL_STATS_BUFSIZE - count, 2515 buf+count, &retsize); 2516 if (status != XGE_HAL_OK) { 2517 kmem_free(buf, XGELL_STATS_BUFSIZE); 2518 xge_debug_ll(XGE_ERR, "rmac_read(): status %d", status); 2519 return (EINVAL); 2520 } 2521 count += retsize; 2522 2523 status = xge_hal_aux_stats_pci_read(lldev->devh, 2524 XGELL_STATS_BUFSIZE - count, buf + count, &retsize); 2525 if (status != XGE_HAL_OK) { 2526 kmem_free(buf, XGELL_STATS_BUFSIZE); 2527 xge_debug_ll(XGE_ERR, "pci_read(): status %d", status); 2528 return (EINVAL); 2529 } 2530 count += retsize; 2531 2532 status = xge_hal_aux_stats_sw_dev_read(lldev->devh, 2533 XGELL_STATS_BUFSIZE - count, buf + count, &retsize); 2534 if (status != XGE_HAL_OK) { 2535 kmem_free(buf, XGELL_STATS_BUFSIZE); 2536 xge_debug_ll(XGE_ERR, "sw_dev_read(): status %d", status); 2537 return (EINVAL); 2538 } 2539 count += retsize; 2540 2541 status = xge_hal_aux_stats_hal_read(lldev->devh, 2542 XGELL_STATS_BUFSIZE - count, buf + count, &retsize); 2543 if (status != XGE_HAL_OK) { 2544 kmem_free(buf, XGELL_STATS_BUFSIZE); 2545 xge_debug_ll(XGE_ERR, "pci_read(): status %d", status); 2546 return (EINVAL); 2547 } 2548 count += retsize; 2549 2550 *(buf + count - 1) = '\0'; /* remove last '\n' */ 2551 (void) mi_mpprintf(mp, "%s", buf); 2552 kmem_free(buf, XGELL_STATS_BUFSIZE); 2553 2554 return (0); 2555 } 2556 2557 static int 2558 xgell_pciconf_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2559 { 2560 xgelldev_t *lldev = (xgelldev_t *)cp; 2561 xge_hal_status_e status; 2562 int retsize; 2563 char *buf; 2564 2565 buf = kmem_alloc(XGELL_PCICONF_BUFSIZE, KM_SLEEP); 2566 if (buf == NULL) { 2567 return (ENOSPC); 2568 } 2569 status = xge_hal_aux_pci_config_read(lldev->devh, XGELL_PCICONF_BUFSIZE, 2570 buf, &retsize); 2571 if (status != XGE_HAL_OK) { 2572 kmem_free(buf, XGELL_PCICONF_BUFSIZE); 2573 xge_debug_ll(XGE_ERR, "pci_config_read(): status %d", status); 2574 return (EINVAL); 2575 } 2576 *(buf + retsize - 1) = '\0'; /* remove last '\n' */ 2577 (void) mi_mpprintf(mp, "%s", buf); 2578 kmem_free(buf, XGELL_PCICONF_BUFSIZE); 2579 2580 return (0); 2581 } 2582 2583 static int 2584 xgell_about_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2585 { 2586 xgelldev_t *lldev = (xgelldev_t *)cp; 2587 xge_hal_status_e status; 2588 int retsize; 2589 char *buf; 2590 2591 buf = kmem_alloc(XGELL_ABOUT_BUFSIZE, KM_SLEEP); 2592 if (buf == NULL) { 2593 return (ENOSPC); 2594 } 2595 status = xge_hal_aux_about_read(lldev->devh, XGELL_ABOUT_BUFSIZE, 2596 buf, &retsize); 2597 if (status != XGE_HAL_OK) { 2598 kmem_free(buf, XGELL_ABOUT_BUFSIZE); 2599 xge_debug_ll(XGE_ERR, "about_read(): status %d", status); 2600 return (EINVAL); 2601 } 2602 *(buf + retsize - 1) = '\0'; /* remove last '\n' */ 2603 (void) mi_mpprintf(mp, "%s", buf); 2604 kmem_free(buf, XGELL_ABOUT_BUFSIZE); 2605 2606 return (0); 2607 } 2608 2609 static unsigned long bar0_offset = 0x110; /* adapter_control */ 2610 2611 static int 2612 xgell_bar0_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2613 { 2614 xgelldev_t *lldev = (xgelldev_t *)cp; 2615 xge_hal_status_e status; 2616 int retsize; 2617 char *buf; 2618 2619 buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP); 2620 if (buf == NULL) { 2621 return (ENOSPC); 2622 } 2623 status = xge_hal_aux_bar0_read(lldev->devh, bar0_offset, 2624 XGELL_IOCTL_BUFSIZE, buf, &retsize); 2625 if (status != XGE_HAL_OK) { 2626 kmem_free(buf, XGELL_IOCTL_BUFSIZE); 2627 xge_debug_ll(XGE_ERR, "bar0_read(): status %d", status); 2628 return (EINVAL); 2629 } 2630 *(buf + retsize - 1) = '\0'; /* remove last '\n' */ 2631 (void) mi_mpprintf(mp, "%s", buf); 2632 kmem_free(buf, XGELL_IOCTL_BUFSIZE); 2633 2634 return (0); 2635 } 2636 2637 static int 2638 xgell_bar0_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp) 2639 { 2640 unsigned long old_offset = bar0_offset; 2641 char *end; 2642 2643 if (value && *value == '0' && 2644 (*(value + 1) == 'x' || *(value + 1) == 'X')) { 2645 value += 2; 2646 } 2647 2648 bar0_offset = mi_strtol(value, &end, 16); 2649 if (end == value) { 2650 bar0_offset = old_offset; 2651 return (EINVAL); 2652 } 2653 2654 xge_debug_ll(XGE_TRACE, "bar0: new value %s:%lX", value, bar0_offset); 2655 2656 return (0); 2657 } 2658 2659 static int 2660 xgell_debug_level_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2661 { 2662 char *buf; 2663 2664 buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP); 2665 if (buf == NULL) { 2666 return (ENOSPC); 2667 } 2668 (void) mi_mpprintf(mp, "debug_level %d", xge_hal_driver_debug_level()); 2669 kmem_free(buf, XGELL_IOCTL_BUFSIZE); 2670 2671 return (0); 2672 } 2673 2674 static int 2675 xgell_debug_level_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 2676 cred_t *credp) 2677 { 2678 int level; 2679 char *end; 2680 2681 level = mi_strtol(value, &end, 10); 2682 if (level < XGE_NONE || level > XGE_ERR || end == value) { 2683 return (EINVAL); 2684 } 2685 2686 xge_hal_driver_debug_level_set(level); 2687 2688 return (0); 2689 } 2690 2691 static int 2692 xgell_debug_module_mask_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2693 { 2694 char *buf; 2695 2696 buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP); 2697 if (buf == NULL) { 2698 return (ENOSPC); 2699 } 2700 (void) mi_mpprintf(mp, "debug_module_mask 0x%08x", 2701 xge_hal_driver_debug_module_mask()); 2702 kmem_free(buf, XGELL_IOCTL_BUFSIZE); 2703 2704 return (0); 2705 } 2706 2707 static int 2708 xgell_debug_module_mask_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, 2709 cred_t *credp) 2710 { 2711 u32 mask; 2712 char *end; 2713 2714 if (value && *value == '0' && 2715 (*(value + 1) == 'x' || *(value + 1) == 'X')) { 2716 value += 2; 2717 } 2718 2719 mask = mi_strtol(value, &end, 16); 2720 if (end == value) { 2721 return (EINVAL); 2722 } 2723 2724 xge_hal_driver_debug_module_mask_set(mask); 2725 2726 return (0); 2727 } 2728 2729 static int 2730 xgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 2731 { 2732 xgelldev_t *lldev = (xgelldev_t *)(void *)cp; 2733 xge_hal_status_e status; 2734 int retsize; 2735 char *buf; 2736 2737 buf = kmem_alloc(XGELL_DEVCONF_BUFSIZE, KM_SLEEP); 2738 if (buf == NULL) { 2739 return (ENOSPC); 2740 } 2741 status = xge_hal_aux_device_config_read(lldev->devh, 2742 XGELL_DEVCONF_BUFSIZE, buf, &retsize); 2743 if (status != XGE_HAL_OK) { 2744 kmem_free(buf, XGELL_DEVCONF_BUFSIZE); 2745 xge_debug_ll(XGE_ERR, "device_config_read(): status %d", 2746 status); 2747 return (EINVAL); 2748 } 2749 *(buf + retsize - 1) = '\0'; /* remove last '\n' */ 2750 (void) mi_mpprintf(mp, "%s", buf); 2751 kmem_free(buf, XGELL_DEVCONF_BUFSIZE); 2752 2753 return (0); 2754 } 2755 2756 /* 2757 * xgell_device_register 2758 * @devh: pointer on HAL device 2759 * @config: pointer on this network device configuration 2760 * @ll_out: output pointer. Will be assigned to valid LL device. 2761 * 2762 * This function will allocate and register network device 2763 */ 2764 int 2765 xgell_device_register(xgelldev_t *lldev, xgell_config_t *config) 2766 { 2767 mac_register_t *macp = NULL; 2768 xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh; 2769 2770 /* 2771 * Initialize some NDD interface for internal debug. 2772 */ 2773 if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL, 2774 (caddr_t)lldev) == B_FALSE) 2775 goto xgell_ndd_fail; 2776 2777 if (nd_load(&lldev->ndp, "about", xgell_about_get, NULL, 2778 (caddr_t)lldev) == B_FALSE) 2779 goto xgell_ndd_fail; 2780 2781 if (nd_load(&lldev->ndp, "stats", xgell_stats_get, NULL, 2782 (caddr_t)lldev) == B_FALSE) 2783 goto xgell_ndd_fail; 2784 2785 if (nd_load(&lldev->ndp, "bar0", xgell_bar0_get, xgell_bar0_set, 2786 (caddr_t)lldev) == B_FALSE) 2787 goto xgell_ndd_fail; 2788 2789 if (nd_load(&lldev->ndp, "debug_level", xgell_debug_level_get, 2790 xgell_debug_level_set, (caddr_t)lldev) == B_FALSE) 2791 goto xgell_ndd_fail; 2792 2793 if (nd_load(&lldev->ndp, "debug_module_mask", 2794 xgell_debug_module_mask_get, xgell_debug_module_mask_set, 2795 (caddr_t)lldev) == B_FALSE) 2796 goto xgell_ndd_fail; 2797 2798 if (nd_load(&lldev->ndp, "devconfig", xgell_devconfig_get, NULL, 2799 (caddr_t)lldev) == B_FALSE) 2800 goto xgell_ndd_fail; 2801 2802 bcopy(config, &lldev->config, sizeof (xgell_config_t)); 2803 2804 mutex_init(&lldev->genlock, NULL, MUTEX_DRIVER, 2805 DDI_INTR_PRI(hldev->irqh)); 2806 2807 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 2808 goto xgell_register_fail; 2809 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2810 macp->m_driver = lldev; 2811 macp->m_dip = lldev->dev_info; 2812 macp->m_src_addr = hldev->macaddr[0]; 2813 macp->m_callbacks = &xgell_m_callbacks; 2814 macp->m_min_sdu = 0; 2815 macp->m_max_sdu = hldev->config.mtu; 2816 macp->m_margin = VLAN_TAGSZ; 2817 macp->m_v12n = MAC_VIRT_LEVEL1; 2818 2819 /* 2820 * MAC Registration. 2821 */ 2822 if (mac_register(macp, &lldev->mh) != 0) 2823 goto xgell_register_fail; 2824 2825 /* Always free the macp after register */ 2826 if (macp != NULL) 2827 mac_free(macp); 2828 2829 /* Calculate tx_copied_max here ??? */ 2830 lldev->tx_copied_max = hldev->config.fifo.max_frags * 2831 hldev->config.fifo.alignment_size * 2832 hldev->config.fifo.max_aligned_frags; 2833 2834 xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered", 2835 XGELL_IFNAME, lldev->instance); 2836 2837 return (DDI_SUCCESS); 2838 2839 xgell_ndd_fail: 2840 nd_free(&lldev->ndp); 2841 xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter"); 2842 return (DDI_FAILURE); 2843 2844 xgell_register_fail: 2845 if (macp != NULL) 2846 mac_free(macp); 2847 nd_free(&lldev->ndp); 2848 mutex_destroy(&lldev->genlock); 2849 xge_debug_ll(XGE_ERR, "%s", "unable to register networking device"); 2850 return (DDI_FAILURE); 2851 } 2852 2853 /* 2854 * xgell_device_unregister 2855 * @devh: pointer on HAL device 2856 * @lldev: pointer to valid LL device. 2857 * 2858 * This function will unregister and free network device 2859 */ 2860 int 2861 xgell_device_unregister(xgelldev_t *lldev) 2862 { 2863 if (mac_unregister(lldev->mh) != 0) { 2864 xge_debug_ll(XGE_ERR, "unable to unregister device %s%d", 2865 XGELL_IFNAME, lldev->instance); 2866 return (DDI_FAILURE); 2867 } 2868 2869 mutex_destroy(&lldev->genlock); 2870 2871 nd_free(&lldev->ndp); 2872 2873 xge_debug_ll(XGE_TRACE, "etherenet device %s%d unregistered", 2874 XGELL_IFNAME, lldev->instance); 2875 2876 return (DDI_SUCCESS); 2877 } 2878