/* internal pkt allocation, no BCM_RPC_TP_ENCAP_LEN */ static rpc_buf_t * bcm_rpc_tp_pktget(rpc_tp_info_t * rpcb, int len, bool send) { rpc_buf_t* b; #if defined(NDIS) struct lbuf *lb; if (len > LBDATASZ) return (NULL); if (send) lb = shared_lb_get(rpcb->sh, &rpcb->sh->txfree); else lb = shared_lb_get(rpcb->sh, &rpcb->sh->rxfree); if (lb != NULL) lb->len = len; b = (rpc_buf_t*)lb; #else struct sk_buff *skb; #if defined(CTFPOOL) skb = PKTGET(rpcb->osh, len, FALSE); #else if ((skb = dev_alloc_skb(len))) { skb_put(skb, len); skb->priority = 0; } #endif /* defined(CTFPOOL) */ b = (rpc_buf_t*)skb; if (b != NULL) { #ifdef CTFMAP /* Clear the ctf buf flag to allow full dma map */ PKTCLRCTF(rpcb->osh, skb); CTFMAPPTR(rpcb->osh, skb) = NULL; #endif /* CTFMAP */ RPC_TP_LOCK(rpcb); rpcb->bufalloc++; if (!rpcb->rxflowctrl && (rpcb->buf_cnt_inuse >= RPCRX_WM_HI)) { rpcb->rxflowctrl = TRUE; RPC_TP_ERR(("%s, rxflowctrl change to %d\n", __FUNCTION__, rpcb->rxflowctrl)); dbus_flowctrl_rx(rpcb->bus, TRUE); } rpcb->buf_cnt_inuse++; if (rpcb->buf_cnt_inuse > (int)rpcb->buf_cnt_max) rpcb->buf_cnt_max = rpcb->buf_cnt_inuse; RPC_TP_UNLOCK(rpcb); } else { printf("%s: buf alloc failed buf_cnt_inuse %d rxflowctrl:%d\n", __FUNCTION__, rpcb->buf_cnt_inuse, rpcb->rxflowctrl); ASSERT(0); } #endif /* NDIS */ return b; }
/* * Convert the ndis packet chain into an lbuf . */ struct lbuf* shared_txlb_convert(shared_info_t *sh, ND_PKT *p) { #ifndef NDIS60 struct lbuf *lb; PNDIS_BUFFER b, next; uchar *bdata, *buf; uint blen, tot; struct lbfree *txlbfree; ASSERT(p); NdisQueryPacket(p, NULL, NULL, &b, &tot); ASSERT(b); ASSERT(tot <= LBDATASZ); if ((b == NULL) || (tot > LBDATASZ)) return (NULL); txlbfree = &sh->txfree; /* txqueue free buffer count shouldn't go below threshold */ if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total)) return (NULL); /* alloc lbuf */ if ((lb = shared_lb_get(sh, txlbfree)) == NULL) return (NULL); /* Adjust for the head room requested */ ASSERT(txlbfree->size > txlbfree->headroom); lb->data += txlbfree->headroom; /* * In case of dongle, make sure the begining of the buffer is * aligned at 32 bytes for DMA efficiency, after inserting * header of 16 bytes later in DHD layer */ if (((uintptr)lb->data % 32) <= 16) lb->data += 16 - (uintptr)lb->data % 32; else lb->data -= (uintptr)lb->data % 32 - 16; buf = lb->data; while (b && tot) { #if defined(NDIS51) NdisQueryBufferSafe(b, &bdata, &blen, NormalPagePriority); #else NdisQueryBuffer(b, &bdata, &blen); #endif /* defined (NDIS51) */ blen = MIN(blen, tot); if (blen) { bcopy(bdata, buf, blen); lb->tail += blen; lb->len += blen; buf += blen; tot -= blen; } NdisGetNextBuffer(b, &next); b = next; } /* save a pointer to the ndis packet for later sendcomplete */ lb->p = p; return (lb); #else /* !NDIS60 */ struct lbuf *lb; PNET_BUFFER nb; PMDL b, next; uint offset; uchar *bdata, *buf; uint blen, tot; struct lbfree *txlbfree; ASSERT(p); tot = 0; for (nb = NET_BUFFER_LIST_FIRST_NB(p); nb; nb = NET_BUFFER_NEXT_NB(nb)) tot += NET_BUFFER_DATA_LENGTH(nb); nb = NET_BUFFER_LIST_FIRST_NB(p); if (nb == NULL) return (NULL); b = NET_BUFFER_CURRENT_MDL(nb); offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb); ASSERT(b); ASSERT(tot <= LBDATASZ); if ((b == NULL) || (tot > LBDATASZ)) return (NULL); txlbfree = &sh->txfree; /* txqueue free buffer count shouldn't go below threshold */ if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total)) return (NULL); /* alloc lbuf */ if ((lb = shared_lb_get(sh, txlbfree)) == NULL) return (NULL); #if defined(NDIS60) /* Adjust for the head room requested */ /* ASSERT(txlbfree->size > txlbfree->headroom); */ lb->data += txlbfree->headroom; /* * In case of dongle, make sure the begining of the buffer is * aligned at 32 bytes for DMA efficiency, after inserting * header of 16 bytes later in DHD layer */ if (((uintptr)lb->data % 32) <= 16) lb->data += 16 - (uintptr)lb->data % 32; else lb->data -= (uintptr)lb->data % 32 - 16; #endif /* UNDER_CE && NDIS60 */ buf = lb->data; while (b && tot) { NdisQueryMdl(b, &bdata, &blen, NormalPagePriority); if (bdata == NULL) goto next_mdl; if (blen > offset) { bdata += offset; blen -= offset; } else { offset -= blen; goto next_mdl; } blen = MIN(blen, tot); if (blen) { bcopy(bdata, buf, blen); lb->tail += blen; lb->len += blen; buf += blen; tot -= blen; offset = 0; } next_mdl: NdisGetNextMdl(b, &next); if (!next) { nb = NET_BUFFER_NEXT_NB(nb); if (nb) { next = NET_BUFFER_CURRENT_MDL(nb); offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb); } } b = next; } /* save a pointer to the ndis packet for later sendcomplete */ lb->p = p; return (lb); #endif /* !NDIS60 */ }