1 /*
2 * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2023 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
21 #define ATH_MODULE_NAME hif
22 #include <qdf_types.h>
23 #include <qdf_status.h>
24 #include <qdf_timer.h>
25 #include <qdf_time.h>
26 #include <qdf_lock.h>
27 #include <qdf_mem.h>
28 #include <qdf_util.h>
29 #include <qdf_defer.h>
30 #include <qdf_atomic.h>
31 #include <qdf_nbuf.h>
32 #include <athdefs.h>
33 #include <qdf_net_types.h>
34 #include <a_types.h>
35 #include <athdefs.h>
36 #include <a_osapi.h>
37 #include <hif.h>
38 #include <htc_services.h>
39 #include <a_debug.h>
40 #include <htc_internal.h>
41 #include "hif_sdio_internal.h"
42 #include "transfer.h"
43
44 /**
45 * hif_dev_rw_completion_handler() - Completion routine
46 * for ALL HIF layer async I/O
47 * @ctx: hif send context
48 * @status: completion routine sync/async context
49 *
50 * Return: 0 for success and non-zero for failure
51 */
52
hif_dev_rw_completion_handler(void * ctx,QDF_STATUS status)53 QDF_STATUS hif_dev_rw_completion_handler(void *ctx, QDF_STATUS status)
54 {
55 QDF_STATUS (*txCompHandler)(void *, qdf_nbuf_t, uint32_t, uint32_t);
56 struct hif_sendContext *sctx = (struct hif_sendContext *)ctx;
57 struct hif_sdio_device *pdev = sctx->pDev;
58 unsigned int xfer_id = sctx->transferID;
59 uint32_t toeplitz_hash_result = 0;
60 qdf_nbuf_t buf = sctx->netbuf;
61
62 if (sctx->bNewAlloc)
63 qdf_mem_free(ctx);
64 else
65 qdf_nbuf_pull_head(buf, sctx->head_data_len);
66
67 txCompHandler = pdev->hif_callbacks.txCompletionHandler;
68 if (txCompHandler) {
69 txCompHandler(pdev->hif_callbacks.Context, buf,
70 xfer_id, toeplitz_hash_result);
71 }
72
73 return QDF_STATUS_SUCCESS;
74 }
75
76 /**
77 * hif_dev_send_buffer() - send buffer to sdio device
78 * @pdev: HIf device object
79 * @xfer_id: transfer id
80 * @pipe: ul/dl pipe
81 * @nbytes: no of bytes to transfer
82 * @buf: pointer to buffer
83 *
84 * Return: 0 for success and non-zero for failure
85 */
hif_dev_send_buffer(struct hif_sdio_device * pdev,uint32_t xfer_id,uint8_t pipe,uint32_t nbytes,qdf_nbuf_t buf)86 QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *pdev, uint32_t xfer_id,
87 uint8_t pipe, uint32_t nbytes, qdf_nbuf_t buf)
88 {
89 QDF_STATUS status;
90 unsigned char *pData;
91 struct hif_sendContext *sctx;
92 uint32_t request = hif_get_send_buffer_flags(pdev);
93 uint32_t padded_length;
94 unsigned long addr = 0;
95 int frag_count = 0, i, count, head_len;
96
97 if (hif_get_send_address(pdev, pipe, &addr)) {
98 hif_err("Invalid address map for pipe 0x%x", pipe);
99
100 return QDF_STATUS_E_INVAL;
101 }
102
103 padded_length = DEV_CALC_SEND_PADDED_LEN(pdev, nbytes);
104 A_ASSERT(padded_length - nbytes < HIF_DUMMY_SPACE_MASK + 1);
105
106 request |= ((padded_length - nbytes) << 16);
107
108 frag_count = qdf_nbuf_get_num_frags(buf);
109
110 if (frag_count > 1) {
111 /* Header data length should be total sending length.
112 * Subtract internal data length of netbuf
113 */
114 head_len = sizeof(struct hif_sendContext) +
115 (nbytes - qdf_nbuf_get_frag_len(buf, frag_count - 1));
116 } else {
117 /*
118 * | hif_sendContext | netbuf->data
119 */
120 head_len = sizeof(struct hif_sendContext);
121 }
122
123 /* Check whether head room is enough to save extra head data */
124 if ((head_len <= qdf_nbuf_headroom(buf)) &&
125 (qdf_nbuf_tailroom(buf) >= (padded_length - nbytes))) {
126 sctx = (struct hif_sendContext *)qdf_nbuf_push_head(buf,
127 head_len);
128 sctx->bNewAlloc = false;
129 } else {
130 sctx = (struct hif_sendContext *)qdf_mem_malloc(sizeof(*sctx) +
131 padded_length);
132 if (sctx)
133 sctx->bNewAlloc = true;
134 else
135 return QDF_STATUS_E_NOMEM;
136 }
137
138 sctx->netbuf = buf;
139 sctx->pDev = pdev;
140 sctx->transferID = xfer_id;
141 sctx->head_data_len = head_len;
142 /*
143 * Copy data to head part of netbuf or head of allocated buffer.
144 * if buffer is new allocated, the last buffer should be copied also.
145 * It assume last fragment is internal buffer of netbuf
146 * sometime total length of fragments larger than nbytes
147 */
148 pData = (unsigned char *)sctx + sizeof(struct hif_sendContext);
149 for (i = 0, count = sctx->bNewAlloc ? frag_count : frag_count - 1;
150 i < count;
151 i++) {
152 int frag_len = qdf_nbuf_get_frag_len(buf, i);
153 unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i);
154
155 if (frag_len > nbytes)
156 frag_len = nbytes;
157 memcpy(pData, frag_addr, frag_len);
158 pData += frag_len;
159 nbytes -= frag_len;
160 if (nbytes <= 0)
161 break;
162 }
163
164 /* Reset pData pointer and sctx out */
165 pData = (unsigned char *)sctx + sizeof(struct hif_sendContext);
166
167 status = hif_read_write(pdev->HIFDevice, addr, (char *)pData,
168 padded_length, request, (void *)sctx);
169
170 if (status == QDF_STATUS_E_PENDING) {
171 /*
172 * it will return QDF_STATUS_E_PENDING in native HIF
173 * implementation, which should be treated as successful
174 * result here.
175 */
176 status = QDF_STATUS_SUCCESS;
177 }
178
179 /* release buffer or move back data pointer when failed */
180 if (status != QDF_STATUS_SUCCESS) {
181 if (sctx->bNewAlloc)
182 qdf_mem_free(sctx);
183 else
184 qdf_nbuf_pull_head(buf, head_len);
185 }
186
187 return status;
188 }
189
190 /**
191 * hif_dev_alloc_and_prepare_rx_packets() - Allocate packets for recv frames.
192 * @pdev : HIF device object
193 * @look_aheads : Look ahead information on the frames
194 * @messages : Number of messages
195 * @queue : Queue to put the allocated frames
196 *
197 * Return : QDF_STATUS_SUCCESS on success else error value
198 */
hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device * pdev,uint32_t look_aheads[],int messages,HTC_PACKET_QUEUE * queue)199 QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev,
200 uint32_t look_aheads[],
201 int messages,
202 HTC_PACKET_QUEUE *queue)
203 {
204 int i, j;
205 bool no_recycle;
206 int num_messages;
207 HTC_PACKET *packet;
208 HTC_FRAME_HDR *hdr;
209 uint32_t full_length;
210 QDF_STATUS status = QDF_STATUS_SUCCESS;
211
212 /* lock RX while we assemble the packet buffers */
213 LOCK_HIF_DEV_RX(pdev);
214
215 for (i = 0; i < messages; i++) {
216 hdr = (HTC_FRAME_HDR *)&look_aheads[i];
217 if (hdr->EndpointID >= ENDPOINT_MAX) {
218 hif_err("Invalid Endpoint:%d", hdr->EndpointID);
219 status = QDF_STATUS_E_INVAL;
220 break;
221 }
222
223 if (hdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
224 hif_err("Payload length %d exceeds max HTC : %u",
225 hdr->PayloadLen,
226 (uint32_t)HTC_MAX_PAYLOAD_LENGTH);
227 status = QDF_STATUS_E_INVAL;
228 break;
229 }
230
231 if ((hdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
232 /* HTC header only indicates 1 message to fetch */
233 num_messages = 1;
234 } else {
235 /* HTC header indicates that every packet to follow
236 * has the same padded length so that it can
237 * be optimally fetched as a full bundle
238 */
239 num_messages = GET_RECV_BUNDLE_COUNT(hdr->Flags);
240 /* the count doesn't include the starter frame, just
241 * a count of frames to follow
242 */
243 num_messages++;
244
245 hif_info("HTC header : %u messages in bundle",
246 num_messages);
247 }
248
249 full_length = DEV_CALC_RECV_PADDED_LEN(pdev,
250 hdr->PayloadLen +
251 sizeof(HTC_FRAME_HDR));
252
253 /* get packet buffers for each message, if there was a
254 * bundle detected in the header,
255 * use pHdr as a template to fetch all packets in the bundle
256 */
257 for (j = 0; j < num_messages; j++) {
258 /* reset flag, any packets allocated using the
259 * RecvAlloc() API cannot be recycled on cleanup,
260 * they must be explicitly returned
261 */
262 no_recycle = false;
263 packet = hif_dev_alloc_rx_buffer(pdev);
264
265 if (!packet) {
266 /* No error, simply need to mark that
267 * we are waiting for buffers.
268 */
269 pdev->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
270 /* pDev->EpWaitingForBuffers = pEndpoint->Id; */
271 status = QDF_STATUS_E_RESOURCES;
272 break;
273 }
274 /* clear flags */
275 packet->PktInfo.AsRx.HTCRxFlags = 0;
276 packet->PktInfo.AsRx.IndicationFlags = 0;
277 packet->Status = QDF_STATUS_SUCCESS;
278
279 if (no_recycle) {
280 /* flag that these packets cannot be recycled,
281 * they have to be returned to the user
282 */
283 packet->PktInfo.AsRx.HTCRxFlags |=
284 HTC_RX_PKT_NO_RECYCLE;
285 }
286 /* add packet to queue (also incase we need to
287 * cleanup down below)
288 */
289 HTC_PACKET_ENQUEUE(queue, packet);
290
291 /* if (HTC_STOPPING(target)) {
292 * status = QDF_STATUS_E_CANCELED;
293 * break;
294 * }
295 */
296
297 /* make sure message can fit in the endpoint buffer */
298 if (full_length > packet->BufferLength) {
299 hif_err("Payload Length Error");
300 hif_err("header reports payload: %u(%u)",
301 hdr->PayloadLen,
302 full_length);
303 hif_err("endpoint buffer size: %d",
304 packet->BufferLength);
305 status = QDF_STATUS_E_INVAL;
306 break;
307 }
308
309 if (j > 0) {
310 /* for messages fetched in a bundle the expected
311 * lookahead is unknown as we are only using the
312 * lookahead of the first packet as a template
313 * of what to expect for lengths
314 */
315 packet->PktInfo.AsRx.HTCRxFlags |=
316 HTC_RX_PKT_REFRESH_HDR;
317 /* set it to something invalid */
318 packet->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
319 } else {
320 packet->PktInfo.AsRx.ExpectedHdr =
321 look_aheads[i];
322 }
323 /* set the amount of data to fetch */
324 packet->ActualLength =
325 hdr->PayloadLen + HTC_HDR_LENGTH;
326 if ((j == (num_messages - 1)) &&
327 ((hdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK))
328 packet->PktInfo.AsRx.HTCRxFlags |=
329 HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK;
330 packet->Endpoint = hdr->EndpointID;
331 packet->Completion = NULL;
332 }
333
334 if (QDF_IS_STATUS_ERROR(status))
335 break;
336 }
337
338 UNLOCK_HIF_DEV_RX(pdev);
339
340 /* for NO RESOURCE error, no need to flush data queue */
341 if (QDF_IS_STATUS_ERROR(status) &&
342 (status != QDF_STATUS_E_RESOURCES)) {
343 while (!HTC_QUEUE_EMPTY(queue)) {
344 qdf_nbuf_t netbuf;
345
346 packet = htc_packet_dequeue(queue);
347 if (!packet)
348 break;
349 netbuf = (qdf_nbuf_t)packet->pNetBufContext;
350 if (netbuf)
351 qdf_nbuf_free(netbuf);
352 }
353 }
354 if (status == QDF_STATUS_E_RESOURCES)
355 status = QDF_STATUS_SUCCESS;
356 return status;
357 }
358
359 /**
360 * hif_dev_process_trailer() - Process the receive frame trailer
361 * @pdev : HIF device object
362 * @buffer : The buffer containing the trailer
363 * @length : Length of the buffer
364 * @next_look_aheads : The lookahead that is next
365 * @num_look_aheads : Number of lookahead information
366 * @from_endpoint : The endpoint on which the trailer is received
367 */
hif_dev_process_trailer(struct hif_sdio_device * pdev,uint8_t * buffer,int length,uint32_t * next_look_aheads,int * num_look_aheads,HTC_ENDPOINT_ID from_endpoint)368 QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev,
369 uint8_t *buffer, int length,
370 uint32_t *next_look_aheads,
371 int *num_look_aheads,
372 HTC_ENDPOINT_ID from_endpoint)
373 {
374 int orig_length;
375 QDF_STATUS status;
376 uint8_t *record_buf;
377 uint8_t *orig_buffer;
378 HTC_RECORD_HDR *record;
379 HTC_LOOKAHEAD_REPORT *look_ahead;
380
381 hif_debug("length:%d", length);
382
383 orig_buffer = buffer;
384 orig_length = length;
385 status = QDF_STATUS_SUCCESS;
386
387 while (length > 0) {
388 if (length < sizeof(HTC_RECORD_HDR)) {
389 status = QDF_STATUS_E_PROTO;
390 break;
391 }
392 /* these are byte aligned structs */
393 record = (HTC_RECORD_HDR *)buffer;
394 length -= sizeof(HTC_RECORD_HDR);
395 buffer += sizeof(HTC_RECORD_HDR);
396
397 if (record->Length > length) {
398 /* no room left in buffer for record */
399 hif_err("Invalid record len: (%u, %u)",
400 record->Length,
401 record->RecordID);
402 hif_err("Buffer has %d bytes left", length);
403 status = QDF_STATUS_E_PROTO;
404 break;
405 }
406 /* start of record follows the header */
407 record_buf = buffer;
408
409 switch (record->RecordID) {
410 case HTC_RECORD_CREDITS:
411 /* Process in HTC, ignore here */
412 break;
413 case HTC_RECORD_LOOKAHEAD:
414 A_ASSERT(record->Length >= sizeof(*look_ahead));
415 look_ahead = (HTC_LOOKAHEAD_REPORT *)record_buf;
416 if ((look_ahead->PreValid ==
417 ((~look_ahead->PostValid) & 0xFF)) &&
418 next_look_aheads) {
419 hif_debug("Look_ahead Report");
420 hif_debug("Prevalid:0x%x, postvalid:0x%x",
421 look_ahead->PreValid,
422 look_ahead->PostValid);
423 hif_debug("From endpoint %d : %u",
424 from_endpoint,
425 look_ahead->LookAhead0);
426 /* look ahead bytes are valid, copy them over */
427 ((uint8_t *)(&next_look_aheads[0]))[0] =
428 look_ahead->LookAhead0;
429 ((uint8_t *)(&next_look_aheads[0]))[1] =
430 look_ahead->LookAhead1;
431 ((uint8_t *)(&next_look_aheads[0]))[2] =
432 look_ahead->LookAhead2;
433 ((uint8_t *)(&next_look_aheads[0]))[3] =
434 look_ahead->LookAhead3;
435
436 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
437 debug_dump_bytes((uint8_t *)
438 next_look_aheads, 4,
439 "Next Look Ahead");
440 }
441 /* just one normal lookahead */
442 if (num_look_aheads)
443 *num_look_aheads = 1;
444 }
445 break;
446 case HTC_RECORD_LOOKAHEAD_BUNDLE:
447 A_ASSERT(record->Length >=
448 sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
449 if ((record->Length >=
450 sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)) &&
451 next_look_aheads) {
452 HTC_BUNDLED_LOOKAHEAD_REPORT
453 *pBundledLookAheadRpt;
454 int i;
455
456 pBundledLookAheadRpt =
457 (HTC_BUNDLED_LOOKAHEAD_REPORT *)record_buf;
458
459 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
460 debug_dump_bytes(record_buf,
461 record->Length,
462 "Bundle look_ahead");
463 }
464
465 if ((record->Length /
466 (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)))
467 > HTC_MAX_MSG_PER_BUNDLE_RX) {
468 /* this should never happen, the target
469 * restricts the number of messages per
470 * bundle configured by the host
471 */
472 A_ASSERT(false);
473 status = QDF_STATUS_E_PROTO;
474 break;
475 }
476 for (i = 0;
477 i <
478 (int)(record->Length /
479 (sizeof
480 (HTC_BUNDLED_LOOKAHEAD_REPORT)));
481 i++) {
482 ((uint8_t *)(&next_look_aheads[i]))[0] =
483 pBundledLookAheadRpt->LookAhead0;
484 ((uint8_t *)(&next_look_aheads[i]))[1] =
485 pBundledLookAheadRpt->LookAhead1;
486 ((uint8_t *)(&next_look_aheads[i]))[2] =
487 pBundledLookAheadRpt->LookAhead2;
488 ((uint8_t *)(&next_look_aheads[i]))[3] =
489 pBundledLookAheadRpt->LookAhead3;
490 pBundledLookAheadRpt++;
491 }
492 if (num_look_aheads)
493 *num_look_aheads = i;
494 }
495 break;
496 default:
497 hif_err("HIF unhandled record: id:%u length:%u",
498 record->RecordID, record->Length);
499 break;
500 }
501
502 if (QDF_IS_STATUS_ERROR(status))
503 break;
504
505 /* advance buffer past this record for next time around */
506 buffer += record->Length;
507 length -= record->Length;
508 }
509
510 if (QDF_IS_STATUS_ERROR(status))
511 debug_dump_bytes(orig_buffer, orig_length,
512 "BAD Recv Trailer");
513
514 hif_debug("status = %d", status);
515
516 return status;
517 }
518
519 /* process a received message (i.e. strip off header,
520 * process any trailer data).
521 * note : locks must be released when this function is called
522 */
hif_dev_process_recv_header(struct hif_sdio_device * pdev,HTC_PACKET * packet,uint32_t * next_look_aheads,int * num_look_aheads)523 QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev,
524 HTC_PACKET *packet,
525 uint32_t *next_look_aheads,
526 int *num_look_aheads)
527 {
528 uint8_t temp;
529 uint8_t *buf;
530 QDF_STATUS status = QDF_STATUS_SUCCESS;
531 uint16_t payloadLen;
532 uint32_t look_ahead, actual_length;
533
534 buf = packet->pBuffer;
535 actual_length = packet->ActualLength;
536
537 if (num_look_aheads)
538 *num_look_aheads = 0;
539
540 AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader\n"));
541
542 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
543 AR_DEBUG_PRINTBUF(buf, packet->ActualLength, "HTC Recv PKT");
544
545 do {
546 /* note, we cannot assume the alignment of pBuffer,
547 * so we use the safe macros to
548 * retrieve 16 bit fields
549 */
550 payloadLen = HTC_GET_FIELD(buf, HTC_FRAME_HDR,
551 PAYLOADLEN);
552
553 ((uint8_t *)&look_ahead)[0] = buf[0];
554 ((uint8_t *)&look_ahead)[1] = buf[1];
555 ((uint8_t *)&look_ahead)[2] = buf[2];
556 ((uint8_t *)&look_ahead)[3] = buf[3];
557
558 if (packet->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
559 /* refresh expected hdr, since this was unknown
560 * at the time we grabbed the packets
561 * as part of a bundle
562 */
563 packet->PktInfo.AsRx.ExpectedHdr = look_ahead;
564 /* refresh actual length since we now have the
565 * real header
566 */
567 packet->ActualLength = payloadLen + HTC_HDR_LENGTH;
568
569 /* validate the actual header that was refreshed */
570 if (packet->ActualLength > packet->BufferLength) {
571 hif_err("Bundled RECV Look ahead: 0x%X",
572 look_ahead);
573 hif_err("Invalid HDR payload length(%d)",
574 payloadLen);
575 /* limit this to max buffer just to print out
576 * some of the buffer
577 */
578 packet->ActualLength =
579 min(packet->ActualLength,
580 packet->BufferLength);
581 status = QDF_STATUS_E_PROTO;
582 break;
583 }
584
585 if (packet->Endpoint
586 != HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID)) {
587 hif_err("Refreshed HDR EP (%d)",
588 HTC_GET_FIELD(buf, HTC_FRAME_HDR,
589 ENDPOINTID));
590 hif_err("Doesn't match expected EP (%d)",
591 packet->Endpoint);
592 status = QDF_STATUS_E_PROTO;
593 break;
594 }
595 }
596
597 if (look_ahead != packet->PktInfo.AsRx.ExpectedHdr) {
598 /* somehow the lookahead that gave us the full read
599 * length did not reflect the actual header
600 * in the pending message
601 */
602 hif_err("Lookahead mismatch!");
603 hif_err("pPkt:0x%lX flags:0x%X",
604 (unsigned long)packet,
605 packet->PktInfo.AsRx.HTCRxFlags);
606 hif_err("Look_ahead 0x%08X != 0x%08X",
607 look_ahead,
608 packet->PktInfo.AsRx.ExpectedHdr);
609 #ifdef ATH_DEBUG_MODULE
610 debug_dump_bytes((uint8_t *)&packet->PktInfo.AsRx.
611 ExpectedHdr, 4,
612 "Expected Message look_ahead");
613 debug_dump_bytes(buf, sizeof(HTC_FRAME_HDR),
614 "Current Frame Header");
615 #ifdef HTC_CAPTURE_LAST_FRAME
616 debug_dump_bytes((uint8_t *)&target->LastFrameHdr,
617 sizeof(HTC_FRAME_HDR),
618 "Last Frame Header");
619 if (target->LastTrailerLength != 0)
620 debug_dump_bytes(target->LastTrailer,
621 target->LastTrailerLength,
622 "Last trailer");
623 #endif
624 #endif
625 status = QDF_STATUS_E_PROTO;
626 break;
627 }
628
629 /* get flags */
630 temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, FLAGS);
631
632 if (temp & HTC_FLAGS_RECV_TRAILER) {
633 /* this packet has a trailer */
634
635 /* extract the trailer length in control byte 0 */
636 temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, CONTROLBYTES0);
637
638 if ((temp < sizeof(HTC_RECORD_HDR)) ||
639 (temp > payloadLen)) {
640 hif_err("Invalid header");
641 hif_err("Payloadlength should be :%d",
642 payloadLen);
643 hif_err("But control bytes is :%d)", temp);
644 status = QDF_STATUS_E_PROTO;
645 break;
646 }
647
648 if (packet->PktInfo.AsRx.
649 HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
650 /* this packet was fetched as part of an HTC
651 * bundle as the lookahead is not valid.
652 * Next packet may have already been fetched as
653 * part of the bundle
654 */
655 next_look_aheads = NULL;
656 num_look_aheads = NULL;
657 }
658
659 /* process trailer data that follows HDR and
660 * application payload
661 */
662 status =
663 hif_dev_process_trailer(pdev,
664 (buf + HTC_HDR_LENGTH +
665 payloadLen - temp),
666 temp,
667 next_look_aheads,
668 num_look_aheads,
669 packet->Endpoint);
670
671 if (QDF_IS_STATUS_ERROR(status))
672 break;
673 }
674 } while (false);
675
676 if (QDF_IS_STATUS_ERROR(status)) {
677 /* dump the whole packet */
678 debug_dump_bytes(buf, packet->ActualLength,
679 "BAD HTC Recv PKT");
680 } else {
681 if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
682 if (packet->ActualLength > 0) {
683 AR_DEBUG_PRINTBUF(packet->pBuffer,
684 packet->ActualLength,
685 "HTC - Application Msg");
686 }
687 }
688 }
689 AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
690 ("-hif_dev_process_recv_header\n"));
691 return status;
692 }
693
694 /**
695 * hif_dev_free_recv_pkt_queue() - Free the allocated recv packets in the queue
696 * @recv_pkt_queue : The queue that contains the packets to be queued
697 *
698 * Return : NONE
699 */
hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE * recv_pkt_queue)700 void hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE *recv_pkt_queue)
701 {
702 HTC_PACKET *packet;
703 qdf_nbuf_t netbuf;
704
705 while (!HTC_QUEUE_EMPTY(recv_pkt_queue)) {
706 packet = htc_packet_dequeue(recv_pkt_queue);
707 if (!packet)
708 break;
709 netbuf = (qdf_nbuf_t)packet->pNetBufContext;
710 if (netbuf)
711 qdf_nbuf_free(netbuf);
712 }
713 }
714