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