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; }
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); }
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; }