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 2014 QLogic Corporation 24 * The contents of this file are subject to the terms of the 25 * QLogic End User License (the "License"). 26 * You may not use this file except in compliance with the License. 27 * 28 * You can obtain a copy of the License at 29 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 30 * QLogic_End_User_Software_License.txt 31 * See the License for the specific language governing permissions 32 * and limitations under the License. 33 */ 34 35 /* 36 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 #include "bnxe.h" 40 41 42 ddi_dma_attr_t bnxeRxDmaAttrib = 43 { 44 DMA_ATTR_V0, /* dma_attr_version */ 45 0, /* dma_attr_addr_lo */ 46 0xffffffffffffffff, /* dma_attr_addr_hi */ 47 0xffffffffffffffff, /* dma_attr_count_max */ 48 BNXE_DMA_ALIGNMENT, /* dma_attr_align */ 49 0xffffffff, /* dma_attr_burstsizes */ 50 1, /* dma_attr_minxfer */ 51 0xffffffffffffffff, /* dma_attr_maxxfer */ 52 0xffffffffffffffff, /* dma_attr_seg */ 53 1, /* dma_attr_sgllen */ 54 1, /* dma_attr_granular */ 55 0, /* dma_attr_flags */ 56 }; 57 58 59 static void BnxeRxPostBuffers(um_device_t * pUM, 60 int idx, 61 s_list_t * pReclaimList) 62 { 63 lm_rx_chain_t * pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); 64 u32_t returnedBytes = 0; 65 lm_packet_t * pLmPkt; 66 67 /* return bytes from reclaimed list to LM */ 68 pLmPkt = (lm_packet_t *)s_list_peek_head(pReclaimList); 69 while (pLmPkt) 70 { 71 returnedBytes += pLmPkt->size; 72 pLmPkt = (lm_packet_t *)s_list_next_entry(&pLmPkt->link); 73 } 74 75 BNXE_LOCK_ENTER_RX(pUM, idx); 76 77 if (pUM->rxq[idx].rxLowWater > s_list_entry_cnt(&pLmRxChain->active_descq)) 78 { 79 pUM->rxq[idx].rxLowWater = s_list_entry_cnt(&pLmRxChain->active_descq); 80 } 81 82 lm_return_packet_bytes(&pUM->lm_dev, idx, returnedBytes); 83 84 s_list_add_tail(&pLmRxChain->common.free_descq, pReclaimList); 85 s_list_clear(pReclaimList); 86 87 #if 0 88 /* 89 * Don't post buffers if we don't have too many free buffers and there are a 90 * lot of buffers already posted. 91 */ 92 if (lm_bd_chain_avail_bds(&pLmRxChain->bd_chain) < 32) 93 { 94 BNXE_LOCK_EXIT_RX(pUM, idx); 95 return; 96 } 97 98 /* 99 * Don't post buffers if there aren't really that many to post yet. 100 */ 101 if (s_list_entry_cnt(&pLmRxChain->common.free_descq) < 32) 102 { 103 BNXE_LOCK_EXIT_RX(pUM, idx); 104 return; 105 } 106 #endif 107 108 lm_post_buffers(&pUM->lm_dev, idx, NULL, 0); 109 110 BNXE_LOCK_EXIT_RX(pUM, idx); 111 } 112 113 114 static u32_t BnxeRxPktDescrSize(um_device_t * pUM) 115 { 116 u32_t descSize; 117 118 (void)pUM; 119 120 descSize = sizeof(um_rxpacket_t) + SIZEOF_SIG; 121 122 return ALIGN_VALUE_TO_WORD_BOUNDARY(descSize); 123 } 124 125 126 static void BnxeRxPktDescrFree(um_device_t * pUM, 127 um_rxpacket_t * pRxPkt) 128 { 129 u32_t descSize; 130 caddr_t pMem; 131 132 BnxeDbgBreakIfFastPath(pUM, SIG(pRxPkt) != L2PACKET_RX_SIG); 133 134 descSize = BnxeRxPktDescrSize(pUM); 135 pMem = (caddr_t)pRxPkt - SIZEOF_SIG; 136 137 kmem_free(pMem, descSize); 138 } 139 140 141 static void BnxeRxPktFree(char * free_arg) 142 { 143 um_rxpacket_t * pRxPkt = (um_rxpacket_t *)free_arg; 144 um_device_t * pUM = (um_device_t *)pRxPkt->pUM; 145 int idx = pRxPkt->idx; 146 s_list_t doneRxQ; 147 148 if (pUM->magic != BNXE_MAGIC) 149 { 150 /* 151 * Oh my! The free_arg data got corrupted. Log a message and leak this 152 * packet. We don't decrement the 'up in the stack count' since we 153 * can't be sure this packet really was a packet we previously sent up. 154 */ 155 BnxeLogWarn(NULL, "ERROR freeing packet - UM is invalid! (%p)", pRxPkt); 156 return; 157 } 158 159 if (pUM->rxBufSignature[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)] != 160 pRxPkt->signature) 161 { 162 /* 163 * The stack is freeing a packet that was from a previous plumb of 164 * the interface. 165 */ 166 pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = 0; 167 pRxPkt->rx_info.mem_virt = NULL; 168 pRxPkt->rx_info.mem_size = 0; 169 170 ddi_dma_unbind_handle(pRxPkt->dmaHandle); 171 ddi_dma_mem_free(&pRxPkt->dmaAccHandle); 172 ddi_dma_free_handle(&pRxPkt->dmaHandle); 173 174 BnxeRxPktDescrFree(pUM, pRxPkt); 175 } 176 else 177 { 178 s_list_clear(&doneRxQ); 179 180 BNXE_LOCK_ENTER_DONERX(pUM, idx); 181 182 s_list_push_tail(&pUM->rxq[idx].doneRxQ, 183 &((lm_packet_t *)pRxPkt)->link); 184 185 /* post packets when a bunch are ready */ 186 if (s_list_entry_cnt(&pUM->rxq[idx].doneRxQ) >= pUM->devParams.maxRxFree) 187 { 188 doneRxQ = pUM->rxq[idx].doneRxQ; 189 s_list_clear(&pUM->rxq[idx].doneRxQ); 190 } 191 192 BNXE_LOCK_EXIT_DONERX(pUM, idx); 193 194 if (s_list_entry_cnt(&doneRxQ)) 195 { 196 BnxeRxPostBuffers(pUM, idx, &doneRxQ); 197 } 198 } 199 200 atomic_dec_32(&pUM->rxq[idx].rxBufUpInStack); 201 } 202 203 204 boolean_t BnxeWaitForPacketsFromClient(um_device_t * pUM, 205 int cliIdx) 206 { 207 int i, idx, cnt=0, tot=0; 208 209 switch (cliIdx) 210 { 211 case LM_CLI_IDX_FCOE: 212 213 for (i = 0; i < 5; i++) 214 { 215 if ((cnt = pUM->rxq[FCOE_CID(&pUM->lm_dev)].rxBufUpInStack) == 0) 216 { 217 break; 218 } 219 220 /* twiddle our thumbs for one second */ 221 delay(drv_usectohz(1000000)); 222 } 223 224 if (cnt) 225 { 226 BnxeLogWarn(pUM, "%d packets still held by FCoE (chain %d)!", 227 cnt, FCOE_CID(&pUM->lm_dev)); 228 return B_FALSE; 229 } 230 231 break; 232 233 case LM_CLI_IDX_NDIS: 234 235 tot = 0; 236 237 LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) 238 { 239 for (i = 0; i < 5; i++) 240 { 241 if ((cnt = pUM->rxq[idx].rxBufUpInStack) == 0) 242 { 243 break; 244 } 245 246 /* twiddle our thumbs for one second */ 247 delay(drv_usectohz(1000000)); 248 } 249 250 tot += cnt; 251 } 252 253 if (tot) 254 { 255 BnxeLogWarn(pUM, "%d packets still held by the stack (chain %d)!", 256 tot, idx); 257 return B_FALSE; 258 } 259 260 break; 261 262 default: 263 264 BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeWaitForPacketsFromClient (%d)", cliIdx); 265 break; 266 } 267 268 return B_TRUE; 269 } 270 271 272 /* numBytes is only valid when polling is TRUE */ 273 mblk_t * BnxeRxRingProcess(um_device_t * pUM, 274 int idx, 275 boolean_t polling, 276 int numBytes) 277 { 278 RxQueue * pRxQ; 279 lm_rx_chain_t * pLmRxChain; 280 u32_t activeDescqCount; 281 boolean_t forceCopy; 282 um_rxpacket_t * pRxPkt; 283 lm_packet_t * pLmPkt; 284 u32_t pktLen; 285 boolean_t dataCopied; 286 u32_t notCopiedCount; 287 mblk_t * pMblk; 288 int ofldFlags; 289 mblk_t * head = NULL; 290 mblk_t * tail = NULL; 291 s_list_t rxList; 292 s_list_t reclaimList; 293 int procBytes = 0; 294 s_list_t tmpList; 295 sp_cqes_info sp_cqes; 296 u32_t pktsRxed; 297 298 pRxQ = &pUM->rxq[idx]; 299 300 s_list_clear(&tmpList); 301 302 /* get the list of packets received */ 303 BNXE_LOCK_ENTER_RX(pUM, idx); 304 305 pktsRxed = lm_get_packets_rcvd(&pUM->lm_dev, idx, &tmpList, &sp_cqes); 306 307 /* grab any waiting packets */ 308 rxList = pRxQ->waitRxQ; 309 s_list_clear(&pRxQ->waitRxQ); 310 311 /* put any new packets at the end of the queue */ 312 s_list_add_tail(&rxList, &tmpList); 313 314 BNXE_LOCK_EXIT_RX(pUM, idx); 315 316 /* now complete the ramrods */ 317 lm_complete_ramrods(&pUM->lm_dev, &sp_cqes); 318 319 if (s_list_entry_cnt(&rxList) == 0) 320 { 321 return NULL; 322 } 323 324 s_list_clear(&reclaimList); 325 notCopiedCount = 0; 326 327 pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); 328 329 activeDescqCount = s_list_entry_cnt(&pLmRxChain->active_descq); 330 331 forceCopy = (activeDescqCount < 332 (pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)] >> 3)); 333 334 /* send the packets up the stack */ 335 while (1) 336 { 337 pRxPkt = (um_rxpacket_t *)s_list_pop_head(&rxList); 338 if (pRxPkt == NULL) 339 { 340 break; 341 } 342 343 pLmPkt = &(pRxPkt->lm_pkt); 344 345 if (pLmPkt->status != LM_STATUS_SUCCESS) 346 { 347 /* XXX increment error stat? */ 348 s_list_push_tail(&reclaimList, &pLmPkt->link); 349 continue; 350 } 351 352 pktLen = pLmPkt->size; 353 354 if (polling == TRUE) 355 { 356 /* When polling an rx ring we can only process up to numBytes */ 357 if ((procBytes + pktLen) <= numBytes) 358 { 359 /* continue to process this packet */ 360 procBytes += pktLen; 361 } 362 else 363 { 364 /* put this packet not processed back on the list (front) */ 365 s_list_push_head(&rxList, &pRxPkt->lm_pkt.link); 366 break; 367 } 368 } 369 370 (void)ddi_dma_sync(pRxPkt->dmaHandle, 371 0, 372 pktLen, 373 DDI_DMA_SYNC_FORKERNEL); 374 375 if (pUM->fmCapabilities && 376 BnxeCheckDmaHandle(pRxPkt->dmaHandle) != DDI_FM_OK) 377 { 378 ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); 379 } 380 381 dataCopied = B_FALSE; 382 383 if (forceCopy || 384 (pUM->devParams.rxCopyThreshold && 385 (pktLen < pUM->devParams.rxCopyThreshold))) 386 { 387 if ((pMblk = allocb(pktLen, BPRI_MED)) == NULL) 388 { 389 pRxQ->rxDiscards++; 390 s_list_push_tail(&reclaimList, &pLmPkt->link); 391 continue; 392 } 393 394 /* copy the packet into the new mblk */ 395 bcopy((pRxPkt->rx_info.mem_virt + BNXE_DMA_RX_OFFSET), 396 pMblk->b_rptr, pktLen); 397 pMblk->b_wptr = (pMblk->b_rptr + pktLen); 398 dataCopied = B_TRUE; 399 400 pRxQ->rxCopied++; 401 402 goto BnxeRxRingProcess_sendup; 403 } 404 405 if ((activeDescqCount == 0) && (s_list_entry_cnt(&rxList) == 0)) 406 { 407 /* 408 * If the hardware is out of receive buffers and we are on the last 409 * receive packet then drop the packet. We do this because we might 410 * not be able to allocate any new receive buffers before the ISR 411 * completes. If this happens, the driver will enter an infinite 412 * interrupt loop where the hardware is requesting rx buffers the 413 * driver cannot allocate. To prevent a system livelock we leave 414 * one buffer perpetually available. Note that we do this after 415 * giving the double copy code a chance to claim the packet. 416 */ 417 418 /* FIXME 419 * Make sure to add one more to the rx packet descriptor count 420 * before allocating them. 421 */ 422 423 pRxQ->rxDiscards++; 424 s_list_push_tail(&reclaimList, &pLmPkt->link); 425 continue; 426 } 427 428 /* 429 * If we got here then the packet wasn't copied so we need to create a 430 * new mblk_t which references the lm_packet_t buffer. 431 */ 432 433 pRxPkt->freeRtn.free_func = BnxeRxPktFree; 434 pRxPkt->freeRtn.free_arg = (char *)pRxPkt; 435 pRxPkt->pUM = (void *)pUM; 436 pRxPkt->idx = idx; 437 438 if ((pMblk = desballoc((pRxPkt->rx_info.mem_virt + BNXE_DMA_RX_OFFSET), 439 pktLen, 440 BPRI_MED, 441 &pRxPkt->freeRtn)) == NULL) 442 { 443 pRxQ->rxDiscards++; 444 s_list_push_tail(&reclaimList, &pLmPkt->link); 445 continue; 446 } 447 448 pMblk->b_wptr = (pMblk->b_rptr + pktLen); 449 450 BnxeRxRingProcess_sendup: 451 452 /* 453 * Check if the checksum was offloaded so we can pass the result to 454 * the stack. 455 */ 456 ofldFlags = 0; 457 458 if ((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_IP_CKSUM) && 459 (pRxPkt->rx_info.flags & LM_RX_FLAG_IP_CKSUM_IS_GOOD)) 460 { 461 ofldFlags |= HCK_IPV4_HDRCKSUM_OK; 462 } 463 464 if (((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_TCP_CKSUM) && 465 (pRxPkt->rx_info.flags & LM_RX_FLAG_TCP_CKSUM_IS_GOOD)) || 466 ((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_UDP_CKSUM) && 467 (pRxPkt->rx_info.flags & LM_RX_FLAG_UDP_CKSUM_IS_GOOD))) 468 { 469 ofldFlags |= HCK_FULLCKSUM_OK; 470 } 471 472 if (ofldFlags != 0) 473 { 474 mac_hcksum_set(pMblk, 0, 0, 0, 0, ofldFlags); 475 } 476 477 /* 478 * If the packet data was copied into a new recieve buffer then put this 479 * descriptor in a list to be reclaimed later. If not, then increment a 480 * counter so we can track how many of our descriptors are held by the 481 * stack. 482 */ 483 if (dataCopied == B_TRUE) 484 { 485 s_list_push_tail(&reclaimList, &pLmPkt->link); 486 } 487 else 488 { 489 notCopiedCount++; 490 } 491 492 if (head == NULL) 493 { 494 head = pMblk; 495 } 496 else 497 { 498 tail->b_next = pMblk; 499 } 500 501 tail = pMblk; 502 tail->b_next = NULL; 503 504 #if 0 505 BnxeDumpPkt(pUM, 506 (BNXE_FCOE(pUM) && (idx == FCOE_CID(&pUM->lm_dev))) ? 507 "<- FCoE L2 RX <-" : "<- L2 RX <-", 508 pMblk, B_TRUE); 509 #endif 510 } 511 512 if (head) 513 { 514 if (notCopiedCount) 515 { 516 /* track all non-copied packets that will be held by the stack */ 517 atomic_add_32(&pUM->rxq[idx].rxBufUpInStack, notCopiedCount); 518 } 519 520 /* pass the mblk chain up the stack */ 521 if (polling == FALSE) 522 { 523 524 /* XXX NEED TO ADD STATS FOR RX PATH UPCALLS */ 525 526 if (BNXE_FCOE(pUM) && (idx == FCOE_CID(&pUM->lm_dev))) 527 { 528 /* XXX verify fcoe frees all packets on success or error */ 529 if (pUM->fcoe.pDev && pUM->fcoe.bind.cliIndicateRx) 530 { 531 pUM->fcoe.bind.cliIndicateRx(pUM->fcoe.pDev, head); 532 } 533 else 534 { 535 /* FCoE isn't bound? Reclaim the chain... */ 536 freemsgchain(head); 537 head = NULL; 538 } 539 } 540 else 541 { 542 #if defined(BNXE_RINGS) && (defined(__S11) || defined(__S12)) 543 mac_rx_ring(pUM->pMac, 544 pUM->rxq[idx].ringHandle, 545 head, 546 pUM->rxq[idx].genNumber); 547 #else 548 mac_rx(pUM->pMac, 549 pUM->macRxResourceHandles[idx], 550 head); 551 #endif 552 } 553 } 554 } 555 556 if ((polling == TRUE) && s_list_entry_cnt(&rxList)) 557 { 558 /* put the packets not processed back on the list (front) */ 559 BNXE_LOCK_ENTER_RX(pUM, idx); 560 s_list_add_head(&pRxQ->waitRxQ, &rxList); 561 BNXE_LOCK_EXIT_RX(pUM, idx); 562 } 563 564 if (s_list_entry_cnt(&reclaimList)) 565 { 566 BnxeRxPostBuffers(pUM, idx, &reclaimList); 567 } 568 569 return (polling == TRUE) ? head : NULL; 570 } 571 572 573 /* 574 * Dumping packets simply moves all packets from the waiting queue to the free 575 * queue. Note that the packets are not posted back to the LM. 576 */ 577 static void BnxeRxRingDump(um_device_t * pUM, 578 int idx) 579 { 580 s_list_t tmpList; 581 582 BNXE_LOCK_ENTER_RX(pUM, idx); 583 584 tmpList = pUM->rxq[idx].waitRxQ; 585 s_list_clear(&pUM->rxq[idx].waitRxQ); 586 587 s_list_add_tail(&LM_RXQ(&pUM->lm_dev, idx).common.free_descq, &tmpList); 588 589 BNXE_LOCK_EXIT_RX(pUM, idx); 590 } 591 592 593 /* 594 * Aborting packets stops all rx processing by dumping the currently waiting 595 * packets and aborting all the rx descriptors currently posted in the LM. 596 */ 597 static void BnxeRxPktsAbortIdx(um_device_t * pUM, 598 int idx) 599 { 600 BnxeRxRingDump(pUM, idx); 601 602 BNXE_LOCK_ENTER_RX(pUM, idx); 603 lm_abort(&pUM->lm_dev, ABORT_OP_RX_CHAIN, idx); 604 BNXE_LOCK_EXIT_RX(pUM, idx); 605 } 606 607 608 void BnxeRxPktsAbort(um_device_t * pUM, 609 int cliIdx) 610 { 611 int idx; 612 613 switch (cliIdx) 614 { 615 case LM_CLI_IDX_FCOE: 616 617 BnxeRxPktsAbortIdx(pUM, FCOE_CID(&pUM->lm_dev)); 618 break; 619 620 case LM_CLI_IDX_NDIS: 621 622 LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) 623 { 624 BnxeRxPktsAbortIdx(pUM, idx); 625 } 626 627 break; 628 629 default: 630 631 BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsAbort (%d)", cliIdx); 632 break; 633 } 634 } 635 636 637 static int BnxeRxBufAlloc(um_device_t * pUM, 638 int idx, 639 um_rxpacket_t * pRxPkt) 640 { 641 ddi_dma_cookie_t cookie; 642 u32_t count; 643 size_t length; 644 int rc; 645 646 if ((rc = ddi_dma_alloc_handle(pUM->pDev, 647 &bnxeRxDmaAttrib, 648 DDI_DMA_DONTWAIT, 649 NULL, 650 &pRxPkt->dmaHandle)) != DDI_SUCCESS) 651 { 652 BnxeLogWarn(pUM, "Failed to alloc DMA handle for rx buffer"); 653 return -1; 654 } 655 656 pRxPkt->rx_info.mem_size = MAX_L2_CLI_BUFFER_SIZE(&pUM->lm_dev, idx); 657 658 if ((rc = ddi_dma_mem_alloc(pRxPkt->dmaHandle, 659 pRxPkt->rx_info.mem_size, 660 &bnxeAccessAttribBUF, 661 DDI_DMA_STREAMING, 662 DDI_DMA_DONTWAIT, 663 NULL, 664 (caddr_t *)&pRxPkt->rx_info.mem_virt, 665 &length, 666 &pRxPkt->dmaAccHandle)) != DDI_SUCCESS) 667 { 668 BnxeLogWarn(pUM, "Failed to alloc DMA memory for rx buffer"); 669 ddi_dma_free_handle(&pRxPkt->dmaHandle); 670 return -1; 671 } 672 673 if ((rc = ddi_dma_addr_bind_handle(pRxPkt->dmaHandle, 674 NULL, 675 (caddr_t)pRxPkt->rx_info.mem_virt, 676 pRxPkt->rx_info.mem_size, 677 DDI_DMA_READ | DDI_DMA_STREAMING, 678 DDI_DMA_DONTWAIT, 679 NULL, 680 &cookie, 681 &count)) != DDI_DMA_MAPPED) 682 { 683 BnxeLogWarn(pUM, "Failed to bind DMA address for rx buffer"); 684 ddi_dma_mem_free(&pRxPkt->dmaAccHandle); 685 ddi_dma_free_handle(&pRxPkt->dmaHandle); 686 return -1; 687 } 688 689 pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = cookie.dmac_laddress; 690 691 return 0; 692 } 693 694 695 static int BnxeRxPktsInitPostBuffersIdx(um_device_t * pUM, 696 int idx) 697 { 698 BNXE_LOCK_ENTER_RX(pUM, idx); 699 lm_post_buffers(&pUM->lm_dev, idx, NULL, 0); 700 BNXE_LOCK_EXIT_RX(pUM, idx); 701 702 return 0; 703 } 704 705 706 int BnxeRxPktsInitPostBuffers(um_device_t * pUM, 707 int cliIdx) 708 { 709 int idx; 710 711 switch (cliIdx) 712 { 713 case LM_CLI_IDX_FCOE: 714 715 BnxeRxPktsInitPostBuffersIdx(pUM, FCOE_CID(&pUM->lm_dev)); 716 break; 717 718 case LM_CLI_IDX_NDIS: 719 720 LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) 721 { 722 BnxeRxPktsInitPostBuffersIdx(pUM, idx); 723 } 724 725 break; 726 727 default: 728 729 BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsInit (%d)", cliIdx); 730 break; 731 } 732 733 return 0; 734 } 735 736 737 static int BnxeRxPktsInitIdx(um_device_t * pUM, 738 int idx) 739 { 740 lm_device_t * pLM = &pUM->lm_dev; 741 lm_rx_chain_t * pLmRxChain; 742 um_rxpacket_t * pRxPkt; 743 lm_packet_t * pLmPkt; 744 u8_t * pTmp; 745 int postCnt, i; 746 747 BNXE_LOCK_ENTER_RX(pUM, idx); 748 749 pLmRxChain = &LM_RXQ(pLM, idx); 750 751 s_list_clear(&pUM->rxq[idx].doneRxQ); 752 pUM->rxq[idx].rxLowWater = pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]; 753 pUM->rxq[idx].rxDiscards = 0; 754 pUM->rxq[idx].rxCopied = 0; 755 756 s_list_clear(&pUM->rxq[idx].waitRxQ); 757 758 /* allocate the packet descriptors */ 759 for (i = 0; 760 i < pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]; 761 i++) 762 { 763 if ((pTmp = kmem_zalloc(BnxeRxPktDescrSize(pUM), 764 KM_NOSLEEP)) == NULL) 765 { 766 BnxeLogWarn(pUM, "Failed to alloc an rx packet descriptor!!!"); 767 break; /* continue without error */ 768 } 769 770 pRxPkt = (um_rxpacket_t *)(pTmp + SIZEOF_SIG); 771 SIG(pRxPkt) = L2PACKET_RX_SIG; 772 pRxPkt->signature = pUM->rxBufSignature[LM_CHAIN_IDX_CLI(pLM, idx)]; 773 774 pLmPkt = (lm_packet_t *)pRxPkt; 775 pLmPkt->u1.rx.hash_val_ptr = &pRxPkt->hash_value; 776 pLmPkt->l2pkt_rx_info = &pRxPkt->rx_info; 777 778 if (BnxeRxBufAlloc(pUM, idx, pRxPkt) != 0) 779 { 780 BnxeRxPktDescrFree(pUM, pRxPkt); 781 break; /* continue without error */ 782 } 783 784 s_list_push_tail(&pLmRxChain->common.free_descq, &pLmPkt->link); 785 } 786 787 postCnt = s_list_entry_cnt(&pLmRxChain->common.free_descq); 788 789 if (postCnt != pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]) 790 { 791 BnxeLogWarn(pUM, "%d rx buffers requested and only %d allocated!!!", 792 pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)], 793 postCnt); 794 } 795 796 BNXE_LOCK_EXIT_RX(pUM, idx); 797 798 return 0; 799 } 800 801 802 int BnxeRxPktsInit(um_device_t * pUM, 803 int cliIdx) 804 { 805 int idx; 806 807 /* set the rx buffer signature for this plumb */ 808 atomic_swap_32(&pUM->rxBufSignature[cliIdx], (u32_t)ddi_get_time()); 809 810 switch (cliIdx) 811 { 812 case LM_CLI_IDX_FCOE: 813 814 BnxeRxPktsInitIdx(pUM, FCOE_CID(&pUM->lm_dev)); 815 break; 816 817 case LM_CLI_IDX_NDIS: 818 819 LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) 820 { 821 BnxeRxPktsInitIdx(pUM, idx); 822 } 823 824 break; 825 826 default: 827 828 BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsInit (%d)", cliIdx); 829 break; 830 } 831 832 return 0; 833 } 834 835 836 static void BnxeRxPktsFiniIdx(um_device_t * pUM, 837 int idx) 838 { 839 lm_rx_chain_t * pLmRxChain; 840 um_rxpacket_t * pRxPkt; 841 s_list_t tmpList; 842 843 pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); 844 845 s_list_clear(&tmpList); 846 847 BNXE_LOCK_ENTER_RX(pUM, idx); 848 s_list_add_tail(&tmpList, &pLmRxChain->common.free_descq); 849 s_list_clear(&pLmRxChain->common.free_descq); 850 BNXE_LOCK_EXIT_RX(pUM, idx); 851 852 BNXE_LOCK_ENTER_DONERX(pUM, idx); 853 s_list_add_tail(&tmpList, &pUM->rxq[idx].doneRxQ); 854 s_list_clear(&pUM->rxq[idx].doneRxQ); 855 BNXE_LOCK_EXIT_DONERX(pUM, idx); 856 857 if (s_list_entry_cnt(&tmpList) != 858 pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)]) 859 { 860 BnxeLogWarn(pUM, "WARNING Missing RX packets (idx:%d) (%lu / %d - %u in stack)", 861 idx, s_list_entry_cnt(&tmpList), 862 pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)], 863 pUM->rxq[idx].rxBufUpInStack); 864 } 865 866 /* 867 * Back out all the packets in the "available for hardware use" queue. 868 * Free the buffers associated with the descriptors as we go. 869 */ 870 while (1) 871 { 872 pRxPkt = (um_rxpacket_t *)s_list_pop_head(&tmpList); 873 if (pRxPkt == NULL) 874 { 875 break; 876 } 877 878 pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = 0; 879 pRxPkt->rx_info.mem_virt = NULL; 880 pRxPkt->rx_info.mem_size = 0; 881 882 ddi_dma_unbind_handle(pRxPkt->dmaHandle); 883 ddi_dma_mem_free(&pRxPkt->dmaAccHandle); 884 ddi_dma_free_handle(&pRxPkt->dmaHandle); 885 886 BnxeRxPktDescrFree(pUM, pRxPkt); 887 } 888 } 889 890 891 void BnxeRxPktsFini(um_device_t * pUM, 892 int cliIdx) 893 { 894 int idx; 895 896 /* reset the signature for this unplumb */ 897 atomic_swap_32(&pUM->rxBufSignature[cliIdx], 0); 898 899 switch (cliIdx) 900 { 901 case LM_CLI_IDX_FCOE: 902 903 BnxeRxPktsFiniIdx(pUM, FCOE_CID(&pUM->lm_dev)); 904 break; 905 906 case LM_CLI_IDX_NDIS: 907 908 LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) 909 { 910 BnxeRxPktsFiniIdx(pUM, idx); 911 } 912 913 break; 914 915 default: 916 917 BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsFini (%d)", cliIdx); 918 break; 919 } 920 } 921 922