文件
android_kernel_samsung_sm86…/htc/htc_recv.c
Jeff Johnson 5a6cc79b9e qcacmn: htc: Replace explicit comparison to NULL
Per the Linux Kernel coding style, as enforced by the kernel
checkpatch script, pointers should not be explicitly compared to
NULL. Therefore within htc replace any such comparisons with logical
operations performed on the pointer itself.

Change-Id: Ibb6d24aff9824d7e7cf253c1fe3081443cbfb63b
CRs-Fixed: 2418252
2019-03-27 06:09:57 -07:00

723 行
18 KiB
C

/*
* Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "htc_debug.h"
#include "htc_internal.h"
#include "htc_credit_history.h"
#include <qdf_nbuf.h> /* qdf_nbuf_t */
/* HTC Control message receive timeout msec */
#define HTC_CONTROL_RX_TIMEOUT 6000
#if defined(WLAN_DEBUG) || defined(DEBUG)
void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
{
int8_t stream[60];
int8_t byteOffsetStr[10];
uint32_t i;
uint16_t offset, count, byteOffset;
A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length,
pDescription);
count = 0;
offset = 0;
byteOffset = 0;
for (i = 0; i < length; i++) {
A_SNPRINTF(stream + offset, (sizeof(stream) - offset),
"%02X ", buffer[i]);
count++;
offset += 3;
if (count == 16) {
count = 0;
offset = 0;
A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",
byteOffset);
A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
qdf_mem_zero(stream, 60);
byteOffset += 16;
}
}
if (offset != 0) {
A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",
byteOffset);
A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
}
A_PRINTF("<------------------------------------------------->\n");
}
#else
void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
{
}
#endif
static A_STATUS htc_process_trailer(HTC_TARGET *target,
uint8_t *pBuffer,
int Length, HTC_ENDPOINT_ID FromEndpoint);
static void do_recv_completion_pkt(HTC_ENDPOINT *pEndpoint,
HTC_PACKET *pPacket)
{
if (!pEndpoint->EpCallBacks.EpRecv) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("HTC ep %d has NULL recv callback on packet %pK\n",
pEndpoint->Id,
pPacket));
if (pPacket)
qdf_nbuf_free(pPacket->pPktContext);
} else {
AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
("HTC calling ep %d recv callback on packet %pK\n",
pEndpoint->Id, pPacket));
pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext,
pPacket);
}
}
static void do_recv_completion(HTC_ENDPOINT *pEndpoint,
HTC_PACKET_QUEUE *pQueueToIndicate)
{
HTC_PACKET *pPacket;
if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
/* nothing to indicate */
return;
}
while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) {
pPacket = htc_packet_dequeue(pQueueToIndicate);
do_recv_completion_pkt(pEndpoint, pPacket);
}
}
void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket)
{
/* TODO, can't really receive HTC control messages yet.... */
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("Invalid call to htc_control_rx_complete\n"));
}
void htc_unblock_recv(HTC_HANDLE HTCHandle)
{
/* TODO find the Need in new model */
}
void htc_enable_recv(HTC_HANDLE HTCHandle)
{
/* TODO find the Need in new model */
}
void htc_disable_recv(HTC_HANDLE HTCHandle)
{
/* TODO find the Need in new model */
}
int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
{
HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue);
}
HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target)
{
HTC_PACKET *pPacket;
LOCK_HTC_RX(target);
if (!target->pHTCPacketStructPool) {
UNLOCK_HTC_RX(target);
return NULL;
}
pPacket = target->pHTCPacketStructPool;
target->pHTCPacketStructPool = (HTC_PACKET *) pPacket->ListLink.pNext;
UNLOCK_HTC_RX(target);
pPacket->ListLink.pNext = NULL;
return pPacket;
}
void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket)
{
pPacket->ListLink.pPrev = NULL;
LOCK_HTC_RX(target);
if (!target->pHTCPacketStructPool) {
target->pHTCPacketStructPool = pPacket;
pPacket->ListLink.pNext = NULL;
} else {
pPacket->ListLink.pNext =
(DL_LIST *) target->pHTCPacketStructPool;
target->pHTCPacketStructPool = pPacket;
}
UNLOCK_HTC_RX(target);
}
#ifdef RX_SG_SUPPORT
qdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target)
{
qdf_nbuf_t skb;
uint8_t *anbdata;
uint8_t *anbdata_new;
uint32_t anblen;
qdf_nbuf_t new_skb = NULL;
uint32_t sg_queue_len;
qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
sg_queue_len = qdf_nbuf_queue_len(rx_sg_queue);
if (sg_queue_len <= 1) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("rx_sg_to_single_netbuf: invalid sg queue len %u\n"));
goto _failed;
}
new_skb = qdf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, false);
if (!new_skb) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("rx_sg_to_single_netbuf: can't allocate %u size netbuf\n",
target->ExpRxSgTotalLen));
goto _failed;
}
qdf_nbuf_peek_header(new_skb, &anbdata_new, &anblen);
skb = qdf_nbuf_queue_remove(rx_sg_queue);
do {
qdf_nbuf_peek_header(skb, &anbdata, &anblen);
qdf_mem_copy(anbdata_new, anbdata, qdf_nbuf_len(skb));
qdf_nbuf_put_tail(new_skb, qdf_nbuf_len(skb));
anbdata_new += qdf_nbuf_len(skb);
qdf_nbuf_free(skb);
skb = qdf_nbuf_queue_remove(rx_sg_queue);
} while (skb);
RESET_RX_SG_CONFIG(target);
return new_skb;
_failed:
while ((skb = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
qdf_nbuf_free(skb);
RESET_RX_SG_CONFIG(target);
return NULL;
}
#endif
#ifdef CONFIG_WIN
#define HTC_MSG_NACK_SUSPEND 7
#endif
QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf,
uint8_t pipeID)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
HTC_FRAME_HDR *HtcHdr;
HTC_TARGET *target = (HTC_TARGET *) Context;
uint8_t *netdata;
uint32_t netlen;
HTC_ENDPOINT *pEndpoint;
HTC_PACKET *pPacket;
uint16_t payloadLen;
uint32_t trailerlen = 0;
uint8_t htc_ep_id;
#ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
struct htc_init_info *info;
#endif
#ifdef RX_SG_SUPPORT
LOCK_HTC_RX(target);
if (target->IsRxSgInprogress) {
target->CurRxSgTotalLen += qdf_nbuf_len(netbuf);
qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) {
netbuf = rx_sg_to_single_netbuf(target);
if (!netbuf) {
UNLOCK_HTC_RX(target);
goto _out;
}
} else {
netbuf = NULL;
UNLOCK_HTC_RX(target);
goto _out;
}
}
UNLOCK_HTC_RX(target);
#endif
netdata = qdf_nbuf_data(netbuf);
netlen = qdf_nbuf_len(netbuf);
HtcHdr = (HTC_FRAME_HDR *) netdata;
do {
htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID);
if (htc_ep_id >= ENDPOINT_MAX) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("HTC Rx: invalid EndpointID=%d\n",
htc_ep_id));
debug_dump_bytes((uint8_t *) HtcHdr,
sizeof(HTC_FRAME_HDR),
"BAD HTC Header");
status = QDF_STATUS_E_FAILURE;
DPTRACE(qdf_dp_trace(
netbuf,
QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
QDF_TRACE_DEFAULT_PDEV_ID,
qdf_nbuf_data_addr(netbuf),
sizeof(qdf_nbuf_data(netbuf)),
QDF_RX));
break;
}
pEndpoint = &target->endpoint[htc_ep_id];
/*
* If this endpoint that received a message from the target has
* a to-target HIF pipe whose send completions are polled rather
* than interrupt driven, this is a good point to ask HIF to
* check whether it has any completed sends to handle.
*/
if (pEndpoint->ul_is_polled)
htc_send_complete_check(pEndpoint, 1);
payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN);
if (netlen < (payloadLen + HTC_HDR_LENGTH)) {
#ifdef RX_SG_SUPPORT
LOCK_HTC_RX(target);
target->IsRxSgInprogress = true;
qdf_nbuf_queue_init(&target->RxSgQueue);
qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH);
target->CurRxSgTotalLen += netlen;
UNLOCK_HTC_RX(target);
netbuf = NULL;
break;
#else
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("HTC Rx: insufficient length, got:%d expected =%zu\n",
netlen, payloadLen + HTC_HDR_LENGTH));
debug_dump_bytes((uint8_t *) HtcHdr,
sizeof(HTC_FRAME_HDR),
"BAD RX packet length");
status = QDF_STATUS_E_FAILURE;
DPTRACE(qdf_dp_trace(
netbuf,
QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
QDF_TRACE_DEFAULT_PDEV_ID,
qdf_nbuf_data_addr(netbuf),
sizeof(qdf_nbuf_data(netbuf)),
QDF_RX));
break;
#endif
}
#ifdef HTC_EP_STAT_PROFILING
LOCK_HTC_RX(target);
INC_HTC_EP_STAT(pEndpoint, RxReceived, 1);
UNLOCK_HTC_RX(target);
#endif
/* if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { */
{
uint8_t temp;
A_STATUS temp_status;
/* get flags to check for trailer */
temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS);
if (temp & HTC_FLAGS_RECV_TRAILER) {
/* extract the trailer length */
temp =
HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR,
CONTROLBYTES0);
if ((temp < sizeof(HTC_RECORD_HDR))
|| (temp > payloadLen)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("htc_rx_completion_handler, invalid header (payloadlength should be :%d, CB[0] is:%d)\n",
payloadLen, temp));
status = QDF_STATUS_E_INVAL;
break;
}
trailerlen = temp;
/* process trailer data that follows HDR +
* application payload
*/
temp_status = htc_process_trailer(target,
((uint8_t *) HtcHdr +
HTC_HDR_LENGTH +
payloadLen - temp),
temp, htc_ep_id);
if (A_FAILED(temp_status)) {
status = QDF_STATUS_E_FAILURE;
break;
}
}
}
if (((int)payloadLen - (int)trailerlen) <= 0) {
/* 0 length packet with trailer data, just drop these */
break;
}
if (htc_ep_id == ENDPOINT_0) {
uint16_t message_id;
HTC_UNKNOWN_MSG *htc_msg;
bool wow_nack;
/* remove HTC header */
qdf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH);
netdata = qdf_nbuf_data(netbuf);
netlen = qdf_nbuf_len(netbuf);
htc_msg = (HTC_UNKNOWN_MSG *) netdata;
message_id = HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG,
MESSAGEID);
switch (message_id) {
default:
/* handle HTC control message */
if (target->CtrlResponseProcessing) {
/* this is a fatal error, target should
* not be sending unsolicited messages
* on the endpoint 0
*/
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("HTC Rx Ctrl still processing\n"));
status = QDF_STATUS_E_FAILURE;
QDF_BUG(false);
break;
}
LOCK_HTC_RX(target);
target->CtrlResponseLength =
min((int)netlen,
HTC_MAX_CONTROL_MESSAGE_LENGTH);
qdf_mem_copy(target->CtrlResponseBuffer,
netdata,
target->CtrlResponseLength);
/* Requester will clear this flag */
target->CtrlResponseProcessing = true;
UNLOCK_HTC_RX(target);
qdf_event_set(&target->ctrl_response_valid);
break;
#ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
case HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
("Received initial wake up"));
htc_credit_record(HTC_INITIAL_WAKE_UP,
pEndpoint->TxCredits,
HTC_PACKET_QUEUE_DEPTH(
&pEndpoint->TxQueue));
info = &target->HTCInitInfo;
if (info && info->target_initial_wakeup_cb)
info->target_initial_wakeup_cb(
info->target_psoc);
else
AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
("No initial wake up cb"));
break;
#endif
case HTC_MSG_SEND_SUSPEND_COMPLETE:
wow_nack = false;
htc_credit_record(HTC_SUSPEND_ACK,
pEndpoint->TxCredits,
HTC_PACKET_QUEUE_DEPTH(
&pEndpoint->TxQueue));
target->HTCInitInfo.TargetSendSuspendComplete(
target->HTCInitInfo.target_psoc,
wow_nack);
break;
case HTC_MSG_NACK_SUSPEND:
wow_nack = true;
htc_credit_record(HTC_SUSPEND_ACK,
pEndpoint->TxCredits,
HTC_PACKET_QUEUE_DEPTH(
&pEndpoint->TxQueue));
target->HTCInitInfo.TargetSendSuspendComplete(
target->HTCInitInfo.target_psoc,
wow_nack);
break;
}
qdf_nbuf_free(netbuf);
netbuf = NULL;
break;
}
/* the current message based HIF architecture allocates net bufs
* for recv packets since this layer bridges that HIF to upper
* layers , which expects HTC packets, we form the packets here
* TODO_FIXME
*/
pPacket = allocate_htc_packet_container(target);
if (!pPacket) {
status = QDF_STATUS_E_RESOURCES;
break;
}
pPacket->Status = QDF_STATUS_SUCCESS;
pPacket->Endpoint = htc_ep_id;
pPacket->pPktContext = netbuf;
pPacket->pBuffer = qdf_nbuf_data(netbuf) + HTC_HDR_LENGTH;
pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen;
qdf_nbuf_pull_head(netbuf, HTC_HEADER_LEN);
qdf_nbuf_set_pktlen(netbuf, pPacket->ActualLength);
do_recv_completion_pkt(pEndpoint, pPacket);
/* recover the packet container */
free_htc_packet_container(target, pPacket);
netbuf = NULL;
} while (false);
#ifdef RX_SG_SUPPORT
_out:
#endif
if (netbuf)
qdf_nbuf_free(netbuf);
return status;
}
A_STATUS htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle,
HTC_PACKET_QUEUE *pPktQueue)
{
HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
HTC_ENDPOINT *pEndpoint;
HTC_PACKET *pFirstPacket;
A_STATUS status = A_OK;
HTC_PACKET *pPacket;
pFirstPacket = htc_get_pkt_at_head(pPktQueue);
if (!pFirstPacket) {
A_ASSERT(false);
return A_EINVAL;
}
if (pFirstPacket->Endpoint >= ENDPOINT_MAX) {
A_ASSERT(false);
return A_EINVAL;
}
AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
("+- htc_add_receive_pkt_multiple : endPointId: %d, cnt:%d, length: %d\n",
pFirstPacket->Endpoint,
HTC_PACKET_QUEUE_DEPTH(pPktQueue),
pFirstPacket->BufferLength));
pEndpoint = &target->endpoint[pFirstPacket->Endpoint];
LOCK_HTC_RX(target);
do {
if (HTC_STOPPING(target)) {
status = A_ERROR;
break;
}
/* store receive packets */
HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,
pPktQueue);
} while (false);
UNLOCK_HTC_RX(target);
if (A_FAILED(status)) {
/* walk through queue and mark each one canceled */
HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue, pPacket) {
pPacket->Status = QDF_STATUS_E_CANCELED;
}
HTC_PACKET_QUEUE_ITERATE_END;
do_recv_completion(pEndpoint, pPktQueue);
}
return status;
}
void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
{
HTC_PACKET *pPacket;
LOCK_HTC_RX(target);
while (1) {
pPacket = htc_packet_dequeue(&pEndpoint->RxBufferHoldQueue);
if (!pPacket)
break;
UNLOCK_HTC_RX(target);
pPacket->Status = QDF_STATUS_E_CANCELED;
pPacket->ActualLength = 0;
AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
("Flushing RX packet:%pK, length:%d, ep:%d\n",
pPacket, pPacket->BufferLength,
pPacket->Endpoint));
/* give the packet back */
do_recv_completion_pkt(pEndpoint, pPacket);
LOCK_HTC_RX(target);
}
UNLOCK_HTC_RX(target);
}
void htc_recv_init(HTC_TARGET *target)
{
/* Initialize ctrl_response_valid to block */
qdf_event_create(&target->ctrl_response_valid);
}
/* polling routine to wait for a control packet to be received */
QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target)
{
/* int count = HTC_TARGET_MAX_RESPONSE_POLL; */
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCWaitCtrlMessageRecv\n"));
/* Wait for BMI request/response transaction to complete */
if (qdf_wait_single_event(&target->ctrl_response_valid,
HTC_CONTROL_RX_TIMEOUT)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("Failed to receive control message\n"));
return QDF_STATUS_E_FAILURE;
}
LOCK_HTC_RX(target);
/* caller will clear this flag */
target->CtrlResponseProcessing = true;
UNLOCK_HTC_RX(target);
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCWaitCtrlMessageRecv success\n"));
return QDF_STATUS_SUCCESS;
}
static A_STATUS htc_process_trailer(HTC_TARGET *target,
uint8_t *pBuffer,
int Length, HTC_ENDPOINT_ID FromEndpoint)
{
HTC_RECORD_HDR *pRecord;
uint8_t htc_rec_id;
uint8_t htc_rec_len;
uint8_t *pRecordBuf;
uint8_t *pOrigBuffer;
int origLength;
A_STATUS status;
AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
("+htc_process_trailer (length:%d)\n", Length));
if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
AR_DEBUG_PRINTBUF(pBuffer, Length, "Recv Trailer");
pOrigBuffer = pBuffer;
origLength = Length;
status = A_OK;
while (Length > 0) {
if (Length < sizeof(HTC_RECORD_HDR)) {
status = A_EPROTO;
break;
}
/* these are byte aligned structs */
pRecord = (HTC_RECORD_HDR *) pBuffer;
Length -= sizeof(HTC_RECORD_HDR);
pBuffer += sizeof(HTC_RECORD_HDR);
htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH);
htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID);
if (htc_rec_len > Length) {
/* no room left in buffer for record */
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("invalid record length: %d (id:%d) buffer has: %d bytes left\n",
htc_rec_len, htc_rec_id, Length));
status = A_EPROTO;
break;
}
/* start of record follows the header */
pRecordBuf = pBuffer;
switch (htc_rec_id) {
case HTC_RECORD_CREDITS:
AR_DEBUG_ASSERT(htc_rec_len >=
sizeof(HTC_CREDIT_REPORT));
htc_process_credit_rpt(target,
(HTC_CREDIT_REPORT *) pRecordBuf,
htc_rec_len /
(sizeof(HTC_CREDIT_REPORT)),
FromEndpoint);
break;
#ifdef HIF_SDIO
case HTC_RECORD_LOOKAHEAD:
/* Process in HIF layer */
break;
case HTC_RECORD_LOOKAHEAD_BUNDLE:
/* Process in HIF layer */
break;
#endif /* HIF_SDIO */
default:
AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
("HTC unhandled record: id:%d length:%d\n",
htc_rec_id, htc_rec_len));
break;
}
if (A_FAILED(status)) {
break;
}
/* advance buffer past this record for next time around */
pBuffer += htc_rec_len;
Length -= htc_rec_len;
}
if (A_FAILED(status))
debug_dump_bytes(pOrigBuffer, origLength, "BAD Recv Trailer");
AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer\n"));
return status;
}