コード例 #1
0
ファイル: hnd_pktpool.c プロジェクト: MethHeadAlert/M9
int
pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal)
{
	void *p;
	int err = 0;
	int len, psize, maxlen;

	ASSERT(pktp->plen != 0);

	maxlen = pktp->maxlen;
	psize = minimal ? (maxlen >> 2) : maxlen;
	for (len = (int)pktp->len; len < psize; len++) {

		p = PKTGET(osh, pktp->len, TRUE);

		if (p == NULL) {
			err = BCME_NOMEM;
			break;
		}

		if (pktpool_add(pktp, p) != BCME_OK) {
			PKTFREE(osh, p, FALSE);
			err = BCME_ERROR;
			break;
		}
	}

	return err;
}
コード例 #2
0
rpc_buf_t *
bcm_rpc_tp_buf_alloc(rpc_tp_info_t * rpc_th, int len)
{
	rpc_buf_t * b;
	size_t tp_len = len + BCM_RPC_TP_ENCAP_LEN;
	size_t padlen;

#ifdef BCMUSBDEV
	padlen = MAX(BCM_RPC_TP_DNGL_TOTLEN_BAD_PAD, BCM_RPC_TP_DNGL_ZLP_PAD);
	padlen = ROUNDUP(padlen, sizeof(int));
#else
	padlen = 0;
#endif /* BCMUSBDEV */

	/* get larger packet with  padding which might be required due to USB ZLP */
	b = (rpc_buf_t*)PKTGET(rpc_th->osh, tp_len + padlen, FALSE);

	if (b != NULL) {
		rpc_th->bufalloc++;
		rpc_th->buf_cnt_inuse++;
		/* set the len back to tp_len */
		bcm_rpc_buf_len_set(rpc_th, b, tp_len);
		PKTPULL(rpc_th->osh, b, BCM_RPC_TP_ENCAP_LEN);
	}

	return b;
}
コード例 #3
0
/* totally bogus -- d11 hdr only + tx hdrs */
static void *
wlc_olpc_get_pkt(wlc_info_t *wlc, uint ac, uint* fifo)
{
    int buflen = (TXOFF + WL_OLPC_PKT_LEN);
    void* p = NULL;
    osl_t *osh = wlc->osh;
    const char* macaddr = NULL;
    struct dot11_header *hdr = NULL;

    if ((p = PKTGET(osh, buflen, TRUE)) == NULL) {
        WL_ERROR(("wl%d: %s: pktget error for len %d \n",
                  wlc->pub->unit, __FUNCTION__, buflen));
        goto fatal;
    }
    macaddr = WLC_MACADDR(wlc);

    WL_NONE(("pkt manip\n"));
    /* reserve TXOFF bytes of headroom */
    PKTPULL(osh, p, TXOFF);
    PKTSETLEN(osh, p, WL_OLPC_PKT_LEN);

    WL_NONE(("d11_hdr\n"));
    hdr = (struct dot11_header*)PKTDATA(osh, p);
    bzero((char*)hdr, WL_OLPC_PKT_LEN);
    hdr->fc = htol16(FC_DATA);
    hdr->durid = 0;
    bcopy((const char*)macaddr, (char*)&(hdr->a1.octet), ETHER_ADDR_LEN);
    bcopy((const char*)macaddr, (char*)&(hdr->a2.octet), ETHER_ADDR_LEN);
    bcopy((const char*)macaddr, (char*)&(hdr->a3.octet), ETHER_ADDR_LEN);
    hdr->seq = 0;
    WL_NONE(("prep raw 80211\n"));
    wlc->olpc_info->tx_cal_pkts = TRUE;
    /* frameid returned here -- ignore for now -- may speed up using this */
    (void)wlc_prep80211_raw(wlc, NULL, ac, TRUE, p, fifo);
    wlc->olpc_info->tx_cal_pkts = FALSE;

    return p;
fatal:
    return (NULL);
}
コード例 #4
0
ファイル: vx_osl.c プロジェクト: ariavie/bcm
void*
osl_pktdup(void *drv, void *p)
{
	END_OBJ *end;
	M_BLK_ID m;
	int len = pkttotlen(drv, p);

	/* drv is a pointer to an END_OBJ in disguise */
	end = (END_OBJ*)drv;

	/* dont use a real dup until PR14233 is fixed 
	m = netMblkChainDup(end->pNetPool, (M_BLK_ID)p, 0, M_COPYALL, M_DONTWAIT);	 */
	
	/* alloc a new mbuf */
	if ((m = PKTGET(drv, len, TRUE)) == NULL)
		return (NULL);

	/* copy data into mbuf */
	pktcopy(drv, p, 0, len, (uchar*)PKTDATA(drv, m));
	ASSERT(len == PKTLEN(drv,  m));

	return (m);
}
コード例 #5
0
ファイル: hnd_pktpool.c プロジェクト: MethHeadAlert/M9
/*
 * pktpool_init:
 * User provides a pktpool_t sturcture and specifies the number of packets to
 * be pre-filled into the pool (pplen). The size of all packets in a pool must
 * be the same and is specified by plen.
 * pktpool_init first attempts to register the pool and fetch a unique poolid.
 * If registration fails, it is considered an BCME_ERR, caused by either the
 * registry was not pre-created (pktpool_attach) or the registry is full.
 * If registration succeeds, then the requested number of packets will be filled
 * into the pool as part of initialization. In the event that there is no
 * available memory to service the request, then BCME_NOMEM will be returned
 * along with the count of how many packets were successfully allocated.
 * In dongle builds, prior to memory reclaimation, one should limit the number
 * of packets to be allocated during pktpool_init and fill the pool up after
 * reclaim stage.
 */
int
pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 type)
{
	int i, err = BCME_OK;
	int pktplen;
	uint8 pktp_id;

	ASSERT(pktp != NULL);
	ASSERT(osh != NULL);
	ASSERT(pplen != NULL);

	pktplen = *pplen;

	bzero(pktp, sizeof(pktpool_t));

	/* assign a unique pktpool id */
	if ((pktp_id = (uint8) pktpool_register(pktp)) == PKTPOOL_INVALID_ID) {
		return BCME_ERROR;
	}
	POOLSETID(pktp, pktp_id);

	pktp->inited = TRUE;
	pktp->istx = istx ? TRUE : FALSE;
	pktp->plen = (uint16)plen;
	pktp->type = type;

	pktp->maxlen = PKTPOOL_LEN_MAX;
	pktplen = LIMIT_TO_MAX(pktplen, pktp->maxlen);

	for (i = 0; i < pktplen; i++) {
		void *p;
		p = PKTGET(osh, plen, TRUE);

		if (p == NULL) {
			/* Not able to allocate all requested pkts
			 * so just return what was actually allocated
			 * We can add to the pool later
			 */
			if (pktp->freelist == NULL) /* pktpool free list is empty */
				err = BCME_NOMEM;

			goto exit;
		}

		PKTSETPOOL(osh, p, TRUE, pktp); /* Tag packet with pool ID */

		PKTSETFREELIST(p, pktp->freelist); /* insert p at head of free list */
		pktp->freelist = p;

		pktp->avail++;

#ifdef BCMDBG_POOL
		pktp->dbg_q[pktp->dbg_qlen++].p = p;
#endif
	}

exit:
	pktp->len = pktp->avail;

	*pplen = pktp->len;
	return err;
}
コード例 #6
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;
}
コード例 #7
0
static void BCMFASTPATH
rpc_dbus_recv_buf(void *handle, uint8 *buf, int len)
{
	rpc_tp_info_t *rpcb = handle;
	void *pkt;
	uint32 rpc_len;
	uint frag;
	uint agglen;
	if ((rpcb == NULL) || (buf == NULL))
		return;
	frag = rpcb->tp_host_deagg_cnt_sf;
	agglen = len;

	/* TP pkt should have more than encapsulation header */
	if (len <= BCM_RPC_TP_ENCAP_LEN) {
		RPC_TP_ERR(("%s: wrong len %d\n", __FUNCTION__, len));
		goto error;
	}

	while (len > BCM_RPC_TP_ENCAP_LEN) {
		rpc_len = ltoh32_ua(buf);

		if (rpc_len > (uint32)(len - BCM_RPC_TP_ENCAP_LEN)) {
			rpcb->tp_host_deagg_cnt_badsflen++;
			return;
		}
		/* RPC_BUFFER_RX: allocate */
#if defined(BCM_RPC_ROC)
		if ((pkt = PKTGET(rpcb->osh, rpc_len, FALSE)) == NULL) {
#else
		if ((pkt = bcm_rpc_tp_pktget(rpcb, rpc_len, FALSE)) == NULL) {
#endif
			printf("%s: bcm_rpc_tp_pktget failed (len %d)\n", __FUNCTION__, len);
			goto error;
		}
		/* RPC_BUFFER_RX: BYTE_COPY from dbus buffer */
		bcopy(buf + BCM_RPC_TP_ENCAP_LEN, bcm_rpc_buf_data(rpcb, pkt), rpc_len);

		/* !! send up */
		bcm_rpc_tp_rx(rpcb, pkt);

		len -= (BCM_RPC_TP_ENCAP_LEN + rpc_len);
		buf += (BCM_RPC_TP_ENCAP_LEN + rpc_len);

		if (len > BCM_RPC_TP_ENCAP_LEN) {	/* more frag */
			rpcb->tp_host_deagg_cnt_sf++;
			RPC_TP_DEAGG(("%s: deagg %d(remaining %d) bytes\n", __FUNCTION__,
				rpc_len, len));
		} else {
			if (len != 0) {
				printf("%s: deagg, remaining len %d is not 0\n", __FUNCTION__, len);
			}
			rpcb->tp_host_deagg_cnt_pass++;
		}
	}

	if (frag < rpcb->tp_host_deagg_cnt_sf) {	/* aggregated frames */
		rpcb->tp_host_deagg_cnt_sf++;	/* last one was not counted */
		rpcb->tp_host_deagg_cnt_chain++;

		rpcb->tp_host_deagg_cnt_bytes += agglen;
	}
error:
	return;
}

int BCMFASTPATH
bcm_rpc_tp_recv_rtn(rpc_tp_info_t *rpcb)
{
	void *pkt;
	int status = 0;
	if (!rpcb)
		return BCME_BADARG;

	if ((pkt = bcm_rpc_tp_pktget(rpcb, PKTBUFSZ, FALSE)) == NULL) {
		return BCME_NORESOURCE;
	}

	RPC_TP_LOCK(rpcb);
	if (rpcb->rx_rtn_pkt != NULL) {
		RPC_TP_UNLOCK(rpcb);
		if (pkt != NULL)
			bcm_rpc_tp_pktfree(rpcb, pkt, FALSE);
		return BCME_BUSY;
	}
	rpcb->rx_rtn_pkt = pkt;
	RPC_TP_UNLOCK(rpcb);

#ifndef  BCMUSBDEV_EP_FOR_RPCRETURN
	status = dbus_recv_ctl(rpcb->bus, bcm_rpc_buf_data(rpcb, rpcb->rx_rtn_pkt), PKTBUFSZ);
#else
	if (rpcb->has_2nd_bulk_in_ep) {
		status = dbus_recv_bulk(rpcb->bus, USBDEV_BULK_IN_EP2);
	} else {
		status = dbus_recv_ctl(rpcb->bus, bcm_rpc_buf_data(rpcb, rpcb->rx_rtn_pkt),
			PKTBUFSZ);
	}
#endif /* BCMUSBDEV_EP_FOR_RPCRETURN */
	if (status) {
		/* May have been cleared by complete routine */
		RPC_TP_LOCK(rpcb);
		pkt = rpcb->rx_rtn_pkt;
		rpcb->rx_rtn_pkt = NULL;
		RPC_TP_UNLOCK(rpcb);
		if (pkt != NULL)
			bcm_rpc_tp_pktfree(rpcb, pkt, FALSE);
		if (status == DBUS_ERR_RXFAIL)
			status  = BCME_RXFAIL;
		else if (status == DBUS_ERR_NODEVICE)
			status  = BCME_NODEVICE;
		else
			status  = BCME_ERROR;
	}
	return status;
}
コード例 #8
0
ファイル: hnddma.c プロジェクト: ariavie/bcm
/* post receive buffers */
void
dma_rxfill(dma_info_t *di)
{
	void *p;
	uint rxin, rxout;
	uint ctrl;
	uint n;
	uint i;
	uint32 pa;
	uint rxbufsize;

	/*
	 * Determine how many receive buffers we're lacking
	 * from the full complement, allocate, initialize,
	 * and post them, then update the chip rx lastdscr.
	 */

	rxin = di->rxin;
	rxout = di->rxout;
	rxbufsize = di->rxbufsize;

	n = di->nrxpost - NRXDACTIVE(rxin, rxout);

	DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n));

	for (i = 0; i < n; i++) {
		if ((p = PKTGET(di->drv, rxbufsize, FALSE)) == NULL) {
			DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name));
			di->hnddma.rxnobuf++;
			break;
		}

		/* PR3263 & PR3387 & PR4642 war: rxh.len=0 means dma writes not complete */
		*(uint32*)(OSL_UNCACHED(PKTDATA(di->drv, p))) = 0;

		pa = (uint32) DMA_MAP(di->dev, PKTDATA(di->drv, p), rxbufsize, DMA_RX, p);
		ASSERT(ISALIGNED(pa, 4));

		/* save the free packet pointer */
#if 0
		ASSERT(di->rxp[rxout] == NULL);
#endif
		di->rxp[rxout] = p;

		/* paranoia */
		ASSERT(R_SM(&di->rxd[rxout].addr) == 0);

		/* prep the descriptor control value */
		ctrl = rxbufsize;
		if (rxout == (di->nrxd - 1))
			ctrl |= CTRL_EOT;

		/* init the rx descriptor */
		W_SM(&di->rxd[rxout].ctrl, BUS_SWAP32(ctrl));
		W_SM(&di->rxd[rxout].addr, BUS_SWAP32(pa + di->dataoffset));

		DMA_TRACE(("%s: dma_rxfill:  ctrl %08x dataoffset: %08x\n", di->name, BUS_SWAP32(ctrl), BUS_SWAP32(pa + di->dataoffset)));

		rxout = NEXTRXD(rxout);
	}

	di->rxout = rxout;

	/* update the chip lastdscr pointer */
	W_REG(&di->regs->rcvptr, I2B(rxout));
}