123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- /*
- * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. 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 */
- #include <wbuff.h>
- #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(byteOffsetStr), "%4.4X",
- byteOffset);
- A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
- qdf_mem_zero(stream, 60);
- byteOffset += 16;
- }
- }
- if (offset != 0) {
- A_SNPRINTF(byteOffsetStr, sizeof(byteOffsetStr), "%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);
- #ifdef WLAN_FEATURE_CE_RX_BUFFER_REUSE
- static void htc_rx_nbuf_free(qdf_nbuf_t nbuf)
- {
- nbuf = wbuff_buff_put(nbuf);
- if (nbuf)
- qdf_nbuf_free(nbuf);
- }
- #else
- static inline void htc_rx_nbuf_free(qdf_nbuf_t nbuf)
- {
- return qdf_nbuf_free(nbuf);
- }
- #endif
- 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)
- htc_rx_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);
- htc_rx_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)
- htc_rx_nbuf_free(skb);
- RESET_RX_SG_CONFIG(target);
- return NULL;
- }
- #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, *currendpoint;
- HTC_PACKET *pPacket;
- uint16_t payloadLen;
- uint32_t trailerlen = 0;
- uint8_t htc_ep_id;
- int i;
- #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) {
- for (i = 0; i < ENDPOINT_MAX; i++) {
- currendpoint = &target->endpoint[i];
- if ((currendpoint->DL_PipeID ==
- pEndpoint->DL_PipeID) &&
- currendpoint->ul_is_polled) {
- htc_send_complete_check(currendpoint,
- 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;
- uint16_t reason_code;
- /* 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;
- reason_code = 0;
- htc_credit_record(HTC_SUSPEND_ACK,
- pEndpoint->TxCredits,
- HTC_PACKET_QUEUE_DEPTH(
- &pEndpoint->TxQueue));
- target->HTCInitInfo.TargetSendSuspendComplete(
- target->HTCInitInfo.target_psoc,
- wow_nack, reason_code);
- break;
- case HTC_MSG_NACK_SUSPEND:
- wow_nack = true;
- reason_code = HTC_GET_FIELD(htc_msg,
- HTC_UNKNOWN_MSG,
- METADATA);
- htc_credit_record(HTC_SUSPEND_ACK,
- pEndpoint->TxCredits,
- HTC_PACKET_QUEUE_DEPTH(
- &pEndpoint->TxQueue));
- target->HTCInitInfo.TargetSendSuspendComplete(
- target->HTCInitInfo.target_psoc,
- wow_nack, reason_code);
- break;
- }
- htc_rx_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)
- htc_rx_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,
- (target->HTCInitInfo.htc_ready_timeout_ms))) {
- 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;
- }
|