Example #1
0
static int
bcm_rpc_tp_tx_agg_release(rpc_tp_info_t * rpcb)
{
	rpc_buf_t *b;
	int err;

	/* no aggregation formed */
	if (rpcb->tp_tx_agg_p == NULL)
		return 0;

	RPC_TP_AGG(("%s: send %d, sframe %d\n", __FUNCTION__,
		rpcb->tp_tx_agg_bytes, rpcb->tp_tx_agg_sframes));

	b = rpcb->tp_tx_agg_p;
	rpcb->tp_tx_agg_cnt_chain++;
	rpcb->tp_tx_agg_cnt_sf += rpcb->tp_tx_agg_sframes;
	rpcb->tp_tx_agg_cnt_bytes += rpcb->tp_tx_agg_bytes;

	if (rpcb->tp_tx_agg_sframes == 1)
		rpcb->tp_tx_agg_cnt_noagg++;

	err = bcm_rpc_tp_buf_send_internal(rpcb, b);
	bcm_rpc_tp_tx_agg_initstate(rpcb);
	return err;
}
Example #2
0
int
bcm_rpc_tp_buf_send(rpc_tp_info_t * rpcb, rpc_buf_t *b)
{
	int err;

	/* Add the TP encapsulation */
	bcm_rpc_tp_tx_encap(rpcb, b);

	/* if aggregation enabled use the agg path, otherwise send immediately */
	if (rpcb->tp_tx_aggregation) {
		err = bcm_rpc_tp_tx_agg(rpcb, b);
	} else {
		rpcb->tp_tx_agg_cnt_pass++;
		err = bcm_rpc_tp_buf_send_internal(rpcb, b);
	}

	return err;
}
Example #3
0
/* This is called by dngl_txstop as txflowcontrol (stopping tx from dongle to host) of bcmwl,
 * but is called rxflowcontrol in wl driver (pausing rx of wl driver). This is for low driver only.
 */
void
bcm_rpc_tp_txflowctl(rpc_tp_info_t *rpc_th, bool state, int prio)
{
	rpc_buf_t *b;

	ASSERT(rpc_th);

	if (rpc_th->tx_flowctl == state)
		return;

	RPC_TP_AGG(("tp_txflowctl %d\n", state));

	rpc_th->tx_flowctl = state;
	rpc_th->tx_flowctl_cnt++;
	rpc_th->tx_flowcontrolled = state;

	/* when get out of flowcontrol, send all queued packets in a loop
	 *  but need to check tx_flowctl every iteration and stop if we got flowcontrolled again
	 */
	while (!rpc_th->tx_flowctl && !pktq_empty(rpc_th->tx_flowctlq)) {

		b = pktdeq(rpc_th->tx_flowctlq);
		if (b == NULL) break;

		rpc_th->tx_q_flowctl_segcnt -= pktsegcnt(rpc_th->osh, b);

		bcm_rpc_tp_buf_send_internal(rpc_th, b, USBDEV_BULK_IN_EP1);
	}

	/* bcm_rpc_tp_agg_set(rpc_th, BCM_RPC_TP_DNGL_AGG_FLOWCTL, state); */

	/* if lowm is reached, release wldriver
	 *   TODO, count more(average 3?) if agg is ON
	 */
	if (rpc_th->tx_q_flowctl_segcnt < rpc_th->tx_q_flowctl_lowm) {
		RPC_TP_AGG(("bcm_rpc_tp_txflowctl, wm hit low!\n"));
		rpc_th->txflowctl_cb(rpc_th->txflowctl_ctx, OFF);
	}

	return;
}
Example #4
0
static int
bcm_rpc_tp_dngl_agg_release(rpc_tp_info_t * rpcb)
{
	int err;
	rpc_buf_t *b;

	if (rpcb->tp_dngl_agg_p == NULL) {	/* no aggregation formed */
		return 0;
	}

	RPC_TP_AGG(("%s, send %d, sframe %d\n", __FUNCTION__,
		rpcb->tp_dngl_agg_bytes, rpcb->tp_dngl_agg_sframes));

	b = rpcb->tp_dngl_agg_p;
	rpcb->tp_dngl_agg_cnt_chain++;
	rpcb->tp_dngl_agg_cnt_sf += rpcb->tp_dngl_agg_sframes;
	rpcb->tp_dngl_agg_cnt_bytes += rpcb->tp_dngl_agg_bytes;
	if (rpcb->tp_dngl_agg_sframes == 1)
		rpcb->tp_dngl_agg_cnt_noagg++;

	bcm_rpc_tp_dngl_agg_initstate(rpcb);

	rpcb->tp_dngl_agg_txpending++;

	if (rpcb->tx_flowctl) {
		bcm_rpc_tp_buf_send_enq(rpcb, b);
		err = 0;
	} else {
		err = bcm_rpc_tp_buf_send_internal(rpcb, b, USBDEV_BULK_IN_EP1);
	}

	if (err != 0) {
		RPC_TP_ERR(("bcm_rpc_tp_dngl_agg_release: send err!!!\n"));
		/* ASSERT(0) */
	}

	return err;
}
Example #5
0
int
bcm_rpc_tp_buf_send(rpc_tp_info_t * rpc_th, rpc_buf_t *b)
{
	int err;

	/* Add the TP encapsulation */
	bcm_rpc_tp_tx_encap(rpc_th, b);

	/* if agg successful, done; otherwise, send it */
	if (rpc_th->tp_dngl_aggregation) {
		err = bcm_rpc_tp_dngl_agg(rpc_th, b);
		return err;
	}
	rpc_th->tp_dngl_agg_cnt_pass++;

	if (rpc_th->tx_flowctl) {
		bcm_rpc_tp_buf_send_enq(rpc_th, b);
		err = 0;
	} else {
		err = bcm_rpc_tp_buf_send_internal(rpc_th, b, USBDEV_BULK_IN_EP1);
	}

	return err;
}