xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/usb/hif_usb.c (revision c8e2987f9325baadee03d0265544a08c4a0217b0)
1 /*
2  * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 #include <qdf_time.h>
28 #include <qdf_lock.h>
29 #include <qdf_mem.h>
30 #include <qdf_util.h>
31 #include <qdf_defer.h>
32 #include <qdf_atomic.h>
33 #include <qdf_nbuf.h>
34 #include "qdf_net_types.h"
35 #include <hif_usb_internal.h>
36 #include <htc_services.h>
37 #include <hif_debug.h>
38 #define ATH_MODULE_NAME hif
39 #include <a_debug.h>
40 #include "qdf_module.h"
41 #include "hif_usb_internal.h"
42 #include "if_usb.h"
43 #include "usb_api.h"
44 
45 #if defined(WLAN_DEBUG) || defined(DEBUG)
46 static ATH_DEBUG_MASK_DESCRIPTION g_hif_debug_description[] = {
47 	{USB_HIF_DEBUG_CTRL_TRANS, "Control Transfers"},
48 	{USB_HIF_DEBUG_BULK_IN, "BULK In Transfers"},
49 	{USB_HIF_DEBUG_BULK_OUT, "BULK Out Transfers"},
50 	{USB_HIF_DEBUG_DUMP_DATA, "Dump data"},
51 	{USB_HIF_DEBUG_ENUM, "Enumeration"},
52 };
53 
54 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
55 				 "hif",
56 				 "USB Host Interface",
57 				 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO |
58 				 USB_HIF_DEBUG_ENUM,
59 				 ATH_DEBUG_DESCRIPTION_COUNT
60 				 (g_hif_debug_description),
61 				 g_hif_debug_description);
62 
63 #endif
64 
65 #ifdef USB_ISOC_SUPPORT
66 unsigned int hif_usb_isoch_vo = 1;
67 #else
68 unsigned int hif_usb_isoch_vo;
69 #endif
70 unsigned int hif_usb_disable_rxdata2 = 1;
71 
72 /**
73  * usb_hif_usb_transmit_complete() - completion routing for tx urb's
74  * @urb: pointer to urb for which tx completion is called
75  *
76  * Return: none
77  */
78 static void usb_hif_usb_transmit_complete(struct urb *urb)
79 {
80 	struct HIF_URB_CONTEXT *urb_context =
81 		(struct HIF_URB_CONTEXT *)urb->context;
82 	qdf_nbuf_t buf;
83 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
84 	struct hif_usb_send_context *send_context;
85 
86 	HIF_DBG("+%s: pipe: %d, stat:%d, len:%d", __func__,
87 		pipe->logical_pipe_num, urb->status, urb->actual_length);
88 
89 	/* this urb is not pending anymore */
90 	usb_hif_remove_pending_transfer(urb_context);
91 
92 	if (urb->status != 0) {
93 		HIF_ERROR("%s:  pipe: %d, failed:%d",
94 			  __func__, pipe->logical_pipe_num, urb->status);
95 	}
96 
97 	buf = urb_context->buf;
98 	send_context = urb_context->send_context;
99 
100 	if (send_context->new_alloc)
101 		qdf_mem_free(send_context);
102 	else
103 		qdf_nbuf_pull_head(buf, send_context->head_data_len);
104 
105 	urb_context->buf = NULL;
106 	usb_hif_cleanup_transmit_urb(urb_context);
107 
108 	/* note: queue implements a lock */
109 	skb_queue_tail(&pipe->io_comp_queue, buf);
110 	HIF_USB_SCHEDULE_WORK(pipe);
111 
112 	HIF_DBG("-%s", __func__);
113 }
114 
115 /**
116  * hif_send_internal() - HIF internal routine to prepare and submit tx urbs
117  * @hif_usb_device: pointer to HIF_DEVICE_USB structure
118  * @pipe_id: HIF pipe on which data is to be sent
119  * @hdr_buf: any header buf to be prepended, currently ignored
120  * @buf: qdf_nbuf_t containing data to be transmitted
121  * @nbytes: number of bytes to be transmitted
122  *
123  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
124  */
125 static QDF_STATUS hif_send_internal(struct HIF_DEVICE_USB *hif_usb_device,
126 				    uint8_t pipe_id,
127 				    qdf_nbuf_t hdr_buf,
128 				    qdf_nbuf_t buf, unsigned int nbytes)
129 {
130 	QDF_STATUS status = QDF_STATUS_SUCCESS;
131 	struct HIF_DEVICE_USB *device = hif_usb_device;
132 	struct HIF_USB_PIPE *pipe = &device->pipes[pipe_id];
133 	struct HIF_URB_CONTEXT *urb_context;
134 	uint8_t *data;
135 	uint32_t len;
136 	struct urb *urb;
137 	int usb_status;
138 	int i;
139 	struct hif_usb_send_context *send_context;
140 	uint8_t frag_count;
141 	uint32_t head_data_len, tmp_frag_count = 0;
142 	unsigned char *data_ptr;
143 
144 	HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u",
145 		__func__, pipe_id, buf, nbytes);
146 
147 	frag_count = qdf_nbuf_get_num_frags(buf);
148 	if (frag_count == 1) {
149 		/*
150 		 * | hif_usb_send_context | netbuf->data
151 		 */
152 		head_data_len = sizeof(struct hif_usb_send_context);
153 	} else if ((frag_count - 1) <= QDF_NBUF_CB_TX_MAX_EXTRA_FRAGS) {
154 		/*
155 		 * means have extra fragment buf in skb
156 		 * header data length should be total sending length substract
157 		 * internal data length of netbuf
158 		 * | hif_usb_send_context | fragments except internal buffer |
159 		 * netbuf->data
160 		 */
161 		head_data_len = sizeof(struct hif_usb_send_context);
162 		while (tmp_frag_count < (frag_count - 1)) {
163 			head_data_len =
164 				head_data_len + qdf_nbuf_get_frag_len(buf,
165 						tmp_frag_count);
166 			tmp_frag_count = tmp_frag_count + 1;
167 		}
168 	} else {
169 		/* Extra fragments overflow */
170 		HIF_ERROR("%s Extra fragments count overflow : %d\n",
171 			  __func__, frag_count);
172 		status = QDF_STATUS_E_RESOURCES;
173 		goto err;
174 	}
175 
176 	/* Check whether head room is enough to save extra head data */
177 	if (head_data_len <= qdf_nbuf_headroom(buf)) {
178 		send_context = (struct hif_usb_send_context *)
179 		    qdf_nbuf_push_head(buf, head_data_len);
180 		send_context->new_alloc = false;
181 	} else {
182 		send_context =
183 		    qdf_mem_malloc(sizeof(struct hif_usb_send_context)
184 				   + head_data_len + nbytes);
185 		if (send_context == NULL) {
186 			HIF_ERROR("%s: qdf_mem_malloc failed", __func__);
187 			status = QDF_STATUS_E_NOMEM;
188 			goto err;
189 		}
190 		send_context->new_alloc = true;
191 	}
192 	send_context->netbuf = buf;
193 	send_context->hif_usb_device = hif_usb_device;
194 	send_context->transfer_id = pipe_id;
195 	send_context->head_data_len = head_data_len;
196 	/*
197 	 * Copy data to head part of netbuf or head of allocated buffer.
198 	 * if buffer is new allocated, the last buffer should be copied also.
199 	 * It assume last fragment is internal buffer of netbuf
200 	 * sometime total length of fragments larger than nbytes
201 	 */
202 	data_ptr = (unsigned char *)send_context +
203 				sizeof(struct hif_usb_send_context);
204 	for (i = 0;
205 	     i < (send_context->new_alloc ? frag_count : frag_count - 1); i++) {
206 		int frag_len = qdf_nbuf_get_frag_len(buf, i);
207 		unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i);
208 
209 		qdf_mem_copy(data_ptr, frag_addr, frag_len);
210 		data_ptr += frag_len;
211 	}
212 	/* Reset pData pointer and send out */
213 	data_ptr = (unsigned char *)send_context +
214 				sizeof(struct hif_usb_send_context);
215 
216 	urb_context = usb_hif_alloc_urb_from_pipe(pipe);
217 	if (NULL == urb_context) {
218 		/* TODO : note, it is possible to run out of urbs if 2
219 		 * endpoints map to the same pipe ID
220 		 */
221 		HIF_ERROR("%s pipe:%d no urbs left. URB Cnt : %d",
222 			__func__, pipe_id, pipe->urb_cnt);
223 		status = QDF_STATUS_E_RESOURCES;
224 		goto err;
225 	}
226 	urb_context->send_context = send_context;
227 	urb = urb_context->urb;
228 	urb_context->buf = buf;
229 	data = data_ptr;
230 	len = nbytes;
231 
232 	usb_fill_bulk_urb(urb,
233 			  device->udev,
234 			  pipe->usb_pipe_handle,
235 			  data,
236 			  (len % pipe->max_packet_size) ==
237 			  0 ? (len + 1) : len,
238 			  usb_hif_usb_transmit_complete, urb_context);
239 
240 	if ((len % pipe->max_packet_size) == 0)
241 		/* hit a max packet boundary on this pipe */
242 
243 	HIF_DBG
244 	    ("athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes",
245 	     pipe->logical_pipe_num, pipe->usb_pipe_handle,
246 	     pipe->ep_address, nbytes);
247 
248 	usb_hif_enqueue_pending_transfer(pipe, urb_context);
249 	usb_status = usb_submit_urb(urb, GFP_ATOMIC);
250 	if (usb_status) {
251 		if (send_context->new_alloc)
252 			qdf_mem_free(send_context);
253 		else
254 			qdf_nbuf_pull_head(buf, head_data_len);
255 		urb_context->buf = NULL;
256 		HIF_ERROR("athusb : usb bulk transmit failed %d",
257 				usb_status);
258 		usb_hif_remove_pending_transfer(urb_context);
259 		usb_hif_cleanup_transmit_urb(urb_context);
260 		status = QDF_STATUS_E_FAILURE;
261 		goto err;
262 	}
263 
264 err:
265 	if (!QDF_IS_STATUS_SUCCESS(status) &&
266 				(status != QDF_STATUS_E_RESOURCES)) {
267 		HIF_ERROR("athusb send failed %d", status);
268 	}
269 
270 	HIF_DBG("-%s pipe : %d", __func__, pipe_id);
271 
272 	return status;
273 }
274 
275 /**
276  * hif_send_head() - HIF routine exposed to upper layers to send data
277  * @scn: pointer to hif_opaque_softc structure
278  * @pipe_id: HIF pipe on which data is to be sent
279  * @transfer_id: endpoint ID on which data is to be sent
280  * @nbytes: number of bytes to be transmitted
281  * @wbuf: qdf_nbuf_t containing data to be transmitted
282  * @hdr_buf: any header buf to be prepended, currently ignored
283  * @data_attr: data_attr field from cvg_nbuf_cb of wbuf
284  *
285  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
286  */
287 QDF_STATUS hif_send_head(struct hif_opaque_softc *scn, uint8_t pipe_id,
288 				uint32_t transfer_id, uint32_t nbytes,
289 				qdf_nbuf_t wbuf, uint32_t data_attr)
290 {
291 	QDF_STATUS status = QDF_STATUS_SUCCESS;
292 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
293 
294 	HIF_TRACE("+%s", __func__);
295 	status = hif_send_internal(device, pipe_id, NULL, wbuf, nbytes);
296 	HIF_TRACE("-%s", __func__);
297 	return status;
298 }
299 
300 /**
301  * hif_get_free_queue_number() - get # of free TX resources in a given HIF pipe
302  * @scn: pointer to hif_opaque_softc structure
303  * @pipe_id: HIF pipe which is being polled for free resources
304  *
305  * Return: # of free resources in pipe_id
306  */
307 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn,
308 				   uint8_t pipe_id)
309 {
310 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
311 
312 	return device->pipes[pipe_id].urb_cnt;
313 }
314 
315 /**
316  * hif_post_init() - copy HTC callbacks to HIF
317  * @scn: pointer to hif_opaque_softc structure
318  * @target: pointer to HTC_TARGET structure
319  * @callbacks: htc callbacks
320  *
321  * Return: none
322  */
323 void hif_post_init(struct hif_opaque_softc *scn, void *target,
324 		struct hif_msg_callbacks *callbacks)
325 {
326 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
327 
328 	qdf_mem_copy(&device->htc_callbacks, callbacks,
329 			sizeof(device->htc_callbacks));
330 }
331 
332 /**
333  * hif_detach_htc() - remove HTC callbacks from HIF
334  * @scn: pointer to hif_opaque_softc structure
335  *
336  * Return: none
337  */
338 void hif_detach_htc(struct hif_opaque_softc *scn)
339 {
340 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
341 
342 	usb_hif_flush_all(device);
343 	qdf_mem_zero(&device->htc_callbacks, sizeof(device->htc_callbacks));
344 }
345 
346 /**
347  * hif_usb_device_deinit() - de- init  HIF_DEVICE_USB, cleanup pipe resources
348  * @sc: pointer to hif_usb_softc structure
349  *
350  * Return: None
351  */
352 void hif_usb_device_deinit(struct hif_usb_softc *sc)
353 {
354 	struct HIF_DEVICE_USB *device = &sc->hif_hdl;
355 
356 	HIF_TRACE("+%s", __func__);
357 
358 	usb_hif_cleanup_pipe_resources(device);
359 
360 	usb_set_intfdata(device->interface, NULL);
361 
362 	if (device->diag_cmd_buffer != NULL)
363 		qdf_mem_free(device->diag_cmd_buffer);
364 
365 	if (device->diag_resp_buffer != NULL)
366 		qdf_mem_free(device->diag_resp_buffer);
367 
368 	HIF_TRACE("-%s", __func__);
369 }
370 
371 /**
372  * hif_usb_device_init() - init  HIF_DEVICE_USB, setup pipe resources
373  * @sc: pointer to hif_usb_softc structure
374  *
375  * Return: QDF_STATUS_SUCCESS on success or a QDF error
376  */
377 QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc)
378 {
379 	int i;
380 	struct HIF_DEVICE_USB *device = &sc->hif_hdl;
381 	struct usb_interface *interface = sc->interface;
382 	struct usb_device *dev = interface_to_usbdev(interface);
383 	QDF_STATUS status = QDF_STATUS_SUCCESS;
384 	struct HIF_USB_PIPE *pipe;
385 
386 	HIF_TRACE("+%s", __func__);
387 
388 	do {
389 
390 		usb_set_intfdata(interface, device);
391 		qdf_spinlock_create(&(device->cs_lock));
392 		qdf_spinlock_create(&(device->rx_lock));
393 		qdf_spinlock_create(&(device->tx_lock));
394 		device->udev = dev;
395 		device->interface = interface;
396 
397 		HIF_ERROR("%s device %pK device->udev %pK device->interface %pK",
398 			__func__,
399 			device,
400 			device->udev,
401 			device->interface);
402 
403 		for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
404 			pipe = &device->pipes[i];
405 
406 			HIF_USB_INIT_WORK(pipe);
407 			skb_queue_head_init(&pipe->io_comp_queue);
408 		}
409 
410 		device->diag_cmd_buffer =
411 			qdf_mem_malloc(USB_CTRL_MAX_DIAG_CMD_SIZE);
412 		if (NULL == device->diag_cmd_buffer) {
413 			status = QDF_STATUS_E_NOMEM;
414 			break;
415 		}
416 		device->diag_resp_buffer =
417 			qdf_mem_malloc(USB_CTRL_MAX_DIAG_RESP_SIZE);
418 		if (NULL == device->diag_resp_buffer) {
419 			status = QDF_STATUS_E_NOMEM;
420 			break;
421 		}
422 
423 		status = usb_hif_setup_pipe_resources(device);
424 
425 	} while (false);
426 
427 	if (status != QDF_STATUS_SUCCESS)
428 		HIF_ERROR("%s: abnormal condition", __func__);
429 
430 	HIF_TRACE("+%s", __func__);
431 	return status;
432 }
433 
434 /**
435  * hif_start() - Enable HIF TX and RX
436  * @scn: pointer to hif_opaque_softc structure
437  *
438  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
439  */
440 QDF_STATUS hif_start(struct hif_opaque_softc *scn)
441 {
442 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
443 	int i;
444 
445 	HIF_TRACE("+%s", __func__);
446 	usb_hif_prestart_recv_pipes(device);
447 
448 	/* set the TX resource avail threshold for each TX pipe */
449 	for (i = HIF_TX_CTRL_PIPE; i <= HIF_TX_DATA_HP_PIPE; i++) {
450 		device->pipes[i].urb_cnt_thresh =
451 		    device->pipes[i].urb_alloc / 2;
452 	}
453 
454 	HIF_TRACE("-%s", __func__);
455 	return QDF_STATUS_SUCCESS;
456 }
457 
458 /**
459  * hif_usb_stop_device() - Stop/flush all HIF communication
460  * @scn: pointer to hif_opaque_softc structure
461  *
462  * Return: none
463  */
464 void hif_usb_stop_device(struct hif_softc *hif_sc)
465 {
466 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_sc);
467 
468 	HIF_TRACE("+%s", __func__);
469 
470 	usb_hif_flush_all(device);
471 
472 	HIF_TRACE("-%s", __func__);
473 }
474 
475 /**
476  * hif_get_default_pipe() - get default pipes for HIF TX/RX
477  * @scn: pointer to hif_opaque_softc structure
478  * @ul_pipe: pointer to TX pipe
479  * @ul_pipe: pointer to TX pipe
480  *
481  * Return: none
482  */
483 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe,
484 			  uint8_t *dl_pipe)
485 {
486 	*ul_pipe = HIF_TX_CTRL_PIPE;
487 	*dl_pipe = HIF_RX_CTRL_PIPE;
488 }
489 
490 #if defined(USB_MULTI_IN_TEST) || defined(USB_ISOC_TEST)
491 /**
492  * hif_map_service_to_pipe() - maps ul/dl pipe to service id.
493  * @scn: HIF context
494  * @svc_id: sevice index
495  * @ul_pipe: pointer to uplink pipe id
496  * @dl_pipe: pointer to down-linklink pipe id
497  * @ul_is_polled: if ul is polling based
498  * @ul_is_polled: if dl is polling based
499  *
500  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
501  */
502 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id,
503 			    uint8_t *ul_pipe, uint8_t *dl_pipe,
504 			    int *ul_is_polled, int *dl_is_polled)
505 {
506 	QDF_STATUS status = QDF_STATUS_SUCCESS;
507 
508 	switch (svc_id) {
509 	case HTC_CTRL_RSVD_SVC:
510 	case WMI_CONTROL_SVC:
511 	case HTC_RAW_STREAMS_SVC:
512 		*ul_pipe = HIF_TX_CTRL_PIPE;
513 		*dl_pipe = HIF_RX_DATA_PIPE;
514 		break;
515 	case WMI_DATA_BE_SVC:
516 		*ul_pipe = HIF_TX_DATA_LP_PIPE;
517 		*dl_pipe = HIF_RX_DATA_PIPE;
518 		break;
519 	case WMI_DATA_BK_SVC:
520 		*ul_pipe = HIF_TX_DATA_MP_PIPE;
521 		*dl_pipe = HIF_RX_DATA2_PIPE;
522 		break;
523 	case WMI_DATA_VI_SVC:
524 		*ul_pipe = HIF_TX_DATA_HP_PIPE;
525 		*dl_pipe = HIF_RX_DATA_PIPE;
526 		break;
527 	case WMI_DATA_VO_SVC:
528 		*ul_pipe = HIF_TX_DATA_LP_PIPE;
529 		*dl_pipe = HIF_RX_DATA_PIPE;
530 		break;
531 	default:
532 		status = QDF_STATUS_E_FAILURE;
533 		break;
534 	}
535 
536 	return status;
537 }
538 #else
539 
540 #ifdef QCA_TX_HTT2_SUPPORT
541 #define USB_TX_CHECK_HTT2_SUPPORT 1
542 #else
543 #define USB_TX_CHECK_HTT2_SUPPORT 0
544 #endif
545 
546 /**
547  * hif_map_service_to_pipe() - maps ul/dl pipe to service id.
548  * @scn: HIF context
549  * @svc_id: sevice index
550  * @ul_pipe: pointer to uplink pipe id
551  * @dl_pipe: pointer to down-linklink pipe id
552  * @ul_is_polled: if ul is polling based
553  * @ul_is_polled: if dl is polling based
554  *
555  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
556  */
557 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id,
558 			    uint8_t *ul_pipe, uint8_t *dl_pipe,
559 			    int *ul_is_polled, int *dl_is_polled)
560 {
561 	QDF_STATUS status = QDF_STATUS_SUCCESS;
562 
563 	switch (svc_id) {
564 	case HTC_CTRL_RSVD_SVC:
565 	case WMI_CONTROL_SVC:
566 		*ul_pipe = HIF_TX_CTRL_PIPE;
567 		*dl_pipe = HIF_RX_DATA_PIPE;
568 		break;
569 	case WMI_DATA_BE_SVC:
570 	case WMI_DATA_BK_SVC:
571 		*ul_pipe = HIF_TX_DATA_LP_PIPE;
572 		if (hif_usb_disable_rxdata2)
573 			*dl_pipe = HIF_RX_DATA_PIPE;
574 		else
575 			*dl_pipe = HIF_RX_DATA2_PIPE;
576 		break;
577 	case WMI_DATA_VI_SVC:
578 		*ul_pipe = HIF_TX_DATA_MP_PIPE;
579 		if (hif_usb_disable_rxdata2)
580 			*dl_pipe = HIF_RX_DATA_PIPE;
581 		else
582 			*dl_pipe = HIF_RX_DATA2_PIPE;
583 		break;
584 	case WMI_DATA_VO_SVC:
585 		*ul_pipe = HIF_TX_DATA_HP_PIPE;
586 		if (hif_usb_disable_rxdata2)
587 			*dl_pipe = HIF_RX_DATA_PIPE;
588 		else
589 			*dl_pipe = HIF_RX_DATA2_PIPE;
590 		break;
591 	case HTC_RAW_STREAMS_SVC:
592 		*ul_pipe = HIF_TX_CTRL_PIPE;
593 		*dl_pipe = HIF_RX_DATA_PIPE;
594 		break;
595 	case HTT_DATA_MSG_SVC:
596 		*ul_pipe = HIF_TX_DATA_LP_PIPE;
597 		if (hif_usb_disable_rxdata2)
598 			*dl_pipe = HIF_RX_DATA_PIPE;
599 		else
600 			*dl_pipe = HIF_RX_DATA2_PIPE;
601 		break;
602 	case HTT_DATA2_MSG_SVC:
603 		if (USB_TX_CHECK_HTT2_SUPPORT) {
604 			*ul_pipe = HIF_TX_DATA_HP_PIPE;
605 			if (hif_usb_disable_rxdata2)
606 				*dl_pipe = HIF_RX_DATA_PIPE;
607 			else
608 				*dl_pipe = HIF_RX_DATA2_PIPE;
609 			}
610 		break;
611 	default:
612 		status = QDF_STATUS_E_FAILURE;
613 		break;
614 	}
615 
616 	return status;
617 }
618 #endif
619 
620 /**
621  * hif_ctrl_msg_exchange() - send usb ctrl message and receive response
622  * @macp: pointer to HIF_DEVICE_USB
623  * @send_req_val: USB send message request value
624  * @send_msg: pointer to data to send
625  * @len: length in bytes of the data to send
626  * @response_req_val: USB response message request value
627  * @response_msg: pointer to response msg
628  * @response_len: length of the response message
629  *
630  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
631  */
632 static QDF_STATUS hif_ctrl_msg_exchange(struct HIF_DEVICE_USB *macp,
633 					uint8_t send_req_val,
634 					uint8_t *send_msg,
635 					uint32_t len,
636 					uint8_t response_req_val,
637 					uint8_t *response_msg,
638 					uint32_t *response_len)
639 {
640 	QDF_STATUS status;
641 
642 	do {
643 
644 		/* send command */
645 		status = usb_hif_submit_ctrl_out(macp, send_req_val, 0, 0,
646 						 send_msg, len);
647 
648 		if (!QDF_IS_STATUS_SUCCESS(status))
649 			break;
650 
651 		if (NULL == response_msg) {
652 			/* no expected response */
653 			break;
654 		}
655 
656 		/* get response */
657 		status = usb_hif_submit_ctrl_in(macp, response_req_val, 0, 0,
658 						response_msg, *response_len);
659 
660 		if (!QDF_IS_STATUS_SUCCESS(status))
661 			break;
662 
663 	} while (false);
664 
665 	return status;
666 }
667 
668 /**
669  * hif_exchange_bmi_msg() - send/recev ctrl message of type BMI_CMD/BMI_RESP
670  * @scn: pointer to hif_opaque_softc
671  * @bmi_request: pointer to data to send
672  * @request_length: length in bytes of the data to send
673  * @bmi_response: pointer to response msg
674  * @bmi_response_length: length of the response message
675  * @timeout_ms: timeout to wait for response (ignored in current implementation)
676  *
677  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
678  */
679 
680 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *scn,
681 				qdf_dma_addr_t cmd, qdf_dma_addr_t rsp,
682 				uint8_t *bmi_request,
683 				uint32_t request_length,
684 				uint8_t *bmi_response,
685 				uint32_t *bmi_response_lengthp,
686 				uint32_t timeout_ms)
687 {
688 	struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn);
689 
690 	return hif_ctrl_msg_exchange(macp,
691 				USB_CONTROL_REQ_SEND_BMI_CMD,
692 				bmi_request,
693 				request_length,
694 				USB_CONTROL_REQ_RECV_BMI_RESP,
695 				bmi_response, bmi_response_lengthp);
696 }
697 
698 /**
699  * hif_diag_read_access() - Read data from target memory or register
700  * @scn: pointer to hif_opaque_softc
701  * @address: register address to read from
702  * @data: pointer to buffer to store the value read from the register
703  *
704  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
705  */
706 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *scn, uint32_t address,
707 					uint32_t *data)
708 {
709 	struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn);
710 	QDF_STATUS status;
711 	USB_CTRL_DIAG_CMD_READ *cmd;
712 	uint32_t respLength;
713 
714 	cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer;
715 
716 	qdf_mem_zero(cmd, sizeof(*cmd));
717 	cmd->Cmd = USB_CTRL_DIAG_CC_READ;
718 	cmd->Address = address;
719 	respLength = sizeof(USB_CTRL_DIAG_RESP_READ);
720 
721 	status = hif_ctrl_msg_exchange(macp,
722 				USB_CONTROL_REQ_DIAG_CMD,
723 				(uint8_t *) cmd,
724 				sizeof(*cmd),
725 				USB_CONTROL_REQ_DIAG_RESP,
726 				macp->diag_resp_buffer, &respLength);
727 
728 	if (QDF_IS_STATUS_SUCCESS(status)) {
729 		USB_CTRL_DIAG_RESP_READ *pResp =
730 			(USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer;
731 		*data = pResp->ReadValue;
732 		status = QDF_STATUS_SUCCESS;
733 	} else {
734 		status = QDF_STATUS_E_FAILURE;
735 	}
736 
737 	return status;
738 }
739 
740 /**
741  * hif_diag_write_access() - write data to target memory or register
742  * @scn: pointer to hif_opaque_softc
743  * @address: register address to write to
744  * @data: value to be written to the address
745  *
746  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
747  */
748 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *scn,
749 					uint32_t address,
750 					uint32_t data)
751 {
752 	struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn);
753 	USB_CTRL_DIAG_CMD_WRITE *cmd;
754 
755 	cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer;
756 
757 	qdf_mem_zero(cmd, sizeof(*cmd));
758 	cmd->Cmd = USB_CTRL_DIAG_CC_WRITE;
759 	cmd->Address = address;
760 	cmd->Value = data;
761 
762 	return hif_ctrl_msg_exchange(macp,
763 				USB_CONTROL_REQ_DIAG_CMD,
764 				(uint8_t *) cmd,
765 				sizeof(*cmd), 0, NULL, 0);
766 }
767 
768 /**
769  * hif_dump_info() - dump info about all HIF pipes and endpoints
770  * @scn: pointer to hif_opaque_softc
771  *
772  * Return: none
773  */
774 void hif_dump_info(struct hif_opaque_softc *scn)
775 {
776 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
777 	struct HIF_USB_PIPE *pipe = NULL;
778 	struct usb_host_interface *iface_desc = NULL;
779 	struct usb_endpoint_descriptor *ep_desc;
780 	uint8_t i = 0;
781 
782 	for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
783 		pipe = &device->pipes[i];
784 		HIF_ERROR("PipeIndex : %d URB Cnt : %d PipeHandle : %x",
785 			i, pipe->urb_cnt,
786 			pipe->usb_pipe_handle);
787 		if (usb_pipeisoc(pipe->usb_pipe_handle))
788 			HIF_INFO("Pipe Type ISOC");
789 		else if (usb_pipebulk(pipe->usb_pipe_handle))
790 			HIF_INFO("Pipe Type BULK");
791 		else if (usb_pipeint(pipe->usb_pipe_handle))
792 			HIF_INFO("Pipe Type INT");
793 		else if (usb_pipecontrol(pipe->usb_pipe_handle))
794 			HIF_INFO("Pipe Type control");
795 	}
796 
797 	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
798 		ep_desc = &iface_desc->endpoint[i].desc;
799 		if (ep_desc) {
800 			HIF_INFO(
801 				"ep_desc : %pK Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d",
802 				ep_desc, i, ep_desc->bDescriptorType,
803 				ep_desc->bEndpointAddress,
804 				ep_desc->wMaxPacketSize,
805 				ep_desc->bmAttributes);
806 			if ((ep_desc) && (usb_endpoint_type(ep_desc) ==
807 						USB_ENDPOINT_XFER_ISOC)) {
808 				HIF_INFO("ISOC EP Detected");
809 			}
810 		}
811 	}
812 
813 }
814 
815 /**
816  * hif_flush_surprise_remove() - Cleanup residual buffers for device shutdown
817  * @scn: HIF context
818  *
819  * Not applicable to USB bus
820  *
821  * Return: none
822  */
823 void hif_flush_surprise_remove(struct hif_opaque_softc *scn)
824 {
825 /* TO DO... */
826 }
827 
828 /**
829  * hif_diag_read_mem() -read nbytes of data from target memory or register
830  * @scn: pointer to hif_opaque_softc
831  * @address: register address to read from
832  * @data: buffer to store the value read
833  * @nbytes: number of bytes to be read from 'address'
834  *
835  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
836  */
837 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn,
838 					 uint32_t address, uint8_t *data,
839 					 int nbytes)
840 {
841 	QDF_STATUS status = QDF_STATUS_SUCCESS;
842 
843 	HIF_TRACE("+%s", __func__);
844 
845 	if ((address & 0x3) || ((uintptr_t)data & 0x3))
846 		return QDF_STATUS_E_IO;
847 
848 	while ((nbytes >= 4) &&
849 		QDF_IS_STATUS_SUCCESS(status =
850 					hif_diag_read_access(scn,
851 							address,
852 							(uint32_t *)data))) {
853 
854 		nbytes -= sizeof(uint32_t);
855 		address += sizeof(uint32_t);
856 		data += sizeof(uint32_t);
857 
858 	}
859 	HIF_TRACE("-%s", __func__);
860 	return status;
861 }
862 qdf_export_symbol(hif_diag_read_mem);
863 
864 /**
865  * hif_diag_write_mem() -write  nbytes of data to target memory or register
866  * @scn: pointer to hif_opaque_softc
867  * @address: register address to write to
868  * @data: buffer containing data to be written
869  * @nbytes: number of bytes to be written
870  *
871  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
872  */
873 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn,
874 					   uint32_t address,
875 					   uint8_t *data, int nbytes)
876 {
877 	QDF_STATUS status = QDF_STATUS_SUCCESS;
878 
879 	HIF_TRACE("+%s", __func__);
880 	if ((address & 0x3) || ((uintptr_t)data & 0x3))
881 		return QDF_STATUS_E_IO;
882 
883 	while (nbytes >= 4 &&
884 		QDF_IS_STATUS_SUCCESS(status =
885 					hif_diag_write_access(scn,
886 						address,
887 						*((uint32_t *)data)))) {
888 
889 		nbytes -= sizeof(uint32_t);
890 		address += sizeof(uint32_t);
891 		data += sizeof(uint32_t);
892 
893 	}
894 	HIF_TRACE("-%s", __func__);
895 	return status;
896 }
897 
898 void hif_send_complete_check(struct hif_opaque_softc *scn,
899 						uint8_t PipeID, int force)
900 {
901 	/* NO-OP*/
902 }
903 
904 /* diagnostic command defnitions */
905 #define USB_CTRL_DIAG_CC_READ       0
906 #define USB_CTRL_DIAG_CC_WRITE      1
907 #define USB_CTRL_DIAG_CC_WARM_RESET 2
908 
909 void hif_suspend_wow(struct hif_opaque_softc *scn)
910 {
911 	HIF_INFO("HIFsuspendwow - TODO");
912 }
913 
914 /**
915  * hif_usb_set_bundle_mode() - enable bundling and set default rx bundle cnt
916  * @scn: pointer to hif_opaque_softc structure
917  * @enabled: flag to enable/disable bundling
918  * @rx_bundle_cnt: bundle count to be used for RX
919  *
920  * Return: none
921  */
922 void hif_usb_set_bundle_mode(struct hif_softc *scn,
923 					bool enabled, int rx_bundle_cnt)
924 {
925 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn);
926 
927 	device->is_bundle_enabled = enabled;
928 	device->rx_bundle_cnt = rx_bundle_cnt;
929 	if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0))
930 		device->rx_bundle_cnt = 1;
931 
932 	device->rx_bundle_buf_len = device->rx_bundle_cnt *
933 					HIF_USB_RX_BUNDLE_ONE_PKT_SIZE;
934 
935 	HIF_DBG("athusb bundle %s cnt %d", enabled ? "enabled" : "disabled",
936 			rx_bundle_cnt);
937 }
938