1 /*
2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #define ATH_MODULE_NAME hif
21 #include "a_debug.h"
22 #include "hif_usb_internal.h"
23 #include "if_usb.h"
24 #include "cds_api.h"
25 #include "hif_debug.h"
26
27 #define IS_BULK_EP(attr) (((attr) & 3) == 0x02)
28 #define IS_INT_EP(attr) (((attr) & 3) == 0x03)
29 #define IS_ISOC_EP(attr) (((attr) & 3) == 0x01)
30 #define IS_DIR_IN(addr) ((addr) & 0x80)
31
32 #define IS_FW_CRASH_DUMP(x)(((x == FW_ASSERT_PATTERN) || \
33 (x == FW_REG_PATTERN) || \
34 ((x & FW_RAMDUMP_PATTERN_MASK) == \
35 FW_RAMDUMP_PATTERN)) ? 1 : 0)
36
37 static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
38 int buffer_length);
39 static void usb_hif_post_recv_bundle_transfers
40 (struct HIF_USB_PIPE *recv_pipe,
41 int buffer_length);
42 static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context);
43
44
45 /**
46 * usb_hif_free_urb_to_pipe() - add urb back to urb list of a pipe
47 * @pipe: pointer to struct HIF_USB_PIPE
48 * @urb_context: pointer to struct HIF_URB_CONTEXT
49 *
50 * Return: none
51 */
usb_hif_free_urb_to_pipe(struct HIF_USB_PIPE * pipe,struct HIF_URB_CONTEXT * urb_context)52 static void usb_hif_free_urb_to_pipe(struct HIF_USB_PIPE *pipe,
53 struct HIF_URB_CONTEXT *urb_context)
54 {
55 qdf_spin_lock_irqsave(&pipe->device->cs_lock);
56 pipe->urb_cnt++;
57 DL_ListAdd(&pipe->urb_list_head, &urb_context->link);
58 qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
59 }
60
61 /**
62 * usb_hif_alloc_urb_from_pipe() - remove urb back from urb list of a pipe
63 * @pipe: pointer to struct HIF_USB_PIPE
64 *
65 * Return: struct HIF_URB_CONTEXT urb context removed from the urb list
66 */
usb_hif_alloc_urb_from_pipe(struct HIF_USB_PIPE * pipe)67 struct HIF_URB_CONTEXT *usb_hif_alloc_urb_from_pipe(struct HIF_USB_PIPE *pipe)
68 {
69 struct HIF_URB_CONTEXT *urb_context = NULL;
70 DL_LIST *item;
71
72 qdf_spin_lock_irqsave(&pipe->device->cs_lock);
73 item = dl_list_remove_item_from_head(&pipe->urb_list_head);
74 if (item) {
75 urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
76 link);
77 pipe->urb_cnt--;
78 }
79 qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
80
81 return urb_context;
82 }
83
84 /**
85 * usb_hif_dequeue_pending_transfer() - remove urb from pending xfer list
86 * @pipe: pointer to struct HIF_USB_PIPE
87 *
88 * Return: struct HIF_URB_CONTEXT urb context removed from the pending xfer list
89 */
usb_hif_dequeue_pending_transfer(struct HIF_USB_PIPE * pipe)90 static struct HIF_URB_CONTEXT *usb_hif_dequeue_pending_transfer
91 (struct HIF_USB_PIPE *pipe)
92 {
93 struct HIF_URB_CONTEXT *urb_context = NULL;
94 DL_LIST *item;
95
96 qdf_spin_lock_irqsave(&pipe->device->cs_lock);
97 item = dl_list_remove_item_from_head(&pipe->urb_pending_list);
98 if (item)
99 urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
100 link);
101 qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
102
103 return urb_context;
104 }
105
106 /**
107 * usb_hif_enqueue_pending_transfer() - add urb to pending xfer list
108 * @pipe: pointer to struct HIF_USB_PIPE
109 * @urb_context: pointer to struct HIF_URB_CONTEXT to be added to the xfer list
110 *
111 * Return: none
112 */
usb_hif_enqueue_pending_transfer(struct HIF_USB_PIPE * pipe,struct HIF_URB_CONTEXT * urb_context)113 void usb_hif_enqueue_pending_transfer(struct HIF_USB_PIPE *pipe,
114 struct HIF_URB_CONTEXT *urb_context)
115 {
116 qdf_spin_lock_irqsave(&pipe->device->cs_lock);
117 dl_list_insert_tail(&pipe->urb_pending_list, &urb_context->link);
118 qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
119 }
120
121
122 /**
123 * usb_hif_remove_pending_transfer() - remove urb from its own list
124 * @urb_context: pointer to struct HIF_URB_CONTEXT to be removed
125 *
126 * Return: none
127 */
128 void
usb_hif_remove_pending_transfer(struct HIF_URB_CONTEXT * urb_context)129 usb_hif_remove_pending_transfer(struct HIF_URB_CONTEXT *urb_context)
130 {
131 qdf_spin_lock_irqsave(&urb_context->pipe->device->cs_lock);
132 dl_list_remove(&urb_context->link);
133 qdf_spin_unlock_irqrestore(&urb_context->pipe->device->cs_lock);
134 }
135
136 /**
137 * usb_hif_alloc_pipe_resources() - allocate urb_cnt urbs to a HIF pipe
138 * @pipe: pointer to struct HIF_USB_PIPE to which resources will be allocated
139 * @urb_cnt: number of urbs to be added to the HIF pipe
140 *
141 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
142 */
usb_hif_alloc_pipe_resources(struct HIF_USB_PIPE * pipe,int urb_cnt)143 static QDF_STATUS usb_hif_alloc_pipe_resources
144 (struct HIF_USB_PIPE *pipe, int urb_cnt)
145 {
146 QDF_STATUS status = QDF_STATUS_SUCCESS;
147 int i;
148 struct HIF_URB_CONTEXT *urb_context;
149
150 DL_LIST_INIT(&pipe->urb_list_head);
151 DL_LIST_INIT(&pipe->urb_pending_list);
152
153 for (i = 0; i < urb_cnt; i++) {
154 urb_context = qdf_mem_malloc(sizeof(*urb_context));
155 if (!urb_context) {
156 status = QDF_STATUS_E_NOMEM;
157 break;
158 }
159 urb_context->pipe = pipe;
160 urb_context->urb = usb_alloc_urb(0, GFP_KERNEL);
161
162 if (!urb_context->urb) {
163 status = QDF_STATUS_E_NOMEM;
164 qdf_mem_free(urb_context);
165 hif_err("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_debug("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 */
usb_hif_free_pipe_resources(struct HIF_USB_PIPE * pipe)191 static void usb_hif_free_pipe_resources(struct HIF_USB_PIPE *pipe)
192 {
193 struct HIF_URB_CONTEXT *urb_context;
194
195 if (!pipe->device) {
196 /* nothing allocated for this pipe */
197 hif_err("pipe->device is null");
198 return;
199 }
200
201 hif_info("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_err("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 (!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 endpoint
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 */
usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB * device,uint8_t ep_address,int * urb_count)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 endpoint
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 */
usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB * device,uint8_t ep_address,int * urb_count)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_setup_pipe_resources() - 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 */
usb_hif_setup_pipe_resources(struct HIF_DEVICE_USB * device)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 descriptors 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_debug("%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_debug("%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_debug("%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) {
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 */
usb_hif_cleanup_pipe_resources(struct HIF_DEVICE_USB * device)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 */
usb_hif_flush_pending_transfers(struct HIF_USB_PIPE * pipe)459 static void usb_hif_flush_pending_transfers(struct HIF_USB_PIPE *pipe)
460 {
461 struct HIF_URB_CONTEXT *urb_context;
462
463 hif_info("+ pipe: %d", pipe->logical_pipe_num);
464
465 while (1) {
466 urb_context = usb_hif_dequeue_pending_transfer(pipe);
467 if (!urb_context) {
468 hif_warn("urb_context is NULL");
469 break;
470 }
471 hif_info("pending urb ctxt: 0x%pK", urb_context);
472 if (urb_context->urb) {
473 hif_info("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_info("-");
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 */
usb_hif_flush_all(struct HIF_DEVICE_USB * device)489 void usb_hif_flush_all(struct HIF_DEVICE_USB *device)
490 {
491 int i;
492 struct HIF_USB_PIPE *pipe;
493
494 hif_info("+");
495
496 for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
497 if (device->pipes[i].device) {
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_info("-");
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 */
usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT * urb_context)514 static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context)
515 {
516
517 if (urb_context->buf) {
518 qdf_nbuf_free(urb_context->buf);
519 urb_context->buf = NULL;
520 }
521
522 usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
523 }
524
525 /**
526 * usb_hif_cleanup_transmit_urb() - cleanup transmit urb
527 * @urb_context: pointer to struct HIF_URB_CONTEXT structure
528 *
529 * Return: none
530 */
usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT * urb_context)531 void usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT *urb_context)
532 {
533 usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
534 }
535
536 /**
537 * usb_hif_usb_recv_prestart_complete() - completion routine for prestart rx urb
538 * @urb: urb for which the completion routine is being called
539 *
540 * Return: none
541 */
usb_hif_usb_recv_prestart_complete(struct urb * urb)542 static void usb_hif_usb_recv_prestart_complete
543 (struct urb *urb)
544 {
545 struct HIF_URB_CONTEXT *urb_context =
546 (struct HIF_URB_CONTEXT *) urb->context;
547 QDF_STATUS status = QDF_STATUS_SUCCESS;
548 qdf_nbuf_t buf = NULL;
549 struct HIF_USB_PIPE *pipe = urb_context->pipe;
550 struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
551
552 hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
553 pipe->logical_pipe_num,
554 urb->status, urb->actual_length,
555 urb);
556
557 /* this urb is not pending anymore */
558 usb_hif_remove_pending_transfer(urb_context);
559 do {
560 if (urb->status != 0) {
561 status = A_ECOMM;
562 switch (urb->status) {
563 case -ECONNRESET:
564 case -ENOENT:
565 case -ESHUTDOWN:
566 /* NOTE: no need to spew these errors when
567 * device is removed
568 * or urb is killed due to driver shutdown
569 */
570 status = A_ECANCELED;
571 break;
572 default:
573 hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
574 pipe->logical_pipe_num,
575 pipe->ep_address,
576 urb->status);
577 break;
578 }
579 break;
580 }
581 if (urb->actual_length == 0)
582 break;
583 buf = urb_context->buf;
584 /* we are going to pass it up */
585 urb_context->buf = NULL;
586 qdf_nbuf_put_tail(buf, urb->actual_length);
587
588 if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
589 uint8_t *data;
590 uint32_t len;
591
592 qdf_nbuf_peek_header(buf, &data, &len);
593 debug_dump_bytes(data, len, "hif recv data");
594 }
595 /* note: queue implements a lock */
596 skb_queue_tail(&pipe->io_comp_queue, buf);
597
598 HIF_USB_SCHEDULE_WORK(pipe);
599 } while (false);
600
601 usb_hif_cleanup_recv_urb(urb_context);
602
603 /* Prestart URBs runs out and now start working receive pipe. */
604 qdf_spin_lock_irqsave(&pipe->device->rx_prestart_lock);
605 if ((--pipe->urb_prestart_cnt == 0) && !sc->suspend_state)
606 usb_hif_start_recv_pipes(pipe->device);
607 qdf_spin_unlock_irqrestore(&pipe->device->rx_prestart_lock);
608
609 hif_debug("-");
610 }
611
612 /**
613 * usb_hif_usb_recv_complete() - completion routine for rx urb
614 * @urb: urb for which the completion routine is being called
615 *
616 * Return: none
617 */
usb_hif_usb_recv_complete(struct urb * urb)618 static void usb_hif_usb_recv_complete(struct urb *urb)
619 {
620 struct HIF_URB_CONTEXT *urb_context =
621 (struct HIF_URB_CONTEXT *) urb->context;
622 QDF_STATUS status = QDF_STATUS_SUCCESS;
623 qdf_nbuf_t buf = NULL;
624 struct HIF_USB_PIPE *pipe = urb_context->pipe;
625 struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
626
627 hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
628 pipe->logical_pipe_num,
629 urb->status, urb->actual_length,
630 urb);
631
632 /* this urb is not pending anymore */
633 usb_hif_remove_pending_transfer(urb_context);
634
635 do {
636
637 if (urb->status != 0) {
638 status = A_ECOMM;
639 switch (urb->status) {
640 #ifdef RX_SG_SUPPORT
641 case -EOVERFLOW:
642 urb->actual_length = HIF_USB_RX_BUFFER_SIZE;
643 status = QDF_STATUS_SUCCESS;
644 break;
645 #endif
646 case -ECONNRESET:
647 case -ENOENT:
648 case -ESHUTDOWN:
649 /* NOTE: no need to spew these errors when
650 * device is removed
651 * or urb is killed due to driver shutdown
652 */
653 status = A_ECANCELED;
654 break;
655 default:
656 hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
657 pipe->logical_pipe_num,
658 pipe->ep_address,
659 urb->status);
660 break;
661 }
662 break;
663 }
664 if (urb->actual_length == 0)
665 break;
666 buf = urb_context->buf;
667 /* we are going to pass it up */
668 urb_context->buf = NULL;
669 qdf_nbuf_put_tail(buf, urb->actual_length);
670 if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
671 uint8_t *data;
672 uint32_t len;
673
674 qdf_nbuf_peek_header(buf, &data, &len);
675 debug_dump_bytes(data, len, "hif recv data");
676 }
677 /* note: queue implements a lock */
678 skb_queue_tail(&pipe->io_comp_queue, buf);
679
680 if (pipe->device->htc_callbacks.update_bundle_stats)
681 pipe->device->htc_callbacks.update_bundle_stats
682 (pipe->device->htc_callbacks.Context, 1);
683
684 HIF_USB_SCHEDULE_WORK(pipe);
685 } while (false);
686
687 usb_hif_cleanup_recv_urb(urb_context);
688
689 /* Only re-submit URB when STATUS is success and HIF is not at the
690 * suspend state.
691 */
692 if (QDF_IS_STATUS_SUCCESS(status) && !sc->suspend_state) {
693 if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
694 /* our free urbs are piling up, post more transfers */
695 usb_hif_post_recv_transfers(pipe,
696 HIF_USB_RX_BUFFER_SIZE);
697 }
698 } else {
699 hif_err("pipe: %d, fail to post URB: status: %d suspend: %d",
700 pipe->logical_pipe_num,
701 urb->status,
702 sc->suspend_state);
703 }
704
705 hif_debug("-");
706 }
707
708 /**
709 * usb_hif_usb_recv_bundle_complete() - completion routine for rx bundling urb
710 * @urb: urb for which the completion routine is being called
711 *
712 * Return: none
713 */
usb_hif_usb_recv_bundle_complete(struct urb * urb)714 static void usb_hif_usb_recv_bundle_complete(struct urb *urb)
715 {
716 struct HIF_URB_CONTEXT *urb_context =
717 (struct HIF_URB_CONTEXT *) urb->context;
718 QDF_STATUS status = QDF_STATUS_SUCCESS;
719 qdf_nbuf_t buf = NULL;
720 struct HIF_USB_PIPE *pipe = urb_context->pipe;
721 uint8_t *netdata, *netdata_new;
722 uint32_t netlen, netlen_new;
723 HTC_FRAME_HDR *HtcHdr;
724 uint16_t payloadLen;
725 qdf_nbuf_t new_skb = NULL;
726 uint8_t no_of_pkt_in_bundle;
727
728 hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
729 pipe->logical_pipe_num,
730 urb->status, urb->actual_length,
731 urb);
732
733 /* this urb is not pending anymore */
734 usb_hif_remove_pending_transfer(urb_context);
735
736 do {
737
738 if (urb->status != 0) {
739 status = A_ECOMM;
740 switch (urb->status) {
741 case -ECONNRESET:
742 case -ENOENT:
743 case -ESHUTDOWN:
744 /* NOTE: no need to spew these errors when
745 * device is removed
746 * or urb is killed due to driver shutdown
747 */
748 status = A_ECANCELED;
749 break;
750 default:
751 hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
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 no_of_pkt_in_bundle = 0;
773
774 do {
775 uint16_t frame_len;
776
777 if (IS_FW_CRASH_DUMP(*(uint32_t *) netdata))
778 frame_len = netlen;
779 else {
780 /* Hack into HTC header for bundle processing */
781 HtcHdr = (HTC_FRAME_HDR *) netdata;
782 if (HtcHdr->EndpointID >= ENDPOINT_MAX) {
783 hif_err("athusb: Rx: invalid EndpointID=%d",
784 HtcHdr->EndpointID);
785 break;
786 }
787
788 payloadLen = HtcHdr->PayloadLen;
789 payloadLen = qdf_le16_to_cpu(payloadLen);
790
791 if (payloadLen > HIF_USB_RX_BUFFER_SIZE) {
792 hif_err("athusb: payloadLen too long %u",
793 payloadLen);
794 break;
795 }
796 frame_len = (HTC_HDR_LENGTH + payloadLen);
797 }
798
799 if (netlen < frame_len) {
800 hif_err("athusb: subframe length %d not fitted into bundle packet length %d"
801 , netlen, frame_len);
802 break;
803 }
804
805 /* allocate a new skb and copy */
806 new_skb =
807 qdf_nbuf_alloc(NULL, frame_len, 0, 4, false);
808 if (!new_skb) {
809 hif_err("athusb: allocate skb (len=%u) failed"
810 , frame_len);
811 break;
812 }
813
814 qdf_nbuf_peek_header(new_skb, &netdata_new,
815 &netlen_new);
816 qdf_mem_copy(netdata_new, netdata, frame_len);
817 qdf_nbuf_put_tail(new_skb, frame_len);
818 skb_queue_tail(&pipe->io_comp_queue, new_skb);
819 new_skb = NULL;
820 netdata += frame_len;
821 netlen -= frame_len;
822 no_of_pkt_in_bundle++;
823 } while (netlen);
824
825 if (pipe->device->htc_callbacks.update_bundle_stats)
826 pipe->device->htc_callbacks.update_bundle_stats
827 (pipe->device->htc_callbacks.Context,
828 no_of_pkt_in_bundle);
829
830 HIF_USB_SCHEDULE_WORK(pipe);
831 } while (false);
832
833 if (!urb_context->buf)
834 hif_err("athusb: buffer in urb_context is NULL");
835
836 /* reset urb_context->buf ==> seems not necessary */
837 usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
838
839 if (QDF_IS_STATUS_SUCCESS(status)) {
840 if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
841 /* our free urbs are piling up, post more transfers */
842 usb_hif_post_recv_bundle_transfers(pipe,
843 pipe->device->rx_bundle_buf_len);
844 }
845 }
846
847 hif_debug("-");
848 }
849
850 /**
851 * usb_hif_post_recv_prestart_transfers() - post prestart recv urbs for a pipe
852 * @recv_pipe: rx data pipe
853 * @prestart_urb: number of prestart recv urbs to be posted
854 *
855 * Return: none
856 */
usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE * recv_pipe,int prestart_urb)857 static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe,
858 int prestart_urb)
859 {
860 struct HIF_URB_CONTEXT *urb_context;
861 uint8_t *data;
862 uint32_t len;
863 struct urb *urb;
864 int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE;
865
866 hif_info("+");
867
868 qdf_spin_lock_irqsave(&recv_pipe->device->rx_prestart_lock);
869 for (i = 0; i < prestart_urb; i++) {
870 urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
871 if (!urb_context)
872 break;
873
874 urb_context->buf =
875 qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
876 if (!urb_context->buf) {
877 usb_hif_cleanup_recv_urb(urb_context);
878 break;
879 }
880
881 qdf_nbuf_peek_header(urb_context->buf, &data, &len);
882
883 urb = urb_context->urb;
884
885 usb_fill_bulk_urb(urb,
886 recv_pipe->device->udev,
887 recv_pipe->usb_pipe_handle,
888 data,
889 buffer_length,
890 usb_hif_usb_recv_prestart_complete,
891 urb_context);
892
893 hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
894 recv_pipe->logical_pipe_num,
895 recv_pipe->usb_pipe_handle,
896 recv_pipe->ep_address, buffer_length,
897 urb_context->buf);
898
899 usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
900 usb_status = usb_submit_urb(urb, GFP_ATOMIC);
901
902 if (usb_status) {
903 hif_err("athusb : usb bulk recv failed %d",
904 usb_status);
905 usb_hif_remove_pending_transfer(urb_context);
906 usb_hif_cleanup_recv_urb(urb_context);
907 break;
908 }
909 recv_pipe->urb_prestart_cnt++;
910 }
911 qdf_spin_unlock_irqrestore(&recv_pipe->device->rx_prestart_lock);
912
913 hif_info("-");
914 }
915
916 /**
917 * usb_hif_post_recv_transfers() - post recv urbs for a given pipe
918 * @recv_pipe: recv pipe for which urbs need to be posted
919 * @buffer_length: buffer length of the recv urbs
920 *
921 * Return: none
922 */
usb_hif_post_recv_transfers(struct HIF_USB_PIPE * recv_pipe,int buffer_length)923 static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
924 int buffer_length)
925 {
926 struct HIF_URB_CONTEXT *urb_context;
927 uint8_t *data;
928 uint32_t len;
929 struct urb *urb;
930 int usb_status;
931
932 while (1) {
933
934 urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
935 if (!urb_context)
936 break;
937
938 urb_context->buf = qdf_nbuf_alloc(NULL, buffer_length, 0,
939 4, false);
940 if (!urb_context->buf) {
941 usb_hif_cleanup_recv_urb(urb_context);
942 break;
943 }
944
945 qdf_nbuf_peek_header(urb_context->buf, &data, &len);
946
947 urb = urb_context->urb;
948
949 usb_fill_bulk_urb(urb,
950 recv_pipe->device->udev,
951 recv_pipe->usb_pipe_handle,
952 data,
953 buffer_length,
954 usb_hif_usb_recv_complete, urb_context);
955
956 hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
957 recv_pipe->logical_pipe_num,
958 recv_pipe->usb_pipe_handle,
959 recv_pipe->ep_address, buffer_length,
960 urb_context->buf);
961
962 usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
963
964 usb_status = usb_submit_urb(urb, GFP_ATOMIC);
965
966 if (usb_status) {
967 hif_err("athusb : usb bulk recv failed %d",
968 usb_status);
969 usb_hif_remove_pending_transfer(urb_context);
970 usb_hif_cleanup_recv_urb(urb_context);
971 break;
972 }
973 }
974
975 }
976
977 /**
978 * usb_hif_post_recv_bundle_transfers() - post recv urbs for a given pipe
979 * @recv_pipe: recv pipe for which urbs need to be posted
980 * @buffer_length: maximum length of rx bundle
981 *
982 * Return: none
983 */
usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE * recv_pipe,int buffer_length)984 static void usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE *recv_pipe,
985 int buffer_length)
986 {
987 struct HIF_URB_CONTEXT *urb_context;
988 uint8_t *data;
989 uint32_t len;
990 struct urb *urb;
991 int usb_status;
992
993 while (1) {
994
995 urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
996 if (!urb_context)
997 break;
998
999 if (!urb_context->buf) {
1000 urb_context->buf =
1001 qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
1002 if (!urb_context->buf) {
1003 usb_hif_cleanup_recv_urb(urb_context);
1004 break;
1005 }
1006 }
1007
1008 qdf_nbuf_peek_header(urb_context->buf, &data, &len);
1009
1010 urb = urb_context->urb;
1011 usb_fill_bulk_urb(urb,
1012 recv_pipe->device->udev,
1013 recv_pipe->usb_pipe_handle,
1014 data,
1015 buffer_length,
1016 usb_hif_usb_recv_bundle_complete,
1017 urb_context);
1018
1019 hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
1020 recv_pipe->logical_pipe_num,
1021 recv_pipe->usb_pipe_handle,
1022 recv_pipe->ep_address, buffer_length,
1023 urb_context->buf);
1024
1025 usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
1026
1027 usb_status = usb_submit_urb(urb, GFP_ATOMIC);
1028
1029 if (usb_status) {
1030 hif_err("athusb : usb bulk recv failed %d",
1031 usb_status);
1032 usb_hif_remove_pending_transfer(urb_context);
1033 usb_hif_free_urb_to_pipe(urb_context->pipe,
1034 urb_context);
1035 break;
1036 }
1037
1038 }
1039
1040 }
1041
1042 /**
1043 * usb_hif_prestart_recv_pipes() - post prestart recv urbs
1044 * @device: HIF device for which prestart recv urbs need to be posted
1045 *
1046 * Return: none
1047 */
usb_hif_prestart_recv_pipes(struct HIF_DEVICE_USB * device)1048 void usb_hif_prestart_recv_pipes(struct HIF_DEVICE_USB *device)
1049 {
1050 struct HIF_USB_PIPE *pipe;
1051 int prestart_cnt = 8;
1052
1053 if (device->rx_ctrl_pipe_supported) {
1054 pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1055 prestart_cnt = 4;
1056 usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1057 }
1058 /*
1059 * USB driver learn to support bundle or not until the firmware
1060 * download and ready. Only allocate some URBs for control message
1061 * communication during the initial phase then start the final
1062 * working pipe after all information understood.
1063 */
1064 pipe = &device->pipes[HIF_RX_DATA_PIPE];
1065 usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1066 }
1067
1068 /**
1069 * usb_hif_start_recv_pipes() - start recv urbs
1070 * @device: HIF device for which recv urbs need to be posted
1071 *
1072 * This function is called after all prestart recv urbs are exhausted
1073 *
1074 * Return: none
1075 */
usb_hif_start_recv_pipes(struct HIF_DEVICE_USB * device)1076 void usb_hif_start_recv_pipes(struct HIF_DEVICE_USB *device)
1077 {
1078 struct HIF_USB_PIPE *pipe;
1079 uint32_t buf_len;
1080
1081 HIF_ENTER();
1082 pipe = &device->pipes[HIF_RX_DATA_PIPE];
1083 pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1084
1085 hif_info("Post URBs to RX_DATA_PIPE: %d is_bundle %d",
1086 device->pipes[HIF_RX_DATA_PIPE].urb_cnt,
1087 device->is_bundle_enabled);
1088 if (device->is_bundle_enabled) {
1089 usb_hif_post_recv_bundle_transfers(pipe,
1090 pipe->device->rx_bundle_buf_len);
1091 } else {
1092 buf_len = HIF_USB_RX_BUFFER_SIZE;
1093 usb_hif_post_recv_transfers(pipe, buf_len);
1094 }
1095
1096 hif_debug("athusb bulk recv len %d", buf_len);
1097
1098 if (!hif_usb_disable_rxdata2) {
1099 hif_info("Post URBs to RX_DATA2_PIPE: %d",
1100 device->pipes[HIF_RX_DATA2_PIPE].urb_cnt);
1101
1102 pipe = &device->pipes[HIF_RX_DATA2_PIPE];
1103 pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1104 usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1105 }
1106
1107 if (device->rx_ctrl_pipe_supported) {
1108 hif_info("Post URBs to RX_CONTROL_PIPE: %d",
1109 device->pipes[HIF_RX_CTRL_PIPE].urb_cnt);
1110
1111 pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1112 pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1113 usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1114 }
1115 HIF_EXIT();
1116 }
1117
1118 /**
1119 * usb_hif_submit_ctrl_out() - send out a ctrl urb
1120 * @device: HIF device for which urb needs to be posted
1121 * @req: request value for the ctrl message
1122 * @value: USB message value
1123 * @index: USB message index value
1124 * @data: pointer to data containing ctrl message to send
1125 * @size: size of the control message to send
1126 *
1127 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1128 */
usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB * device,uint8_t req,uint16_t value,uint16_t index,void * data,uint32_t size)1129 QDF_STATUS usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB *device,
1130 uint8_t req, uint16_t value, uint16_t index,
1131 void *data, uint32_t size)
1132 {
1133 int32_t result = 0;
1134 QDF_STATUS ret = QDF_STATUS_SUCCESS;
1135 uint8_t *buf = NULL;
1136
1137 do {
1138
1139 if (size > 0) {
1140 buf = qdf_mem_malloc(size);
1141 if (!buf) {
1142 ret = QDF_STATUS_E_NOMEM;
1143 break;
1144 }
1145 qdf_mem_copy(buf, (uint8_t *) data, size);
1146 }
1147
1148 hif_debug("ctrl-out req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1149 req, value, index, size);
1150
1151 result = usb_control_msg(device->udev,
1152 usb_sndctrlpipe(device->udev, 0),
1153 req,
1154 USB_DIR_OUT | USB_TYPE_VENDOR |
1155 USB_RECIP_DEVICE, value, index, buf,
1156 size, 2 * HZ);
1157
1158 if (result < 0) {
1159 hif_err("usb_control_msg failed, (result=%d)", result);
1160 ret = QDF_STATUS_E_FAILURE;
1161 }
1162
1163 } while (false);
1164
1165 if (buf)
1166 qdf_mem_free(buf);
1167
1168 return ret;
1169 }
1170
1171 /**
1172 * usb_hif_submit_ctrl_in() - recv a response to the ctrl message sent out
1173 * @device: HIF device for which urb needs to be received
1174 * @req: request value for the ctrl message
1175 * @value: USB message value
1176 * @index: USB message index value
1177 * @data: pointer to data containing ctrl message to be received
1178 * @size: size of the control message to be received
1179 *
1180 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1181 */
usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB * device,uint8_t req,uint16_t value,uint16_t index,void * data,uint32_t size)1182 QDF_STATUS usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB *device,
1183 uint8_t req, uint16_t value, uint16_t index,
1184 void *data, uint32_t size)
1185 {
1186 int32_t result = 0;
1187 QDF_STATUS ret = QDF_STATUS_SUCCESS;
1188 uint8_t *buf = NULL;
1189
1190 do {
1191
1192 if (size > 0) {
1193 buf = qdf_mem_malloc(size);
1194 if (!buf) {
1195 ret = QDF_STATUS_E_NOMEM;
1196 break;
1197 }
1198 }
1199
1200 hif_debug("ctrl-in req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1201 req, value, index, size);
1202
1203 result = usb_control_msg(device->udev,
1204 usb_rcvctrlpipe(device->udev, 0),
1205 req,
1206 USB_DIR_IN | USB_TYPE_VENDOR |
1207 USB_RECIP_DEVICE, value, index, buf,
1208 size, 2 * HZ);
1209
1210 if (result < 0) {
1211 hif_err("usb_control_msg failed, (result=%d)", result);
1212 ret = QDF_STATUS_E_FAILURE;
1213 break;
1214 }
1215
1216 qdf_mem_copy((uint8_t *) data, buf, size);
1217
1218 } while (false);
1219
1220 if (buf)
1221 qdf_mem_free(buf);
1222
1223 return ret;
1224 }
1225
1226 /**
1227 * usb_hif_io_complete() - transmit call back for tx urb
1228 * @pipe: pointer to struct HIF_USB_PIPE
1229 *
1230 * Return: none
1231 */
usb_hif_io_complete(struct HIF_USB_PIPE * pipe)1232 static void usb_hif_io_complete(struct HIF_USB_PIPE *pipe)
1233 {
1234 qdf_nbuf_t buf;
1235 struct HIF_DEVICE_USB *device;
1236 HTC_FRAME_HDR *HtcHdr;
1237 uint8_t *data;
1238 uint32_t len;
1239 struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
1240
1241 device = pipe->device;
1242 HIF_ENTER();
1243 while ((buf = skb_dequeue(&pipe->io_comp_queue))) {
1244 if (pipe->flags & HIF_USB_PIPE_FLAG_TX) {
1245 hif_debug("+athusb xmit callback buf:0x%pK", buf);
1246 HtcHdr = (HTC_FRAME_HDR *)
1247 qdf_nbuf_get_frag_vaddr(buf, 0);
1248
1249 #ifdef ATH_11AC_TXCOMPACT
1250 /* ATH_11AC_TXCOMPACT does not support High Latency mode */
1251 #else
1252 device->htc_callbacks.txCompletionHandler(device->
1253 htc_callbacks.
1254 Context, buf,
1255 HtcHdr->
1256 EndpointID, 0);
1257 #endif
1258 hif_debug("-athusb xmit callback");
1259 } else {
1260 hif_debug("+athusb recv callback buf: 0x%pK", buf);
1261 qdf_nbuf_peek_header(buf, &data, &len);
1262
1263 if (IS_FW_CRASH_DUMP(*((uint32_t *) data))) {
1264 sc->fw_data = data;
1265 sc->fw_data_len = len;
1266 device->htc_callbacks.fwEventHandler(
1267 device->htc_callbacks.Context,
1268 QDF_STATUS_E_USB_ERROR);
1269 qdf_nbuf_free(buf);
1270 } else {
1271 device->htc_callbacks.rxCompletionHandler(
1272 device->htc_callbacks.Context, buf,
1273 pipe->logical_pipe_num);
1274 }
1275 hif_debug("-athusb recv callback");
1276 }
1277 }
1278
1279 HIF_EXIT();
1280 }
1281
1282 #ifdef HIF_USB_TASKLET
1283 /**
1284 * usb_hif_io_comp_tasklet() - per pipe tasklet routine
1285 * @context: pointer to HIF USB pipe
1286 *
1287 * Return: none
1288 */
usb_hif_io_comp_tasklet(unsigned long context)1289 void usb_hif_io_comp_tasklet(unsigned long context)
1290 {
1291 struct HIF_USB_PIPE *pipe = (struct HIF_USB_PIPE *) context;
1292
1293 usb_hif_io_complete(pipe);
1294 }
1295
1296 #else
1297 /**
1298 * usb_hif_io_comp_work() - per pipe work queue
1299 * @work: pointer to struct work_struct
1300 *
1301 * Return: none
1302 */
usb_hif_io_comp_work(struct work_struct * work)1303 void usb_hif_io_comp_work(struct work_struct *work)
1304 {
1305 struct HIF_USB_PIPE *pipe = container_of(work, struct HIF_USB_PIPE,
1306 io_complete_work);
1307
1308 usb_hif_io_complete(pipe);
1309 }
1310 #endif
1311