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
BnxeRxPostBuffers(um_device_t * pUM,int idx,s_list_t * pReclaimList)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
BnxeRxPktDescrSize(um_device_t * pUM)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
BnxeRxPktDescrFree(um_device_t * pUM,um_rxpacket_t * pRxPkt)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
BnxeRxPktFree(char * free_arg)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
BnxeWaitForPacketsFromClient(um_device_t * pUM,int cliIdx)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 */
BnxeRxRingProcess(um_device_t * pUM,int idx,boolean_t polling,int numBytes)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 */
BnxeRxRingDump(um_device_t * pUM,int idx)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 */
BnxeRxPktsAbortIdx(um_device_t * pUM,int idx)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
BnxeRxPktsAbort(um_device_t * pUM,int cliIdx)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
BnxeRxBufAlloc(um_device_t * pUM,int idx,um_rxpacket_t * pRxPkt)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
BnxeRxPktsInitPostBuffersIdx(um_device_t * pUM,int idx)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
BnxeRxPktsInitPostBuffers(um_device_t * pUM,int cliIdx)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
BnxeRxPktsInitIdx(um_device_t * pUM,int idx)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
BnxeRxPktsInit(um_device_t * pUM,int cliIdx)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
BnxeRxPktsFiniIdx(um_device_t * pUM,int idx)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
BnxeRxPktsFini(um_device_t * pUM,int cliIdx)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