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(c) 2007-2008 Intel Corporation. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #include "ixgbe_sw.h" 32 33 static int ixgbe_tx_copy(ixgbe_tx_ring_t *, tx_control_block_t *, mblk_t *, 34 uint32_t, boolean_t); 35 static int ixgbe_tx_bind(ixgbe_tx_ring_t *, tx_control_block_t *, mblk_t *, 36 uint32_t); 37 static int ixgbe_tx_fill_ring(ixgbe_tx_ring_t *, link_list_t *, 38 ixgbe_tx_context_t *, size_t); 39 static void ixgbe_save_desc(tx_control_block_t *, uint64_t, size_t); 40 static tx_control_block_t *ixgbe_get_free_list(ixgbe_tx_ring_t *); 41 42 static int ixgbe_get_context(mblk_t *, ixgbe_tx_context_t *); 43 static boolean_t ixgbe_check_context(ixgbe_tx_ring_t *, 44 ixgbe_tx_context_t *); 45 static void ixgbe_fill_context(struct ixgbe_adv_tx_context_desc *, 46 ixgbe_tx_context_t *, int); 47 48 #ifndef IXGBE_DEBUG 49 #pragma inline(ixgbe_save_desc) 50 #pragma inline(ixgbe_get_context) 51 #pragma inline(ixgbe_check_context) 52 #pragma inline(ixgbe_fill_context) 53 #endif 54 55 /* 56 * ixgbe_ring_tx 57 * 58 * To transmit one mblk through one specified ring. 59 * 60 * One mblk can consist of several fragments, each fragment 61 * will be processed with different methods based on the size. 62 * For the fragments with size less than the bcopy threshold, 63 * they will be processed by using bcopy; otherwise, they will 64 * be processed by using DMA binding. 65 * 66 * To process the mblk, a tx control block is got from the 67 * free list. One tx control block contains one tx buffer, which 68 * is used to copy mblk fragments' data; and one tx DMA handle, 69 * which is used to bind a mblk fragment with DMA resource. 70 * 71 * Several small mblk fragments can be copied into one tx control 72 * block's buffer, and then the buffer will be transmitted with 73 * one tx descriptor. 74 * 75 * A large fragment only binds with one tx control block's DMA 76 * handle, and it can span several tx descriptors for transmitting. 77 * 78 * So to transmit a packet (mblk), several tx control blocks can 79 * be used. After the processing, those tx control blocks will 80 * be put to the work list. 81 */ 82 mblk_t * 83 ixgbe_ring_tx(void *arg, mblk_t *mp) 84 { 85 ixgbe_tx_ring_t *tx_ring = (ixgbe_tx_ring_t *)arg; 86 ixgbe_t *ixgbe = tx_ring->ixgbe; 87 tx_type_t current_flag, next_flag; 88 uint32_t current_len, next_len; 89 uint32_t desc_total; 90 size_t mbsize; 91 int desc_num; 92 boolean_t copy_done, eop; 93 mblk_t *current_mp, *next_mp, *nmp; 94 tx_control_block_t *tcb; 95 ixgbe_tx_context_t tx_context, *ctx; 96 link_list_t pending_list; 97 uint32_t len, hdr_frag_len, hdr_len; 98 uint32_t copy_thresh; 99 mblk_t *new_mp; 100 mblk_t *pre_mp; 101 102 ASSERT(mp->b_next == NULL); 103 104 copy_thresh = tx_ring->copy_thresh; 105 106 /* Get the mblk size */ 107 mbsize = 0; 108 for (nmp = mp; nmp != NULL; nmp = nmp->b_cont) { 109 mbsize += MBLKL(nmp); 110 } 111 112 if (ixgbe->tx_hcksum_enable) { 113 /* 114 * Retrieve checksum context information from the mblk 115 * that will be used to decide whether/how to fill the 116 * context descriptor. 117 */ 118 ctx = &tx_context; 119 if (ixgbe_get_context(mp, ctx) < 0) { 120 freemsg(mp); 121 return (NULL); 122 } 123 124 /* 125 * If the mblk size exceeds the max size ixgbe could 126 * process, then discard this mblk, and return NULL. 127 */ 128 if ((ctx->lso_flag && ((mbsize - ctx->mac_hdr_len) 129 > IXGBE_LSO_MAXLEN)) || (!ctx->lso_flag && 130 (mbsize > (ixgbe->max_frame_size - ETHERFCSL)))) { 131 freemsg(mp); 132 IXGBE_DEBUGLOG_0(ixgbe, "ixgbe_tx: packet oversize"); 133 return (NULL); 134 } 135 } else { 136 ctx = NULL; 137 } 138 139 /* 140 * Check and recycle tx descriptors. 141 * The recycle threshold here should be selected carefully 142 */ 143 if (tx_ring->tbd_free < tx_ring->recycle_thresh) 144 tx_ring->tx_recycle(tx_ring); 145 146 /* 147 * After the recycling, if the tbd_free is less than the 148 * overload_threshold, assert overload, return mp; 149 * and we need to re-schedule the tx again. 150 */ 151 if (tx_ring->tbd_free < tx_ring->overload_thresh) { 152 tx_ring->reschedule = B_TRUE; 153 IXGBE_DEBUG_STAT(tx_ring->stat_overload); 154 return (mp); 155 } 156 157 /* 158 * The pending_list is a linked list that is used to save 159 * the tx control blocks that have packet data processed 160 * but have not put the data to the tx descriptor ring. 161 * It is used to reduce the lock contention of the tx_lock. 162 */ 163 LINK_LIST_INIT(&pending_list); 164 desc_num = 0; 165 desc_total = 0; 166 167 /* 168 * The software should guarantee LSO packet header(MAC+IP+TCP) 169 * to be within one descriptor. Here we reallocate and refill the 170 * the header if it's physical memory non-contiguous. 171 */ 172 if ((ctx != NULL) && ctx->lso_flag) { 173 /* find the last fragment of the header */ 174 len = MBLKL(mp); 175 ASSERT(len > 0); 176 nmp = mp; 177 pre_mp = NULL; 178 hdr_len = ctx->ip_hdr_len + ctx->mac_hdr_len + ctx->l4_hdr_len; 179 while (len < hdr_len) { 180 pre_mp = nmp; 181 nmp = nmp->b_cont; 182 len += MBLKL(nmp); 183 } 184 /* 185 * If the header and the payload are in different mblks, 186 * we simply force the header to be copied into pre-allocated 187 * page-aligned buffer. 188 */ 189 if (len == hdr_len) 190 goto adjust_threshold; 191 192 hdr_frag_len = hdr_len - (len - MBLKL(nmp)); 193 /* 194 * There are two cases we need to reallocate a mblk for the 195 * last header fragment: 196 * 1. the header is in multiple mblks and the last fragment 197 * share the same mblk with the payload 198 * 2. the header is in a single mblk shared with the payload 199 * and the header is physical memory non-contiguous 200 */ 201 if ((nmp != mp) || 202 (P2NPHASE((uintptr_t)nmp->b_rptr, ixgbe->sys_page_size) 203 < len)) { 204 IXGBE_DEBUG_STAT(tx_ring->stat_lso_header_fail); 205 /* 206 * reallocate the mblk for the last header fragment, 207 * expect to bcopy into pre-allocated page-aligned 208 * buffer 209 */ 210 new_mp = allocb(hdr_frag_len, NULL); 211 if (!new_mp) 212 return (B_FALSE); 213 bcopy(nmp->b_rptr, new_mp->b_rptr, hdr_frag_len); 214 /* link the new header fragment with the other parts */ 215 new_mp->b_wptr = new_mp->b_rptr + hdr_frag_len; 216 new_mp->b_cont = nmp; 217 if (pre_mp) 218 pre_mp->b_cont = new_mp; 219 nmp->b_rptr += hdr_frag_len; 220 if (hdr_frag_len == hdr_len) 221 mp = new_mp; 222 } 223 adjust_threshold: 224 /* 225 * adjust the bcopy threshhold to guarantee 226 * the header to use bcopy way 227 */ 228 if (copy_thresh < hdr_len) 229 copy_thresh = hdr_len; 230 } 231 232 current_mp = mp; 233 current_len = MBLKL(current_mp); 234 /* 235 * Decide which method to use for the first fragment 236 */ 237 current_flag = (current_len <= copy_thresh) ? 238 USE_COPY : USE_DMA; 239 /* 240 * If the mblk includes several contiguous small fragments, 241 * they may be copied into one buffer. This flag is used to 242 * indicate whether there are pending fragments that need to 243 * be copied to the current tx buffer. 244 * 245 * If this flag is B_TRUE, it indicates that a new tx control 246 * block is needed to process the next fragment using either 247 * copy or DMA binding. 248 * 249 * Otherwise, it indicates that the next fragment will be 250 * copied to the current tx buffer that is maintained by the 251 * current tx control block. No new tx control block is needed. 252 */ 253 copy_done = B_TRUE; 254 while (current_mp) { 255 next_mp = current_mp->b_cont; 256 eop = (next_mp == NULL); /* Last fragment of the packet? */ 257 next_len = eop ? 0: MBLKL(next_mp); 258 259 /* 260 * When the current fragment is an empty fragment, if 261 * the next fragment will still be copied to the current 262 * tx buffer, we cannot skip this fragment here. Because 263 * the copy processing is pending for completion. We have 264 * to process this empty fragment in the tx_copy routine. 265 * 266 * If the copy processing is completed or a DMA binding 267 * processing is just completed, we can just skip this 268 * empty fragment. 269 */ 270 if ((current_len == 0) && (copy_done)) { 271 current_mp = next_mp; 272 current_len = next_len; 273 current_flag = (current_len <= copy_thresh) ? 274 USE_COPY : USE_DMA; 275 continue; 276 } 277 278 if (copy_done) { 279 /* 280 * Get a new tx control block from the free list 281 */ 282 tcb = ixgbe_get_free_list(tx_ring); 283 284 if (tcb == NULL) { 285 IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tcb); 286 goto tx_failure; 287 } 288 289 /* 290 * Push the tx control block to the pending list 291 * to avoid using lock too early 292 */ 293 LIST_PUSH_TAIL(&pending_list, &tcb->link); 294 } 295 296 if (current_flag == USE_COPY) { 297 /* 298 * Check whether to use bcopy or DMA binding to process 299 * the next fragment, and if using bcopy, whether we 300 * need to continue copying the next fragment into the 301 * current tx buffer. 302 */ 303 ASSERT((tcb->tx_buf.len + current_len) <= 304 tcb->tx_buf.size); 305 306 if (eop) { 307 /* 308 * This is the last fragment of the packet, so 309 * the copy processing will be completed with 310 * this fragment. 311 */ 312 next_flag = USE_NONE; 313 copy_done = B_TRUE; 314 } else if ((tcb->tx_buf.len + current_len + next_len) > 315 tcb->tx_buf.size) { 316 /* 317 * If the next fragment is too large to be 318 * copied to the current tx buffer, we need 319 * to complete the current copy processing. 320 */ 321 next_flag = (next_len > copy_thresh) ? 322 USE_DMA: USE_COPY; 323 copy_done = B_TRUE; 324 } else if (next_len > copy_thresh) { 325 /* 326 * The next fragment needs to be processed with 327 * DMA binding. So the copy prcessing will be 328 * completed with the current fragment. 329 */ 330 next_flag = USE_DMA; 331 copy_done = B_TRUE; 332 } else { 333 /* 334 * Continue to copy the next fragment to the 335 * current tx buffer. 336 */ 337 next_flag = USE_COPY; 338 copy_done = B_FALSE; 339 } 340 341 desc_num = ixgbe_tx_copy(tx_ring, tcb, current_mp, 342 current_len, copy_done); 343 } else { 344 /* 345 * Check whether to use bcopy or DMA binding to process 346 * the next fragment. 347 */ 348 next_flag = (next_len > copy_thresh) ? 349 USE_DMA: USE_COPY; 350 ASSERT(copy_done == B_TRUE); 351 352 desc_num = ixgbe_tx_bind(tx_ring, tcb, current_mp, 353 current_len); 354 } 355 356 if (desc_num > 0) 357 desc_total += desc_num; 358 else if (desc_num < 0) 359 goto tx_failure; 360 361 current_mp = next_mp; 362 current_len = next_len; 363 current_flag = next_flag; 364 } 365 366 /* 367 * Attach the mblk to the last tx control block 368 */ 369 ASSERT(tcb); 370 ASSERT(tcb->mp == NULL); 371 tcb->mp = mp; 372 373 /* 374 * Before fill the tx descriptor ring with the data, we need to 375 * ensure there are adequate free descriptors for transmit 376 * (including one context descriptor). 377 */ 378 if (tx_ring->tbd_free < (desc_total + 1)) { 379 tx_ring->tx_recycle(tx_ring); 380 } 381 382 mutex_enter(&tx_ring->tx_lock); 383 384 /* 385 * If the number of free tx descriptors is not enough for transmit 386 * then return mp. 387 * 388 * Note: we must put this check under the mutex protection to 389 * ensure the correctness when multiple threads access it in 390 * parallel. 391 */ 392 if (tx_ring->tbd_free < (desc_total + 1)) { 393 IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tbd); 394 mutex_exit(&tx_ring->tx_lock); 395 goto tx_failure; 396 } 397 398 desc_num = ixgbe_tx_fill_ring(tx_ring, &pending_list, ctx, 399 mbsize); 400 401 ASSERT((desc_num == desc_total) || (desc_num == (desc_total + 1))); 402 403 mutex_exit(&tx_ring->tx_lock); 404 405 return (NULL); 406 407 tx_failure: 408 /* 409 * Discard the mblk and free the used resources 410 */ 411 tcb = (tx_control_block_t *)LIST_GET_HEAD(&pending_list); 412 while (tcb) { 413 tcb->mp = NULL; 414 415 ixgbe_free_tcb(tcb); 416 417 tcb = (tx_control_block_t *) 418 LIST_GET_NEXT(&pending_list, &tcb->link); 419 } 420 421 /* 422 * Return the tx control blocks in the pending list to the free list. 423 */ 424 ixgbe_put_free_list(tx_ring, &pending_list); 425 426 /* Transmit failed, do not drop the mblk, rechedule the transmit */ 427 tx_ring->reschedule = B_TRUE; 428 429 return (mp); 430 } 431 432 /* 433 * ixgbe_tx_copy 434 * 435 * Copy the mblk fragment to the pre-allocated tx buffer 436 */ 437 static int 438 ixgbe_tx_copy(ixgbe_tx_ring_t *tx_ring, tx_control_block_t *tcb, mblk_t *mp, 439 uint32_t len, boolean_t copy_done) 440 { 441 dma_buffer_t *tx_buf; 442 uint32_t desc_num; 443 _NOTE(ARGUNUSED(tx_ring)); 444 445 tx_buf = &tcb->tx_buf; 446 447 /* 448 * Copy the packet data of the mblk fragment into the 449 * pre-allocated tx buffer, which is maintained by the 450 * tx control block. 451 * 452 * Several mblk fragments can be copied into one tx buffer. 453 * The destination address of the current copied fragment in 454 * the tx buffer is next to the end of the previous copied 455 * fragment. 456 */ 457 if (len > 0) { 458 bcopy(mp->b_rptr, tx_buf->address + tx_buf->len, len); 459 460 tx_buf->len += len; 461 tcb->frag_num++; 462 } 463 464 desc_num = 0; 465 466 /* 467 * If it is the last fragment copied to the current tx buffer, 468 * in other words, if there's no remaining fragment or the remaining 469 * fragment requires a new tx control block to process, we need to 470 * complete the current copy processing by syncing up the current 471 * DMA buffer and saving the descriptor data. 472 */ 473 if (copy_done) { 474 /* 475 * Sync the DMA buffer of the packet data 476 */ 477 DMA_SYNC(tx_buf, DDI_DMA_SYNC_FORDEV); 478 479 tcb->tx_type = USE_COPY; 480 481 /* 482 * Save the address and length to the private data structure 483 * of the tx control block, which will be used to fill the 484 * tx descriptor ring after all the fragments are processed. 485 */ 486 ixgbe_save_desc(tcb, tx_buf->dma_address, tx_buf->len); 487 desc_num++; 488 } 489 490 return (desc_num); 491 } 492 493 /* 494 * ixgbe_tx_bind 495 * 496 * Bind the mblk fragment with DMA 497 */ 498 static int 499 ixgbe_tx_bind(ixgbe_tx_ring_t *tx_ring, tx_control_block_t *tcb, mblk_t *mp, 500 uint32_t len) 501 { 502 int status, i; 503 ddi_dma_cookie_t dma_cookie; 504 uint_t ncookies; 505 int desc_num; 506 507 /* 508 * Use DMA binding to process the mblk fragment 509 */ 510 status = ddi_dma_addr_bind_handle(tcb->tx_dma_handle, NULL, 511 (caddr_t)mp->b_rptr, len, 512 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 513 0, &dma_cookie, &ncookies); 514 515 if (status != DDI_DMA_MAPPED) { 516 IXGBE_DEBUG_STAT(tx_ring->stat_fail_dma_bind); 517 return (-1); 518 } 519 520 tcb->frag_num++; 521 tcb->tx_type = USE_DMA; 522 /* 523 * Each fragment can span several cookies. One cookie will have 524 * one tx descriptor to transmit. 525 */ 526 desc_num = 0; 527 for (i = ncookies; i > 0; i--) { 528 /* 529 * Save the address and length to the private data structure 530 * of the tx control block, which will be used to fill the 531 * tx descriptor ring after all the fragments are processed. 532 */ 533 ixgbe_save_desc(tcb, 534 dma_cookie.dmac_laddress, 535 dma_cookie.dmac_size); 536 537 desc_num++; 538 539 if (i > 1) 540 ddi_dma_nextcookie(tcb->tx_dma_handle, &dma_cookie); 541 } 542 543 return (desc_num); 544 } 545 546 /* 547 * ixgbe_get_context 548 * 549 * Get the context information from the mblk 550 */ 551 static int 552 ixgbe_get_context(mblk_t *mp, ixgbe_tx_context_t *ctx) 553 { 554 uint32_t start; 555 uint32_t hckflags; 556 uint32_t lsoflags; 557 uint32_t mss; 558 uint32_t len; 559 uint32_t size; 560 uint32_t offset; 561 unsigned char *pos; 562 ushort_t etype; 563 uint32_t mac_hdr_len; 564 uint32_t l4_proto; 565 uint32_t l4_hdr_len; 566 567 ASSERT(mp != NULL); 568 569 hcksum_retrieve(mp, NULL, NULL, &start, NULL, NULL, NULL, &hckflags); 570 bzero(ctx, sizeof (ixgbe_tx_context_t)); 571 572 if (hckflags == 0) 573 return (0); 574 ctx->hcksum_flags = hckflags; 575 576 lso_info_get(mp, &mss, &lsoflags); 577 ctx->mss = mss; 578 ctx->lso_flag = (lsoflags == HW_LSO); 579 580 /* 581 * LSO relies on tx h/w checksum, so here will drop the package 582 * if h/w checksum flag is not declared. 583 */ 584 if (ctx->lso_flag) { 585 if (!((ctx->hcksum_flags & HCK_PARTIALCKSUM) && 586 (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM))) { 587 IXGBE_DEBUGLOG_0(NULL, "ixgbe_tx: h/w " 588 "checksum flags are not specified when doing LSO"); 589 return (-1); 590 } 591 } 592 593 etype = 0; 594 mac_hdr_len = 0; 595 l4_proto = 0; 596 597 /* 598 * Firstly get the position of the ether_type/ether_tpid. 599 * Here we don't assume the ether (VLAN) header is fully included 600 * in one mblk fragment, so we go thourgh the fragments to parse 601 * the ether type. 602 */ 603 size = len = MBLKL(mp); 604 offset = offsetof(struct ether_header, ether_type); 605 while (size <= offset) { 606 mp = mp->b_cont; 607 ASSERT(mp != NULL); 608 len = MBLKL(mp); 609 size += len; 610 } 611 pos = mp->b_rptr + offset + len - size; 612 613 etype = ntohs(*(ushort_t *)(uintptr_t)pos); 614 if (etype == ETHERTYPE_VLAN) { 615 /* 616 * Get the position of the ether_type in VLAN header 617 */ 618 offset = offsetof(struct ether_vlan_header, ether_type); 619 while (size <= offset) { 620 mp = mp->b_cont; 621 ASSERT(mp != NULL); 622 len = MBLKL(mp); 623 size += len; 624 } 625 pos = mp->b_rptr + offset + len - size; 626 627 etype = ntohs(*(ushort_t *)(uintptr_t)pos); 628 mac_hdr_len = sizeof (struct ether_vlan_header); 629 } else { 630 mac_hdr_len = sizeof (struct ether_header); 631 } 632 633 /* 634 * Here we don't assume the IP(V6) header is fully included in 635 * one mblk fragment. 636 */ 637 switch (etype) { 638 case ETHERTYPE_IP: 639 if (ctx->lso_flag) { 640 offset = offsetof(ipha_t, ipha_length) + mac_hdr_len; 641 while (size <= offset) { 642 mp = mp->b_cont; 643 ASSERT(mp != NULL); 644 len = MBLKL(mp); 645 size += len; 646 } 647 pos = mp->b_rptr + offset + len - size; 648 *((uint16_t *)(uintptr_t)(pos)) = 0; 649 650 offset = offsetof(ipha_t, ipha_hdr_checksum) + 651 mac_hdr_len; 652 while (size <= offset) { 653 mp = mp->b_cont; 654 ASSERT(mp != NULL); 655 len = MBLKL(mp); 656 size += len; 657 } 658 pos = mp->b_rptr + offset + len - size; 659 *((uint16_t *)(uintptr_t)(pos)) = 0; 660 661 /* 662 * To perform ixgbe LSO, here also need to fill 663 * the tcp checksum field of the packet with the 664 * following pseudo-header checksum: 665 * (ip_source_addr, ip_destination_addr, l4_proto) 666 * Currently the tcp/ip stack has done it. 667 */ 668 } 669 670 offset = offsetof(ipha_t, ipha_protocol) + mac_hdr_len; 671 while (size <= offset) { 672 mp = mp->b_cont; 673 ASSERT(mp != NULL); 674 len = MBLKL(mp); 675 size += len; 676 } 677 pos = mp->b_rptr + offset + len - size; 678 679 l4_proto = *(uint8_t *)pos; 680 break; 681 case ETHERTYPE_IPV6: 682 offset = offsetof(ip6_t, ip6_nxt) + mac_hdr_len; 683 while (size <= offset) { 684 mp = mp->b_cont; 685 ASSERT(mp != NULL); 686 len = MBLKL(mp); 687 size += len; 688 } 689 pos = mp->b_rptr + offset + len - size; 690 691 l4_proto = *(uint8_t *)pos; 692 break; 693 default: 694 /* Unrecoverable error */ 695 IXGBE_DEBUGLOG_0(NULL, "Ether type error with tx hcksum"); 696 return (-2); 697 } 698 699 if (ctx->lso_flag) { 700 offset = mac_hdr_len + start; 701 while (size <= offset) { 702 mp = mp->b_cont; 703 ASSERT(mp != NULL); 704 len = MBLKL(mp); 705 size += len; 706 } 707 pos = mp->b_rptr + offset + len - size; 708 709 l4_hdr_len = TCP_HDR_LENGTH((tcph_t *)pos); 710 } else { 711 /* 712 * l4 header length is only required for LSO 713 */ 714 l4_hdr_len = 0; 715 } 716 717 ctx->mac_hdr_len = mac_hdr_len; 718 ctx->ip_hdr_len = start; 719 ctx->l4_proto = l4_proto; 720 ctx->l4_hdr_len = l4_hdr_len; 721 722 return (0); 723 } 724 725 /* 726 * ixgbe_check_context 727 * 728 * Check if a new context descriptor is needed 729 */ 730 static boolean_t 731 ixgbe_check_context(ixgbe_tx_ring_t *tx_ring, ixgbe_tx_context_t *ctx) 732 { 733 ixgbe_tx_context_t *last; 734 735 if (ctx == NULL) 736 return (B_FALSE); 737 738 /* 739 * Compare the context data retrieved from the mblk and the 740 * stored data of the last context descriptor. The data need 741 * to be checked are: 742 * hcksum_flags 743 * l4_proto 744 * mac_hdr_len 745 * ip_hdr_len 746 * lso_flag 747 * mss (only checked for LSO) 748 * l4_hr_len (only checked for LSO) 749 * Either one of the above data is changed, a new context descriptor 750 * will be needed. 751 */ 752 last = &tx_ring->tx_context; 753 754 if ((ctx->hcksum_flags != last->hcksum_flags) || 755 (ctx->l4_proto != last->l4_proto) || 756 (ctx->mac_hdr_len != last->mac_hdr_len) || 757 (ctx->ip_hdr_len != last->ip_hdr_len) || 758 (ctx->lso_flag != last->lso_flag) || 759 (ctx->lso_flag && ((ctx->mss != last->mss) || 760 (ctx->l4_hdr_len != last->l4_hdr_len)))) { 761 return (B_TRUE); 762 } 763 764 return (B_FALSE); 765 } 766 767 /* 768 * ixgbe_fill_context 769 * 770 * Fill the context descriptor with hardware checksum informations 771 */ 772 static void 773 ixgbe_fill_context(struct ixgbe_adv_tx_context_desc *ctx_tbd, 774 ixgbe_tx_context_t *ctx, int ring_index) 775 { 776 /* 777 * Fill the context descriptor with the checksum 778 * context information we've got. 779 */ 780 ctx_tbd->vlan_macip_lens = ctx->ip_hdr_len; 781 ctx_tbd->vlan_macip_lens |= ctx->mac_hdr_len << 782 IXGBE_ADVTXD_MACLEN_SHIFT; 783 784 ctx_tbd->type_tucmd_mlhl = 785 IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; 786 787 if (ctx->hcksum_flags & HCK_IPV4_HDRCKSUM) 788 ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV4; 789 790 if (ctx->hcksum_flags & HCK_PARTIALCKSUM) { 791 switch (ctx->l4_proto) { 792 case IPPROTO_TCP: 793 ctx_tbd->type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP; 794 break; 795 case IPPROTO_UDP: 796 /* 797 * We don't have to explicitly set: 798 * ctx_tbd->type_tucmd_mlhl |= 799 * IXGBE_ADVTXD_TUCMD_L4T_UDP; 800 * Because IXGBE_ADVTXD_TUCMD_L4T_UDP == 0b 801 */ 802 break; 803 default: 804 /* Unrecoverable error */ 805 IXGBE_DEBUGLOG_0(NULL, "L4 type error with tx hcksum"); 806 break; 807 } 808 } 809 810 ctx_tbd->seqnum_seed = 0; 811 ctx_tbd->mss_l4len_idx = ring_index << 4; 812 813 if (ctx->lso_flag) { 814 ctx_tbd->mss_l4len_idx |= 815 (ctx->l4_hdr_len << IXGBE_ADVTXD_L4LEN_SHIFT) | 816 (ctx->mss << IXGBE_ADVTXD_MSS_SHIFT); 817 } 818 } 819 820 /* 821 * ixgbe_tx_fill_ring 822 * 823 * Fill the tx descriptor ring with the data 824 */ 825 static int 826 ixgbe_tx_fill_ring(ixgbe_tx_ring_t *tx_ring, link_list_t *pending_list, 827 ixgbe_tx_context_t *ctx, size_t mbsize) 828 { 829 struct ixgbe_hw *hw = &tx_ring->ixgbe->hw; 830 boolean_t load_context; 831 uint32_t index, tcb_index, desc_num; 832 union ixgbe_adv_tx_desc *tbd, *first_tbd; 833 tx_control_block_t *tcb, *first_tcb; 834 uint32_t hcksum_flags; 835 int i; 836 837 ASSERT(mutex_owned(&tx_ring->tx_lock)); 838 839 tbd = NULL; 840 first_tbd = NULL; 841 first_tcb = NULL; 842 desc_num = 0; 843 hcksum_flags = 0; 844 load_context = B_FALSE; 845 846 /* 847 * Get the index of the first tx descriptor that will be filled, 848 * and the index of the first work list item that will be attached 849 * with the first used tx control block in the pending list. 850 * Note: the two indexes are the same. 851 */ 852 index = tx_ring->tbd_tail; 853 tcb_index = tx_ring->tbd_tail; 854 855 if (ctx != NULL) { 856 hcksum_flags = ctx->hcksum_flags; 857 858 /* 859 * Check if a new context descriptor is needed for this packet 860 */ 861 load_context = ixgbe_check_context(tx_ring, ctx); 862 863 if (load_context) { 864 first_tcb = (tx_control_block_t *) 865 LIST_GET_HEAD(pending_list); 866 tbd = &tx_ring->tbd_ring[index]; 867 868 /* 869 * Fill the context descriptor with the 870 * hardware checksum offload informations. 871 */ 872 ixgbe_fill_context( 873 (struct ixgbe_adv_tx_context_desc *)tbd, 874 ctx, tx_ring->index); 875 876 index = NEXT_INDEX(index, 1, tx_ring->ring_size); 877 desc_num++; 878 879 /* 880 * Store the checksum context data if 881 * a new context descriptor is added 882 */ 883 tx_ring->tx_context = *ctx; 884 } 885 } 886 887 first_tbd = &tx_ring->tbd_ring[index]; 888 889 /* 890 * Fill tx data descriptors with the data saved in the pending list. 891 * The tx control blocks in the pending list are added to the work list 892 * at the same time. 893 * 894 * The work list is strictly 1:1 corresponding to the descriptor ring. 895 * One item of the work list corresponds to one tx descriptor. Because 896 * one tx control block can span multiple tx descriptors, the tx 897 * control block will be added to the first work list item that 898 * corresponds to the first tx descriptor generated from that tx 899 * control block. 900 */ 901 tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list); 902 while (tcb != NULL) { 903 904 for (i = 0; i < tcb->desc_num; i++) { 905 tbd = &tx_ring->tbd_ring[index]; 906 907 tbd->read.buffer_addr = tcb->desc[i].address; 908 tbd->read.cmd_type_len = tcb->desc[i].length; 909 910 tbd->read.cmd_type_len |= IXGBE_ADVTXD_DCMD_RS | 911 IXGBE_ADVTXD_DCMD_DEXT | IXGBE_ADVTXD_DTYP_DATA; 912 913 tbd->read.olinfo_status = 0; 914 915 index = NEXT_INDEX(index, 1, tx_ring->ring_size); 916 desc_num++; 917 } 918 919 if (first_tcb != NULL) { 920 /* 921 * Count the checksum context descriptor for 922 * the first tx control block. 923 */ 924 first_tcb->desc_num++; 925 first_tcb = NULL; 926 } 927 928 /* 929 * Add the tx control block to the work list 930 */ 931 ASSERT(tx_ring->work_list[tcb_index] == NULL); 932 tx_ring->work_list[tcb_index] = tcb; 933 934 tcb_index = index; 935 tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list); 936 } 937 938 /* 939 * The Insert Ethernet CRC (IFCS) bit and the checksum fields are only 940 * valid in the first descriptor of the packet. 941 */ 942 ASSERT(first_tbd != NULL); 943 first_tbd->read.cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS; 944 first_tbd->read.olinfo_status |= (tx_ring->index << 4); 945 946 if (ctx != NULL && ctx->lso_flag) { 947 first_tbd->read.cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; 948 first_tbd->read.olinfo_status |= 949 (mbsize - ctx->mac_hdr_len - ctx->ip_hdr_len 950 - ctx->l4_hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT; 951 } 952 953 if (ctx != NULL && ctx->lso_flag) { 954 first_tbd->read.cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE; 955 first_tbd->read.olinfo_status |= 956 (mbsize - ctx->mac_hdr_len - ctx->ip_hdr_len 957 - ctx->l4_hdr_len) << IXGBE_ADVTXD_PAYLEN_SHIFT; 958 } 959 960 /* Set hardware checksum bits */ 961 if (hcksum_flags != 0) { 962 if (hcksum_flags & HCK_IPV4_HDRCKSUM) 963 first_tbd->read.olinfo_status |= 964 IXGBE_ADVTXD_POPTS_IXSM; 965 if (hcksum_flags & HCK_PARTIALCKSUM) 966 first_tbd->read.olinfo_status |= 967 IXGBE_ADVTXD_POPTS_TXSM; 968 } 969 970 /* 971 * The last descriptor of packet needs End Of Packet (EOP), 972 * and Report Status (RS) bits set 973 */ 974 ASSERT(tbd != NULL); 975 tbd->read.cmd_type_len |= 976 IXGBE_ADVTXD_DCMD_EOP | IXGBE_ADVTXD_DCMD_RS; 977 978 /* 979 * Sync the DMA buffer of the tx descriptor ring 980 */ 981 DMA_SYNC(&tx_ring->tbd_area, DDI_DMA_SYNC_FORDEV); 982 983 if (ixgbe_check_dma_handle(tx_ring->tbd_area.dma_handle) != DDI_FM_OK) { 984 ddi_fm_service_impact(tx_ring->ixgbe->dip, 985 DDI_SERVICE_DEGRADED); 986 } 987 988 /* 989 * Update the number of the free tx descriptors. 990 * The mutual exclusion between the transmission and the recycling 991 * (for the tx descriptor ring and the work list) is implemented 992 * with the atomic operation on the number of the free tx descriptors. 993 * 994 * Note: we should always decrement the counter tbd_free before 995 * advancing the hardware TDT pointer to avoid the race condition - 996 * before the counter tbd_free is decremented, the transmit of the 997 * tx descriptors has done and the counter tbd_free is increased by 998 * the tx recycling. 999 */ 1000 i = ixgbe_atomic_reserve(&tx_ring->tbd_free, desc_num); 1001 ASSERT(i >= 0); 1002 1003 tx_ring->tbd_tail = index; 1004 1005 /* 1006 * Advance the hardware TDT pointer of the tx descriptor ring 1007 */ 1008 IXGBE_WRITE_REG(hw, IXGBE_TDT(tx_ring->index), index); 1009 1010 if (ixgbe_check_acc_handle(tx_ring->ixgbe->osdep.reg_handle) != 1011 DDI_FM_OK) { 1012 ddi_fm_service_impact(tx_ring->ixgbe->dip, 1013 DDI_SERVICE_DEGRADED); 1014 } 1015 1016 return (desc_num); 1017 } 1018 1019 /* 1020 * ixgbe_save_desc 1021 * 1022 * Save the address/length pair to the private array 1023 * of the tx control block. The address/length pairs 1024 * will be filled into the tx descriptor ring later. 1025 */ 1026 static void 1027 ixgbe_save_desc(tx_control_block_t *tcb, uint64_t address, size_t length) 1028 { 1029 sw_desc_t *desc; 1030 1031 desc = &tcb->desc[tcb->desc_num]; 1032 desc->address = address; 1033 desc->length = length; 1034 1035 tcb->desc_num++; 1036 } 1037 1038 /* 1039 * ixgbe_tx_recycle_legacy 1040 * 1041 * Recycle the tx descriptors and tx control blocks. 1042 * 1043 * The work list is traversed to check if the corresponding 1044 * tx descriptors have been transmitted. If so, the resources 1045 * bound to the tx control blocks will be freed, and those 1046 * tx control blocks will be returned to the free list. 1047 */ 1048 uint32_t 1049 ixgbe_tx_recycle_legacy(ixgbe_tx_ring_t *tx_ring) 1050 { 1051 uint32_t index, last_index; 1052 int desc_num; 1053 boolean_t desc_done; 1054 tx_control_block_t *tcb; 1055 link_list_t pending_list; 1056 1057 /* 1058 * The mutex_tryenter() is used to avoid unnecessary 1059 * lock contention. 1060 */ 1061 mutex_enter(&tx_ring->recycle_lock); 1062 1063 ASSERT(tx_ring->tbd_free <= tx_ring->ring_size); 1064 1065 if (tx_ring->tbd_free == tx_ring->ring_size) { 1066 tx_ring->recycle_fail = 0; 1067 tx_ring->stall_watchdog = 0; 1068 if (tx_ring->reschedule) { 1069 tx_ring->reschedule = B_FALSE; 1070 mac_tx_ring_update(tx_ring->ixgbe->mac_hdl, 1071 tx_ring->ring_handle); 1072 } 1073 mutex_exit(&tx_ring->recycle_lock); 1074 return (0); 1075 } 1076 1077 /* 1078 * Sync the DMA buffer of the tx descriptor ring 1079 */ 1080 DMA_SYNC(&tx_ring->tbd_area, DDI_DMA_SYNC_FORKERNEL); 1081 1082 if (ixgbe_check_dma_handle(tx_ring->tbd_area.dma_handle) != DDI_FM_OK) { 1083 ddi_fm_service_impact(tx_ring->ixgbe->dip, 1084 DDI_SERVICE_DEGRADED); 1085 } 1086 1087 LINK_LIST_INIT(&pending_list); 1088 desc_num = 0; 1089 index = tx_ring->tbd_head; /* Index of next tbd/tcb to recycle */ 1090 1091 tcb = tx_ring->work_list[index]; 1092 ASSERT(tcb != NULL); 1093 1094 desc_done = B_TRUE; 1095 while (desc_done && (tcb != NULL)) { 1096 1097 /* 1098 * Get the last tx descriptor of the tx control block. 1099 * If the last tx descriptor is done, it is done with 1100 * all the tx descriptors of the tx control block. 1101 * Then the tx control block and all the corresponding 1102 * tx descriptors can be recycled. 1103 */ 1104 last_index = NEXT_INDEX(index, tcb->desc_num - 1, 1105 tx_ring->ring_size); 1106 1107 /* 1108 * Check if the Descriptor Done bit is set 1109 */ 1110 desc_done = tx_ring->tbd_ring[last_index].wb.status & 1111 IXGBE_TXD_STAT_DD; 1112 if (desc_done) { 1113 /* 1114 * Strip off the tx control block from the work list, 1115 * and add it to the pending list. 1116 */ 1117 tx_ring->work_list[index] = NULL; 1118 LIST_PUSH_TAIL(&pending_list, &tcb->link); 1119 1120 /* 1121 * Count the total number of the tx descriptors recycled 1122 */ 1123 desc_num += tcb->desc_num; 1124 1125 /* 1126 * Advance the index of the tx descriptor ring 1127 */ 1128 index = NEXT_INDEX(last_index, 1, tx_ring->ring_size); 1129 1130 tcb = tx_ring->work_list[index]; 1131 } 1132 } 1133 1134 /* 1135 * If no tx descriptors are recycled, no need to do more processing 1136 */ 1137 if (desc_num == 0) { 1138 tx_ring->recycle_fail++; 1139 mutex_exit(&tx_ring->recycle_lock); 1140 return (0); 1141 } 1142 1143 tx_ring->recycle_fail = 0; 1144 tx_ring->stall_watchdog = 0; 1145 1146 /* 1147 * Update the head index of the tx descriptor ring 1148 */ 1149 tx_ring->tbd_head = index; 1150 1151 /* 1152 * Update the number of the free tx descriptors with atomic operations 1153 */ 1154 atomic_add_32(&tx_ring->tbd_free, desc_num); 1155 1156 if ((tx_ring->tbd_free >= tx_ring->resched_thresh) && 1157 (tx_ring->reschedule)) { 1158 tx_ring->reschedule = B_FALSE; 1159 mac_tx_ring_update(tx_ring->ixgbe->mac_hdl, 1160 tx_ring->ring_handle); 1161 } 1162 mutex_exit(&tx_ring->recycle_lock); 1163 1164 /* 1165 * Free the resources used by the tx control blocks 1166 * in the pending list 1167 */ 1168 tcb = (tx_control_block_t *)LIST_GET_HEAD(&pending_list); 1169 while (tcb != NULL) { 1170 /* 1171 * Release the resources occupied by the tx control block 1172 */ 1173 ixgbe_free_tcb(tcb); 1174 1175 tcb = (tx_control_block_t *) 1176 LIST_GET_NEXT(&pending_list, &tcb->link); 1177 } 1178 1179 /* 1180 * Add the tx control blocks in the pending list to the free list. 1181 */ 1182 ixgbe_put_free_list(tx_ring, &pending_list); 1183 1184 return (desc_num); 1185 } 1186 1187 /* 1188 * ixgbe_tx_recycle_head_wb 1189 * 1190 * Check the head write-back, and recycle all the transmitted 1191 * tx descriptors and tx control blocks. 1192 */ 1193 uint32_t 1194 ixgbe_tx_recycle_head_wb(ixgbe_tx_ring_t *tx_ring) 1195 { 1196 uint32_t index; 1197 uint32_t head_wb; 1198 int desc_num; 1199 tx_control_block_t *tcb; 1200 link_list_t pending_list; 1201 1202 /* 1203 * The mutex_tryenter() is used to avoid unnecessary 1204 * lock contention. 1205 */ 1206 mutex_enter(&tx_ring->recycle_lock); 1207 1208 ASSERT(tx_ring->tbd_free <= tx_ring->ring_size); 1209 1210 if (tx_ring->tbd_free == tx_ring->ring_size) { 1211 tx_ring->recycle_fail = 0; 1212 tx_ring->stall_watchdog = 0; 1213 if (tx_ring->reschedule) { 1214 tx_ring->reschedule = B_FALSE; 1215 mac_tx_ring_update(tx_ring->ixgbe->mac_hdl, 1216 tx_ring->ring_handle); 1217 } 1218 mutex_exit(&tx_ring->recycle_lock); 1219 return (0); 1220 } 1221 1222 /* 1223 * Sync the DMA buffer of the tx descriptor ring 1224 * 1225 * Note: For head write-back mode, the tx descriptors will not 1226 * be written back, but the head write-back value is stored at 1227 * the last extra tbd at the end of the DMA area, we still need 1228 * to sync the head write-back value for kernel. 1229 * 1230 * DMA_SYNC(&tx_ring->tbd_area, DDI_DMA_SYNC_FORKERNEL); 1231 */ 1232 (void) ddi_dma_sync(tx_ring->tbd_area.dma_handle, 1233 sizeof (union ixgbe_adv_tx_desc) * tx_ring->ring_size, 1234 sizeof (uint32_t), 1235 DDI_DMA_SYNC_FORKERNEL); 1236 1237 if (ixgbe_check_dma_handle(tx_ring->tbd_area.dma_handle) != DDI_FM_OK) { 1238 ddi_fm_service_impact(tx_ring->ixgbe->dip, 1239 DDI_SERVICE_DEGRADED); 1240 } 1241 1242 LINK_LIST_INIT(&pending_list); 1243 desc_num = 0; 1244 index = tx_ring->tbd_head; /* Next index to clean */ 1245 1246 /* 1247 * Get the value of head write-back 1248 */ 1249 head_wb = *tx_ring->tbd_head_wb; 1250 while (index != head_wb) { 1251 tcb = tx_ring->work_list[index]; 1252 ASSERT(tcb != NULL); 1253 1254 if (OFFSET(index, head_wb, tx_ring->ring_size) < 1255 tcb->desc_num) { 1256 /* 1257 * The current tx control block is not 1258 * completely transmitted, stop recycling 1259 */ 1260 break; 1261 } 1262 1263 /* 1264 * Strip off the tx control block from the work list, 1265 * and add it to the pending list. 1266 */ 1267 tx_ring->work_list[index] = NULL; 1268 LIST_PUSH_TAIL(&pending_list, &tcb->link); 1269 1270 /* 1271 * Advance the index of the tx descriptor ring 1272 */ 1273 index = NEXT_INDEX(index, tcb->desc_num, tx_ring->ring_size); 1274 1275 /* 1276 * Count the total number of the tx descriptors recycled 1277 */ 1278 desc_num += tcb->desc_num; 1279 } 1280 1281 /* 1282 * If no tx descriptors are recycled, no need to do more processing 1283 */ 1284 if (desc_num == 0) { 1285 tx_ring->recycle_fail++; 1286 mutex_exit(&tx_ring->recycle_lock); 1287 return (0); 1288 } 1289 1290 tx_ring->recycle_fail = 0; 1291 tx_ring->stall_watchdog = 0; 1292 1293 /* 1294 * Update the head index of the tx descriptor ring 1295 */ 1296 tx_ring->tbd_head = index; 1297 1298 /* 1299 * Update the number of the free tx descriptors with atomic operations 1300 */ 1301 atomic_add_32(&tx_ring->tbd_free, desc_num); 1302 1303 if ((tx_ring->tbd_free >= tx_ring->resched_thresh) && 1304 (tx_ring->reschedule)) { 1305 tx_ring->reschedule = B_FALSE; 1306 mac_tx_ring_update(tx_ring->ixgbe->mac_hdl, 1307 tx_ring->ring_handle); 1308 } 1309 mutex_exit(&tx_ring->recycle_lock); 1310 1311 /* 1312 * Free the resources used by the tx control blocks 1313 * in the pending list 1314 */ 1315 tcb = (tx_control_block_t *)LIST_GET_HEAD(&pending_list); 1316 while (tcb) { 1317 /* 1318 * Release the resources occupied by the tx control block 1319 */ 1320 ixgbe_free_tcb(tcb); 1321 1322 tcb = (tx_control_block_t *) 1323 LIST_GET_NEXT(&pending_list, &tcb->link); 1324 } 1325 1326 /* 1327 * Add the tx control blocks in the pending list to the free list. 1328 */ 1329 ixgbe_put_free_list(tx_ring, &pending_list); 1330 1331 return (desc_num); 1332 } 1333 1334 /* 1335 * ixgbe_free_tcb - free up the tx control block 1336 * 1337 * Free the resources of the tx control block, including 1338 * unbind the previously bound DMA handle, and reset other 1339 * control fields. 1340 */ 1341 void 1342 ixgbe_free_tcb(tx_control_block_t *tcb) 1343 { 1344 switch (tcb->tx_type) { 1345 case USE_COPY: 1346 /* 1347 * Reset the buffer length that is used for copy 1348 */ 1349 tcb->tx_buf.len = 0; 1350 break; 1351 case USE_DMA: 1352 /* 1353 * Release the DMA resource that is used for 1354 * DMA binding. 1355 */ 1356 (void) ddi_dma_unbind_handle(tcb->tx_dma_handle); 1357 break; 1358 default: 1359 break; 1360 } 1361 1362 /* 1363 * Free the mblk 1364 */ 1365 if (tcb->mp != NULL) { 1366 freemsg(tcb->mp); 1367 tcb->mp = NULL; 1368 } 1369 1370 tcb->tx_type = USE_NONE; 1371 tcb->frag_num = 0; 1372 tcb->desc_num = 0; 1373 } 1374 1375 /* 1376 * ixgbe_get_free_list - Get a free tx control block from the free list 1377 * 1378 * The atomic operation on the number of the available tx control block 1379 * in the free list is used to keep this routine mutual exclusive with 1380 * the routine ixgbe_put_check_list. 1381 */ 1382 static tx_control_block_t * 1383 ixgbe_get_free_list(ixgbe_tx_ring_t *tx_ring) 1384 { 1385 tx_control_block_t *tcb; 1386 1387 /* 1388 * Check and update the number of the free tx control block 1389 * in the free list. 1390 */ 1391 if (ixgbe_atomic_reserve(&tx_ring->tcb_free, 1) < 0) 1392 return (NULL); 1393 1394 mutex_enter(&tx_ring->tcb_head_lock); 1395 1396 tcb = tx_ring->free_list[tx_ring->tcb_head]; 1397 ASSERT(tcb != NULL); 1398 tx_ring->free_list[tx_ring->tcb_head] = NULL; 1399 tx_ring->tcb_head = NEXT_INDEX(tx_ring->tcb_head, 1, 1400 tx_ring->free_list_size); 1401 1402 mutex_exit(&tx_ring->tcb_head_lock); 1403 1404 return (tcb); 1405 } 1406 1407 /* 1408 * ixgbe_put_free_list 1409 * 1410 * Put a list of used tx control blocks back to the free list 1411 * 1412 * A mutex is used here to ensure the serialization. The mutual exclusion 1413 * between ixgbe_get_free_list and ixgbe_put_free_list is implemented with 1414 * the atomic operation on the counter tcb_free. 1415 */ 1416 void 1417 ixgbe_put_free_list(ixgbe_tx_ring_t *tx_ring, link_list_t *pending_list) 1418 { 1419 uint32_t index; 1420 int tcb_num; 1421 tx_control_block_t *tcb; 1422 1423 mutex_enter(&tx_ring->tcb_tail_lock); 1424 1425 index = tx_ring->tcb_tail; 1426 1427 tcb_num = 0; 1428 tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list); 1429 while (tcb != NULL) { 1430 ASSERT(tx_ring->free_list[index] == NULL); 1431 tx_ring->free_list[index] = tcb; 1432 1433 tcb_num++; 1434 1435 index = NEXT_INDEX(index, 1, tx_ring->free_list_size); 1436 1437 tcb = (tx_control_block_t *)LIST_POP_HEAD(pending_list); 1438 } 1439 1440 tx_ring->tcb_tail = index; 1441 1442 /* 1443 * Update the number of the free tx control block 1444 * in the free list. This operation must be placed 1445 * under the protection of the lock. 1446 */ 1447 atomic_add_32(&tx_ring->tcb_free, tcb_num); 1448 1449 mutex_exit(&tx_ring->tcb_tail_lock); 1450 } 1451