xref: /wlan-driver/qca-wifi-host-cmn/hif/src/usb/usbdrv.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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