Beispiel #1
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;
}
Beispiel #2
0
static void
bcm_rpc_tp_buf_pad(rpc_tp_info_t * rpcb, rpc_buf_t *bb, uint padbytes)
{
	uint32 *tp_lenp = (uint32 *)bcm_rpc_buf_data(rpcb, bb);
	uint32 tp_len = ltoh32(*tp_lenp);
	uint32 pktlen = bcm_rpc_buf_len_get(rpcb, bb);
	ASSERT(tp_len + BCM_RPC_TP_ENCAP_LEN == pktlen);

	tp_len += padbytes;
	pktlen += padbytes;
	*tp_lenp = htol32(tp_len);
	bcm_rpc_buf_len_set(rpcb, bb, pktlen);
}
Beispiel #3
0
static int BCMFASTPATH
bcm_rpc_tp_buf_send_internal(rpc_tp_info_t * rpcb, rpc_buf_t *b)
{
	int err;
	bool tx_flow_control;
	int timeout = RPC_BUS_SEND_WAIT_TIMEOUT_MSEC;
	bool timedout = FALSE;
	uint pktlen;

	UNUSED_PARAMETER(pktlen);
	RPC_TP_LOCK(rpcb);

	rpcb->rpctp_dbus_hist[rpcb->bus_txpending]++;

	/* Increment before sending to avoid race condition */
	rpcb->bus_txpending++;
	tx_flow_control = (rpcb->bus_txpending >= rpcb->bus_txdepth);

	if (rpcb->tx_flowctl != tx_flow_control) {
		rpcb->tx_flowctl = tx_flow_control;
		RPC_TP_DBG(("%s, tx_flowctl change to %d pending %d\n", __FUNCTION__,
			rpcb->tx_flowctl, rpcb->bus_txpending));
	}
	rpcb->tx_flowctl_cnt += rpcb->tx_flowctl ? 1 : 0;
	RPC_TP_UNLOCK(rpcb);

	if (rpcb->tx_flowctl_override) {
		timeout = RPC_BUS_SEND_WAIT_EXT_TIMEOUT_MSEC;
	}

	if (rpcb->tx_flowctl || rpcb->tx_flowctl_override) {
		err = RPC_OSL_WAIT(rpcb->rpc_osh, timeout, &timedout);
		if (timedout) {
			printf("%s: RPC_OSL_WAIT error %d timeout %d(ms)\n", __FUNCTION__, err,
			       RPC_BUS_SEND_WAIT_TIMEOUT_MSEC);
			RPC_TP_LOCK(rpcb);
			rpcb->txerr_cnt++;
			rpcb->bus_txpending--;
			RPC_TP_UNLOCK(rpcb);
			return err;
		}
	}

#if defined(BCMUSB) || defined(USBAP)
	if (rpcb->tp_tx_agg_bytes != 0) {
		ASSERT(rpcb->tp_tx_agg_p == b);
		ASSERT(rpcb->tp_tx_agg_ptail != NULL);

		/* Make sure pktlen is not multiple of 512 bytes even after possible dbus padding */
		if ((ROUNDUP(rpcb->tp_tx_agg_bytes, sizeof(uint32)) % BCM_RPC_TP_HOST_TOTALLEN_ZLP)
			== 0) {
			uint32 *tp_lenp = (uint32 *)bcm_rpc_buf_data(rpcb, rpcb->tp_tx_agg_ptail);
			uint32 tp_len = ltoh32(*tp_lenp);
			pktlen = bcm_rpc_buf_len_get(rpcb, rpcb->tp_tx_agg_ptail);
			ASSERT(tp_len + BCM_RPC_TP_ENCAP_LEN == pktlen);

			RPC_TP_DBG(("%s, agg pkt is multiple of 512 bytes\n", __FUNCTION__));

			tp_len += BCM_RPC_TP_HOST_TOTALLEN_ZLP_PAD;
			pktlen += BCM_RPC_TP_HOST_TOTALLEN_ZLP_PAD;
			*tp_lenp = htol32(tp_len);
			bcm_rpc_buf_len_set(rpcb, rpcb->tp_tx_agg_ptail, pktlen);
		}
	} else {	/* not aggregated */
		ASSERT(b != NULL);
		pktlen = bcm_rpc_buf_len_get(rpcb, b);
		/* Make sure pktlen is not multiple of 512 bytes even after possible dbus padding */
		if ((pktlen != 0) &&
			((ROUNDUP(pktlen, sizeof(uint32)) % BCM_RPC_TP_HOST_TOTALLEN_ZLP) == 0)) {
			uint32 *tp_lenp = (uint32 *)bcm_rpc_buf_data(rpcb, b);
			uint32 tp_len = ltoh32(*tp_lenp);
			ASSERT(tp_len + BCM_RPC_TP_ENCAP_LEN == pktlen);

			RPC_TP_DBG(("%s, nonagg pkt is multiple of 512 bytes\n", __FUNCTION__));

			tp_len += BCM_RPC_TP_HOST_TOTALLEN_ZLP_PAD;
			pktlen += BCM_RPC_TP_HOST_TOTALLEN_ZLP_PAD;
			*tp_lenp = htol32(tp_len);
			bcm_rpc_buf_len_set(rpcb, b, pktlen);
		}
	}
#endif /* defined(BCMUSB) || defined(USBAP) */

#ifdef EHCI_FASTPATH_TX
	/* With optimization, submit code is lockless, use RPC_TP_LOCK */
	RPC_TP_LOCK(rpcb);
	err = dbus_send_pkt(rpcb->bus, b, b);
#else
	err = dbus_send_pkt(rpcb->bus, b, b);
	RPC_TP_LOCK(rpcb);
#endif	/* EHCI_FASTPATH_TX */

	if (err != 0) {
		printf("%s: dbus_send_pkt failed\n", __FUNCTION__);
		rpcb->txerr_cnt++;
		rpcb->bus_txpending--;
	} else {
		rpcb->tx_cnt++;
	}
	RPC_TP_UNLOCK(rpcb);

	return err;
}