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