xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/usb/usbdrv.c (revision 1f55ed1a9f5050d8da228aa8dd3fff7c0242aa71)
1 /*
2  * Copyright (c) 2013-2018 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 != NULL) {
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 != NULL)
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 (NULL == urb_context) {
155 			status = QDF_STATUS_E_NOMEM;
156 			HIF_ERROR("urb_context is null");
157 			break;
158 		}
159 		urb_context->pipe = pipe;
160 		urb_context->urb = usb_alloc_urb(0, GFP_KERNEL);
161 
162 		if (NULL == urb_context->urb) {
163 			status = QDF_STATUS_E_NOMEM;
164 			qdf_mem_free(urb_context);
165 			HIF_ERROR("urb_context->urb is null");
166 			break;
167 		}
168 
169 		/* note we are only allocate the urb contexts here, the actual
170 		 * URB is
171 		 * allocated from the kernel as needed to do a transaction
172 		 */
173 		pipe->urb_alloc++;
174 
175 		usb_hif_free_urb_to_pipe(pipe, urb_context);
176 	}
177 
178 	HIF_DBG("athusb: alloc resources lpipe:%d hpipe:0x%X urbs:%d",
179 		pipe->logical_pipe_num,
180 		pipe->usb_pipe_handle,
181 		pipe->urb_alloc);
182 	return status;
183 }
184 
185 /**
186  * usb_hif_free_pipe_resources() - free urb resources allocated to a HIF pipe
187  * @pipe: pointer to struct HIF_USB_PIPE
188  *
189  * Return: none
190  */
191 static void usb_hif_free_pipe_resources(struct HIF_USB_PIPE *pipe)
192 {
193 	struct HIF_URB_CONTEXT *urb_context;
194 
195 	if (NULL == pipe->device) {
196 		/* nothing allocated for this pipe */
197 		HIF_ERROR("pipe->device is null");
198 		return;
199 	}
200 
201 	HIF_TRACE("athusb: free resources lpipe:%d hpipe:0x%X urbs:%d avail:%d",
202 			 pipe->logical_pipe_num,
203 			 pipe->usb_pipe_handle, pipe->urb_alloc,
204 			 pipe->urb_cnt);
205 
206 	if (pipe->urb_alloc != pipe->urb_cnt) {
207 		HIF_ERROR("athusb: urb leak! lpipe:%d hpipe:0x%X urbs:%d avail:%d",
208 				 pipe->logical_pipe_num,
209 				 pipe->usb_pipe_handle, pipe->urb_alloc,
210 				 pipe->urb_cnt);
211 	}
212 
213 	while (true) {
214 		urb_context = usb_hif_alloc_urb_from_pipe(pipe);
215 		if (NULL == urb_context)
216 			break;
217 
218 		if (urb_context->buf) {
219 			qdf_nbuf_free(urb_context->buf);
220 			urb_context->buf = NULL;
221 		}
222 
223 		usb_free_urb(urb_context->urb);
224 		urb_context->urb = NULL;
225 		qdf_mem_free(urb_context);
226 	}
227 
228 }
229 
230 #ifdef QCN7605_SUPPORT
231 /**
232  * usb_hif_get_logical_pipe_num() - get pipe number for a particular enpoint
233  * @device: pointer to HIF_DEVICE_USB structure
234  * @ep_address: endpoint address
235  * @urb_count: number of urb resources to be allocated to the pipe
236  *
237  * Return: uint8_t pipe number corresponding to ep_address
238  */
239 static uint8_t usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB *device,
240 					    uint8_t ep_address,
241 					    int *urb_count)
242 {
243 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
244 
245 	switch (ep_address) {
246 	case USB_EP_ADDR_APP_CTRL_IN:
247 		pipe_num = HIF_RX_CTRL_PIPE;
248 		*urb_count = RX_URB_COUNT;
249 		break;
250 	case USB_EP_ADDR_APP_DATA_IN:
251 		pipe_num = HIF_RX_DATA_PIPE;
252 		*urb_count = RX_URB_COUNT;
253 		break;
254 		break;
255 	case USB_EP_ADDR_APP_CTRL_OUT:
256 		pipe_num = HIF_TX_CTRL_PIPE;
257 		*urb_count = TX_URB_COUNT;
258 		break;
259 	case USB_EP_ADDR_APP_DATA_OUT:
260 		pipe_num = HIF_TX_DATA_LP_PIPE;
261 		*urb_count = TX_URB_COUNT;
262 		break;
263 	default:
264 		/* note: there may be endpoints not currently used */
265 		break;
266 	}
267 
268 	return pipe_num;
269 }
270 #else
271 /**
272  * usb_hif_get_logical_pipe_num() - get pipe number for a particular enpoint
273  * @device: pointer to HIF_DEVICE_USB structure
274  * @ep_address: endpoint address
275  * @urb_count: number of urb resources to be allocated to the pipe
276  *
277  * Return: uint8_t pipe number corresponding to ep_address
278  */
279 static uint8_t usb_hif_get_logical_pipe_num
280 					(struct HIF_DEVICE_USB *device,
281 					uint8_t ep_address,
282 					int *urb_count)
283 {
284 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
285 
286 	switch (ep_address) {
287 	case USB_EP_ADDR_APP_CTRL_IN:
288 		pipe_num = HIF_RX_CTRL_PIPE;
289 		*urb_count = RX_URB_COUNT;
290 		break;
291 	case USB_EP_ADDR_APP_DATA_IN:
292 		pipe_num = HIF_RX_DATA_PIPE;
293 		*urb_count = RX_URB_COUNT;
294 		break;
295 	case USB_EP_ADDR_APP_INT_IN:
296 		pipe_num = HIF_RX_INT_PIPE;
297 		*urb_count = RX_URB_COUNT;
298 		break;
299 	case USB_EP_ADDR_APP_DATA2_IN:
300 		pipe_num = HIF_RX_DATA2_PIPE;
301 		*urb_count = RX_URB_COUNT;
302 		break;
303 	case USB_EP_ADDR_APP_CTRL_OUT:
304 		pipe_num = HIF_TX_CTRL_PIPE;
305 		*urb_count = TX_URB_COUNT;
306 		break;
307 	case USB_EP_ADDR_APP_DATA_LP_OUT:
308 		pipe_num = HIF_TX_DATA_LP_PIPE;
309 		*urb_count = TX_URB_COUNT;
310 		break;
311 	case USB_EP_ADDR_APP_DATA_MP_OUT:
312 		pipe_num = HIF_TX_DATA_MP_PIPE;
313 		*urb_count = TX_URB_COUNT;
314 		break;
315 	case USB_EP_ADDR_APP_DATA_HP_OUT:
316 		pipe_num = HIF_TX_DATA_HP_PIPE;
317 		*urb_count = TX_URB_COUNT;
318 		break;
319 	default:
320 		/* note: there may be endpoints not currently used */
321 		break;
322 	}
323 
324 	return pipe_num;
325 }
326 #endif /* QCN7605_SUPPORT */
327 
328 /**
329  * usb_hif_get_logical_pipe_num() - setup urb resources for all pipes
330  * @device: pointer to HIF_DEVICE_USB structure
331  *
332  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
333  */
334 QDF_STATUS usb_hif_setup_pipe_resources(struct HIF_DEVICE_USB *device)
335 {
336 	struct usb_interface *interface = device->interface;
337 	struct usb_host_interface *iface_desc = interface->cur_altsetting;
338 	struct usb_endpoint_descriptor *endpoint;
339 	int i;
340 	int urbcount;
341 	QDF_STATUS status = QDF_STATUS_SUCCESS;
342 	struct HIF_USB_PIPE *pipe;
343 	uint8_t pipe_num;
344 
345 	/* walk decriptors and setup pipes */
346 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
347 		endpoint = &iface_desc->endpoint[i].desc;
348 
349 		if (IS_BULK_EP(endpoint->bmAttributes)) {
350 			HIF_DBG("%s Bulk Ep:0x%2.2X maxpktsz:%d",
351 				IS_DIR_IN(endpoint->bEndpointAddress) ?
352 								"RX" : "TX",
353 				endpoint->bEndpointAddress,
354 				qdf_le16_to_cpu(endpoint->wMaxPacketSize));
355 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
356 			HIF_DBG("%s Int Ep:0x%2.2X maxpktsz:%d interval:%d",
357 				IS_DIR_IN(endpoint->bEndpointAddress) ?
358 								"RX" : "TX",
359 				endpoint->bEndpointAddress,
360 				qdf_le16_to_cpu(endpoint->wMaxPacketSize),
361 				endpoint->bInterval);
362 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
363 			/* TODO for ISO */
364 			HIF_DBG("%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d",
365 				IS_DIR_IN(endpoint->bEndpointAddress) ?
366 								"RX" : "TX",
367 				endpoint->bEndpointAddress,
368 				qdf_le16_to_cpu(endpoint->wMaxPacketSize),
369 				endpoint->bInterval);
370 		}
371 		urbcount = 0;
372 
373 		pipe_num = usb_hif_get_logical_pipe_num(device,
374 						endpoint->bEndpointAddress,
375 						&urbcount);
376 		if (HIF_USB_PIPE_INVALID == pipe_num)
377 			continue;
378 
379 		pipe = &device->pipes[pipe_num];
380 		if (pipe->device != NULL) {
381 			/*pipe was already setup */
382 			continue;
383 		}
384 
385 		pipe->device = device;
386 		pipe->logical_pipe_num = pipe_num;
387 		pipe->ep_address = endpoint->bEndpointAddress;
388 		pipe->max_packet_size =
389 			qdf_le16_to_cpu(endpoint->wMaxPacketSize);
390 
391 		if (IS_BULK_EP(endpoint->bmAttributes)) {
392 			if (IS_DIR_IN(pipe->ep_address)) {
393 				pipe->usb_pipe_handle =
394 					usb_rcvbulkpipe(device->udev,
395 							pipe->ep_address);
396 			} else {
397 				pipe->usb_pipe_handle =
398 					usb_sndbulkpipe(device->udev,
399 						pipe->ep_address);
400 			}
401 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
402 			if (IS_DIR_IN(pipe->ep_address)) {
403 				pipe->usb_pipe_handle =
404 					usb_rcvintpipe(device->udev,
405 						pipe->ep_address);
406 			} else {
407 				pipe->usb_pipe_handle =
408 					usb_sndintpipe(device->udev,
409 						pipe->ep_address);
410 			}
411 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
412 			/* TODO for ISO */
413 			if (IS_DIR_IN(pipe->ep_address)) {
414 				pipe->usb_pipe_handle =
415 					usb_rcvisocpipe(device->udev,
416 						pipe->ep_address);
417 			} else {
418 				pipe->usb_pipe_handle =
419 					usb_sndisocpipe(device->udev,
420 						pipe->ep_address);
421 			}
422 		}
423 		pipe->ep_desc = endpoint;
424 
425 		if (!IS_DIR_IN(pipe->ep_address))
426 			pipe->flags |= HIF_USB_PIPE_FLAG_TX;
427 
428 		status = usb_hif_alloc_pipe_resources(pipe, urbcount);
429 
430 		if (!QDF_IS_STATUS_SUCCESS(status))
431 			break;
432 
433 	}
434 
435 	return status;
436 }
437 
438 
439 /**
440  * usb_hif_cleanup_pipe_resources() - free urb resources for all pipes
441  * @device: pointer to HIF_DEVICE_USB structure
442  *
443  * Return: none
444  */
445 void usb_hif_cleanup_pipe_resources(struct HIF_DEVICE_USB *device)
446 {
447 	int i;
448 
449 	for (i = 0; i < HIF_USB_PIPE_MAX; i++)
450 		usb_hif_free_pipe_resources(&device->pipes[i]);
451 }
452 
453 /**
454  * usb_hif_flush_pending_transfers() - kill pending urbs for a pipe
455  * @pipe: pointer to struct HIF_USB_PIPE structure
456  *
457  * Return: none
458  */
459 static void usb_hif_flush_pending_transfers(struct HIF_USB_PIPE *pipe)
460 {
461 	struct HIF_URB_CONTEXT *urb_context;
462 
463 	HIF_TRACE("+%s pipe : %d", __func__, pipe->logical_pipe_num);
464 
465 	while (1) {
466 		urb_context = usb_hif_dequeue_pending_transfer(pipe);
467 		if (NULL == urb_context) {
468 			HIF_WARN("urb_context is NULL");
469 			break;
470 		}
471 		HIF_TRACE("  pending urb ctxt: 0x%pK", urb_context);
472 		if (urb_context->urb != NULL) {
473 			HIF_TRACE("  killing urb: 0x%pK", urb_context->urb);
474 			/* killing the URB will cause the completion routines to
475 			 * run
476 			 */
477 			usb_kill_urb(urb_context->urb);
478 		}
479 	}
480 	HIF_TRACE("-%s", __func__);
481 }
482 
483 /**
484  * usb_hif_flush_all() - flush pending transfers for all pipes for a usb bus
485  * @device: pointer to HIF_DEVICE_USB structure
486  *
487  * Return: none
488  */
489 void usb_hif_flush_all(struct HIF_DEVICE_USB *device)
490 {
491 	int i;
492 	struct HIF_USB_PIPE *pipe;
493 
494 	HIF_TRACE("+%s", __func__);
495 
496 	for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
497 		if (device->pipes[i].device != NULL) {
498 			usb_hif_flush_pending_transfers(&device->pipes[i]);
499 			pipe = &device->pipes[i];
500 
501 		HIF_USB_FLUSH_WORK(pipe);
502 		}
503 	}
504 
505 	HIF_TRACE("-%s", __func__);
506 }
507 
508 /**
509  * usb_hif_cleanup_recv_urb() - cleanup recv urb
510  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
511  *
512  * Return: none
513  */
514 static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context)
515 {
516 	HIF_TRACE("+%s", __func__);
517 
518 	if (urb_context->buf != NULL) {
519 		qdf_nbuf_free(urb_context->buf);
520 		urb_context->buf = NULL;
521 	}
522 
523 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
524 	HIF_TRACE("-%s", __func__);
525 }
526 
527 /**
528  * usb_hif_cleanup_transmit_urb() - cleanup transmit urb
529  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
530  *
531  * Return: none
532  */
533 void usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT *urb_context)
534 {
535 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
536 }
537 
538 /**
539  * usb_hif_usb_recv_prestart_complete() - completion routine for prestart rx urb
540  * @urb: urb for which the completion routine is being called
541  *
542  * Return: none
543  */
544 static void usb_hif_usb_recv_prestart_complete
545 							(struct urb *urb)
546 {
547 	struct HIF_URB_CONTEXT *urb_context =
548 					(struct HIF_URB_CONTEXT *) urb->context;
549 	QDF_STATUS status = QDF_STATUS_SUCCESS;
550 	qdf_nbuf_t buf = NULL;
551 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
552 
553 	HIF_DBG("+%s: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
554 		__func__,
555 		pipe->logical_pipe_num,
556 		urb->status, urb->actual_length,
557 		urb);
558 
559 	/* this urb is not pending anymore */
560 	usb_hif_remove_pending_transfer(urb_context);
561 	do {
562 		if (urb->status != 0) {
563 			status = A_ECOMM;
564 			switch (urb->status) {
565 			case -ECONNRESET:
566 			case -ENOENT:
567 			case -ESHUTDOWN:
568 				/* NOTE: no need to spew these errors when
569 				 * device is removed
570 				 * or urb is killed due to driver shutdown
571 				 */
572 				status = A_ECANCELED;
573 				break;
574 			default:
575 				HIF_ERROR("%s recv pipe: %d (ep:0x%2.2X), failed:%d",
576 					__func__,
577 					pipe->logical_pipe_num,
578 					pipe->ep_address,
579 					urb->status);
580 				break;
581 			}
582 			break;
583 		}
584 		if (urb->actual_length == 0)
585 			break;
586 		buf = urb_context->buf;
587 		/* we are going to pass it up */
588 		urb_context->buf = NULL;
589 		qdf_nbuf_put_tail(buf, urb->actual_length);
590 
591 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
592 			uint8_t *data;
593 			uint32_t len;
594 
595 			qdf_nbuf_peek_header(buf, &data, &len);
596 			debug_dump_bytes(data, len, "hif recv data");
597 		}
598 		/* note: queue implements a lock */
599 		skb_queue_tail(&pipe->io_comp_queue, buf);
600 
601 		HIF_USB_SCHEDULE_WORK(pipe);
602 	} while (false);
603 
604 	usb_hif_cleanup_recv_urb(urb_context);
605 
606 	/* Prestart URBs runs out and now start working receive pipe. */
607 	if (--pipe->urb_prestart_cnt == 0)
608 		usb_hif_start_recv_pipes(pipe->device);
609 
610 	HIF_DBG("-%s", __func__);
611 }
612 
613 /**
614  * usb_hif_usb_recv_complete() - completion routine for rx urb
615  * @urb: urb for which the completion routine is being called
616  *
617  * Return: none
618  */
619 static void usb_hif_usb_recv_complete(struct urb *urb)
620 {
621 	struct HIF_URB_CONTEXT *urb_context =
622 					(struct HIF_URB_CONTEXT *) urb->context;
623 	QDF_STATUS status = QDF_STATUS_SUCCESS;
624 	qdf_nbuf_t buf = NULL;
625 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
626 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
627 
628 	HIF_DBG("+%s: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
629 		__func__,
630 		pipe->logical_pipe_num,
631 		urb->status, urb->actual_length,
632 		urb);
633 
634 	/* this urb is not pending anymore */
635 	usb_hif_remove_pending_transfer(urb_context);
636 
637 	do {
638 
639 		if (urb->status != 0) {
640 			status = A_ECOMM;
641 			switch (urb->status) {
642 #ifdef RX_SG_SUPPORT
643 			case -EOVERFLOW:
644 				urb->actual_length = HIF_USB_RX_BUFFER_SIZE;
645 				status = QDF_STATUS_SUCCESS;
646 				break;
647 #endif
648 			case -ECONNRESET:
649 			case -ENOENT:
650 			case -ESHUTDOWN:
651 				/* NOTE: no need to spew these errors when
652 				 * device is removed
653 				 * or urb is killed due to driver shutdown
654 				 */
655 				status = A_ECANCELED;
656 				break;
657 			default:
658 				HIF_ERROR("%s recv pipe: %d (ep:0x%2.2X), failed:%d",
659 					__func__,
660 					pipe->logical_pipe_num,
661 					pipe->ep_address,
662 					urb->status);
663 				break;
664 			}
665 			break;
666 		}
667 		if (urb->actual_length == 0)
668 			break;
669 		buf = urb_context->buf;
670 		/* we are going to pass it up */
671 		urb_context->buf = NULL;
672 		qdf_nbuf_put_tail(buf, urb->actual_length);
673 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
674 			uint8_t *data;
675 			uint32_t len;
676 
677 			qdf_nbuf_peek_header(buf, &data, &len);
678 			debug_dump_bytes(data, len, "hif recv data");
679 		}
680 		/* note: queue implements a lock */
681 		skb_queue_tail(&pipe->io_comp_queue, buf);
682 		HIF_USB_SCHEDULE_WORK(pipe);
683 	} while (false);
684 
685 	usb_hif_cleanup_recv_urb(urb_context);
686 
687 	/* Only re-submit URB when STATUS is success and HIF is not at the
688 	 * suspend state.
689 	 */
690 	if (QDF_IS_STATUS_SUCCESS(status) && !sc->suspend_state) {
691 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
692 			/* our free urbs are piling up, post more transfers */
693 			usb_hif_post_recv_transfers(pipe,
694 						HIF_USB_RX_BUFFER_SIZE);
695 		}
696 	} else {
697 		HIF_ERROR("%s:  pipe: %d, fail to post URB: status(%d) suspend (%d)",
698 				__func__,
699 				pipe->logical_pipe_num,
700 				urb->status,
701 				sc->suspend_state);
702 	}
703 
704 	HIF_DBG("-%s", __func__);
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 
726 	HIF_DBG("+%s: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
727 		__func__,
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_ERROR("%s recv pipe: %d (ep:0x%2.2X), failed:%d",
751 					__func__,
752 					pipe->logical_pipe_num,
753 					pipe->ep_address,
754 					urb->status);
755 				break;
756 			}
757 			break;
758 		}
759 		if (urb->actual_length == 0)
760 			break;
761 		buf = urb_context->buf;
762 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
763 			uint8_t *data;
764 			uint32_t len;
765 
766 			qdf_nbuf_peek_header(buf, &data, &len);
767 			debug_dump_bytes(data, len, "hif recv data");
768 		}
769 
770 		qdf_nbuf_peek_header(buf, &netdata, &netlen);
771 		netlen = urb->actual_length;
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_ERROR("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_ERROR("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_ERROR("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 == NULL) {
808 				HIF_ERROR("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 		} while (netlen);
822 		HIF_USB_SCHEDULE_WORK(pipe);
823 	} while (false);
824 
825 	if (urb_context->buf == NULL)
826 		HIF_ERROR("athusb: buffer in urb_context is NULL");
827 
828 	/* reset urb_context->buf ==> seems not necessary */
829 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
830 
831 	if (QDF_IS_STATUS_SUCCESS(status)) {
832 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
833 			/* our free urbs are piling up, post more transfers */
834 			usb_hif_post_recv_bundle_transfers(pipe,
835 					pipe->device->rx_bundle_buf_len);
836 		}
837 	}
838 
839 	HIF_DBG("-%s", __func__);
840 }
841 
842 /**
843  * usb_hif_post_recv_prestart_transfers() - post prestart recv urbs for a pipe
844  * @recv_pipe: rx data pipe
845  * @prestart_urb: number of prestart recv urbs to be posted
846  *
847  * Return: none
848  */
849 static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe,
850 						int prestart_urb)
851 {
852 	struct HIF_URB_CONTEXT *urb_context;
853 	uint8_t *data;
854 	uint32_t len;
855 	struct urb *urb;
856 	int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE;
857 
858 	HIF_TRACE("+%s", __func__);
859 
860 	for (i = 0; i < prestart_urb; i++) {
861 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
862 		if (NULL == urb_context)
863 			break;
864 
865 		urb_context->buf =
866 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
867 		if (NULL == urb_context->buf) {
868 			usb_hif_cleanup_recv_urb(urb_context);
869 			break;
870 		}
871 
872 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
873 
874 		urb = urb_context->urb;
875 
876 		usb_fill_bulk_urb(urb,
877 				recv_pipe->device->udev,
878 				recv_pipe->usb_pipe_handle,
879 				data,
880 				buffer_length,
881 				usb_hif_usb_recv_prestart_complete,
882 				urb_context);
883 
884 		HIF_DBG("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
885 			recv_pipe->logical_pipe_num,
886 			recv_pipe->usb_pipe_handle,
887 			recv_pipe->ep_address, buffer_length,
888 			urb_context->buf);
889 
890 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
891 
892 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
893 
894 		if (usb_status) {
895 			HIF_ERROR("athusb : usb bulk recv failed %d",
896 				usb_status);
897 			usb_hif_remove_pending_transfer(urb_context);
898 			usb_hif_cleanup_recv_urb(urb_context);
899 			break;
900 		}
901 		recv_pipe->urb_prestart_cnt++;
902 	}
903 
904 	HIF_TRACE("-%s", __func__);
905 }
906 
907 /**
908  * usb_hif_post_recv_transfers() - post recv urbs for a given pipe
909  * @recv_pipe: recv pipe for which urbs need to be posted
910  * @buffer_length: buffer length of the recv urbs
911  *
912  * Return: none
913  */
914 static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
915 							int buffer_length)
916 {
917 	struct HIF_URB_CONTEXT *urb_context;
918 	uint8_t *data;
919 	uint32_t len;
920 	struct urb *urb;
921 	int usb_status;
922 
923 	HIF_TRACE("+%s", __func__);
924 
925 	while (1) {
926 
927 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
928 		if (NULL == urb_context)
929 			break;
930 
931 		urb_context->buf = qdf_nbuf_alloc(NULL, buffer_length, 0,
932 						4, false);
933 		if (NULL == urb_context->buf) {
934 			usb_hif_cleanup_recv_urb(urb_context);
935 			break;
936 		}
937 
938 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
939 
940 		urb = urb_context->urb;
941 
942 		usb_fill_bulk_urb(urb,
943 				recv_pipe->device->udev,
944 				recv_pipe->usb_pipe_handle,
945 				data,
946 				buffer_length,
947 				usb_hif_usb_recv_complete, urb_context);
948 
949 		HIF_DBG("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
950 			recv_pipe->logical_pipe_num,
951 			recv_pipe->usb_pipe_handle,
952 			recv_pipe->ep_address, buffer_length,
953 			urb_context->buf);
954 
955 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
956 
957 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
958 
959 		if (usb_status) {
960 			HIF_ERROR("athusb : usb bulk recv failed %d",
961 				usb_status);
962 			usb_hif_remove_pending_transfer(urb_context);
963 			usb_hif_cleanup_recv_urb(urb_context);
964 			break;
965 		}
966 	}
967 
968 	HIF_TRACE("-%s", __func__);
969 
970 }
971 
972 /**
973  * usb_hif_post_recv_bundle_transfers() - post recv urbs for a given pipe
974  * @recv_pipe: recv pipe for which urbs need to be posted
975  * @buffer_length: maximum length of rx bundle
976  *
977  * Return: none
978  */
979 static void usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE *recv_pipe,
980 						int buffer_length)
981 {
982 	struct HIF_URB_CONTEXT *urb_context;
983 	uint8_t *data;
984 	uint32_t len;
985 	struct urb *urb;
986 	int usb_status;
987 
988 	HIF_TRACE("+%s", __func__);
989 
990 	while (1) {
991 
992 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
993 		if (NULL == urb_context)
994 			break;
995 
996 		if (NULL == urb_context->buf) {
997 			urb_context->buf =
998 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
999 			if (NULL == urb_context->buf) {
1000 				usb_hif_cleanup_recv_urb(urb_context);
1001 				break;
1002 			}
1003 		}
1004 
1005 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
1006 
1007 		urb = urb_context->urb;
1008 		usb_fill_bulk_urb(urb,
1009 				recv_pipe->device->udev,
1010 				recv_pipe->usb_pipe_handle,
1011 				data,
1012 				buffer_length,
1013 				usb_hif_usb_recv_bundle_complete,
1014 				urb_context);
1015 
1016 		HIF_DBG("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
1017 			recv_pipe->logical_pipe_num,
1018 			recv_pipe->usb_pipe_handle,
1019 			recv_pipe->ep_address, buffer_length,
1020 			urb_context->buf);
1021 
1022 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
1023 
1024 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
1025 
1026 		if (usb_status) {
1027 			HIF_ERROR("athusb : usb bulk recv failed %d",
1028 				usb_status);
1029 			usb_hif_remove_pending_transfer(urb_context);
1030 			usb_hif_free_urb_to_pipe(urb_context->pipe,
1031 						urb_context);
1032 			break;
1033 		}
1034 
1035 	}
1036 
1037 	HIF_TRACE("-%s", __func__);
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_TRACE("Post URBs to RX_DATA_PIPE: %d",
1085 		device->pipes[HIF_RX_DATA_PIPE].urb_cnt);
1086 	if (device->is_bundle_enabled) {
1087 		usb_hif_post_recv_bundle_transfers(pipe,
1088 					pipe->device->rx_bundle_buf_len);
1089 	} else {
1090 		buf_len = HIF_USB_RX_BUFFER_SIZE;
1091 		usb_hif_post_recv_transfers(pipe, buf_len);
1092 	}
1093 
1094 	HIF_DBG("athusb bulk recv len %d", buf_len);
1095 
1096 	if (!hif_usb_disable_rxdata2) {
1097 		HIF_TRACE("Post URBs to RX_DATA2_PIPE: %d",
1098 			device->pipes[HIF_RX_DATA2_PIPE].urb_cnt);
1099 
1100 		pipe = &device->pipes[HIF_RX_DATA2_PIPE];
1101 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1102 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1103 	}
1104 
1105 	if (device->rx_ctrl_pipe_supported) {
1106 		HIF_TRACE("Post URBs to RX_CONTROL_PIPE: %d",
1107 			  device->pipes[HIF_RX_CTRL_PIPE].urb_cnt);
1108 
1109 		pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1110 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1111 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1112 	}
1113 	HIF_EXIT();
1114 }
1115 
1116 /**
1117  * usb_hif_submit_ctrl_out() - send out a ctrl urb
1118  * @device: HIF device for which urb needs to be posted
1119  * @req: request value for the ctrl message
1120  * @value: USB message value
1121  * @index: USB message index value
1122  * @data: pointer to data containing ctrl message to send
1123  * @size: size of the control message to send
1124  *
1125  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1126  */
1127 QDF_STATUS usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB *device,
1128 				   uint8_t req, uint16_t value, uint16_t index,
1129 				   void *data, uint32_t size)
1130 {
1131 	int32_t result = 0;
1132 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1133 	uint8_t *buf = NULL;
1134 
1135 	do {
1136 
1137 		if (size > 0) {
1138 			buf = qdf_mem_malloc(size);
1139 			if (NULL == buf) {
1140 				ret = QDF_STATUS_E_NOMEM;
1141 				break;
1142 			}
1143 			qdf_mem_copy(buf, (uint8_t *) data, size);
1144 		}
1145 
1146 		HIF_DBG("ctrl-out req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1147 				req, value, index, size);
1148 
1149 		result = usb_control_msg(device->udev,
1150 					usb_sndctrlpipe(device->udev, 0),
1151 					req,
1152 					USB_DIR_OUT | USB_TYPE_VENDOR |
1153 					USB_RECIP_DEVICE, value, index, buf,
1154 					size, 2 * HZ);
1155 
1156 		if (result < 0) {
1157 			HIF_ERROR("%s failed,result = %d", __func__, result);
1158 			ret = QDF_STATUS_E_FAILURE;
1159 		}
1160 
1161 	} while (false);
1162 
1163 	if (buf != NULL)
1164 		qdf_mem_free(buf);
1165 
1166 	return ret;
1167 }
1168 
1169 /**
1170  * usb_hif_submit_ctrl_in() - recv a resonse to the ctrl message sent out
1171  * @device: HIF device for which urb needs to be received
1172  * @req: request value for the ctrl message
1173  * @value: USB message value
1174  * @index: USB message index value
1175  * @data: pointer to data containing ctrl message to be received
1176  * @size: size of the control message to be received
1177  *
1178  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1179  */
1180 QDF_STATUS usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB *device,
1181 				  uint8_t req, uint16_t value, uint16_t index,
1182 				  void *data, uint32_t size)
1183 {
1184 	int32_t result = 0;
1185 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1186 	uint8_t *buf = NULL;
1187 
1188 	do {
1189 
1190 		if (size > 0) {
1191 			buf = qdf_mem_malloc(size);
1192 			if (NULL == buf) {
1193 				ret = QDF_STATUS_E_NOMEM;
1194 				break;
1195 			}
1196 		}
1197 
1198 		HIF_DBG("ctrl-in req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1199 				 req, value, index, size);
1200 
1201 		result = usb_control_msg(device->udev,
1202 					usb_rcvctrlpipe(device->udev, 0),
1203 					req,
1204 					USB_DIR_IN | USB_TYPE_VENDOR |
1205 					USB_RECIP_DEVICE, value, index, buf,
1206 					size, 2 * HZ);
1207 
1208 		if (result < 0) {
1209 			HIF_ERROR("%s failed, result = %d", __func__, result);
1210 			ret = QDF_STATUS_E_FAILURE;
1211 			break;
1212 		}
1213 
1214 		qdf_mem_copy((uint8_t *) data, buf, size);
1215 
1216 	} while (false);
1217 
1218 	if (buf != NULL)
1219 		qdf_mem_free(buf);
1220 
1221 	return ret;
1222 }
1223 
1224 /**
1225  * usb_hif_io_complete() - transmit call back for tx urb
1226  * @pipe: pointer to struct HIF_USB_PIPE
1227  *
1228  * Return: none
1229  */
1230 static void usb_hif_io_complete(struct HIF_USB_PIPE *pipe)
1231 {
1232 	qdf_nbuf_t buf;
1233 	struct HIF_DEVICE_USB *device;
1234 	HTC_FRAME_HDR *HtcHdr;
1235 	uint8_t *data;
1236 	uint32_t len;
1237 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
1238 
1239 	device = pipe->device;
1240 	HIF_ENTER();
1241 	while ((buf = skb_dequeue(&pipe->io_comp_queue))) {
1242 		if (pipe->flags & HIF_USB_PIPE_FLAG_TX) {
1243 			HIF_DBG("+athusb xmit callback buf:0x%pK", buf);
1244 			HtcHdr = (HTC_FRAME_HDR *)
1245 					qdf_nbuf_get_frag_vaddr(buf, 0);
1246 
1247 #ifdef ATH_11AC_TXCOMPACT
1248 /* ATH_11AC_TXCOMPACT does not support High Latency mode */
1249 #else
1250 			device->htc_callbacks.txCompletionHandler(device->
1251 								htc_callbacks.
1252 								Context, buf,
1253 								HtcHdr->
1254 								EndpointID, 0);
1255 #endif
1256 			HIF_DBG("-athusb xmit callback");
1257 		} else {
1258 			HIF_DBG("+athusb recv callback buf: 0x%pK", buf);
1259 			qdf_nbuf_peek_header(buf, &data, &len);
1260 
1261 			if (IS_FW_CRASH_DUMP(*((uint32_t *) data))) {
1262 				sc->fw_data = data;
1263 				sc->fw_data_len = len;
1264 				device->htc_callbacks.fwEventHandler(
1265 					device->htc_callbacks.Context,
1266 					QDF_STATUS_E_USB_ERROR);
1267 				qdf_nbuf_free(buf);
1268 			} else {
1269 				device->htc_callbacks.rxCompletionHandler(
1270 				device->htc_callbacks.Context, buf,
1271 				pipe->logical_pipe_num);
1272 			}
1273 			HIF_DBG("-athusb recv callback");
1274 		}
1275 	}
1276 
1277 	HIF_EXIT();
1278 }
1279 
1280 #ifdef HIF_USB_TASKLET
1281 /**
1282  * usb_hif_io_comp_tasklet() - per pipe tasklet routine
1283  * @context: pointer to HIF USB pipe
1284  *
1285  * Return: none
1286  */
1287 void usb_hif_io_comp_tasklet(unsigned long context)
1288 {
1289 	struct HIF_USB_PIPE *pipe = (struct HIF_USB_PIPE *) context;
1290 
1291 	usb_hif_io_complete(pipe);
1292 }
1293 
1294 #else
1295 /**
1296  * usb_hif_io_comp_work() - per pipe work queue
1297  * @work: pointer to struct work_struct
1298  *
1299  * Return: none
1300  */
1301 void usb_hif_io_comp_work(struct work_struct *work)
1302 {
1303 	struct HIF_USB_PIPE *pipe = container_of(work, struct HIF_USB_PIPE,
1304 						 io_complete_work);
1305 
1306 	usb_hif_io_complete(pipe);
1307 }
1308 #endif
1309