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