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