Пример #1
0
/* 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;
}
Пример #2
0
/*
 * 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 */
}