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