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