1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "htc_debug.h"
21 #include "htc_internal.h"
22 #include "htc_credit_history.h"
23 #include <qdf_nbuf.h> /* qdf_nbuf_t */
24 #include <wbuff.h>
25
26 #if defined(WLAN_DEBUG) || defined(DEBUG)
debug_dump_bytes(uint8_t * buffer,uint16_t length,char * pDescription)27 void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
28 {
29 int8_t stream[60];
30 int8_t byteOffsetStr[10];
31 uint32_t i;
32 uint16_t offset, count, byteOffset;
33
34 A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length,
35 pDescription);
36
37 count = 0;
38 offset = 0;
39 byteOffset = 0;
40 for (i = 0; i < length; i++) {
41 A_SNPRINTF(stream + offset, (sizeof(stream) - offset),
42 "%02X ", buffer[i]);
43 count++;
44 offset += 3;
45
46 if (count == 16) {
47 count = 0;
48 offset = 0;
49 A_SNPRINTF(byteOffsetStr, sizeof(byteOffsetStr), "%4.4X",
50 byteOffset);
51 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
52 qdf_mem_zero(stream, 60);
53 byteOffset += 16;
54 }
55 }
56
57 if (offset != 0) {
58 A_SNPRINTF(byteOffsetStr, sizeof(byteOffsetStr), "%4.4X",
59 byteOffset);
60 A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
61 }
62
63 A_PRINTF("<------------------------------------------------->\n");
64 }
65 #else
debug_dump_bytes(uint8_t * buffer,uint16_t length,char * pDescription)66 void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
67 {
68 }
69 #endif
70
71 static A_STATUS htc_process_trailer(HTC_TARGET *target,
72 uint8_t *pBuffer,
73 int Length, HTC_ENDPOINT_ID FromEndpoint);
74
75 #ifdef WLAN_FEATURE_CE_RX_BUFFER_REUSE
htc_rx_nbuf_free(qdf_nbuf_t nbuf)76 static void htc_rx_nbuf_free(qdf_nbuf_t nbuf)
77 {
78 nbuf = wbuff_buff_put(nbuf);
79 if (nbuf)
80 qdf_nbuf_free(nbuf);
81 }
82 #else
htc_rx_nbuf_free(qdf_nbuf_t nbuf)83 static inline void htc_rx_nbuf_free(qdf_nbuf_t nbuf)
84 {
85 return qdf_nbuf_free(nbuf);
86 }
87 #endif
88
do_recv_completion_pkt(HTC_ENDPOINT * pEndpoint,HTC_PACKET * pPacket)89 static void do_recv_completion_pkt(HTC_ENDPOINT *pEndpoint,
90 HTC_PACKET *pPacket)
91 {
92 if (!pEndpoint->EpCallBacks.EpRecv) {
93 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
94 ("HTC ep %d has NULL recv callback on packet %pK\n",
95 pEndpoint->Id,
96 pPacket));
97 if (pPacket)
98 htc_rx_nbuf_free(pPacket->pPktContext);
99 } else {
100 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
101 ("HTC calling ep %d recv callback on packet %pK\n",
102 pEndpoint->Id, pPacket));
103 pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext,
104 pPacket);
105 }
106 }
107
do_recv_completion(HTC_ENDPOINT * pEndpoint,HTC_PACKET_QUEUE * pQueueToIndicate)108 static void do_recv_completion(HTC_ENDPOINT *pEndpoint,
109 HTC_PACKET_QUEUE *pQueueToIndicate)
110 {
111 HTC_PACKET *pPacket;
112
113 if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
114 /* nothing to indicate */
115 return;
116 }
117
118 while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) {
119 pPacket = htc_packet_dequeue(pQueueToIndicate);
120 do_recv_completion_pkt(pEndpoint, pPacket);
121 }
122 }
123
htc_control_rx_complete(void * Context,HTC_PACKET * pPacket)124 void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket)
125 {
126 /* TODO, can't really receive HTC control messages yet.... */
127 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
128 ("Invalid call to htc_control_rx_complete\n"));
129 }
130
htc_unblock_recv(HTC_HANDLE HTCHandle)131 void htc_unblock_recv(HTC_HANDLE HTCHandle)
132 {
133 /* TODO find the Need in new model */
134 }
135
htc_enable_recv(HTC_HANDLE HTCHandle)136 void htc_enable_recv(HTC_HANDLE HTCHandle)
137 {
138
139 /* TODO find the Need in new model */
140 }
141
htc_disable_recv(HTC_HANDLE HTCHandle)142 void htc_disable_recv(HTC_HANDLE HTCHandle)
143 {
144
145 /* TODO find the Need in new model */
146 }
147
htc_get_num_recv_buffers(HTC_HANDLE HTCHandle,HTC_ENDPOINT_ID Endpoint)148 int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
149 {
150 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
151
152 HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
153 return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue);
154 }
155
allocate_htc_packet_container(HTC_TARGET * target)156 HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target)
157 {
158 HTC_PACKET *pPacket;
159
160 LOCK_HTC_RX(target);
161
162 if (!target->pHTCPacketStructPool) {
163 UNLOCK_HTC_RX(target);
164 return NULL;
165 }
166
167 pPacket = target->pHTCPacketStructPool;
168 target->pHTCPacketStructPool = (HTC_PACKET *) pPacket->ListLink.pNext;
169
170 UNLOCK_HTC_RX(target);
171
172 pPacket->ListLink.pNext = NULL;
173 return pPacket;
174 }
175
free_htc_packet_container(HTC_TARGET * target,HTC_PACKET * pPacket)176 void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket)
177 {
178 pPacket->ListLink.pPrev = NULL;
179
180 LOCK_HTC_RX(target);
181 if (!target->pHTCPacketStructPool) {
182 target->pHTCPacketStructPool = pPacket;
183 pPacket->ListLink.pNext = NULL;
184 } else {
185 pPacket->ListLink.pNext =
186 (DL_LIST *) target->pHTCPacketStructPool;
187 target->pHTCPacketStructPool = pPacket;
188 }
189
190 UNLOCK_HTC_RX(target);
191 }
192
193 #ifdef RX_SG_SUPPORT
rx_sg_to_single_netbuf(HTC_TARGET * target)194 qdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target)
195 {
196 qdf_nbuf_t skb;
197 uint8_t *anbdata;
198 uint8_t *anbdata_new;
199 uint32_t anblen;
200 qdf_nbuf_t new_skb = NULL;
201 uint32_t sg_queue_len;
202 qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
203
204 sg_queue_len = qdf_nbuf_queue_len(rx_sg_queue);
205
206 if (sg_queue_len <= 1) {
207 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
208 ("rx_sg_to_single_netbuf: invalid sg queue len %u\n"));
209 goto _failed;
210 }
211
212 new_skb = qdf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, false);
213 if (!new_skb) {
214 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
215 ("rx_sg_to_single_netbuf: can't allocate %u size netbuf\n",
216 target->ExpRxSgTotalLen));
217 goto _failed;
218 }
219
220 qdf_nbuf_peek_header(new_skb, &anbdata_new, &anblen);
221
222 skb = qdf_nbuf_queue_remove(rx_sg_queue);
223 do {
224 qdf_nbuf_peek_header(skb, &anbdata, &anblen);
225 qdf_mem_copy(anbdata_new, anbdata, qdf_nbuf_len(skb));
226 qdf_nbuf_put_tail(new_skb, qdf_nbuf_len(skb));
227 anbdata_new += qdf_nbuf_len(skb);
228 htc_rx_nbuf_free(skb);
229 skb = qdf_nbuf_queue_remove(rx_sg_queue);
230 } while (skb);
231
232 RESET_RX_SG_CONFIG(target);
233 return new_skb;
234
235 _failed:
236
237 while ((skb = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
238 htc_rx_nbuf_free(skb);
239
240 RESET_RX_SG_CONFIG(target);
241 return NULL;
242 }
243 #endif
244
htc_rx_completion_handler(void * Context,qdf_nbuf_t netbuf,uint8_t pipeID)245 QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf,
246 uint8_t pipeID)
247 {
248 QDF_STATUS status = QDF_STATUS_SUCCESS;
249 HTC_FRAME_HDR *HtcHdr;
250 HTC_TARGET *target = (HTC_TARGET *) Context;
251 uint8_t *netdata;
252 uint32_t netlen;
253 HTC_ENDPOINT *pEndpoint, *currendpoint;
254 HTC_PACKET *pPacket;
255 uint16_t payloadLen;
256 uint32_t trailerlen = 0;
257 uint8_t htc_ep_id;
258 int i;
259 #ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
260 struct htc_init_info *info;
261 #endif
262
263 #ifdef RX_SG_SUPPORT
264 LOCK_HTC_RX(target);
265 if (target->IsRxSgInprogress) {
266 target->CurRxSgTotalLen += qdf_nbuf_len(netbuf);
267 qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
268 if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) {
269 netbuf = rx_sg_to_single_netbuf(target);
270 if (!netbuf) {
271 UNLOCK_HTC_RX(target);
272 goto _out;
273 }
274 } else {
275 netbuf = NULL;
276 UNLOCK_HTC_RX(target);
277 goto _out;
278 }
279 }
280 UNLOCK_HTC_RX(target);
281 #endif
282
283 netdata = qdf_nbuf_data(netbuf);
284 netlen = qdf_nbuf_len(netbuf);
285
286 HtcHdr = (HTC_FRAME_HDR *) netdata;
287
288 do {
289
290 htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID);
291
292 if (htc_ep_id >= ENDPOINT_MAX) {
293 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
294 ("HTC Rx: invalid EndpointID=%d\n",
295 htc_ep_id));
296 debug_dump_bytes((uint8_t *) HtcHdr,
297 sizeof(HTC_FRAME_HDR),
298 "BAD HTC Header");
299 status = QDF_STATUS_E_FAILURE;
300 DPTRACE(qdf_dp_trace(
301 netbuf,
302 QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
303 QDF_TRACE_DEFAULT_PDEV_ID,
304 qdf_nbuf_data_addr(netbuf),
305 sizeof(qdf_nbuf_data(netbuf)),
306 QDF_RX));
307 break;
308 }
309
310 pEndpoint = &target->endpoint[htc_ep_id];
311
312 /*
313 * If this endpoint that received a message from the target has
314 * a to-target HIF pipe whose send completions are polled rather
315 * than interrupt driven, this is a good point to ask HIF to
316 * check whether it has any completed sends to handle.
317 */
318 if (pEndpoint->ul_is_polled) {
319 for (i = 0; i < ENDPOINT_MAX; i++) {
320 currendpoint = &target->endpoint[i];
321 if ((currendpoint->DL_PipeID ==
322 pEndpoint->DL_PipeID) &&
323 currendpoint->ul_is_polled) {
324 htc_send_complete_check(currendpoint,
325 1);
326 }
327 }
328 }
329
330 payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN);
331
332 if (netlen < (payloadLen + HTC_HDR_LENGTH)) {
333 #ifdef RX_SG_SUPPORT
334 LOCK_HTC_RX(target);
335 target->IsRxSgInprogress = true;
336 qdf_nbuf_queue_init(&target->RxSgQueue);
337 qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
338 target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH);
339 target->CurRxSgTotalLen += netlen;
340 UNLOCK_HTC_RX(target);
341 netbuf = NULL;
342 break;
343 #else
344 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
345 ("HTC Rx: insufficient length, got:%d expected =%zu\n",
346 netlen, payloadLen + HTC_HDR_LENGTH));
347 debug_dump_bytes((uint8_t *) HtcHdr,
348 sizeof(HTC_FRAME_HDR),
349 "BAD RX packet length");
350 status = QDF_STATUS_E_FAILURE;
351 DPTRACE(qdf_dp_trace(
352 netbuf,
353 QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
354 QDF_TRACE_DEFAULT_PDEV_ID,
355 qdf_nbuf_data_addr(netbuf),
356 sizeof(qdf_nbuf_data(netbuf)),
357 QDF_RX));
358 break;
359 #endif
360 }
361 #ifdef HTC_EP_STAT_PROFILING
362 LOCK_HTC_RX(target);
363 INC_HTC_EP_STAT(pEndpoint, RxReceived, 1);
364 UNLOCK_HTC_RX(target);
365 #endif
366
367 /* if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { */
368 {
369 uint8_t temp;
370 A_STATUS temp_status;
371 /* get flags to check for trailer */
372 temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS);
373 if (temp & HTC_FLAGS_RECV_TRAILER) {
374 /* extract the trailer length */
375 temp =
376 HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR,
377 CONTROLBYTES0);
378 if ((temp < sizeof(HTC_RECORD_HDR))
379 || (temp > payloadLen)) {
380 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
381 ("htc_rx_completion_handler, invalid header (payloadlength should be :%d, CB[0] is:%d)\n",
382 payloadLen, temp));
383 status = QDF_STATUS_E_INVAL;
384 break;
385 }
386
387 trailerlen = temp;
388 /* process trailer data that follows HDR +
389 * application payload
390 */
391 temp_status = htc_process_trailer(target,
392 ((uint8_t *) HtcHdr +
393 HTC_HDR_LENGTH +
394 payloadLen - temp),
395 temp, htc_ep_id);
396 if (A_FAILED(temp_status)) {
397 status = QDF_STATUS_E_FAILURE;
398 break;
399 }
400
401 }
402 }
403
404 if (((int)payloadLen - (int)trailerlen) <= 0) {
405 /* 0 length packet with trailer data, just drop these */
406 break;
407 }
408
409 if (htc_ep_id == ENDPOINT_0) {
410 uint16_t message_id;
411 HTC_UNKNOWN_MSG *htc_msg;
412 bool wow_nack;
413 uint16_t reason_code;
414
415 /* remove HTC header */
416 qdf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH);
417 netdata = qdf_nbuf_data(netbuf);
418 netlen = qdf_nbuf_len(netbuf);
419
420 htc_msg = (HTC_UNKNOWN_MSG *) netdata;
421 message_id = HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG,
422 MESSAGEID);
423
424 switch (message_id) {
425 default:
426 /* handle HTC control message */
427 if (target->CtrlResponseProcessing) {
428 /* this is a fatal error, target should
429 * not be sending unsolicited messages
430 * on the endpoint 0
431 */
432 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
433 ("HTC Rx Ctrl still processing\n"));
434 status = QDF_STATUS_E_FAILURE;
435 QDF_BUG(false);
436 break;
437 }
438
439 LOCK_HTC_RX(target);
440 target->CtrlResponseLength =
441 min((int)netlen,
442 HTC_MAX_CONTROL_MESSAGE_LENGTH);
443 qdf_mem_copy(target->CtrlResponseBuffer,
444 netdata,
445 target->CtrlResponseLength);
446
447 /* Requester will clear this flag */
448 target->CtrlResponseProcessing = true;
449 UNLOCK_HTC_RX(target);
450 qdf_event_set(&target->ctrl_response_valid);
451 break;
452 #ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
453 case HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
454 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
455 ("Received initial wake up"));
456 htc_credit_record(HTC_INITIAL_WAKE_UP,
457 pEndpoint->TxCredits,
458 HTC_PACKET_QUEUE_DEPTH(
459 &pEndpoint->TxQueue));
460 info = &target->HTCInitInfo;
461 if (info && info->target_initial_wakeup_cb)
462 info->target_initial_wakeup_cb(
463 info->target_psoc);
464 else
465 AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
466 ("No initial wake up cb"));
467 break;
468 #endif
469 case HTC_MSG_SEND_SUSPEND_COMPLETE:
470 wow_nack = false;
471 reason_code = 0;
472 htc_credit_record(HTC_SUSPEND_ACK,
473 pEndpoint->TxCredits,
474 HTC_PACKET_QUEUE_DEPTH(
475 &pEndpoint->TxQueue));
476 target->HTCInitInfo.TargetSendSuspendComplete(
477 target->HTCInitInfo.target_psoc,
478 wow_nack, reason_code);
479
480 break;
481 case HTC_MSG_NACK_SUSPEND:
482 wow_nack = true;
483 reason_code = HTC_GET_FIELD(htc_msg,
484 HTC_UNKNOWN_MSG,
485 METADATA);
486 htc_credit_record(HTC_SUSPEND_ACK,
487 pEndpoint->TxCredits,
488 HTC_PACKET_QUEUE_DEPTH(
489 &pEndpoint->TxQueue));
490 target->HTCInitInfo.TargetSendSuspendComplete(
491 target->HTCInitInfo.target_psoc,
492 wow_nack, reason_code);
493 break;
494 }
495
496 htc_rx_nbuf_free(netbuf);
497 netbuf = NULL;
498 break;
499 }
500
501 /* the current message based HIF architecture allocates net bufs
502 * for recv packets since this layer bridges that HIF to upper
503 * layers , which expects HTC packets, we form the packets here
504 * TODO_FIXME
505 */
506 pPacket = allocate_htc_packet_container(target);
507 if (!pPacket) {
508 status = QDF_STATUS_E_RESOURCES;
509 break;
510 }
511 pPacket->Status = QDF_STATUS_SUCCESS;
512 pPacket->Endpoint = htc_ep_id;
513 pPacket->pPktContext = netbuf;
514 pPacket->pBuffer = qdf_nbuf_data(netbuf) + HTC_HDR_LENGTH;
515 pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen;
516
517 qdf_nbuf_pull_head(netbuf, HTC_HEADER_LEN);
518 qdf_nbuf_set_pktlen(netbuf, pPacket->ActualLength);
519
520 do_recv_completion_pkt(pEndpoint, pPacket);
521
522 /* recover the packet container */
523 free_htc_packet_container(target, pPacket);
524
525 netbuf = NULL;
526
527 } while (false);
528
529 #ifdef RX_SG_SUPPORT
530 _out:
531 #endif
532
533 if (netbuf)
534 htc_rx_nbuf_free(netbuf);
535
536 return status;
537
538 }
539
htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle,HTC_PACKET_QUEUE * pPktQueue)540 A_STATUS htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle,
541 HTC_PACKET_QUEUE *pPktQueue)
542 {
543 HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
544 HTC_ENDPOINT *pEndpoint;
545 HTC_PACKET *pFirstPacket;
546 A_STATUS status = A_OK;
547 HTC_PACKET *pPacket;
548
549 pFirstPacket = htc_get_pkt_at_head(pPktQueue);
550
551 if (!pFirstPacket) {
552 A_ASSERT(false);
553 return A_EINVAL;
554 }
555
556 if (pFirstPacket->Endpoint >= ENDPOINT_MAX) {
557 A_ASSERT(false);
558 return A_EINVAL;
559 }
560
561 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
562 ("+- htc_add_receive_pkt_multiple : endPointId: %d, cnt:%d, length: %d\n",
563 pFirstPacket->Endpoint,
564 HTC_PACKET_QUEUE_DEPTH(pPktQueue),
565 pFirstPacket->BufferLength));
566
567 pEndpoint = &target->endpoint[pFirstPacket->Endpoint];
568
569 LOCK_HTC_RX(target);
570
571 do {
572
573 if (HTC_STOPPING(target)) {
574 status = A_ERROR;
575 break;
576 }
577
578 /* store receive packets */
579 HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,
580 pPktQueue);
581
582 } while (false);
583
584 UNLOCK_HTC_RX(target);
585
586 if (A_FAILED(status)) {
587 /* walk through queue and mark each one canceled */
588 HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue, pPacket) {
589 pPacket->Status = QDF_STATUS_E_CANCELED;
590 }
591 HTC_PACKET_QUEUE_ITERATE_END;
592
593 do_recv_completion(pEndpoint, pPktQueue);
594 }
595
596 return status;
597 }
598
htc_flush_rx_hold_queue(HTC_TARGET * target,HTC_ENDPOINT * pEndpoint)599 void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
600 {
601 HTC_PACKET *pPacket;
602
603 LOCK_HTC_RX(target);
604
605 while (1) {
606 pPacket = htc_packet_dequeue(&pEndpoint->RxBufferHoldQueue);
607 if (!pPacket)
608 break;
609 UNLOCK_HTC_RX(target);
610 pPacket->Status = QDF_STATUS_E_CANCELED;
611 pPacket->ActualLength = 0;
612 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
613 ("Flushing RX packet:%pK, length:%d, ep:%d\n",
614 pPacket, pPacket->BufferLength,
615 pPacket->Endpoint));
616 /* give the packet back */
617 do_recv_completion_pkt(pEndpoint, pPacket);
618 LOCK_HTC_RX(target);
619 }
620
621 UNLOCK_HTC_RX(target);
622 }
623
htc_recv_init(HTC_TARGET * target)624 void htc_recv_init(HTC_TARGET *target)
625 {
626 /* Initialize ctrl_response_valid to block */
627 qdf_event_create(&target->ctrl_response_valid);
628 }
629
630 /* polling routine to wait for a control packet to be received */
htc_wait_recv_ctrl_message(HTC_TARGET * target)631 QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target)
632 {
633 /* int count = HTC_TARGET_MAX_RESPONSE_POLL; */
634
635 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCWaitCtrlMessageRecv\n"));
636
637 /* Wait for BMI request/response transaction to complete */
638 if (qdf_wait_single_event(&target->ctrl_response_valid,
639 (target->HTCInitInfo.htc_ready_timeout_ms))) {
640 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
641 ("Failed to receive control message\n"));
642 return QDF_STATUS_E_FAILURE;
643 }
644
645 LOCK_HTC_RX(target);
646 /* caller will clear this flag */
647 target->CtrlResponseProcessing = true;
648
649 UNLOCK_HTC_RX(target);
650
651 AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCWaitCtrlMessageRecv success\n"));
652 return QDF_STATUS_SUCCESS;
653 }
654
htc_process_trailer(HTC_TARGET * target,uint8_t * pBuffer,int Length,HTC_ENDPOINT_ID FromEndpoint)655 static A_STATUS htc_process_trailer(HTC_TARGET *target,
656 uint8_t *pBuffer,
657 int Length, HTC_ENDPOINT_ID FromEndpoint)
658 {
659 HTC_RECORD_HDR *pRecord;
660 uint8_t htc_rec_id;
661 uint8_t htc_rec_len;
662 uint8_t *pRecordBuf;
663 uint8_t *pOrigBuffer;
664 int origLength;
665 A_STATUS status;
666
667 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
668 ("+htc_process_trailer (length:%d)\n", Length));
669
670 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
671 AR_DEBUG_PRINTBUF(pBuffer, Length, "Recv Trailer");
672
673 pOrigBuffer = pBuffer;
674 origLength = Length;
675 status = A_OK;
676
677 while (Length > 0) {
678
679 if (Length < sizeof(HTC_RECORD_HDR)) {
680 status = A_EPROTO;
681 break;
682 }
683 /* these are byte aligned structs */
684 pRecord = (HTC_RECORD_HDR *) pBuffer;
685 Length -= sizeof(HTC_RECORD_HDR);
686 pBuffer += sizeof(HTC_RECORD_HDR);
687
688 htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH);
689 htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID);
690
691 if (htc_rec_len > Length) {
692 /* no room left in buffer for record */
693 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
694 ("invalid record length: %d (id:%d) buffer has: %d bytes left\n",
695 htc_rec_len, htc_rec_id, Length));
696 status = A_EPROTO;
697 break;
698 }
699 /* start of record follows the header */
700 pRecordBuf = pBuffer;
701
702 switch (htc_rec_id) {
703 case HTC_RECORD_CREDITS:
704 AR_DEBUG_ASSERT(htc_rec_len >=
705 sizeof(HTC_CREDIT_REPORT));
706 htc_process_credit_rpt(target,
707 (HTC_CREDIT_REPORT *) pRecordBuf,
708 htc_rec_len /
709 (sizeof(HTC_CREDIT_REPORT)),
710 FromEndpoint);
711 break;
712
713 #ifdef HIF_SDIO
714 case HTC_RECORD_LOOKAHEAD:
715 /* Process in HIF layer */
716 break;
717
718 case HTC_RECORD_LOOKAHEAD_BUNDLE:
719 /* Process in HIF layer */
720 break;
721 #endif /* HIF_SDIO */
722
723 default:
724 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
725 ("HTC unhandled record: id:%d length:%d\n",
726 htc_rec_id, htc_rec_len));
727 break;
728 }
729
730 if (A_FAILED(status)) {
731 break;
732 }
733
734 /* advance buffer past this record for next time around */
735 pBuffer += htc_rec_len;
736 Length -= htc_rec_len;
737 }
738
739 if (A_FAILED(status))
740 debug_dump_bytes(pOrigBuffer, origLength, "BAD Recv Trailer");
741
742 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer\n"));
743 return status;
744
745 }
746