xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/usb/usbdrv.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #define ATH_MODULE_NAME hif
20 #include "a_debug.h"
21 #include "hif_usb_internal.h"
22 #include "if_usb.h"
23 #include "cds_api.h"
24 #include "hif_debug.h"
25 
26 #define IS_BULK_EP(attr) (((attr) & 3) == 0x02)
27 #define IS_INT_EP(attr) (((attr) & 3) == 0x03)
28 #define IS_ISOC_EP(attr) (((attr) & 3) == 0x01)
29 #define IS_DIR_IN(addr) ((addr) & 0x80)
30 
31 #define IS_FW_CRASH_DUMP(x)(((x == FW_ASSERT_PATTERN) || \
32 				(x == FW_REG_PATTERN) || \
33 				((x & FW_RAMDUMP_PATTERN_MASK) ==  \
34 						FW_RAMDUMP_PATTERN)) ? 1 : 0)
35 
36 static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
37 					int buffer_length);
38 static void usb_hif_post_recv_bundle_transfers
39 						(struct HIF_USB_PIPE *recv_pipe,
40 						int buffer_length);
41 static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context);
42 
43 
44 /**
45  * usb_hif_free_urb_to_pipe() - add urb back to urb list of a pipe
46  * @pipe: pointer to struct HIF_USB_PIPE
47  * @urb_context: pointer to struct HIF_URB_CONTEXT
48  *
49  * Return: none
50  */
51 static void usb_hif_free_urb_to_pipe(struct HIF_USB_PIPE *pipe,
52 					struct HIF_URB_CONTEXT *urb_context)
53 {
54 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
55 	pipe->urb_cnt++;
56 	DL_ListAdd(&pipe->urb_list_head, &urb_context->link);
57 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
58 }
59 
60 /**
61  * usb_hif_alloc_urb_from_pipe() - remove urb back from urb list of a pipe
62  * @pipe: pointer to struct HIF_USB_PIPE
63  *
64  * Return: struct HIF_URB_CONTEXT urb context removed from the urb list
65  */
66 struct HIF_URB_CONTEXT *usb_hif_alloc_urb_from_pipe(struct HIF_USB_PIPE *pipe)
67 {
68 	struct HIF_URB_CONTEXT *urb_context = NULL;
69 	DL_LIST *item;
70 
71 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
72 	item = dl_list_remove_item_from_head(&pipe->urb_list_head);
73 	if (item) {
74 		urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
75 						  link);
76 		pipe->urb_cnt--;
77 	}
78 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
79 
80 	return urb_context;
81 }
82 
83 /**
84  * usb_hif_dequeue_pending_transfer() - remove urb from pending xfer list
85  * @pipe: pointer to struct HIF_USB_PIPE
86  *
87  * Return: struct HIF_URB_CONTEXT urb context removed from the pending xfer list
88  */
89 static struct HIF_URB_CONTEXT *usb_hif_dequeue_pending_transfer
90 						(struct HIF_USB_PIPE *pipe)
91 {
92 	struct HIF_URB_CONTEXT *urb_context = NULL;
93 	DL_LIST *item;
94 
95 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
96 	item = dl_list_remove_item_from_head(&pipe->urb_pending_list);
97 	if (item)
98 		urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
99 						  link);
100 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
101 
102 	return urb_context;
103 }
104 
105 /**
106  * usb_hif_enqueue_pending_transfer() - add urb to pending xfer list
107  * @pipe: pointer to struct HIF_USB_PIPE
108  * @urb_context: pointer to struct HIF_URB_CONTEXT to be added to the xfer list
109  *
110  * Return: none
111  */
112 void usb_hif_enqueue_pending_transfer(struct HIF_USB_PIPE *pipe,
113 					struct HIF_URB_CONTEXT *urb_context)
114 {
115 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
116 	dl_list_insert_tail(&pipe->urb_pending_list, &urb_context->link);
117 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
118 }
119 
120 
121 /**
122  * usb_hif_remove_pending_transfer() - remove urb from its own list
123  * @urb_context: pointer to struct HIF_URB_CONTEXT to be removed
124  *
125  * Return: none
126  */
127 void
128 usb_hif_remove_pending_transfer(struct HIF_URB_CONTEXT *urb_context)
129 {
130 	qdf_spin_lock_irqsave(&urb_context->pipe->device->cs_lock);
131 	dl_list_remove(&urb_context->link);
132 	qdf_spin_unlock_irqrestore(&urb_context->pipe->device->cs_lock);
133 }
134 
135 /**
136  * usb_hif_alloc_pipe_resources() - allocate urb_cnt urbs to a HIF pipe
137  * @pipe: pointer to struct HIF_USB_PIPE to which resources will be allocated
138  * @urb_cnt: number of urbs to be added to the HIF pipe
139  *
140  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
141  */
142 static QDF_STATUS usb_hif_alloc_pipe_resources
143 					(struct HIF_USB_PIPE *pipe, int urb_cnt)
144 {
145 	QDF_STATUS status = QDF_STATUS_SUCCESS;
146 	int i;
147 	struct HIF_URB_CONTEXT *urb_context;
148 
149 	DL_LIST_INIT(&pipe->urb_list_head);
150 	DL_LIST_INIT(&pipe->urb_pending_list);
151 
152 	for (i = 0; i < urb_cnt; i++) {
153 		urb_context = qdf_mem_malloc(sizeof(*urb_context));
154 		if (!urb_context) {
155 			status = QDF_STATUS_E_NOMEM;
156 			break;
157 		}
158 		urb_context->pipe = pipe;
159 		urb_context->urb = usb_alloc_urb(0, GFP_KERNEL);
160 
161 		if (!urb_context->urb) {
162 			status = QDF_STATUS_E_NOMEM;
163 			qdf_mem_free(urb_context);
164 			hif_err("urb_context->urb is null");
165 			break;
166 		}
167 
168 		/* note we are only allocate the urb contexts here, the actual
169 		 * URB is
170 		 * allocated from the kernel as needed to do a transaction
171 		 */
172 		pipe->urb_alloc++;
173 
174 		usb_hif_free_urb_to_pipe(pipe, urb_context);
175 	}
176 
177 	hif_debug("athusb: alloc resources lpipe:%d hpipe:0x%X urbs:%d",
178 		 pipe->logical_pipe_num,
179 		 pipe->usb_pipe_handle,
180 		 pipe->urb_alloc);
181 	return status;
182 }
183 
184 /**
185  * usb_hif_free_pipe_resources() - free urb resources allocated to a HIF pipe
186  * @pipe: pointer to struct HIF_USB_PIPE
187  *
188  * Return: none
189  */
190 static void usb_hif_free_pipe_resources(struct HIF_USB_PIPE *pipe)
191 {
192 	struct HIF_URB_CONTEXT *urb_context;
193 
194 	if (!pipe->device) {
195 		/* nothing allocated for this pipe */
196 		hif_err("pipe->device is null");
197 		return;
198 	}
199 
200 	hif_info("athusb: free resources lpipe:%d hpipe:0x%X urbs:%d avail:%d",
201 			 pipe->logical_pipe_num,
202 			 pipe->usb_pipe_handle, pipe->urb_alloc,
203 			 pipe->urb_cnt);
204 
205 	if (pipe->urb_alloc != pipe->urb_cnt) {
206 		hif_err("athusb: urb leak! lpipe:%d hpipe:0x%X urbs:%d avail:%d",
207 			 pipe->logical_pipe_num,
208 			 pipe->usb_pipe_handle, pipe->urb_alloc,
209 			 pipe->urb_cnt);
210 	}
211 
212 	while (true) {
213 		urb_context = usb_hif_alloc_urb_from_pipe(pipe);
214 		if (!urb_context)
215 			break;
216 
217 		if (urb_context->buf) {
218 			qdf_nbuf_free(urb_context->buf);
219 			urb_context->buf = NULL;
220 		}
221 
222 		usb_free_urb(urb_context->urb);
223 		urb_context->urb = NULL;
224 		qdf_mem_free(urb_context);
225 	}
226 
227 }
228 
229 #ifdef QCN7605_SUPPORT
230 /**
231  * usb_hif_get_logical_pipe_num() - get pipe number for a particular enpoint
232  * @device: pointer to HIF_DEVICE_USB structure
233  * @ep_address: endpoint address
234  * @urb_count: number of urb resources to be allocated to the pipe
235  *
236  * Return: uint8_t pipe number corresponding to ep_address
237  */
238 static uint8_t usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB *device,
239 					    uint8_t ep_address,
240 					    int *urb_count)
241 {
242 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
243 
244 	switch (ep_address) {
245 	case USB_EP_ADDR_APP_CTRL_IN:
246 		pipe_num = HIF_RX_CTRL_PIPE;
247 		*urb_count = RX_URB_COUNT;
248 		break;
249 	case USB_EP_ADDR_APP_DATA_IN:
250 		pipe_num = HIF_RX_DATA_PIPE;
251 		*urb_count = RX_URB_COUNT;
252 		break;
253 		break;
254 	case USB_EP_ADDR_APP_CTRL_OUT:
255 		pipe_num = HIF_TX_CTRL_PIPE;
256 		*urb_count = TX_URB_COUNT;
257 		break;
258 	case USB_EP_ADDR_APP_DATA_OUT:
259 		pipe_num = HIF_TX_DATA_LP_PIPE;
260 		*urb_count = TX_URB_COUNT;
261 		break;
262 	default:
263 		/* note: there may be endpoints not currently used */
264 		break;
265 	}
266 
267 	return pipe_num;
268 }
269 #else
270 /**
271  * usb_hif_get_logical_pipe_num() - get pipe number for a particular enpoint
272  * @device: pointer to HIF_DEVICE_USB structure
273  * @ep_address: endpoint address
274  * @urb_count: number of urb resources to be allocated to the pipe
275  *
276  * Return: uint8_t pipe number corresponding to ep_address
277  */
278 static uint8_t usb_hif_get_logical_pipe_num
279 					(struct HIF_DEVICE_USB *device,
280 					uint8_t ep_address,
281 					int *urb_count)
282 {
283 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
284 
285 	switch (ep_address) {
286 	case USB_EP_ADDR_APP_CTRL_IN:
287 		pipe_num = HIF_RX_CTRL_PIPE;
288 		*urb_count = RX_URB_COUNT;
289 		break;
290 	case USB_EP_ADDR_APP_DATA_IN:
291 		pipe_num = HIF_RX_DATA_PIPE;
292 		*urb_count = RX_URB_COUNT;
293 		break;
294 	case USB_EP_ADDR_APP_INT_IN:
295 		pipe_num = HIF_RX_INT_PIPE;
296 		*urb_count = RX_URB_COUNT;
297 		break;
298 	case USB_EP_ADDR_APP_DATA2_IN:
299 		pipe_num = HIF_RX_DATA2_PIPE;
300 		*urb_count = RX_URB_COUNT;
301 		break;
302 	case USB_EP_ADDR_APP_CTRL_OUT:
303 		pipe_num = HIF_TX_CTRL_PIPE;
304 		*urb_count = TX_URB_COUNT;
305 		break;
306 	case USB_EP_ADDR_APP_DATA_LP_OUT:
307 		pipe_num = HIF_TX_DATA_LP_PIPE;
308 		*urb_count = TX_URB_COUNT;
309 		break;
310 	case USB_EP_ADDR_APP_DATA_MP_OUT:
311 		pipe_num = HIF_TX_DATA_MP_PIPE;
312 		*urb_count = TX_URB_COUNT;
313 		break;
314 	case USB_EP_ADDR_APP_DATA_HP_OUT:
315 		pipe_num = HIF_TX_DATA_HP_PIPE;
316 		*urb_count = TX_URB_COUNT;
317 		break;
318 	default:
319 		/* note: there may be endpoints not currently used */
320 		break;
321 	}
322 
323 	return pipe_num;
324 }
325 #endif /* QCN7605_SUPPORT */
326 
327 /**
328  * usb_hif_get_logical_pipe_num() - setup urb resources for all pipes
329  * @device: pointer to HIF_DEVICE_USB structure
330  *
331  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
332  */
333 QDF_STATUS usb_hif_setup_pipe_resources(struct HIF_DEVICE_USB *device)
334 {
335 	struct usb_interface *interface = device->interface;
336 	struct usb_host_interface *iface_desc = interface->cur_altsetting;
337 	struct usb_endpoint_descriptor *endpoint;
338 	int i;
339 	int urbcount;
340 	QDF_STATUS status = QDF_STATUS_SUCCESS;
341 	struct HIF_USB_PIPE *pipe;
342 	uint8_t pipe_num;
343 
344 	/* walk decriptors and setup pipes */
345 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
346 		endpoint = &iface_desc->endpoint[i].desc;
347 
348 		if (IS_BULK_EP(endpoint->bmAttributes)) {
349 			hif_debug("%s Bulk Ep:0x%2.2X maxpktsz:%d",
350 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
351 								"RX" : "TX",
352 				 endpoint->bEndpointAddress,
353 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize));
354 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
355 			hif_debug("%s Int Ep:0x%2.2X maxpktsz:%d interval:%d",
356 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
357 								"RX" : "TX",
358 				 endpoint->bEndpointAddress,
359 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize),
360 				 endpoint->bInterval);
361 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
362 			/* TODO for ISO */
363 			hif_debug("%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d",
364 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
365 								"RX" : "TX",
366 				 endpoint->bEndpointAddress,
367 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize),
368 				 endpoint->bInterval);
369 		}
370 		urbcount = 0;
371 
372 		pipe_num = usb_hif_get_logical_pipe_num(device,
373 						endpoint->bEndpointAddress,
374 						&urbcount);
375 		if (HIF_USB_PIPE_INVALID == pipe_num)
376 			continue;
377 
378 		pipe = &device->pipes[pipe_num];
379 		if (pipe->device) {
380 			/*pipe was already setup */
381 			continue;
382 		}
383 
384 		pipe->device = device;
385 		pipe->logical_pipe_num = pipe_num;
386 		pipe->ep_address = endpoint->bEndpointAddress;
387 		pipe->max_packet_size =
388 			qdf_le16_to_cpu(endpoint->wMaxPacketSize);
389 
390 		if (IS_BULK_EP(endpoint->bmAttributes)) {
391 			if (IS_DIR_IN(pipe->ep_address)) {
392 				pipe->usb_pipe_handle =
393 					usb_rcvbulkpipe(device->udev,
394 							pipe->ep_address);
395 			} else {
396 				pipe->usb_pipe_handle =
397 					usb_sndbulkpipe(device->udev,
398 						pipe->ep_address);
399 			}
400 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
401 			if (IS_DIR_IN(pipe->ep_address)) {
402 				pipe->usb_pipe_handle =
403 					usb_rcvintpipe(device->udev,
404 						pipe->ep_address);
405 			} else {
406 				pipe->usb_pipe_handle =
407 					usb_sndintpipe(device->udev,
408 						pipe->ep_address);
409 			}
410 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
411 			/* TODO for ISO */
412 			if (IS_DIR_IN(pipe->ep_address)) {
413 				pipe->usb_pipe_handle =
414 					usb_rcvisocpipe(device->udev,
415 						pipe->ep_address);
416 			} else {
417 				pipe->usb_pipe_handle =
418 					usb_sndisocpipe(device->udev,
419 						pipe->ep_address);
420 			}
421 		}
422 		pipe->ep_desc = endpoint;
423 
424 		if (!IS_DIR_IN(pipe->ep_address))
425 			pipe->flags |= HIF_USB_PIPE_FLAG_TX;
426 
427 		status = usb_hif_alloc_pipe_resources(pipe, urbcount);
428 
429 		if (!QDF_IS_STATUS_SUCCESS(status))
430 			break;
431 
432 	}
433 
434 	return status;
435 }
436 
437 
438 /**
439  * usb_hif_cleanup_pipe_resources() - free urb resources for all pipes
440  * @device: pointer to HIF_DEVICE_USB structure
441  *
442  * Return: none
443  */
444 void usb_hif_cleanup_pipe_resources(struct HIF_DEVICE_USB *device)
445 {
446 	int i;
447 
448 	for (i = 0; i < HIF_USB_PIPE_MAX; i++)
449 		usb_hif_free_pipe_resources(&device->pipes[i]);
450 }
451 
452 /**
453  * usb_hif_flush_pending_transfers() - kill pending urbs for a pipe
454  * @pipe: pointer to struct HIF_USB_PIPE structure
455  *
456  * Return: none
457  */
458 static void usb_hif_flush_pending_transfers(struct HIF_USB_PIPE *pipe)
459 {
460 	struct HIF_URB_CONTEXT *urb_context;
461 
462 	hif_info("+ pipe: %d", pipe->logical_pipe_num);
463 
464 	while (1) {
465 		urb_context = usb_hif_dequeue_pending_transfer(pipe);
466 		if (!urb_context) {
467 			hif_warn("urb_context is NULL");
468 			break;
469 		}
470 		hif_info("pending urb ctxt: 0x%pK", urb_context);
471 		if (urb_context->urb) {
472 			hif_info("killing urb: 0x%pK", urb_context->urb);
473 			/* killing the URB will cause the completion routines to
474 			 * run
475 			 */
476 			usb_kill_urb(urb_context->urb);
477 		}
478 	}
479 	hif_info("-");
480 }
481 
482 /**
483  * usb_hif_flush_all() - flush pending transfers for all pipes for a usb bus
484  * @device: pointer to HIF_DEVICE_USB structure
485  *
486  * Return: none
487  */
488 void usb_hif_flush_all(struct HIF_DEVICE_USB *device)
489 {
490 	int i;
491 	struct HIF_USB_PIPE *pipe;
492 
493 	hif_info("+");
494 
495 	for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
496 		if (device->pipes[i].device) {
497 			usb_hif_flush_pending_transfers(&device->pipes[i]);
498 			pipe = &device->pipes[i];
499 
500 		HIF_USB_FLUSH_WORK(pipe);
501 		}
502 	}
503 
504 	hif_info("-");
505 }
506 
507 /**
508  * usb_hif_cleanup_recv_urb() - cleanup recv urb
509  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
510  *
511  * Return: none
512  */
513 static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context)
514 {
515 
516 	if (urb_context->buf) {
517 		qdf_nbuf_free(urb_context->buf);
518 		urb_context->buf = NULL;
519 	}
520 
521 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
522 }
523 
524 /**
525  * usb_hif_cleanup_transmit_urb() - cleanup transmit urb
526  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
527  *
528  * Return: none
529  */
530 void usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT *urb_context)
531 {
532 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
533 }
534 
535 /**
536  * usb_hif_usb_recv_prestart_complete() - completion routine for prestart rx urb
537  * @urb: urb for which the completion routine is being called
538  *
539  * Return: none
540  */
541 static void usb_hif_usb_recv_prestart_complete
542 							(struct urb *urb)
543 {
544 	struct HIF_URB_CONTEXT *urb_context =
545 					(struct HIF_URB_CONTEXT *) urb->context;
546 	QDF_STATUS status = QDF_STATUS_SUCCESS;
547 	qdf_nbuf_t buf = NULL;
548 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
549 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
550 
551 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
552 		pipe->logical_pipe_num,
553 		urb->status, urb->actual_length,
554 		urb);
555 
556 	/* this urb is not pending anymore */
557 	usb_hif_remove_pending_transfer(urb_context);
558 	do {
559 		if (urb->status != 0) {
560 			status = A_ECOMM;
561 			switch (urb->status) {
562 			case -ECONNRESET:
563 			case -ENOENT:
564 			case -ESHUTDOWN:
565 				/* NOTE: no need to spew these errors when
566 				 * device is removed
567 				 * or urb is killed due to driver shutdown
568 				 */
569 				status = A_ECANCELED;
570 				break;
571 			default:
572 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
573 					pipe->logical_pipe_num,
574 					pipe->ep_address,
575 					urb->status);
576 				break;
577 			}
578 			break;
579 		}
580 		if (urb->actual_length == 0)
581 			break;
582 		buf = urb_context->buf;
583 		/* we are going to pass it up */
584 		urb_context->buf = NULL;
585 		qdf_nbuf_put_tail(buf, urb->actual_length);
586 
587 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
588 			uint8_t *data;
589 			uint32_t len;
590 
591 			qdf_nbuf_peek_header(buf, &data, &len);
592 			debug_dump_bytes(data, len, "hif recv data");
593 		}
594 		/* note: queue implements a lock */
595 		skb_queue_tail(&pipe->io_comp_queue, buf);
596 
597 		HIF_USB_SCHEDULE_WORK(pipe);
598 	} while (false);
599 
600 	usb_hif_cleanup_recv_urb(urb_context);
601 
602 	/* Prestart URBs runs out and now start working receive pipe. */
603 	qdf_spin_lock_irqsave(&pipe->device->rx_prestart_lock);
604 	if ((--pipe->urb_prestart_cnt == 0) && !sc->suspend_state)
605 		usb_hif_start_recv_pipes(pipe->device);
606 	qdf_spin_unlock_irqrestore(&pipe->device->rx_prestart_lock);
607 
608 	hif_debug("-");
609 }
610 
611 /**
612  * usb_hif_usb_recv_complete() - completion routine for rx urb
613  * @urb: urb for which the completion routine is being called
614  *
615  * Return: none
616  */
617 static void usb_hif_usb_recv_complete(struct urb *urb)
618 {
619 	struct HIF_URB_CONTEXT *urb_context =
620 					(struct HIF_URB_CONTEXT *) urb->context;
621 	QDF_STATUS status = QDF_STATUS_SUCCESS;
622 	qdf_nbuf_t buf = NULL;
623 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
624 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
625 
626 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
627 		pipe->logical_pipe_num,
628 		urb->status, urb->actual_length,
629 		urb);
630 
631 	/* this urb is not pending anymore */
632 	usb_hif_remove_pending_transfer(urb_context);
633 
634 	do {
635 
636 		if (urb->status != 0) {
637 			status = A_ECOMM;
638 			switch (urb->status) {
639 #ifdef RX_SG_SUPPORT
640 			case -EOVERFLOW:
641 				urb->actual_length = HIF_USB_RX_BUFFER_SIZE;
642 				status = QDF_STATUS_SUCCESS;
643 				break;
644 #endif
645 			case -ECONNRESET:
646 			case -ENOENT:
647 			case -ESHUTDOWN:
648 				/* NOTE: no need to spew these errors when
649 				 * device is removed
650 				 * or urb is killed due to driver shutdown
651 				 */
652 				status = A_ECANCELED;
653 				break;
654 			default:
655 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
656 					pipe->logical_pipe_num,
657 					pipe->ep_address,
658 					urb->status);
659 				break;
660 			}
661 			break;
662 		}
663 		if (urb->actual_length == 0)
664 			break;
665 		buf = urb_context->buf;
666 		/* we are going to pass it up */
667 		urb_context->buf = NULL;
668 		qdf_nbuf_put_tail(buf, urb->actual_length);
669 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
670 			uint8_t *data;
671 			uint32_t len;
672 
673 			qdf_nbuf_peek_header(buf, &data, &len);
674 			debug_dump_bytes(data, len, "hif recv data");
675 		}
676 		/* note: queue implements a lock */
677 		skb_queue_tail(&pipe->io_comp_queue, buf);
678 
679 		if (pipe->device->htc_callbacks.update_bundle_stats)
680 			pipe->device->htc_callbacks.update_bundle_stats
681 				(pipe->device->htc_callbacks.Context, 1);
682 
683 		HIF_USB_SCHEDULE_WORK(pipe);
684 	} while (false);
685 
686 	usb_hif_cleanup_recv_urb(urb_context);
687 
688 	/* Only re-submit URB when STATUS is success and HIF is not at the
689 	 * suspend state.
690 	 */
691 	if (QDF_IS_STATUS_SUCCESS(status) && !sc->suspend_state) {
692 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
693 			/* our free urbs are piling up, post more transfers */
694 			usb_hif_post_recv_transfers(pipe,
695 						HIF_USB_RX_BUFFER_SIZE);
696 		}
697 	} else {
698 		hif_err("pipe: %d, fail to post URB: status: %d suspend: %d",
699 			pipe->logical_pipe_num,
700 			urb->status,
701 			sc->suspend_state);
702 	}
703 
704 	hif_debug("-");
705 }
706 
707 /**
708  * usb_hif_usb_recv_bundle_complete() - completion routine for rx bundling urb
709  * @urb: urb for which the completion routine is being called
710  *
711  * Return: none
712  */
713 static void usb_hif_usb_recv_bundle_complete(struct urb *urb)
714 {
715 	struct HIF_URB_CONTEXT *urb_context =
716 					(struct HIF_URB_CONTEXT *) urb->context;
717 	QDF_STATUS status = QDF_STATUS_SUCCESS;
718 	qdf_nbuf_t buf = NULL;
719 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
720 	uint8_t *netdata, *netdata_new;
721 	uint32_t netlen, netlen_new;
722 	HTC_FRAME_HDR *HtcHdr;
723 	uint16_t payloadLen;
724 	qdf_nbuf_t new_skb = NULL;
725 	uint8_t no_of_pkt_in_bundle;
726 
727 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
728 		 pipe->logical_pipe_num,
729 		 urb->status, urb->actual_length,
730 		 urb);
731 
732 	/* this urb is not pending anymore */
733 	usb_hif_remove_pending_transfer(urb_context);
734 
735 	do {
736 
737 		if (urb->status != 0) {
738 			status = A_ECOMM;
739 			switch (urb->status) {
740 			case -ECONNRESET:
741 			case -ENOENT:
742 			case -ESHUTDOWN:
743 				/* NOTE: no need to spew these errors when
744 				 * device is removed
745 				 * or urb is killed due to driver shutdown
746 				 */
747 				status = A_ECANCELED;
748 				break;
749 			default:
750 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
751 					pipe->logical_pipe_num,
752 					pipe->ep_address,
753 					urb->status);
754 				break;
755 			}
756 			break;
757 		}
758 		if (urb->actual_length == 0)
759 			break;
760 		buf = urb_context->buf;
761 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
762 			uint8_t *data;
763 			uint32_t len;
764 
765 			qdf_nbuf_peek_header(buf, &data, &len);
766 			debug_dump_bytes(data, len, "hif recv data");
767 		}
768 
769 		qdf_nbuf_peek_header(buf, &netdata, &netlen);
770 		netlen = urb->actual_length;
771 		no_of_pkt_in_bundle = 0;
772 
773 		do {
774 			uint16_t frame_len;
775 
776 			if (IS_FW_CRASH_DUMP(*(uint32_t *) netdata))
777 				frame_len = netlen;
778 			else {
779 				/* Hack into HTC header for bundle processing */
780 				HtcHdr = (HTC_FRAME_HDR *) netdata;
781 				if (HtcHdr->EndpointID >= ENDPOINT_MAX) {
782 					hif_err("athusb: Rx: invalid EndpointID=%d",
783 						HtcHdr->EndpointID);
784 					break;
785 				}
786 
787 				payloadLen = HtcHdr->PayloadLen;
788 				payloadLen = qdf_le16_to_cpu(payloadLen);
789 
790 				if (payloadLen > HIF_USB_RX_BUFFER_SIZE) {
791 					hif_err("athusb: payloadLen too long %u",
792 						payloadLen);
793 					break;
794 				}
795 				frame_len = (HTC_HDR_LENGTH + payloadLen);
796 			}
797 
798 			if (netlen < frame_len) {
799 				hif_err("athusb: subframe length %d not fitted into bundle packet length %d"
800 					, netlen, frame_len);
801 				break;
802 			}
803 
804 			/* allocate a new skb and copy */
805 			new_skb =
806 				qdf_nbuf_alloc(NULL, frame_len, 0, 4, false);
807 			if (!new_skb) {
808 				hif_err("athusb: allocate skb (len=%u) failed"
809 						, frame_len);
810 				break;
811 			}
812 
813 			qdf_nbuf_peek_header(new_skb, &netdata_new,
814 						&netlen_new);
815 			qdf_mem_copy(netdata_new, netdata, frame_len);
816 			qdf_nbuf_put_tail(new_skb, frame_len);
817 			skb_queue_tail(&pipe->io_comp_queue, new_skb);
818 			new_skb = NULL;
819 			netdata += frame_len;
820 			netlen -= frame_len;
821 			no_of_pkt_in_bundle++;
822 		} while (netlen);
823 
824 		if (pipe->device->htc_callbacks.update_bundle_stats)
825 			pipe->device->htc_callbacks.update_bundle_stats
826 				(pipe->device->htc_callbacks.Context,
827 				 no_of_pkt_in_bundle);
828 
829 		HIF_USB_SCHEDULE_WORK(pipe);
830 	} while (false);
831 
832 	if (!urb_context->buf)
833 		hif_err("athusb: buffer in urb_context is NULL");
834 
835 	/* reset urb_context->buf ==> seems not necessary */
836 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
837 
838 	if (QDF_IS_STATUS_SUCCESS(status)) {
839 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
840 			/* our free urbs are piling up, post more transfers */
841 			usb_hif_post_recv_bundle_transfers(pipe,
842 					pipe->device->rx_bundle_buf_len);
843 		}
844 	}
845 
846 	hif_debug("-");
847 }
848 
849 /**
850  * usb_hif_post_recv_prestart_transfers() - post prestart recv urbs for a pipe
851  * @recv_pipe: rx data pipe
852  * @prestart_urb: number of prestart recv urbs to be posted
853  *
854  * Return: none
855  */
856 static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe,
857 						int prestart_urb)
858 {
859 	struct HIF_URB_CONTEXT *urb_context;
860 	uint8_t *data;
861 	uint32_t len;
862 	struct urb *urb;
863 	int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE;
864 
865 	hif_info("+");
866 
867 	qdf_spin_lock_irqsave(&recv_pipe->device->rx_prestart_lock);
868 	for (i = 0; i < prestart_urb; i++) {
869 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
870 		if (!urb_context)
871 			break;
872 
873 		urb_context->buf =
874 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
875 		if (!urb_context->buf) {
876 			usb_hif_cleanup_recv_urb(urb_context);
877 			break;
878 		}
879 
880 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
881 
882 		urb = urb_context->urb;
883 
884 		usb_fill_bulk_urb(urb,
885 				recv_pipe->device->udev,
886 				recv_pipe->usb_pipe_handle,
887 				data,
888 				buffer_length,
889 				usb_hif_usb_recv_prestart_complete,
890 				urb_context);
891 
892 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
893 			 recv_pipe->logical_pipe_num,
894 			 recv_pipe->usb_pipe_handle,
895 			 recv_pipe->ep_address, buffer_length,
896 			 urb_context->buf);
897 
898 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
899 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
900 
901 		if (usb_status) {
902 			hif_err("athusb : usb bulk recv failed %d",
903 				usb_status);
904 			usb_hif_remove_pending_transfer(urb_context);
905 			usb_hif_cleanup_recv_urb(urb_context);
906 			break;
907 		}
908 		recv_pipe->urb_prestart_cnt++;
909 	}
910 	qdf_spin_unlock_irqrestore(&recv_pipe->device->rx_prestart_lock);
911 
912 	hif_info("-");
913 }
914 
915 /**
916  * usb_hif_post_recv_transfers() - post recv urbs for a given pipe
917  * @recv_pipe: recv pipe for which urbs need to be posted
918  * @buffer_length: buffer length of the recv urbs
919  *
920  * Return: none
921  */
922 static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
923 							int buffer_length)
924 {
925 	struct HIF_URB_CONTEXT *urb_context;
926 	uint8_t *data;
927 	uint32_t len;
928 	struct urb *urb;
929 	int usb_status;
930 
931 	while (1) {
932 
933 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
934 		if (!urb_context)
935 			break;
936 
937 		urb_context->buf = qdf_nbuf_alloc(NULL, buffer_length, 0,
938 						4, false);
939 		if (!urb_context->buf) {
940 			usb_hif_cleanup_recv_urb(urb_context);
941 			break;
942 		}
943 
944 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
945 
946 		urb = urb_context->urb;
947 
948 		usb_fill_bulk_urb(urb,
949 				recv_pipe->device->udev,
950 				recv_pipe->usb_pipe_handle,
951 				data,
952 				buffer_length,
953 				usb_hif_usb_recv_complete, urb_context);
954 
955 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
956 			 recv_pipe->logical_pipe_num,
957 			 recv_pipe->usb_pipe_handle,
958 			 recv_pipe->ep_address, buffer_length,
959 			 urb_context->buf);
960 
961 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
962 
963 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
964 
965 		if (usb_status) {
966 			hif_err("athusb : usb bulk recv failed %d",
967 				usb_status);
968 			usb_hif_remove_pending_transfer(urb_context);
969 			usb_hif_cleanup_recv_urb(urb_context);
970 			break;
971 		}
972 	}
973 
974 }
975 
976 /**
977  * usb_hif_post_recv_bundle_transfers() - post recv urbs for a given pipe
978  * @recv_pipe: recv pipe for which urbs need to be posted
979  * @buffer_length: maximum length of rx bundle
980  *
981  * Return: none
982  */
983 static void usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE *recv_pipe,
984 						int buffer_length)
985 {
986 	struct HIF_URB_CONTEXT *urb_context;
987 	uint8_t *data;
988 	uint32_t len;
989 	struct urb *urb;
990 	int usb_status;
991 
992 	while (1) {
993 
994 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
995 		if (!urb_context)
996 			break;
997 
998 		if (!urb_context->buf) {
999 			urb_context->buf =
1000 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
1001 			if (!urb_context->buf) {
1002 				usb_hif_cleanup_recv_urb(urb_context);
1003 				break;
1004 			}
1005 		}
1006 
1007 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
1008 
1009 		urb = urb_context->urb;
1010 		usb_fill_bulk_urb(urb,
1011 				recv_pipe->device->udev,
1012 				recv_pipe->usb_pipe_handle,
1013 				data,
1014 				buffer_length,
1015 				usb_hif_usb_recv_bundle_complete,
1016 				urb_context);
1017 
1018 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
1019 			 recv_pipe->logical_pipe_num,
1020 			 recv_pipe->usb_pipe_handle,
1021 			 recv_pipe->ep_address, buffer_length,
1022 			 urb_context->buf);
1023 
1024 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
1025 
1026 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
1027 
1028 		if (usb_status) {
1029 			hif_err("athusb : usb bulk recv failed %d",
1030 				usb_status);
1031 			usb_hif_remove_pending_transfer(urb_context);
1032 			usb_hif_free_urb_to_pipe(urb_context->pipe,
1033 						urb_context);
1034 			break;
1035 		}
1036 
1037 	}
1038 
1039 }
1040 
1041 /**
1042  * usb_hif_prestart_recv_pipes() - post prestart recv urbs
1043  * @device: HIF device for which prestart recv urbs need to be posted
1044  *
1045  * Return: none
1046  */
1047 void usb_hif_prestart_recv_pipes(struct HIF_DEVICE_USB *device)
1048 {
1049 	struct HIF_USB_PIPE *pipe;
1050 	int prestart_cnt = 8;
1051 
1052 	if (device->rx_ctrl_pipe_supported) {
1053 		pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1054 		prestart_cnt = 4;
1055 		usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1056 	}
1057 	/*
1058 	 * USB driver learn to support bundle or not until the firmware
1059 	 * download and ready. Only allocate some URBs for control message
1060 	 * communication during the initial phase then start the final
1061 	 * working pipe after all information understood.
1062 	 */
1063 	pipe = &device->pipes[HIF_RX_DATA_PIPE];
1064 	usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1065 }
1066 
1067 /**
1068  * usb_hif_start_recv_pipes() - start recv urbs
1069  * @device: HIF device for which recv urbs need to be posted
1070  *
1071  * This function is called after all prestart recv urbs are exhausted
1072  *
1073  * Return: none
1074  */
1075 void usb_hif_start_recv_pipes(struct HIF_DEVICE_USB *device)
1076 {
1077 	struct HIF_USB_PIPE *pipe;
1078 	uint32_t buf_len;
1079 
1080 	HIF_ENTER();
1081 	pipe = &device->pipes[HIF_RX_DATA_PIPE];
1082 	pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1083 
1084 	hif_info("Post URBs to RX_DATA_PIPE: %d is_bundle %d",
1085 		  device->pipes[HIF_RX_DATA_PIPE].urb_cnt,
1086 		  device->is_bundle_enabled);
1087 	if (device->is_bundle_enabled) {
1088 		usb_hif_post_recv_bundle_transfers(pipe,
1089 					pipe->device->rx_bundle_buf_len);
1090 	} else {
1091 		buf_len = HIF_USB_RX_BUFFER_SIZE;
1092 		usb_hif_post_recv_transfers(pipe, buf_len);
1093 	}
1094 
1095 	hif_debug("athusb bulk recv len %d", buf_len);
1096 
1097 	if (!hif_usb_disable_rxdata2) {
1098 		hif_info("Post URBs to RX_DATA2_PIPE: %d",
1099 			device->pipes[HIF_RX_DATA2_PIPE].urb_cnt);
1100 
1101 		pipe = &device->pipes[HIF_RX_DATA2_PIPE];
1102 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1103 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1104 	}
1105 
1106 	if (device->rx_ctrl_pipe_supported) {
1107 		hif_info("Post URBs to RX_CONTROL_PIPE: %d",
1108 			 device->pipes[HIF_RX_CTRL_PIPE].urb_cnt);
1109 
1110 		pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1111 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1112 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1113 	}
1114 	HIF_EXIT();
1115 }
1116 
1117 /**
1118  * usb_hif_submit_ctrl_out() - send out a ctrl urb
1119  * @device: HIF device for which urb needs to be posted
1120  * @req: request value for the ctrl message
1121  * @value: USB message value
1122  * @index: USB message index value
1123  * @data: pointer to data containing ctrl message to send
1124  * @size: size of the control message to send
1125  *
1126  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1127  */
1128 QDF_STATUS usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB *device,
1129 				   uint8_t req, uint16_t value, uint16_t index,
1130 				   void *data, uint32_t size)
1131 {
1132 	int32_t result = 0;
1133 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1134 	uint8_t *buf = NULL;
1135 
1136 	do {
1137 
1138 		if (size > 0) {
1139 			buf = qdf_mem_malloc(size);
1140 			if (!buf) {
1141 				ret = QDF_STATUS_E_NOMEM;
1142 				break;
1143 			}
1144 			qdf_mem_copy(buf, (uint8_t *) data, size);
1145 		}
1146 
1147 		hif_debug("ctrl-out req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1148 			 req, value, index, size);
1149 
1150 		result = usb_control_msg(device->udev,
1151 					usb_sndctrlpipe(device->udev, 0),
1152 					req,
1153 					USB_DIR_OUT | USB_TYPE_VENDOR |
1154 					USB_RECIP_DEVICE, value, index, buf,
1155 					size, 2 * HZ);
1156 
1157 		if (result < 0) {
1158 			hif_err("usb_control_msg failed, (result=%d)", result);
1159 			ret = QDF_STATUS_E_FAILURE;
1160 		}
1161 
1162 	} while (false);
1163 
1164 	if (buf)
1165 		qdf_mem_free(buf);
1166 
1167 	return ret;
1168 }
1169 
1170 /**
1171  * usb_hif_submit_ctrl_in() - recv a resonse to the ctrl message sent out
1172  * @device: HIF device for which urb needs to be received
1173  * @req: request value for the ctrl message
1174  * @value: USB message value
1175  * @index: USB message index value
1176  * @data: pointer to data containing ctrl message to be received
1177  * @size: size of the control message to be received
1178  *
1179  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1180  */
1181 QDF_STATUS usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB *device,
1182 				  uint8_t req, uint16_t value, uint16_t index,
1183 				  void *data, uint32_t size)
1184 {
1185 	int32_t result = 0;
1186 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1187 	uint8_t *buf = NULL;
1188 
1189 	do {
1190 
1191 		if (size > 0) {
1192 			buf = qdf_mem_malloc(size);
1193 			if (!buf) {
1194 				ret = QDF_STATUS_E_NOMEM;
1195 				break;
1196 			}
1197 		}
1198 
1199 		hif_debug("ctrl-in req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1200 			 req, value, index, size);
1201 
1202 		result = usb_control_msg(device->udev,
1203 					usb_rcvctrlpipe(device->udev, 0),
1204 					req,
1205 					USB_DIR_IN | USB_TYPE_VENDOR |
1206 					USB_RECIP_DEVICE, value, index, buf,
1207 					size, 2 * HZ);
1208 
1209 		if (result < 0) {
1210 			hif_err("usb_control_msg failed, (result=%d)", result);
1211 			ret = QDF_STATUS_E_FAILURE;
1212 			break;
1213 		}
1214 
1215 		qdf_mem_copy((uint8_t *) data, buf, size);
1216 
1217 	} while (false);
1218 
1219 	if (buf)
1220 		qdf_mem_free(buf);
1221 
1222 	return ret;
1223 }
1224 
1225 /**
1226  * usb_hif_io_complete() - transmit call back for tx urb
1227  * @pipe: pointer to struct HIF_USB_PIPE
1228  *
1229  * Return: none
1230  */
1231 static void usb_hif_io_complete(struct HIF_USB_PIPE *pipe)
1232 {
1233 	qdf_nbuf_t buf;
1234 	struct HIF_DEVICE_USB *device;
1235 	HTC_FRAME_HDR *HtcHdr;
1236 	uint8_t *data;
1237 	uint32_t len;
1238 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
1239 
1240 	device = pipe->device;
1241 	HIF_ENTER();
1242 	while ((buf = skb_dequeue(&pipe->io_comp_queue))) {
1243 		if (pipe->flags & HIF_USB_PIPE_FLAG_TX) {
1244 			hif_debug("+athusb xmit callback buf:0x%pK", buf);
1245 			HtcHdr = (HTC_FRAME_HDR *)
1246 					qdf_nbuf_get_frag_vaddr(buf, 0);
1247 
1248 #ifdef ATH_11AC_TXCOMPACT
1249 /* ATH_11AC_TXCOMPACT does not support High Latency mode */
1250 #else
1251 			device->htc_callbacks.txCompletionHandler(device->
1252 								htc_callbacks.
1253 								Context, buf,
1254 								HtcHdr->
1255 								EndpointID, 0);
1256 #endif
1257 			hif_debug("-athusb xmit callback");
1258 		} else {
1259 			hif_debug("+athusb recv callback buf: 0x%pK", buf);
1260 			qdf_nbuf_peek_header(buf, &data, &len);
1261 
1262 			if (IS_FW_CRASH_DUMP(*((uint32_t *) data))) {
1263 				sc->fw_data = data;
1264 				sc->fw_data_len = len;
1265 				device->htc_callbacks.fwEventHandler(
1266 					device->htc_callbacks.Context,
1267 					QDF_STATUS_E_USB_ERROR);
1268 				qdf_nbuf_free(buf);
1269 			} else {
1270 				device->htc_callbacks.rxCompletionHandler(
1271 				device->htc_callbacks.Context, buf,
1272 				pipe->logical_pipe_num);
1273 			}
1274 			hif_debug("-athusb recv callback");
1275 		}
1276 	}
1277 
1278 	HIF_EXIT();
1279 }
1280 
1281 #ifdef HIF_USB_TASKLET
1282 /**
1283  * usb_hif_io_comp_tasklet() - per pipe tasklet routine
1284  * @context: pointer to HIF USB pipe
1285  *
1286  * Return: none
1287  */
1288 void usb_hif_io_comp_tasklet(unsigned long context)
1289 {
1290 	struct HIF_USB_PIPE *pipe = (struct HIF_USB_PIPE *) context;
1291 
1292 	usb_hif_io_complete(pipe);
1293 }
1294 
1295 #else
1296 /**
1297  * usb_hif_io_comp_work() - per pipe work queue
1298  * @work: pointer to struct work_struct
1299  *
1300  * Return: none
1301  */
1302 void usb_hif_io_comp_work(struct work_struct *work)
1303 {
1304 	struct HIF_USB_PIPE *pipe = container_of(work, struct HIF_USB_PIPE,
1305 						 io_complete_work);
1306 
1307 	usb_hif_io_complete(pipe);
1308 }
1309 #endif
1310