/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2014 QLogic Corporation * The contents of this file are subject to the terms of the * QLogic End User License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the License at * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ * QLogic_End_User_Software_License.txt * See the License for the specific language governing permissions * and limitations under the License. */ /* * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. */ #include "bnxe.h" ddi_dma_attr_t bnxeRxDmaAttrib = { DMA_ATTR_V0, /* dma_attr_version */ 0, /* dma_attr_addr_lo */ 0xffffffffffffffff, /* dma_attr_addr_hi */ 0xffffffffffffffff, /* dma_attr_count_max */ BNXE_DMA_ALIGNMENT, /* dma_attr_align */ 0xffffffff, /* dma_attr_burstsizes */ 1, /* dma_attr_minxfer */ 0xffffffffffffffff, /* dma_attr_maxxfer */ 0xffffffffffffffff, /* dma_attr_seg */ 1, /* dma_attr_sgllen */ 1, /* dma_attr_granular */ 0, /* dma_attr_flags */ }; static void BnxeRxPostBuffers(um_device_t * pUM, int idx, s_list_t * pReclaimList) { lm_rx_chain_t * pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); u32_t returnedBytes = 0; lm_packet_t * pLmPkt; /* return bytes from reclaimed list to LM */ pLmPkt = (lm_packet_t *)s_list_peek_head(pReclaimList); while (pLmPkt) { returnedBytes += pLmPkt->size; pLmPkt = (lm_packet_t *)s_list_next_entry(&pLmPkt->link); } BNXE_LOCK_ENTER_RX(pUM, idx); if (pUM->rxq[idx].rxLowWater > s_list_entry_cnt(&pLmRxChain->active_descq)) { pUM->rxq[idx].rxLowWater = s_list_entry_cnt(&pLmRxChain->active_descq); } lm_return_packet_bytes(&pUM->lm_dev, idx, returnedBytes); s_list_add_tail(&pLmRxChain->common.free_descq, pReclaimList); s_list_clear(pReclaimList); #if 0 /* * Don't post buffers if we don't have too many free buffers and there are a * lot of buffers already posted. */ if (lm_bd_chain_avail_bds(&pLmRxChain->bd_chain) < 32) { BNXE_LOCK_EXIT_RX(pUM, idx); return; } /* * Don't post buffers if there aren't really that many to post yet. */ if (s_list_entry_cnt(&pLmRxChain->common.free_descq) < 32) { BNXE_LOCK_EXIT_RX(pUM, idx); return; } #endif lm_post_buffers(&pUM->lm_dev, idx, NULL, 0); BNXE_LOCK_EXIT_RX(pUM, idx); } static u32_t BnxeRxPktDescrSize(um_device_t * pUM) { u32_t descSize; (void)pUM; descSize = sizeof(um_rxpacket_t) + SIZEOF_SIG; return ALIGN_VALUE_TO_WORD_BOUNDARY(descSize); } static void BnxeRxPktDescrFree(um_device_t * pUM, um_rxpacket_t * pRxPkt) { u32_t descSize; caddr_t pMem; BnxeDbgBreakIfFastPath(pUM, SIG(pRxPkt) != L2PACKET_RX_SIG); descSize = BnxeRxPktDescrSize(pUM); pMem = (caddr_t)pRxPkt - SIZEOF_SIG; kmem_free(pMem, descSize); } static void BnxeRxPktFree(char * free_arg) { um_rxpacket_t * pRxPkt = (um_rxpacket_t *)free_arg; um_device_t * pUM = (um_device_t *)pRxPkt->pUM; int idx = pRxPkt->idx; s_list_t doneRxQ; if (pUM->magic != BNXE_MAGIC) { /* * Oh my! The free_arg data got corrupted. Log a message and leak this * packet. We don't decrement the 'up in the stack count' since we * can't be sure this packet really was a packet we previously sent up. */ BnxeLogWarn(NULL, "ERROR freeing packet - UM is invalid! (%p)", pRxPkt); return; } if (pUM->rxBufSignature[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)] != pRxPkt->signature) { /* * The stack is freeing a packet that was from a previous plumb of * the interface. */ pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = 0; pRxPkt->rx_info.mem_virt = NULL; pRxPkt->rx_info.mem_size = 0; ddi_dma_unbind_handle(pRxPkt->dmaHandle); ddi_dma_mem_free(&pRxPkt->dmaAccHandle); ddi_dma_free_handle(&pRxPkt->dmaHandle); BnxeRxPktDescrFree(pUM, pRxPkt); } else { s_list_clear(&doneRxQ); BNXE_LOCK_ENTER_DONERX(pUM, idx); s_list_push_tail(&pUM->rxq[idx].doneRxQ, &((lm_packet_t *)pRxPkt)->link); /* post packets when a bunch are ready */ if (s_list_entry_cnt(&pUM->rxq[idx].doneRxQ) >= pUM->devParams.maxRxFree) { doneRxQ = pUM->rxq[idx].doneRxQ; s_list_clear(&pUM->rxq[idx].doneRxQ); } BNXE_LOCK_EXIT_DONERX(pUM, idx); if (s_list_entry_cnt(&doneRxQ)) { BnxeRxPostBuffers(pUM, idx, &doneRxQ); } } atomic_dec_32(&pUM->rxq[idx].rxBufUpInStack); } boolean_t BnxeWaitForPacketsFromClient(um_device_t * pUM, int cliIdx) { int i, idx, cnt=0, tot=0; switch (cliIdx) { case LM_CLI_IDX_FCOE: for (i = 0; i < 5; i++) { if ((cnt = pUM->rxq[FCOE_CID(&pUM->lm_dev)].rxBufUpInStack) == 0) { break; } /* twiddle our thumbs for one second */ delay(drv_usectohz(1000000)); } if (cnt) { BnxeLogWarn(pUM, "%d packets still held by FCoE (chain %d)!", cnt, FCOE_CID(&pUM->lm_dev)); return B_FALSE; } break; case LM_CLI_IDX_NDIS: tot = 0; LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) { for (i = 0; i < 5; i++) { if ((cnt = pUM->rxq[idx].rxBufUpInStack) == 0) { break; } /* twiddle our thumbs for one second */ delay(drv_usectohz(1000000)); } tot += cnt; } if (tot) { BnxeLogWarn(pUM, "%d packets still held by the stack (chain %d)!", tot, idx); return B_FALSE; } break; default: BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeWaitForPacketsFromClient (%d)", cliIdx); break; } return B_TRUE; } /* numBytes is only valid when polling is TRUE */ mblk_t * BnxeRxRingProcess(um_device_t * pUM, int idx, boolean_t polling, int numBytes) { RxQueue * pRxQ; lm_rx_chain_t * pLmRxChain; u32_t activeDescqCount; boolean_t forceCopy; um_rxpacket_t * pRxPkt; lm_packet_t * pLmPkt; u32_t pktLen; boolean_t dataCopied; u32_t notCopiedCount; mblk_t * pMblk; int ofldFlags; mblk_t * head = NULL; mblk_t * tail = NULL; s_list_t rxList; s_list_t reclaimList; int procBytes = 0; s_list_t tmpList; sp_cqes_info sp_cqes; u32_t pktsRxed; pRxQ = &pUM->rxq[idx]; s_list_clear(&tmpList); /* get the list of packets received */ BNXE_LOCK_ENTER_RX(pUM, idx); pktsRxed = lm_get_packets_rcvd(&pUM->lm_dev, idx, &tmpList, &sp_cqes); /* grab any waiting packets */ rxList = pRxQ->waitRxQ; s_list_clear(&pRxQ->waitRxQ); /* put any new packets at the end of the queue */ s_list_add_tail(&rxList, &tmpList); BNXE_LOCK_EXIT_RX(pUM, idx); /* now complete the ramrods */ lm_complete_ramrods(&pUM->lm_dev, &sp_cqes); if (s_list_entry_cnt(&rxList) == 0) { return NULL; } s_list_clear(&reclaimList); notCopiedCount = 0; pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); activeDescqCount = s_list_entry_cnt(&pLmRxChain->active_descq); forceCopy = (activeDescqCount < (pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)] >> 3)); /* send the packets up the stack */ while (1) { pRxPkt = (um_rxpacket_t *)s_list_pop_head(&rxList); if (pRxPkt == NULL) { break; } pLmPkt = &(pRxPkt->lm_pkt); if (pLmPkt->status != LM_STATUS_SUCCESS) { /* XXX increment error stat? */ s_list_push_tail(&reclaimList, &pLmPkt->link); continue; } pktLen = pLmPkt->size; if (polling == TRUE) { /* When polling an rx ring we can only process up to numBytes */ if ((procBytes + pktLen) <= numBytes) { /* continue to process this packet */ procBytes += pktLen; } else { /* put this packet not processed back on the list (front) */ s_list_push_head(&rxList, &pRxPkt->lm_pkt.link); break; } } (void)ddi_dma_sync(pRxPkt->dmaHandle, 0, pktLen, DDI_DMA_SYNC_FORKERNEL); if (pUM->fmCapabilities && BnxeCheckDmaHandle(pRxPkt->dmaHandle) != DDI_FM_OK) { ddi_fm_service_impact(pUM->pDev, DDI_SERVICE_DEGRADED); } dataCopied = B_FALSE; if (forceCopy || (pUM->devParams.rxCopyThreshold && (pktLen < pUM->devParams.rxCopyThreshold))) { if ((pMblk = allocb(pktLen, BPRI_MED)) == NULL) { pRxQ->rxDiscards++; s_list_push_tail(&reclaimList, &pLmPkt->link); continue; } /* copy the packet into the new mblk */ bcopy((pRxPkt->rx_info.mem_virt + BNXE_DMA_RX_OFFSET), pMblk->b_rptr, pktLen); pMblk->b_wptr = (pMblk->b_rptr + pktLen); dataCopied = B_TRUE; pRxQ->rxCopied++; goto BnxeRxRingProcess_sendup; } if ((activeDescqCount == 0) && (s_list_entry_cnt(&rxList) == 0)) { /* * If the hardware is out of receive buffers and we are on the last * receive packet then drop the packet. We do this because we might * not be able to allocate any new receive buffers before the ISR * completes. If this happens, the driver will enter an infinite * interrupt loop where the hardware is requesting rx buffers the * driver cannot allocate. To prevent a system livelock we leave * one buffer perpetually available. Note that we do this after * giving the double copy code a chance to claim the packet. */ /* FIXME * Make sure to add one more to the rx packet descriptor count * before allocating them. */ pRxQ->rxDiscards++; s_list_push_tail(&reclaimList, &pLmPkt->link); continue; } /* * If we got here then the packet wasn't copied so we need to create a * new mblk_t which references the lm_packet_t buffer. */ pRxPkt->freeRtn.free_func = BnxeRxPktFree; pRxPkt->freeRtn.free_arg = (char *)pRxPkt; pRxPkt->pUM = (void *)pUM; pRxPkt->idx = idx; if ((pMblk = desballoc((pRxPkt->rx_info.mem_virt + BNXE_DMA_RX_OFFSET), pktLen, BPRI_MED, &pRxPkt->freeRtn)) == NULL) { pRxQ->rxDiscards++; s_list_push_tail(&reclaimList, &pLmPkt->link); continue; } pMblk->b_wptr = (pMblk->b_rptr + pktLen); BnxeRxRingProcess_sendup: /* * Check if the checksum was offloaded so we can pass the result to * the stack. */ ofldFlags = 0; if ((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_IP_CKSUM) && (pRxPkt->rx_info.flags & LM_RX_FLAG_IP_CKSUM_IS_GOOD)) { ofldFlags |= HCK_IPV4_HDRCKSUM_OK; } if (((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_TCP_CKSUM) && (pRxPkt->rx_info.flags & LM_RX_FLAG_TCP_CKSUM_IS_GOOD)) || ((pUM->devParams.enabled_oflds & LM_OFFLOAD_RX_UDP_CKSUM) && (pRxPkt->rx_info.flags & LM_RX_FLAG_UDP_CKSUM_IS_GOOD))) { ofldFlags |= HCK_FULLCKSUM_OK; } if (ofldFlags != 0) { mac_hcksum_set(pMblk, 0, 0, 0, 0, ofldFlags); } /* * If the packet data was copied into a new recieve buffer then put this * descriptor in a list to be reclaimed later. If not, then increment a * counter so we can track how many of our descriptors are held by the * stack. */ if (dataCopied == B_TRUE) { s_list_push_tail(&reclaimList, &pLmPkt->link); } else { notCopiedCount++; } if (head == NULL) { head = pMblk; } else { tail->b_next = pMblk; } tail = pMblk; tail->b_next = NULL; #if 0 BnxeDumpPkt(pUM, (BNXE_FCOE(pUM) && (idx == FCOE_CID(&pUM->lm_dev))) ? "<- FCoE L2 RX <-" : "<- L2 RX <-", pMblk, B_TRUE); #endif } if (head) { if (notCopiedCount) { /* track all non-copied packets that will be held by the stack */ atomic_add_32(&pUM->rxq[idx].rxBufUpInStack, notCopiedCount); } /* pass the mblk chain up the stack */ if (polling == FALSE) { /* XXX NEED TO ADD STATS FOR RX PATH UPCALLS */ if (BNXE_FCOE(pUM) && (idx == FCOE_CID(&pUM->lm_dev))) { /* XXX verify fcoe frees all packets on success or error */ if (pUM->fcoe.pDev && pUM->fcoe.bind.cliIndicateRx) { pUM->fcoe.bind.cliIndicateRx(pUM->fcoe.pDev, head); } else { /* FCoE isn't bound? Reclaim the chain... */ freemsgchain(head); head = NULL; } } else { #if defined(BNXE_RINGS) && (defined(__S11) || defined(__S12)) mac_rx_ring(pUM->pMac, pUM->rxq[idx].ringHandle, head, pUM->rxq[idx].genNumber); #else mac_rx(pUM->pMac, pUM->macRxResourceHandles[idx], head); #endif } } } if ((polling == TRUE) && s_list_entry_cnt(&rxList)) { /* put the packets not processed back on the list (front) */ BNXE_LOCK_ENTER_RX(pUM, idx); s_list_add_head(&pRxQ->waitRxQ, &rxList); BNXE_LOCK_EXIT_RX(pUM, idx); } if (s_list_entry_cnt(&reclaimList)) { BnxeRxPostBuffers(pUM, idx, &reclaimList); } return (polling == TRUE) ? head : NULL; } /* * Dumping packets simply moves all packets from the waiting queue to the free * queue. Note that the packets are not posted back to the LM. */ static void BnxeRxRingDump(um_device_t * pUM, int idx) { s_list_t tmpList; BNXE_LOCK_ENTER_RX(pUM, idx); tmpList = pUM->rxq[idx].waitRxQ; s_list_clear(&pUM->rxq[idx].waitRxQ); s_list_add_tail(&LM_RXQ(&pUM->lm_dev, idx).common.free_descq, &tmpList); BNXE_LOCK_EXIT_RX(pUM, idx); } /* * Aborting packets stops all rx processing by dumping the currently waiting * packets and aborting all the rx descriptors currently posted in the LM. */ static void BnxeRxPktsAbortIdx(um_device_t * pUM, int idx) { BnxeRxRingDump(pUM, idx); BNXE_LOCK_ENTER_RX(pUM, idx); lm_abort(&pUM->lm_dev, ABORT_OP_RX_CHAIN, idx); BNXE_LOCK_EXIT_RX(pUM, idx); } void BnxeRxPktsAbort(um_device_t * pUM, int cliIdx) { int idx; switch (cliIdx) { case LM_CLI_IDX_FCOE: BnxeRxPktsAbortIdx(pUM, FCOE_CID(&pUM->lm_dev)); break; case LM_CLI_IDX_NDIS: LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) { BnxeRxPktsAbortIdx(pUM, idx); } break; default: BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsAbort (%d)", cliIdx); break; } } static int BnxeRxBufAlloc(um_device_t * pUM, int idx, um_rxpacket_t * pRxPkt) { ddi_dma_cookie_t cookie; u32_t count; size_t length; int rc; if ((rc = ddi_dma_alloc_handle(pUM->pDev, &bnxeRxDmaAttrib, DDI_DMA_DONTWAIT, NULL, &pRxPkt->dmaHandle)) != DDI_SUCCESS) { BnxeLogWarn(pUM, "Failed to alloc DMA handle for rx buffer"); return -1; } pRxPkt->rx_info.mem_size = MAX_L2_CLI_BUFFER_SIZE(&pUM->lm_dev, idx); if ((rc = ddi_dma_mem_alloc(pRxPkt->dmaHandle, pRxPkt->rx_info.mem_size, &bnxeAccessAttribBUF, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, (caddr_t *)&pRxPkt->rx_info.mem_virt, &length, &pRxPkt->dmaAccHandle)) != DDI_SUCCESS) { BnxeLogWarn(pUM, "Failed to alloc DMA memory for rx buffer"); ddi_dma_free_handle(&pRxPkt->dmaHandle); return -1; } if ((rc = ddi_dma_addr_bind_handle(pRxPkt->dmaHandle, NULL, (caddr_t)pRxPkt->rx_info.mem_virt, pRxPkt->rx_info.mem_size, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, &cookie, &count)) != DDI_DMA_MAPPED) { BnxeLogWarn(pUM, "Failed to bind DMA address for rx buffer"); ddi_dma_mem_free(&pRxPkt->dmaAccHandle); ddi_dma_free_handle(&pRxPkt->dmaHandle); return -1; } pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = cookie.dmac_laddress; return 0; } static int BnxeRxPktsInitPostBuffersIdx(um_device_t * pUM, int idx) { BNXE_LOCK_ENTER_RX(pUM, idx); lm_post_buffers(&pUM->lm_dev, idx, NULL, 0); BNXE_LOCK_EXIT_RX(pUM, idx); return 0; } int BnxeRxPktsInitPostBuffers(um_device_t * pUM, int cliIdx) { int idx; switch (cliIdx) { case LM_CLI_IDX_FCOE: BnxeRxPktsInitPostBuffersIdx(pUM, FCOE_CID(&pUM->lm_dev)); break; case LM_CLI_IDX_NDIS: LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) { BnxeRxPktsInitPostBuffersIdx(pUM, idx); } break; default: BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsInit (%d)", cliIdx); break; } return 0; } static int BnxeRxPktsInitIdx(um_device_t * pUM, int idx) { lm_device_t * pLM = &pUM->lm_dev; lm_rx_chain_t * pLmRxChain; um_rxpacket_t * pRxPkt; lm_packet_t * pLmPkt; u8_t * pTmp; int postCnt, i; BNXE_LOCK_ENTER_RX(pUM, idx); pLmRxChain = &LM_RXQ(pLM, idx); s_list_clear(&pUM->rxq[idx].doneRxQ); pUM->rxq[idx].rxLowWater = pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]; pUM->rxq[idx].rxDiscards = 0; pUM->rxq[idx].rxCopied = 0; s_list_clear(&pUM->rxq[idx].waitRxQ); /* allocate the packet descriptors */ for (i = 0; i < pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]; i++) { if ((pTmp = kmem_zalloc(BnxeRxPktDescrSize(pUM), KM_NOSLEEP)) == NULL) { BnxeLogWarn(pUM, "Failed to alloc an rx packet descriptor!!!"); break; /* continue without error */ } pRxPkt = (um_rxpacket_t *)(pTmp + SIZEOF_SIG); SIG(pRxPkt) = L2PACKET_RX_SIG; pRxPkt->signature = pUM->rxBufSignature[LM_CHAIN_IDX_CLI(pLM, idx)]; pLmPkt = (lm_packet_t *)pRxPkt; pLmPkt->u1.rx.hash_val_ptr = &pRxPkt->hash_value; pLmPkt->l2pkt_rx_info = &pRxPkt->rx_info; if (BnxeRxBufAlloc(pUM, idx, pRxPkt) != 0) { BnxeRxPktDescrFree(pUM, pRxPkt); break; /* continue without error */ } s_list_push_tail(&pLmRxChain->common.free_descq, &pLmPkt->link); } postCnt = s_list_entry_cnt(&pLmRxChain->common.free_descq); if (postCnt != pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)]) { BnxeLogWarn(pUM, "%d rx buffers requested and only %d allocated!!!", pLM->params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(pLM, idx)], postCnt); } BNXE_LOCK_EXIT_RX(pUM, idx); return 0; } int BnxeRxPktsInit(um_device_t * pUM, int cliIdx) { int idx; /* set the rx buffer signature for this plumb */ atomic_swap_32(&pUM->rxBufSignature[cliIdx], (u32_t)ddi_get_time()); switch (cliIdx) { case LM_CLI_IDX_FCOE: BnxeRxPktsInitIdx(pUM, FCOE_CID(&pUM->lm_dev)); break; case LM_CLI_IDX_NDIS: LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) { BnxeRxPktsInitIdx(pUM, idx); } break; default: BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsInit (%d)", cliIdx); break; } return 0; } static void BnxeRxPktsFiniIdx(um_device_t * pUM, int idx) { lm_rx_chain_t * pLmRxChain; um_rxpacket_t * pRxPkt; s_list_t tmpList; pLmRxChain = &LM_RXQ(&pUM->lm_dev, idx); s_list_clear(&tmpList); BNXE_LOCK_ENTER_RX(pUM, idx); s_list_add_tail(&tmpList, &pLmRxChain->common.free_descq); s_list_clear(&pLmRxChain->common.free_descq); BNXE_LOCK_EXIT_RX(pUM, idx); BNXE_LOCK_ENTER_DONERX(pUM, idx); s_list_add_tail(&tmpList, &pUM->rxq[idx].doneRxQ); s_list_clear(&pUM->rxq[idx].doneRxQ); BNXE_LOCK_EXIT_DONERX(pUM, idx); if (s_list_entry_cnt(&tmpList) != pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)]) { BnxeLogWarn(pUM, "WARNING Missing RX packets (idx:%d) (%lu / %d - %u in stack)", idx, s_list_entry_cnt(&tmpList), pUM->lm_dev.params.l2_rx_desc_cnt[LM_CHAIN_IDX_CLI(&pUM->lm_dev, idx)], pUM->rxq[idx].rxBufUpInStack); } /* * Back out all the packets in the "available for hardware use" queue. * Free the buffers associated with the descriptors as we go. */ while (1) { pRxPkt = (um_rxpacket_t *)s_list_pop_head(&tmpList); if (pRxPkt == NULL) { break; } pRxPkt->lm_pkt.u1.rx.mem_phys[0].as_u64 = 0; pRxPkt->rx_info.mem_virt = NULL; pRxPkt->rx_info.mem_size = 0; ddi_dma_unbind_handle(pRxPkt->dmaHandle); ddi_dma_mem_free(&pRxPkt->dmaAccHandle); ddi_dma_free_handle(&pRxPkt->dmaHandle); BnxeRxPktDescrFree(pUM, pRxPkt); } } void BnxeRxPktsFini(um_device_t * pUM, int cliIdx) { int idx; /* reset the signature for this unplumb */ atomic_swap_32(&pUM->rxBufSignature[cliIdx], 0); switch (cliIdx) { case LM_CLI_IDX_FCOE: BnxeRxPktsFiniIdx(pUM, FCOE_CID(&pUM->lm_dev)); break; case LM_CLI_IDX_NDIS: LM_FOREACH_RSS_IDX(&pUM->lm_dev, idx) { BnxeRxPktsFiniIdx(pUM, idx); } break; default: BnxeLogWarn(pUM, "ERROR: Invalid cliIdx for BnxeRxPktsFini (%d)", cliIdx); break; } }