xref: /wlan-driver/qca-wifi-host-cmn/hif/src/usb/usbdrv.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 #define ATH_MODULE_NAME hif
21*5113495bSYour Name #include "a_debug.h"
22*5113495bSYour Name #include "hif_usb_internal.h"
23*5113495bSYour Name #include "if_usb.h"
24*5113495bSYour Name #include "cds_api.h"
25*5113495bSYour Name #include "hif_debug.h"
26*5113495bSYour Name 
27*5113495bSYour Name #define IS_BULK_EP(attr) (((attr) & 3) == 0x02)
28*5113495bSYour Name #define IS_INT_EP(attr) (((attr) & 3) == 0x03)
29*5113495bSYour Name #define IS_ISOC_EP(attr) (((attr) & 3) == 0x01)
30*5113495bSYour Name #define IS_DIR_IN(addr) ((addr) & 0x80)
31*5113495bSYour Name 
32*5113495bSYour Name #define IS_FW_CRASH_DUMP(x)(((x == FW_ASSERT_PATTERN) || \
33*5113495bSYour Name 				(x == FW_REG_PATTERN) || \
34*5113495bSYour Name 				((x & FW_RAMDUMP_PATTERN_MASK) ==  \
35*5113495bSYour Name 						FW_RAMDUMP_PATTERN)) ? 1 : 0)
36*5113495bSYour Name 
37*5113495bSYour Name static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
38*5113495bSYour Name 					int buffer_length);
39*5113495bSYour Name static void usb_hif_post_recv_bundle_transfers
40*5113495bSYour Name 						(struct HIF_USB_PIPE *recv_pipe,
41*5113495bSYour Name 						int buffer_length);
42*5113495bSYour Name static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context);
43*5113495bSYour Name 
44*5113495bSYour Name 
45*5113495bSYour Name /**
46*5113495bSYour Name  * usb_hif_free_urb_to_pipe() - add urb back to urb list of a pipe
47*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
48*5113495bSYour Name  * @urb_context: pointer to struct HIF_URB_CONTEXT
49*5113495bSYour Name  *
50*5113495bSYour Name  * Return: none
51*5113495bSYour Name  */
usb_hif_free_urb_to_pipe(struct HIF_USB_PIPE * pipe,struct HIF_URB_CONTEXT * urb_context)52*5113495bSYour Name static void usb_hif_free_urb_to_pipe(struct HIF_USB_PIPE *pipe,
53*5113495bSYour Name 					struct HIF_URB_CONTEXT *urb_context)
54*5113495bSYour Name {
55*5113495bSYour Name 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
56*5113495bSYour Name 	pipe->urb_cnt++;
57*5113495bSYour Name 	DL_ListAdd(&pipe->urb_list_head, &urb_context->link);
58*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
59*5113495bSYour Name }
60*5113495bSYour Name 
61*5113495bSYour Name /**
62*5113495bSYour Name  * usb_hif_alloc_urb_from_pipe() - remove urb back from urb list of a pipe
63*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
64*5113495bSYour Name  *
65*5113495bSYour Name  * Return: struct HIF_URB_CONTEXT urb context removed from the urb list
66*5113495bSYour Name  */
usb_hif_alloc_urb_from_pipe(struct HIF_USB_PIPE * pipe)67*5113495bSYour Name struct HIF_URB_CONTEXT *usb_hif_alloc_urb_from_pipe(struct HIF_USB_PIPE *pipe)
68*5113495bSYour Name {
69*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context = NULL;
70*5113495bSYour Name 	DL_LIST *item;
71*5113495bSYour Name 
72*5113495bSYour Name 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
73*5113495bSYour Name 	item = dl_list_remove_item_from_head(&pipe->urb_list_head);
74*5113495bSYour Name 	if (item) {
75*5113495bSYour Name 		urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
76*5113495bSYour Name 						  link);
77*5113495bSYour Name 		pipe->urb_cnt--;
78*5113495bSYour Name 	}
79*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
80*5113495bSYour Name 
81*5113495bSYour Name 	return urb_context;
82*5113495bSYour Name }
83*5113495bSYour Name 
84*5113495bSYour Name /**
85*5113495bSYour Name  * usb_hif_dequeue_pending_transfer() - remove urb from pending xfer list
86*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
87*5113495bSYour Name  *
88*5113495bSYour Name  * Return: struct HIF_URB_CONTEXT urb context removed from the pending xfer list
89*5113495bSYour Name  */
usb_hif_dequeue_pending_transfer(struct HIF_USB_PIPE * pipe)90*5113495bSYour Name static struct HIF_URB_CONTEXT *usb_hif_dequeue_pending_transfer
91*5113495bSYour Name 						(struct HIF_USB_PIPE *pipe)
92*5113495bSYour Name {
93*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context = NULL;
94*5113495bSYour Name 	DL_LIST *item;
95*5113495bSYour Name 
96*5113495bSYour Name 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
97*5113495bSYour Name 	item = dl_list_remove_item_from_head(&pipe->urb_pending_list);
98*5113495bSYour Name 	if (item)
99*5113495bSYour Name 		urb_context = A_CONTAINING_STRUCT(item, struct HIF_URB_CONTEXT,
100*5113495bSYour Name 						  link);
101*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
102*5113495bSYour Name 
103*5113495bSYour Name 	return urb_context;
104*5113495bSYour Name }
105*5113495bSYour Name 
106*5113495bSYour Name /**
107*5113495bSYour Name  * usb_hif_enqueue_pending_transfer() - add urb to pending xfer list
108*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
109*5113495bSYour Name  * @urb_context: pointer to struct HIF_URB_CONTEXT to be added to the xfer list
110*5113495bSYour Name  *
111*5113495bSYour Name  * Return: none
112*5113495bSYour Name  */
usb_hif_enqueue_pending_transfer(struct HIF_USB_PIPE * pipe,struct HIF_URB_CONTEXT * urb_context)113*5113495bSYour Name void usb_hif_enqueue_pending_transfer(struct HIF_USB_PIPE *pipe,
114*5113495bSYour Name 					struct HIF_URB_CONTEXT *urb_context)
115*5113495bSYour Name {
116*5113495bSYour Name 	qdf_spin_lock_irqsave(&pipe->device->cs_lock);
117*5113495bSYour Name 	dl_list_insert_tail(&pipe->urb_pending_list, &urb_context->link);
118*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&pipe->device->cs_lock);
119*5113495bSYour Name }
120*5113495bSYour Name 
121*5113495bSYour Name 
122*5113495bSYour Name /**
123*5113495bSYour Name  * usb_hif_remove_pending_transfer() - remove urb from its own list
124*5113495bSYour Name  * @urb_context: pointer to struct HIF_URB_CONTEXT to be removed
125*5113495bSYour Name  *
126*5113495bSYour Name  * Return: none
127*5113495bSYour Name  */
128*5113495bSYour Name void
usb_hif_remove_pending_transfer(struct HIF_URB_CONTEXT * urb_context)129*5113495bSYour Name usb_hif_remove_pending_transfer(struct HIF_URB_CONTEXT *urb_context)
130*5113495bSYour Name {
131*5113495bSYour Name 	qdf_spin_lock_irqsave(&urb_context->pipe->device->cs_lock);
132*5113495bSYour Name 	dl_list_remove(&urb_context->link);
133*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&urb_context->pipe->device->cs_lock);
134*5113495bSYour Name }
135*5113495bSYour Name 
136*5113495bSYour Name /**
137*5113495bSYour Name  * usb_hif_alloc_pipe_resources() - allocate urb_cnt urbs to a HIF pipe
138*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE to which resources will be allocated
139*5113495bSYour Name  * @urb_cnt: number of urbs to be added to the HIF pipe
140*5113495bSYour Name  *
141*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
142*5113495bSYour Name  */
usb_hif_alloc_pipe_resources(struct HIF_USB_PIPE * pipe,int urb_cnt)143*5113495bSYour Name static QDF_STATUS usb_hif_alloc_pipe_resources
144*5113495bSYour Name 					(struct HIF_USB_PIPE *pipe, int urb_cnt)
145*5113495bSYour Name {
146*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
147*5113495bSYour Name 	int i;
148*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
149*5113495bSYour Name 
150*5113495bSYour Name 	DL_LIST_INIT(&pipe->urb_list_head);
151*5113495bSYour Name 	DL_LIST_INIT(&pipe->urb_pending_list);
152*5113495bSYour Name 
153*5113495bSYour Name 	for (i = 0; i < urb_cnt; i++) {
154*5113495bSYour Name 		urb_context = qdf_mem_malloc(sizeof(*urb_context));
155*5113495bSYour Name 		if (!urb_context) {
156*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
157*5113495bSYour Name 			break;
158*5113495bSYour Name 		}
159*5113495bSYour Name 		urb_context->pipe = pipe;
160*5113495bSYour Name 		urb_context->urb = usb_alloc_urb(0, GFP_KERNEL);
161*5113495bSYour Name 
162*5113495bSYour Name 		if (!urb_context->urb) {
163*5113495bSYour Name 			status = QDF_STATUS_E_NOMEM;
164*5113495bSYour Name 			qdf_mem_free(urb_context);
165*5113495bSYour Name 			hif_err("urb_context->urb is null");
166*5113495bSYour Name 			break;
167*5113495bSYour Name 		}
168*5113495bSYour Name 
169*5113495bSYour Name 		/* note we are only allocate the urb contexts here, the actual
170*5113495bSYour Name 		 * URB is
171*5113495bSYour Name 		 * allocated from the kernel as needed to do a transaction
172*5113495bSYour Name 		 */
173*5113495bSYour Name 		pipe->urb_alloc++;
174*5113495bSYour Name 
175*5113495bSYour Name 		usb_hif_free_urb_to_pipe(pipe, urb_context);
176*5113495bSYour Name 	}
177*5113495bSYour Name 
178*5113495bSYour Name 	hif_debug("athusb: alloc resources lpipe:%d hpipe:0x%X urbs:%d",
179*5113495bSYour Name 		 pipe->logical_pipe_num,
180*5113495bSYour Name 		 pipe->usb_pipe_handle,
181*5113495bSYour Name 		 pipe->urb_alloc);
182*5113495bSYour Name 	return status;
183*5113495bSYour Name }
184*5113495bSYour Name 
185*5113495bSYour Name /**
186*5113495bSYour Name  * usb_hif_free_pipe_resources() - free urb resources allocated to a HIF pipe
187*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
188*5113495bSYour Name  *
189*5113495bSYour Name  * Return: none
190*5113495bSYour Name  */
usb_hif_free_pipe_resources(struct HIF_USB_PIPE * pipe)191*5113495bSYour Name static void usb_hif_free_pipe_resources(struct HIF_USB_PIPE *pipe)
192*5113495bSYour Name {
193*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
194*5113495bSYour Name 
195*5113495bSYour Name 	if (!pipe->device) {
196*5113495bSYour Name 		/* nothing allocated for this pipe */
197*5113495bSYour Name 		hif_err("pipe->device is null");
198*5113495bSYour Name 		return;
199*5113495bSYour Name 	}
200*5113495bSYour Name 
201*5113495bSYour Name 	hif_info("athusb: free resources lpipe:%d hpipe:0x%X urbs:%d avail:%d",
202*5113495bSYour Name 			 pipe->logical_pipe_num,
203*5113495bSYour Name 			 pipe->usb_pipe_handle, pipe->urb_alloc,
204*5113495bSYour Name 			 pipe->urb_cnt);
205*5113495bSYour Name 
206*5113495bSYour Name 	if (pipe->urb_alloc != pipe->urb_cnt) {
207*5113495bSYour Name 		hif_err("athusb: urb leak! lpipe:%d hpipe:0x%X urbs:%d avail:%d",
208*5113495bSYour Name 			 pipe->logical_pipe_num,
209*5113495bSYour Name 			 pipe->usb_pipe_handle, pipe->urb_alloc,
210*5113495bSYour Name 			 pipe->urb_cnt);
211*5113495bSYour Name 	}
212*5113495bSYour Name 
213*5113495bSYour Name 	while (true) {
214*5113495bSYour Name 		urb_context = usb_hif_alloc_urb_from_pipe(pipe);
215*5113495bSYour Name 		if (!urb_context)
216*5113495bSYour Name 			break;
217*5113495bSYour Name 
218*5113495bSYour Name 		if (urb_context->buf) {
219*5113495bSYour Name 			qdf_nbuf_free(urb_context->buf);
220*5113495bSYour Name 			urb_context->buf = NULL;
221*5113495bSYour Name 		}
222*5113495bSYour Name 
223*5113495bSYour Name 		usb_free_urb(urb_context->urb);
224*5113495bSYour Name 		urb_context->urb = NULL;
225*5113495bSYour Name 		qdf_mem_free(urb_context);
226*5113495bSYour Name 	}
227*5113495bSYour Name 
228*5113495bSYour Name }
229*5113495bSYour Name 
230*5113495bSYour Name #ifdef QCN7605_SUPPORT
231*5113495bSYour Name /**
232*5113495bSYour Name  * usb_hif_get_logical_pipe_num() - get pipe number for a particular endpoint
233*5113495bSYour Name  * @device: pointer to HIF_DEVICE_USB structure
234*5113495bSYour Name  * @ep_address: endpoint address
235*5113495bSYour Name  * @urb_count: number of urb resources to be allocated to the pipe
236*5113495bSYour Name  *
237*5113495bSYour Name  * Return: uint8_t pipe number corresponding to ep_address
238*5113495bSYour Name  */
usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB * device,uint8_t ep_address,int * urb_count)239*5113495bSYour Name static uint8_t usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB *device,
240*5113495bSYour Name 					    uint8_t ep_address,
241*5113495bSYour Name 					    int *urb_count)
242*5113495bSYour Name {
243*5113495bSYour Name 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
244*5113495bSYour Name 
245*5113495bSYour Name 	switch (ep_address) {
246*5113495bSYour Name 	case USB_EP_ADDR_APP_CTRL_IN:
247*5113495bSYour Name 		pipe_num = HIF_RX_CTRL_PIPE;
248*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
249*5113495bSYour Name 		break;
250*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_IN:
251*5113495bSYour Name 		pipe_num = HIF_RX_DATA_PIPE;
252*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
253*5113495bSYour Name 		break;
254*5113495bSYour Name 		break;
255*5113495bSYour Name 	case USB_EP_ADDR_APP_CTRL_OUT:
256*5113495bSYour Name 		pipe_num = HIF_TX_CTRL_PIPE;
257*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
258*5113495bSYour Name 		break;
259*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_OUT:
260*5113495bSYour Name 		pipe_num = HIF_TX_DATA_LP_PIPE;
261*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
262*5113495bSYour Name 		break;
263*5113495bSYour Name 	default:
264*5113495bSYour Name 		/* note: there may be endpoints not currently used */
265*5113495bSYour Name 		break;
266*5113495bSYour Name 	}
267*5113495bSYour Name 
268*5113495bSYour Name 	return pipe_num;
269*5113495bSYour Name }
270*5113495bSYour Name #else
271*5113495bSYour Name /**
272*5113495bSYour Name  * usb_hif_get_logical_pipe_num() - get pipe number for a particular endpoint
273*5113495bSYour Name  * @device: pointer to HIF_DEVICE_USB structure
274*5113495bSYour Name  * @ep_address: endpoint address
275*5113495bSYour Name  * @urb_count: number of urb resources to be allocated to the pipe
276*5113495bSYour Name  *
277*5113495bSYour Name  * Return: uint8_t pipe number corresponding to ep_address
278*5113495bSYour Name  */
usb_hif_get_logical_pipe_num(struct HIF_DEVICE_USB * device,uint8_t ep_address,int * urb_count)279*5113495bSYour Name static uint8_t usb_hif_get_logical_pipe_num
280*5113495bSYour Name 					(struct HIF_DEVICE_USB *device,
281*5113495bSYour Name 					uint8_t ep_address,
282*5113495bSYour Name 					int *urb_count)
283*5113495bSYour Name {
284*5113495bSYour Name 	uint8_t pipe_num = HIF_USB_PIPE_INVALID;
285*5113495bSYour Name 
286*5113495bSYour Name 	switch (ep_address) {
287*5113495bSYour Name 	case USB_EP_ADDR_APP_CTRL_IN:
288*5113495bSYour Name 		pipe_num = HIF_RX_CTRL_PIPE;
289*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
290*5113495bSYour Name 		break;
291*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_IN:
292*5113495bSYour Name 		pipe_num = HIF_RX_DATA_PIPE;
293*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
294*5113495bSYour Name 		break;
295*5113495bSYour Name 	case USB_EP_ADDR_APP_INT_IN:
296*5113495bSYour Name 		pipe_num = HIF_RX_INT_PIPE;
297*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
298*5113495bSYour Name 		break;
299*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA2_IN:
300*5113495bSYour Name 		pipe_num = HIF_RX_DATA2_PIPE;
301*5113495bSYour Name 		*urb_count = RX_URB_COUNT;
302*5113495bSYour Name 		break;
303*5113495bSYour Name 	case USB_EP_ADDR_APP_CTRL_OUT:
304*5113495bSYour Name 		pipe_num = HIF_TX_CTRL_PIPE;
305*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
306*5113495bSYour Name 		break;
307*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_LP_OUT:
308*5113495bSYour Name 		pipe_num = HIF_TX_DATA_LP_PIPE;
309*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
310*5113495bSYour Name 		break;
311*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_MP_OUT:
312*5113495bSYour Name 		pipe_num = HIF_TX_DATA_MP_PIPE;
313*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
314*5113495bSYour Name 		break;
315*5113495bSYour Name 	case USB_EP_ADDR_APP_DATA_HP_OUT:
316*5113495bSYour Name 		pipe_num = HIF_TX_DATA_HP_PIPE;
317*5113495bSYour Name 		*urb_count = TX_URB_COUNT;
318*5113495bSYour Name 		break;
319*5113495bSYour Name 	default:
320*5113495bSYour Name 		/* note: there may be endpoints not currently used */
321*5113495bSYour Name 		break;
322*5113495bSYour Name 	}
323*5113495bSYour Name 
324*5113495bSYour Name 	return pipe_num;
325*5113495bSYour Name }
326*5113495bSYour Name #endif /* QCN7605_SUPPORT */
327*5113495bSYour Name 
328*5113495bSYour Name /**
329*5113495bSYour Name  * usb_hif_setup_pipe_resources() - setup urb resources for all pipes
330*5113495bSYour Name  * @device: pointer to HIF_DEVICE_USB structure
331*5113495bSYour Name  *
332*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
333*5113495bSYour Name  */
usb_hif_setup_pipe_resources(struct HIF_DEVICE_USB * device)334*5113495bSYour Name QDF_STATUS usb_hif_setup_pipe_resources(struct HIF_DEVICE_USB *device)
335*5113495bSYour Name {
336*5113495bSYour Name 	struct usb_interface *interface = device->interface;
337*5113495bSYour Name 	struct usb_host_interface *iface_desc = interface->cur_altsetting;
338*5113495bSYour Name 	struct usb_endpoint_descriptor *endpoint;
339*5113495bSYour Name 	int i;
340*5113495bSYour Name 	int urbcount;
341*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
342*5113495bSYour Name 	struct HIF_USB_PIPE *pipe;
343*5113495bSYour Name 	uint8_t pipe_num;
344*5113495bSYour Name 
345*5113495bSYour Name 	/* walk descriptors and setup pipes */
346*5113495bSYour Name 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
347*5113495bSYour Name 		endpoint = &iface_desc->endpoint[i].desc;
348*5113495bSYour Name 
349*5113495bSYour Name 		if (IS_BULK_EP(endpoint->bmAttributes)) {
350*5113495bSYour Name 			hif_debug("%s Bulk Ep:0x%2.2X maxpktsz:%d",
351*5113495bSYour Name 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
352*5113495bSYour Name 								"RX" : "TX",
353*5113495bSYour Name 				 endpoint->bEndpointAddress,
354*5113495bSYour Name 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize));
355*5113495bSYour Name 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
356*5113495bSYour Name 			hif_debug("%s Int Ep:0x%2.2X maxpktsz:%d interval:%d",
357*5113495bSYour Name 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
358*5113495bSYour Name 								"RX" : "TX",
359*5113495bSYour Name 				 endpoint->bEndpointAddress,
360*5113495bSYour Name 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize),
361*5113495bSYour Name 				 endpoint->bInterval);
362*5113495bSYour Name 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
363*5113495bSYour Name 			/* TODO for ISO */
364*5113495bSYour Name 			hif_debug("%s ISOC Ep:0x%2.2X maxpktsz:%d interval:%d",
365*5113495bSYour Name 				 IS_DIR_IN(endpoint->bEndpointAddress) ?
366*5113495bSYour Name 								"RX" : "TX",
367*5113495bSYour Name 				 endpoint->bEndpointAddress,
368*5113495bSYour Name 				 qdf_le16_to_cpu(endpoint->wMaxPacketSize),
369*5113495bSYour Name 				 endpoint->bInterval);
370*5113495bSYour Name 		}
371*5113495bSYour Name 		urbcount = 0;
372*5113495bSYour Name 
373*5113495bSYour Name 		pipe_num = usb_hif_get_logical_pipe_num(device,
374*5113495bSYour Name 						endpoint->bEndpointAddress,
375*5113495bSYour Name 						&urbcount);
376*5113495bSYour Name 		if (HIF_USB_PIPE_INVALID == pipe_num)
377*5113495bSYour Name 			continue;
378*5113495bSYour Name 
379*5113495bSYour Name 		pipe = &device->pipes[pipe_num];
380*5113495bSYour Name 		if (pipe->device) {
381*5113495bSYour Name 			/*pipe was already setup */
382*5113495bSYour Name 			continue;
383*5113495bSYour Name 		}
384*5113495bSYour Name 
385*5113495bSYour Name 		pipe->device = device;
386*5113495bSYour Name 		pipe->logical_pipe_num = pipe_num;
387*5113495bSYour Name 		pipe->ep_address = endpoint->bEndpointAddress;
388*5113495bSYour Name 		pipe->max_packet_size =
389*5113495bSYour Name 			qdf_le16_to_cpu(endpoint->wMaxPacketSize);
390*5113495bSYour Name 
391*5113495bSYour Name 		if (IS_BULK_EP(endpoint->bmAttributes)) {
392*5113495bSYour Name 			if (IS_DIR_IN(pipe->ep_address)) {
393*5113495bSYour Name 				pipe->usb_pipe_handle =
394*5113495bSYour Name 					usb_rcvbulkpipe(device->udev,
395*5113495bSYour Name 							pipe->ep_address);
396*5113495bSYour Name 			} else {
397*5113495bSYour Name 				pipe->usb_pipe_handle =
398*5113495bSYour Name 					usb_sndbulkpipe(device->udev,
399*5113495bSYour Name 						pipe->ep_address);
400*5113495bSYour Name 			}
401*5113495bSYour Name 		} else if (IS_INT_EP(endpoint->bmAttributes)) {
402*5113495bSYour Name 			if (IS_DIR_IN(pipe->ep_address)) {
403*5113495bSYour Name 				pipe->usb_pipe_handle =
404*5113495bSYour Name 					usb_rcvintpipe(device->udev,
405*5113495bSYour Name 						pipe->ep_address);
406*5113495bSYour Name 			} else {
407*5113495bSYour Name 				pipe->usb_pipe_handle =
408*5113495bSYour Name 					usb_sndintpipe(device->udev,
409*5113495bSYour Name 						pipe->ep_address);
410*5113495bSYour Name 			}
411*5113495bSYour Name 		} else if (IS_ISOC_EP(endpoint->bmAttributes)) {
412*5113495bSYour Name 			/* TODO for ISO */
413*5113495bSYour Name 			if (IS_DIR_IN(pipe->ep_address)) {
414*5113495bSYour Name 				pipe->usb_pipe_handle =
415*5113495bSYour Name 					usb_rcvisocpipe(device->udev,
416*5113495bSYour Name 						pipe->ep_address);
417*5113495bSYour Name 			} else {
418*5113495bSYour Name 				pipe->usb_pipe_handle =
419*5113495bSYour Name 					usb_sndisocpipe(device->udev,
420*5113495bSYour Name 						pipe->ep_address);
421*5113495bSYour Name 			}
422*5113495bSYour Name 		}
423*5113495bSYour Name 		pipe->ep_desc = endpoint;
424*5113495bSYour Name 
425*5113495bSYour Name 		if (!IS_DIR_IN(pipe->ep_address))
426*5113495bSYour Name 			pipe->flags |= HIF_USB_PIPE_FLAG_TX;
427*5113495bSYour Name 
428*5113495bSYour Name 		status = usb_hif_alloc_pipe_resources(pipe, urbcount);
429*5113495bSYour Name 
430*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status))
431*5113495bSYour Name 			break;
432*5113495bSYour Name 
433*5113495bSYour Name 	}
434*5113495bSYour Name 
435*5113495bSYour Name 	return status;
436*5113495bSYour Name }
437*5113495bSYour Name 
438*5113495bSYour Name 
439*5113495bSYour Name /**
440*5113495bSYour Name  * usb_hif_cleanup_pipe_resources() - free urb resources for all pipes
441*5113495bSYour Name  * @device: pointer to HIF_DEVICE_USB structure
442*5113495bSYour Name  *
443*5113495bSYour Name  * Return: none
444*5113495bSYour Name  */
usb_hif_cleanup_pipe_resources(struct HIF_DEVICE_USB * device)445*5113495bSYour Name void usb_hif_cleanup_pipe_resources(struct HIF_DEVICE_USB *device)
446*5113495bSYour Name {
447*5113495bSYour Name 	int i;
448*5113495bSYour Name 
449*5113495bSYour Name 	for (i = 0; i < HIF_USB_PIPE_MAX; i++)
450*5113495bSYour Name 		usb_hif_free_pipe_resources(&device->pipes[i]);
451*5113495bSYour Name }
452*5113495bSYour Name 
453*5113495bSYour Name /**
454*5113495bSYour Name  * usb_hif_flush_pending_transfers() - kill pending urbs for a pipe
455*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE structure
456*5113495bSYour Name  *
457*5113495bSYour Name  * Return: none
458*5113495bSYour Name  */
usb_hif_flush_pending_transfers(struct HIF_USB_PIPE * pipe)459*5113495bSYour Name static void usb_hif_flush_pending_transfers(struct HIF_USB_PIPE *pipe)
460*5113495bSYour Name {
461*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
462*5113495bSYour Name 
463*5113495bSYour Name 	hif_info("+ pipe: %d", pipe->logical_pipe_num);
464*5113495bSYour Name 
465*5113495bSYour Name 	while (1) {
466*5113495bSYour Name 		urb_context = usb_hif_dequeue_pending_transfer(pipe);
467*5113495bSYour Name 		if (!urb_context) {
468*5113495bSYour Name 			hif_warn("urb_context is NULL");
469*5113495bSYour Name 			break;
470*5113495bSYour Name 		}
471*5113495bSYour Name 		hif_info("pending urb ctxt: 0x%pK", urb_context);
472*5113495bSYour Name 		if (urb_context->urb) {
473*5113495bSYour Name 			hif_info("killing urb: 0x%pK", urb_context->urb);
474*5113495bSYour Name 			/* killing the URB will cause the completion routines to
475*5113495bSYour Name 			 * run
476*5113495bSYour Name 			 */
477*5113495bSYour Name 			usb_kill_urb(urb_context->urb);
478*5113495bSYour Name 		}
479*5113495bSYour Name 	}
480*5113495bSYour Name 	hif_info("-");
481*5113495bSYour Name }
482*5113495bSYour Name 
483*5113495bSYour Name /**
484*5113495bSYour Name  * usb_hif_flush_all() - flush pending transfers for all pipes for a usb bus
485*5113495bSYour Name  * @device: pointer to HIF_DEVICE_USB structure
486*5113495bSYour Name  *
487*5113495bSYour Name  * Return: none
488*5113495bSYour Name  */
usb_hif_flush_all(struct HIF_DEVICE_USB * device)489*5113495bSYour Name void usb_hif_flush_all(struct HIF_DEVICE_USB *device)
490*5113495bSYour Name {
491*5113495bSYour Name 	int i;
492*5113495bSYour Name 	struct HIF_USB_PIPE *pipe;
493*5113495bSYour Name 
494*5113495bSYour Name 	hif_info("+");
495*5113495bSYour Name 
496*5113495bSYour Name 	for (i = 0; i < HIF_USB_PIPE_MAX; i++) {
497*5113495bSYour Name 		if (device->pipes[i].device) {
498*5113495bSYour Name 			usb_hif_flush_pending_transfers(&device->pipes[i]);
499*5113495bSYour Name 			pipe = &device->pipes[i];
500*5113495bSYour Name 
501*5113495bSYour Name 		HIF_USB_FLUSH_WORK(pipe);
502*5113495bSYour Name 		}
503*5113495bSYour Name 	}
504*5113495bSYour Name 
505*5113495bSYour Name 	hif_info("-");
506*5113495bSYour Name }
507*5113495bSYour Name 
508*5113495bSYour Name /**
509*5113495bSYour Name  * usb_hif_cleanup_recv_urb() - cleanup recv urb
510*5113495bSYour Name  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
511*5113495bSYour Name  *
512*5113495bSYour Name  * Return: none
513*5113495bSYour Name  */
usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT * urb_context)514*5113495bSYour Name static void usb_hif_cleanup_recv_urb(struct HIF_URB_CONTEXT *urb_context)
515*5113495bSYour Name {
516*5113495bSYour Name 
517*5113495bSYour Name 	if (urb_context->buf) {
518*5113495bSYour Name 		qdf_nbuf_free(urb_context->buf);
519*5113495bSYour Name 		urb_context->buf = NULL;
520*5113495bSYour Name 	}
521*5113495bSYour Name 
522*5113495bSYour Name 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
523*5113495bSYour Name }
524*5113495bSYour Name 
525*5113495bSYour Name /**
526*5113495bSYour Name  * usb_hif_cleanup_transmit_urb() - cleanup transmit urb
527*5113495bSYour Name  * @urb_context: pointer to struct HIF_URB_CONTEXT structure
528*5113495bSYour Name  *
529*5113495bSYour Name  * Return: none
530*5113495bSYour Name  */
usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT * urb_context)531*5113495bSYour Name void usb_hif_cleanup_transmit_urb(struct HIF_URB_CONTEXT *urb_context)
532*5113495bSYour Name {
533*5113495bSYour Name 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
534*5113495bSYour Name }
535*5113495bSYour Name 
536*5113495bSYour Name /**
537*5113495bSYour Name  * usb_hif_usb_recv_prestart_complete() - completion routine for prestart rx urb
538*5113495bSYour Name  * @urb: urb for which the completion routine is being called
539*5113495bSYour Name  *
540*5113495bSYour Name  * Return: none
541*5113495bSYour Name  */
usb_hif_usb_recv_prestart_complete(struct urb * urb)542*5113495bSYour Name static void usb_hif_usb_recv_prestart_complete
543*5113495bSYour Name 							(struct urb *urb)
544*5113495bSYour Name {
545*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context =
546*5113495bSYour Name 					(struct HIF_URB_CONTEXT *) urb->context;
547*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
548*5113495bSYour Name 	qdf_nbuf_t buf = NULL;
549*5113495bSYour Name 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
550*5113495bSYour Name 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
551*5113495bSYour Name 
552*5113495bSYour Name 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
553*5113495bSYour Name 		pipe->logical_pipe_num,
554*5113495bSYour Name 		urb->status, urb->actual_length,
555*5113495bSYour Name 		urb);
556*5113495bSYour Name 
557*5113495bSYour Name 	/* this urb is not pending anymore */
558*5113495bSYour Name 	usb_hif_remove_pending_transfer(urb_context);
559*5113495bSYour Name 	do {
560*5113495bSYour Name 		if (urb->status != 0) {
561*5113495bSYour Name 			status = A_ECOMM;
562*5113495bSYour Name 			switch (urb->status) {
563*5113495bSYour Name 			case -ECONNRESET:
564*5113495bSYour Name 			case -ENOENT:
565*5113495bSYour Name 			case -ESHUTDOWN:
566*5113495bSYour Name 				/* NOTE: no need to spew these errors when
567*5113495bSYour Name 				 * device is removed
568*5113495bSYour Name 				 * or urb is killed due to driver shutdown
569*5113495bSYour Name 				 */
570*5113495bSYour Name 				status = A_ECANCELED;
571*5113495bSYour Name 				break;
572*5113495bSYour Name 			default:
573*5113495bSYour Name 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
574*5113495bSYour Name 					pipe->logical_pipe_num,
575*5113495bSYour Name 					pipe->ep_address,
576*5113495bSYour Name 					urb->status);
577*5113495bSYour Name 				break;
578*5113495bSYour Name 			}
579*5113495bSYour Name 			break;
580*5113495bSYour Name 		}
581*5113495bSYour Name 		if (urb->actual_length == 0)
582*5113495bSYour Name 			break;
583*5113495bSYour Name 		buf = urb_context->buf;
584*5113495bSYour Name 		/* we are going to pass it up */
585*5113495bSYour Name 		urb_context->buf = NULL;
586*5113495bSYour Name 		qdf_nbuf_put_tail(buf, urb->actual_length);
587*5113495bSYour Name 
588*5113495bSYour Name 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
589*5113495bSYour Name 			uint8_t *data;
590*5113495bSYour Name 			uint32_t len;
591*5113495bSYour Name 
592*5113495bSYour Name 			qdf_nbuf_peek_header(buf, &data, &len);
593*5113495bSYour Name 			debug_dump_bytes(data, len, "hif recv data");
594*5113495bSYour Name 		}
595*5113495bSYour Name 		/* note: queue implements a lock */
596*5113495bSYour Name 		skb_queue_tail(&pipe->io_comp_queue, buf);
597*5113495bSYour Name 
598*5113495bSYour Name 		HIF_USB_SCHEDULE_WORK(pipe);
599*5113495bSYour Name 	} while (false);
600*5113495bSYour Name 
601*5113495bSYour Name 	usb_hif_cleanup_recv_urb(urb_context);
602*5113495bSYour Name 
603*5113495bSYour Name 	/* Prestart URBs runs out and now start working receive pipe. */
604*5113495bSYour Name 	qdf_spin_lock_irqsave(&pipe->device->rx_prestart_lock);
605*5113495bSYour Name 	if ((--pipe->urb_prestart_cnt == 0) && !sc->suspend_state)
606*5113495bSYour Name 		usb_hif_start_recv_pipes(pipe->device);
607*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&pipe->device->rx_prestart_lock);
608*5113495bSYour Name 
609*5113495bSYour Name 	hif_debug("-");
610*5113495bSYour Name }
611*5113495bSYour Name 
612*5113495bSYour Name /**
613*5113495bSYour Name  * usb_hif_usb_recv_complete() - completion routine for rx urb
614*5113495bSYour Name  * @urb: urb for which the completion routine is being called
615*5113495bSYour Name  *
616*5113495bSYour Name  * Return: none
617*5113495bSYour Name  */
usb_hif_usb_recv_complete(struct urb * urb)618*5113495bSYour Name static void usb_hif_usb_recv_complete(struct urb *urb)
619*5113495bSYour Name {
620*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context =
621*5113495bSYour Name 					(struct HIF_URB_CONTEXT *) urb->context;
622*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
623*5113495bSYour Name 	qdf_nbuf_t buf = NULL;
624*5113495bSYour Name 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
625*5113495bSYour Name 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
626*5113495bSYour Name 
627*5113495bSYour Name 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
628*5113495bSYour Name 		pipe->logical_pipe_num,
629*5113495bSYour Name 		urb->status, urb->actual_length,
630*5113495bSYour Name 		urb);
631*5113495bSYour Name 
632*5113495bSYour Name 	/* this urb is not pending anymore */
633*5113495bSYour Name 	usb_hif_remove_pending_transfer(urb_context);
634*5113495bSYour Name 
635*5113495bSYour Name 	do {
636*5113495bSYour Name 
637*5113495bSYour Name 		if (urb->status != 0) {
638*5113495bSYour Name 			status = A_ECOMM;
639*5113495bSYour Name 			switch (urb->status) {
640*5113495bSYour Name #ifdef RX_SG_SUPPORT
641*5113495bSYour Name 			case -EOVERFLOW:
642*5113495bSYour Name 				urb->actual_length = HIF_USB_RX_BUFFER_SIZE;
643*5113495bSYour Name 				status = QDF_STATUS_SUCCESS;
644*5113495bSYour Name 				break;
645*5113495bSYour Name #endif
646*5113495bSYour Name 			case -ECONNRESET:
647*5113495bSYour Name 			case -ENOENT:
648*5113495bSYour Name 			case -ESHUTDOWN:
649*5113495bSYour Name 				/* NOTE: no need to spew these errors when
650*5113495bSYour Name 				 * device is removed
651*5113495bSYour Name 				 * or urb is killed due to driver shutdown
652*5113495bSYour Name 				 */
653*5113495bSYour Name 				status = A_ECANCELED;
654*5113495bSYour Name 				break;
655*5113495bSYour Name 			default:
656*5113495bSYour Name 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
657*5113495bSYour Name 					pipe->logical_pipe_num,
658*5113495bSYour Name 					pipe->ep_address,
659*5113495bSYour Name 					urb->status);
660*5113495bSYour Name 				break;
661*5113495bSYour Name 			}
662*5113495bSYour Name 			break;
663*5113495bSYour Name 		}
664*5113495bSYour Name 		if (urb->actual_length == 0)
665*5113495bSYour Name 			break;
666*5113495bSYour Name 		buf = urb_context->buf;
667*5113495bSYour Name 		/* we are going to pass it up */
668*5113495bSYour Name 		urb_context->buf = NULL;
669*5113495bSYour Name 		qdf_nbuf_put_tail(buf, urb->actual_length);
670*5113495bSYour Name 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
671*5113495bSYour Name 			uint8_t *data;
672*5113495bSYour Name 			uint32_t len;
673*5113495bSYour Name 
674*5113495bSYour Name 			qdf_nbuf_peek_header(buf, &data, &len);
675*5113495bSYour Name 			debug_dump_bytes(data, len, "hif recv data");
676*5113495bSYour Name 		}
677*5113495bSYour Name 		/* note: queue implements a lock */
678*5113495bSYour Name 		skb_queue_tail(&pipe->io_comp_queue, buf);
679*5113495bSYour Name 
680*5113495bSYour Name 		if (pipe->device->htc_callbacks.update_bundle_stats)
681*5113495bSYour Name 			pipe->device->htc_callbacks.update_bundle_stats
682*5113495bSYour Name 				(pipe->device->htc_callbacks.Context, 1);
683*5113495bSYour Name 
684*5113495bSYour Name 		HIF_USB_SCHEDULE_WORK(pipe);
685*5113495bSYour Name 	} while (false);
686*5113495bSYour Name 
687*5113495bSYour Name 	usb_hif_cleanup_recv_urb(urb_context);
688*5113495bSYour Name 
689*5113495bSYour Name 	/* Only re-submit URB when STATUS is success and HIF is not at the
690*5113495bSYour Name 	 * suspend state.
691*5113495bSYour Name 	 */
692*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status) && !sc->suspend_state) {
693*5113495bSYour Name 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
694*5113495bSYour Name 			/* our free urbs are piling up, post more transfers */
695*5113495bSYour Name 			usb_hif_post_recv_transfers(pipe,
696*5113495bSYour Name 						HIF_USB_RX_BUFFER_SIZE);
697*5113495bSYour Name 		}
698*5113495bSYour Name 	} else {
699*5113495bSYour Name 		hif_err("pipe: %d, fail to post URB: status: %d suspend: %d",
700*5113495bSYour Name 			pipe->logical_pipe_num,
701*5113495bSYour Name 			urb->status,
702*5113495bSYour Name 			sc->suspend_state);
703*5113495bSYour Name 	}
704*5113495bSYour Name 
705*5113495bSYour Name 	hif_debug("-");
706*5113495bSYour Name }
707*5113495bSYour Name 
708*5113495bSYour Name /**
709*5113495bSYour Name  * usb_hif_usb_recv_bundle_complete() - completion routine for rx bundling urb
710*5113495bSYour Name  * @urb: urb for which the completion routine is being called
711*5113495bSYour Name  *
712*5113495bSYour Name  * Return: none
713*5113495bSYour Name  */
usb_hif_usb_recv_bundle_complete(struct urb * urb)714*5113495bSYour Name static void usb_hif_usb_recv_bundle_complete(struct urb *urb)
715*5113495bSYour Name {
716*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context =
717*5113495bSYour Name 					(struct HIF_URB_CONTEXT *) urb->context;
718*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
719*5113495bSYour Name 	qdf_nbuf_t buf = NULL;
720*5113495bSYour Name 	struct HIF_USB_PIPE *pipe = urb_context->pipe;
721*5113495bSYour Name 	uint8_t *netdata, *netdata_new;
722*5113495bSYour Name 	uint32_t netlen, netlen_new;
723*5113495bSYour Name 	HTC_FRAME_HDR *HtcHdr;
724*5113495bSYour Name 	uint16_t payloadLen;
725*5113495bSYour Name 	qdf_nbuf_t new_skb = NULL;
726*5113495bSYour Name 	uint8_t no_of_pkt_in_bundle;
727*5113495bSYour Name 
728*5113495bSYour Name 	hif_debug("+: recv pipe: %d, stat:%d,len:%d urb:0x%pK",
729*5113495bSYour Name 		 pipe->logical_pipe_num,
730*5113495bSYour Name 		 urb->status, urb->actual_length,
731*5113495bSYour Name 		 urb);
732*5113495bSYour Name 
733*5113495bSYour Name 	/* this urb is not pending anymore */
734*5113495bSYour Name 	usb_hif_remove_pending_transfer(urb_context);
735*5113495bSYour Name 
736*5113495bSYour Name 	do {
737*5113495bSYour Name 
738*5113495bSYour Name 		if (urb->status != 0) {
739*5113495bSYour Name 			status = A_ECOMM;
740*5113495bSYour Name 			switch (urb->status) {
741*5113495bSYour Name 			case -ECONNRESET:
742*5113495bSYour Name 			case -ENOENT:
743*5113495bSYour Name 			case -ESHUTDOWN:
744*5113495bSYour Name 				/* NOTE: no need to spew these errors when
745*5113495bSYour Name 				 * device is removed
746*5113495bSYour Name 				 * or urb is killed due to driver shutdown
747*5113495bSYour Name 				 */
748*5113495bSYour Name 				status = A_ECANCELED;
749*5113495bSYour Name 				break;
750*5113495bSYour Name 			default:
751*5113495bSYour Name 				hif_err("recv pipe: %d (ep:0x%2.2X), status: %d",
752*5113495bSYour Name 					pipe->logical_pipe_num,
753*5113495bSYour Name 					pipe->ep_address,
754*5113495bSYour Name 					urb->status);
755*5113495bSYour Name 				break;
756*5113495bSYour Name 			}
757*5113495bSYour Name 			break;
758*5113495bSYour Name 		}
759*5113495bSYour Name 		if (urb->actual_length == 0)
760*5113495bSYour Name 			break;
761*5113495bSYour Name 		buf = urb_context->buf;
762*5113495bSYour Name 		if (AR_DEBUG_LVL_CHECK(USB_HIF_DEBUG_DUMP_DATA)) {
763*5113495bSYour Name 			uint8_t *data;
764*5113495bSYour Name 			uint32_t len;
765*5113495bSYour Name 
766*5113495bSYour Name 			qdf_nbuf_peek_header(buf, &data, &len);
767*5113495bSYour Name 			debug_dump_bytes(data, len, "hif recv data");
768*5113495bSYour Name 		}
769*5113495bSYour Name 
770*5113495bSYour Name 		qdf_nbuf_peek_header(buf, &netdata, &netlen);
771*5113495bSYour Name 		netlen = urb->actual_length;
772*5113495bSYour Name 		no_of_pkt_in_bundle = 0;
773*5113495bSYour Name 
774*5113495bSYour Name 		do {
775*5113495bSYour Name 			uint16_t frame_len;
776*5113495bSYour Name 
777*5113495bSYour Name 			if (IS_FW_CRASH_DUMP(*(uint32_t *) netdata))
778*5113495bSYour Name 				frame_len = netlen;
779*5113495bSYour Name 			else {
780*5113495bSYour Name 				/* Hack into HTC header for bundle processing */
781*5113495bSYour Name 				HtcHdr = (HTC_FRAME_HDR *) netdata;
782*5113495bSYour Name 				if (HtcHdr->EndpointID >= ENDPOINT_MAX) {
783*5113495bSYour Name 					hif_err("athusb: Rx: invalid EndpointID=%d",
784*5113495bSYour Name 						HtcHdr->EndpointID);
785*5113495bSYour Name 					break;
786*5113495bSYour Name 				}
787*5113495bSYour Name 
788*5113495bSYour Name 				payloadLen = HtcHdr->PayloadLen;
789*5113495bSYour Name 				payloadLen = qdf_le16_to_cpu(payloadLen);
790*5113495bSYour Name 
791*5113495bSYour Name 				if (payloadLen > HIF_USB_RX_BUFFER_SIZE) {
792*5113495bSYour Name 					hif_err("athusb: payloadLen too long %u",
793*5113495bSYour Name 						payloadLen);
794*5113495bSYour Name 					break;
795*5113495bSYour Name 				}
796*5113495bSYour Name 				frame_len = (HTC_HDR_LENGTH + payloadLen);
797*5113495bSYour Name 			}
798*5113495bSYour Name 
799*5113495bSYour Name 			if (netlen < frame_len) {
800*5113495bSYour Name 				hif_err("athusb: subframe length %d not fitted into bundle packet length %d"
801*5113495bSYour Name 					, netlen, frame_len);
802*5113495bSYour Name 				break;
803*5113495bSYour Name 			}
804*5113495bSYour Name 
805*5113495bSYour Name 			/* allocate a new skb and copy */
806*5113495bSYour Name 			new_skb =
807*5113495bSYour Name 				qdf_nbuf_alloc(NULL, frame_len, 0, 4, false);
808*5113495bSYour Name 			if (!new_skb) {
809*5113495bSYour Name 				hif_err("athusb: allocate skb (len=%u) failed"
810*5113495bSYour Name 						, frame_len);
811*5113495bSYour Name 				break;
812*5113495bSYour Name 			}
813*5113495bSYour Name 
814*5113495bSYour Name 			qdf_nbuf_peek_header(new_skb, &netdata_new,
815*5113495bSYour Name 						&netlen_new);
816*5113495bSYour Name 			qdf_mem_copy(netdata_new, netdata, frame_len);
817*5113495bSYour Name 			qdf_nbuf_put_tail(new_skb, frame_len);
818*5113495bSYour Name 			skb_queue_tail(&pipe->io_comp_queue, new_skb);
819*5113495bSYour Name 			new_skb = NULL;
820*5113495bSYour Name 			netdata += frame_len;
821*5113495bSYour Name 			netlen -= frame_len;
822*5113495bSYour Name 			no_of_pkt_in_bundle++;
823*5113495bSYour Name 		} while (netlen);
824*5113495bSYour Name 
825*5113495bSYour Name 		if (pipe->device->htc_callbacks.update_bundle_stats)
826*5113495bSYour Name 			pipe->device->htc_callbacks.update_bundle_stats
827*5113495bSYour Name 				(pipe->device->htc_callbacks.Context,
828*5113495bSYour Name 				 no_of_pkt_in_bundle);
829*5113495bSYour Name 
830*5113495bSYour Name 		HIF_USB_SCHEDULE_WORK(pipe);
831*5113495bSYour Name 	} while (false);
832*5113495bSYour Name 
833*5113495bSYour Name 	if (!urb_context->buf)
834*5113495bSYour Name 		hif_err("athusb: buffer in urb_context is NULL");
835*5113495bSYour Name 
836*5113495bSYour Name 	/* reset urb_context->buf ==> seems not necessary */
837*5113495bSYour Name 	usb_hif_free_urb_to_pipe(urb_context->pipe, urb_context);
838*5113495bSYour Name 
839*5113495bSYour Name 	if (QDF_IS_STATUS_SUCCESS(status)) {
840*5113495bSYour Name 		if (pipe->urb_cnt >= pipe->urb_cnt_thresh) {
841*5113495bSYour Name 			/* our free urbs are piling up, post more transfers */
842*5113495bSYour Name 			usb_hif_post_recv_bundle_transfers(pipe,
843*5113495bSYour Name 					pipe->device->rx_bundle_buf_len);
844*5113495bSYour Name 		}
845*5113495bSYour Name 	}
846*5113495bSYour Name 
847*5113495bSYour Name 	hif_debug("-");
848*5113495bSYour Name }
849*5113495bSYour Name 
850*5113495bSYour Name /**
851*5113495bSYour Name  * usb_hif_post_recv_prestart_transfers() - post prestart recv urbs for a pipe
852*5113495bSYour Name  * @recv_pipe: rx data pipe
853*5113495bSYour Name  * @prestart_urb: number of prestart recv urbs to be posted
854*5113495bSYour Name  *
855*5113495bSYour Name  * Return: none
856*5113495bSYour Name  */
usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE * recv_pipe,int prestart_urb)857*5113495bSYour Name static void usb_hif_post_recv_prestart_transfers(struct HIF_USB_PIPE *recv_pipe,
858*5113495bSYour Name 						int prestart_urb)
859*5113495bSYour Name {
860*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
861*5113495bSYour Name 	uint8_t *data;
862*5113495bSYour Name 	uint32_t len;
863*5113495bSYour Name 	struct urb *urb;
864*5113495bSYour Name 	int i, usb_status, buffer_length = HIF_USB_RX_BUFFER_SIZE;
865*5113495bSYour Name 
866*5113495bSYour Name 	hif_info("+");
867*5113495bSYour Name 
868*5113495bSYour Name 	qdf_spin_lock_irqsave(&recv_pipe->device->rx_prestart_lock);
869*5113495bSYour Name 	for (i = 0; i < prestart_urb; i++) {
870*5113495bSYour Name 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
871*5113495bSYour Name 		if (!urb_context)
872*5113495bSYour Name 			break;
873*5113495bSYour Name 
874*5113495bSYour Name 		urb_context->buf =
875*5113495bSYour Name 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
876*5113495bSYour Name 		if (!urb_context->buf) {
877*5113495bSYour Name 			usb_hif_cleanup_recv_urb(urb_context);
878*5113495bSYour Name 			break;
879*5113495bSYour Name 		}
880*5113495bSYour Name 
881*5113495bSYour Name 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
882*5113495bSYour Name 
883*5113495bSYour Name 		urb = urb_context->urb;
884*5113495bSYour Name 
885*5113495bSYour Name 		usb_fill_bulk_urb(urb,
886*5113495bSYour Name 				recv_pipe->device->udev,
887*5113495bSYour Name 				recv_pipe->usb_pipe_handle,
888*5113495bSYour Name 				data,
889*5113495bSYour Name 				buffer_length,
890*5113495bSYour Name 				usb_hif_usb_recv_prestart_complete,
891*5113495bSYour Name 				urb_context);
892*5113495bSYour Name 
893*5113495bSYour Name 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
894*5113495bSYour Name 			 recv_pipe->logical_pipe_num,
895*5113495bSYour Name 			 recv_pipe->usb_pipe_handle,
896*5113495bSYour Name 			 recv_pipe->ep_address, buffer_length,
897*5113495bSYour Name 			 urb_context->buf);
898*5113495bSYour Name 
899*5113495bSYour Name 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
900*5113495bSYour Name 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
901*5113495bSYour Name 
902*5113495bSYour Name 		if (usb_status) {
903*5113495bSYour Name 			hif_err("athusb : usb bulk recv failed %d",
904*5113495bSYour Name 				usb_status);
905*5113495bSYour Name 			usb_hif_remove_pending_transfer(urb_context);
906*5113495bSYour Name 			usb_hif_cleanup_recv_urb(urb_context);
907*5113495bSYour Name 			break;
908*5113495bSYour Name 		}
909*5113495bSYour Name 		recv_pipe->urb_prestart_cnt++;
910*5113495bSYour Name 	}
911*5113495bSYour Name 	qdf_spin_unlock_irqrestore(&recv_pipe->device->rx_prestart_lock);
912*5113495bSYour Name 
913*5113495bSYour Name 	hif_info("-");
914*5113495bSYour Name }
915*5113495bSYour Name 
916*5113495bSYour Name /**
917*5113495bSYour Name  * usb_hif_post_recv_transfers() - post recv urbs for a given pipe
918*5113495bSYour Name  * @recv_pipe: recv pipe for which urbs need to be posted
919*5113495bSYour Name  * @buffer_length: buffer length of the recv urbs
920*5113495bSYour Name  *
921*5113495bSYour Name  * Return: none
922*5113495bSYour Name  */
usb_hif_post_recv_transfers(struct HIF_USB_PIPE * recv_pipe,int buffer_length)923*5113495bSYour Name static void usb_hif_post_recv_transfers(struct HIF_USB_PIPE *recv_pipe,
924*5113495bSYour Name 							int buffer_length)
925*5113495bSYour Name {
926*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
927*5113495bSYour Name 	uint8_t *data;
928*5113495bSYour Name 	uint32_t len;
929*5113495bSYour Name 	struct urb *urb;
930*5113495bSYour Name 	int usb_status;
931*5113495bSYour Name 
932*5113495bSYour Name 	while (1) {
933*5113495bSYour Name 
934*5113495bSYour Name 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
935*5113495bSYour Name 		if (!urb_context)
936*5113495bSYour Name 			break;
937*5113495bSYour Name 
938*5113495bSYour Name 		urb_context->buf = qdf_nbuf_alloc(NULL, buffer_length, 0,
939*5113495bSYour Name 						4, false);
940*5113495bSYour Name 		if (!urb_context->buf) {
941*5113495bSYour Name 			usb_hif_cleanup_recv_urb(urb_context);
942*5113495bSYour Name 			break;
943*5113495bSYour Name 		}
944*5113495bSYour Name 
945*5113495bSYour Name 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
946*5113495bSYour Name 
947*5113495bSYour Name 		urb = urb_context->urb;
948*5113495bSYour Name 
949*5113495bSYour Name 		usb_fill_bulk_urb(urb,
950*5113495bSYour Name 				recv_pipe->device->udev,
951*5113495bSYour Name 				recv_pipe->usb_pipe_handle,
952*5113495bSYour Name 				data,
953*5113495bSYour Name 				buffer_length,
954*5113495bSYour Name 				usb_hif_usb_recv_complete, urb_context);
955*5113495bSYour Name 
956*5113495bSYour Name 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
957*5113495bSYour Name 			 recv_pipe->logical_pipe_num,
958*5113495bSYour Name 			 recv_pipe->usb_pipe_handle,
959*5113495bSYour Name 			 recv_pipe->ep_address, buffer_length,
960*5113495bSYour Name 			 urb_context->buf);
961*5113495bSYour Name 
962*5113495bSYour Name 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
963*5113495bSYour Name 
964*5113495bSYour Name 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
965*5113495bSYour Name 
966*5113495bSYour Name 		if (usb_status) {
967*5113495bSYour Name 			hif_err("athusb : usb bulk recv failed %d",
968*5113495bSYour Name 				usb_status);
969*5113495bSYour Name 			usb_hif_remove_pending_transfer(urb_context);
970*5113495bSYour Name 			usb_hif_cleanup_recv_urb(urb_context);
971*5113495bSYour Name 			break;
972*5113495bSYour Name 		}
973*5113495bSYour Name 	}
974*5113495bSYour Name 
975*5113495bSYour Name }
976*5113495bSYour Name 
977*5113495bSYour Name /**
978*5113495bSYour Name  * usb_hif_post_recv_bundle_transfers() - post recv urbs for a given pipe
979*5113495bSYour Name  * @recv_pipe: recv pipe for which urbs need to be posted
980*5113495bSYour Name  * @buffer_length: maximum length of rx bundle
981*5113495bSYour Name  *
982*5113495bSYour Name  * Return: none
983*5113495bSYour Name  */
usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE * recv_pipe,int buffer_length)984*5113495bSYour Name static void usb_hif_post_recv_bundle_transfers(struct HIF_USB_PIPE *recv_pipe,
985*5113495bSYour Name 						int buffer_length)
986*5113495bSYour Name {
987*5113495bSYour Name 	struct HIF_URB_CONTEXT *urb_context;
988*5113495bSYour Name 	uint8_t *data;
989*5113495bSYour Name 	uint32_t len;
990*5113495bSYour Name 	struct urb *urb;
991*5113495bSYour Name 	int usb_status;
992*5113495bSYour Name 
993*5113495bSYour Name 	while (1) {
994*5113495bSYour Name 
995*5113495bSYour Name 		urb_context = usb_hif_alloc_urb_from_pipe(recv_pipe);
996*5113495bSYour Name 		if (!urb_context)
997*5113495bSYour Name 			break;
998*5113495bSYour Name 
999*5113495bSYour Name 		if (!urb_context->buf) {
1000*5113495bSYour Name 			urb_context->buf =
1001*5113495bSYour Name 			qdf_nbuf_alloc(NULL, buffer_length, 0, 4, false);
1002*5113495bSYour Name 			if (!urb_context->buf) {
1003*5113495bSYour Name 				usb_hif_cleanup_recv_urb(urb_context);
1004*5113495bSYour Name 				break;
1005*5113495bSYour Name 			}
1006*5113495bSYour Name 		}
1007*5113495bSYour Name 
1008*5113495bSYour Name 		qdf_nbuf_peek_header(urb_context->buf, &data, &len);
1009*5113495bSYour Name 
1010*5113495bSYour Name 		urb = urb_context->urb;
1011*5113495bSYour Name 		usb_fill_bulk_urb(urb,
1012*5113495bSYour Name 				recv_pipe->device->udev,
1013*5113495bSYour Name 				recv_pipe->usb_pipe_handle,
1014*5113495bSYour Name 				data,
1015*5113495bSYour Name 				buffer_length,
1016*5113495bSYour Name 				usb_hif_usb_recv_bundle_complete,
1017*5113495bSYour Name 				urb_context);
1018*5113495bSYour Name 
1019*5113495bSYour Name 		hif_debug("athusb bulk recv submit:%d, 0x%X (ep:0x%2.2X), %d bytes, buf:0x%pK",
1020*5113495bSYour Name 			 recv_pipe->logical_pipe_num,
1021*5113495bSYour Name 			 recv_pipe->usb_pipe_handle,
1022*5113495bSYour Name 			 recv_pipe->ep_address, buffer_length,
1023*5113495bSYour Name 			 urb_context->buf);
1024*5113495bSYour Name 
1025*5113495bSYour Name 		usb_hif_enqueue_pending_transfer(recv_pipe, urb_context);
1026*5113495bSYour Name 
1027*5113495bSYour Name 		usb_status = usb_submit_urb(urb, GFP_ATOMIC);
1028*5113495bSYour Name 
1029*5113495bSYour Name 		if (usb_status) {
1030*5113495bSYour Name 			hif_err("athusb : usb bulk recv failed %d",
1031*5113495bSYour Name 				usb_status);
1032*5113495bSYour Name 			usb_hif_remove_pending_transfer(urb_context);
1033*5113495bSYour Name 			usb_hif_free_urb_to_pipe(urb_context->pipe,
1034*5113495bSYour Name 						urb_context);
1035*5113495bSYour Name 			break;
1036*5113495bSYour Name 		}
1037*5113495bSYour Name 
1038*5113495bSYour Name 	}
1039*5113495bSYour Name 
1040*5113495bSYour Name }
1041*5113495bSYour Name 
1042*5113495bSYour Name /**
1043*5113495bSYour Name  * usb_hif_prestart_recv_pipes() - post prestart recv urbs
1044*5113495bSYour Name  * @device: HIF device for which prestart recv urbs need to be posted
1045*5113495bSYour Name  *
1046*5113495bSYour Name  * Return: none
1047*5113495bSYour Name  */
usb_hif_prestart_recv_pipes(struct HIF_DEVICE_USB * device)1048*5113495bSYour Name void usb_hif_prestart_recv_pipes(struct HIF_DEVICE_USB *device)
1049*5113495bSYour Name {
1050*5113495bSYour Name 	struct HIF_USB_PIPE *pipe;
1051*5113495bSYour Name 	int prestart_cnt = 8;
1052*5113495bSYour Name 
1053*5113495bSYour Name 	if (device->rx_ctrl_pipe_supported) {
1054*5113495bSYour Name 		pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1055*5113495bSYour Name 		prestart_cnt = 4;
1056*5113495bSYour Name 		usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1057*5113495bSYour Name 	}
1058*5113495bSYour Name 	/*
1059*5113495bSYour Name 	 * USB driver learn to support bundle or not until the firmware
1060*5113495bSYour Name 	 * download and ready. Only allocate some URBs for control message
1061*5113495bSYour Name 	 * communication during the initial phase then start the final
1062*5113495bSYour Name 	 * working pipe after all information understood.
1063*5113495bSYour Name 	 */
1064*5113495bSYour Name 	pipe = &device->pipes[HIF_RX_DATA_PIPE];
1065*5113495bSYour Name 	usb_hif_post_recv_prestart_transfers(pipe, prestart_cnt);
1066*5113495bSYour Name }
1067*5113495bSYour Name 
1068*5113495bSYour Name /**
1069*5113495bSYour Name  * usb_hif_start_recv_pipes() - start recv urbs
1070*5113495bSYour Name  * @device: HIF device for which recv urbs need to be posted
1071*5113495bSYour Name  *
1072*5113495bSYour Name  * This function is called after all prestart recv urbs are exhausted
1073*5113495bSYour Name  *
1074*5113495bSYour Name  * Return: none
1075*5113495bSYour Name  */
usb_hif_start_recv_pipes(struct HIF_DEVICE_USB * device)1076*5113495bSYour Name void usb_hif_start_recv_pipes(struct HIF_DEVICE_USB *device)
1077*5113495bSYour Name {
1078*5113495bSYour Name 	struct HIF_USB_PIPE *pipe;
1079*5113495bSYour Name 	uint32_t buf_len;
1080*5113495bSYour Name 
1081*5113495bSYour Name 	HIF_ENTER();
1082*5113495bSYour Name 	pipe = &device->pipes[HIF_RX_DATA_PIPE];
1083*5113495bSYour Name 	pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1084*5113495bSYour Name 
1085*5113495bSYour Name 	hif_info("Post URBs to RX_DATA_PIPE: %d is_bundle %d",
1086*5113495bSYour Name 		  device->pipes[HIF_RX_DATA_PIPE].urb_cnt,
1087*5113495bSYour Name 		  device->is_bundle_enabled);
1088*5113495bSYour Name 	if (device->is_bundle_enabled) {
1089*5113495bSYour Name 		usb_hif_post_recv_bundle_transfers(pipe,
1090*5113495bSYour Name 					pipe->device->rx_bundle_buf_len);
1091*5113495bSYour Name 	} else {
1092*5113495bSYour Name 		buf_len = HIF_USB_RX_BUFFER_SIZE;
1093*5113495bSYour Name 		usb_hif_post_recv_transfers(pipe, buf_len);
1094*5113495bSYour Name 	}
1095*5113495bSYour Name 
1096*5113495bSYour Name 	hif_debug("athusb bulk recv len %d", buf_len);
1097*5113495bSYour Name 
1098*5113495bSYour Name 	if (!hif_usb_disable_rxdata2) {
1099*5113495bSYour Name 		hif_info("Post URBs to RX_DATA2_PIPE: %d",
1100*5113495bSYour Name 			device->pipes[HIF_RX_DATA2_PIPE].urb_cnt);
1101*5113495bSYour Name 
1102*5113495bSYour Name 		pipe = &device->pipes[HIF_RX_DATA2_PIPE];
1103*5113495bSYour Name 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1104*5113495bSYour Name 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1105*5113495bSYour Name 	}
1106*5113495bSYour Name 
1107*5113495bSYour Name 	if (device->rx_ctrl_pipe_supported) {
1108*5113495bSYour Name 		hif_info("Post URBs to RX_CONTROL_PIPE: %d",
1109*5113495bSYour Name 			 device->pipes[HIF_RX_CTRL_PIPE].urb_cnt);
1110*5113495bSYour Name 
1111*5113495bSYour Name 		pipe = &device->pipes[HIF_RX_CTRL_PIPE];
1112*5113495bSYour Name 		pipe->urb_cnt_thresh = pipe->urb_alloc / 2;
1113*5113495bSYour Name 		usb_hif_post_recv_transfers(pipe, HIF_USB_RX_BUFFER_SIZE);
1114*5113495bSYour Name 	}
1115*5113495bSYour Name 	HIF_EXIT();
1116*5113495bSYour Name }
1117*5113495bSYour Name 
1118*5113495bSYour Name /**
1119*5113495bSYour Name  * usb_hif_submit_ctrl_out() - send out a ctrl urb
1120*5113495bSYour Name  * @device: HIF device for which urb needs to be posted
1121*5113495bSYour Name  * @req: request value for the ctrl message
1122*5113495bSYour Name  * @value: USB message value
1123*5113495bSYour Name  * @index: USB message index value
1124*5113495bSYour Name  * @data: pointer to data containing ctrl message to send
1125*5113495bSYour Name  * @size: size of the control message to send
1126*5113495bSYour Name  *
1127*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1128*5113495bSYour Name  */
usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB * device,uint8_t req,uint16_t value,uint16_t index,void * data,uint32_t size)1129*5113495bSYour Name QDF_STATUS usb_hif_submit_ctrl_out(struct HIF_DEVICE_USB *device,
1130*5113495bSYour Name 				   uint8_t req, uint16_t value, uint16_t index,
1131*5113495bSYour Name 				   void *data, uint32_t size)
1132*5113495bSYour Name {
1133*5113495bSYour Name 	int32_t result = 0;
1134*5113495bSYour Name 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1135*5113495bSYour Name 	uint8_t *buf = NULL;
1136*5113495bSYour Name 
1137*5113495bSYour Name 	do {
1138*5113495bSYour Name 
1139*5113495bSYour Name 		if (size > 0) {
1140*5113495bSYour Name 			buf = qdf_mem_malloc(size);
1141*5113495bSYour Name 			if (!buf) {
1142*5113495bSYour Name 				ret = QDF_STATUS_E_NOMEM;
1143*5113495bSYour Name 				break;
1144*5113495bSYour Name 			}
1145*5113495bSYour Name 			qdf_mem_copy(buf, (uint8_t *) data, size);
1146*5113495bSYour Name 		}
1147*5113495bSYour Name 
1148*5113495bSYour Name 		hif_debug("ctrl-out req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1149*5113495bSYour Name 			 req, value, index, size);
1150*5113495bSYour Name 
1151*5113495bSYour Name 		result = usb_control_msg(device->udev,
1152*5113495bSYour Name 					usb_sndctrlpipe(device->udev, 0),
1153*5113495bSYour Name 					req,
1154*5113495bSYour Name 					USB_DIR_OUT | USB_TYPE_VENDOR |
1155*5113495bSYour Name 					USB_RECIP_DEVICE, value, index, buf,
1156*5113495bSYour Name 					size, 2 * HZ);
1157*5113495bSYour Name 
1158*5113495bSYour Name 		if (result < 0) {
1159*5113495bSYour Name 			hif_err("usb_control_msg failed, (result=%d)", result);
1160*5113495bSYour Name 			ret = QDF_STATUS_E_FAILURE;
1161*5113495bSYour Name 		}
1162*5113495bSYour Name 
1163*5113495bSYour Name 	} while (false);
1164*5113495bSYour Name 
1165*5113495bSYour Name 	if (buf)
1166*5113495bSYour Name 		qdf_mem_free(buf);
1167*5113495bSYour Name 
1168*5113495bSYour Name 	return ret;
1169*5113495bSYour Name }
1170*5113495bSYour Name 
1171*5113495bSYour Name /**
1172*5113495bSYour Name  * usb_hif_submit_ctrl_in() - recv a response to the ctrl message sent out
1173*5113495bSYour Name  * @device: HIF device for which urb needs to be received
1174*5113495bSYour Name  * @req: request value for the ctrl message
1175*5113495bSYour Name  * @value: USB message value
1176*5113495bSYour Name  * @index: USB message index value
1177*5113495bSYour Name  * @data: pointer to data containing ctrl message to be received
1178*5113495bSYour Name  * @size: size of the control message to be received
1179*5113495bSYour Name  *
1180*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
1181*5113495bSYour Name  */
usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB * device,uint8_t req,uint16_t value,uint16_t index,void * data,uint32_t size)1182*5113495bSYour Name QDF_STATUS usb_hif_submit_ctrl_in(struct HIF_DEVICE_USB *device,
1183*5113495bSYour Name 				  uint8_t req, uint16_t value, uint16_t index,
1184*5113495bSYour Name 				  void *data, uint32_t size)
1185*5113495bSYour Name {
1186*5113495bSYour Name 	int32_t result = 0;
1187*5113495bSYour Name 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
1188*5113495bSYour Name 	uint8_t *buf = NULL;
1189*5113495bSYour Name 
1190*5113495bSYour Name 	do {
1191*5113495bSYour Name 
1192*5113495bSYour Name 		if (size > 0) {
1193*5113495bSYour Name 			buf = qdf_mem_malloc(size);
1194*5113495bSYour Name 			if (!buf) {
1195*5113495bSYour Name 				ret = QDF_STATUS_E_NOMEM;
1196*5113495bSYour Name 				break;
1197*5113495bSYour Name 			}
1198*5113495bSYour Name 		}
1199*5113495bSYour Name 
1200*5113495bSYour Name 		hif_debug("ctrl-in req:0x%2.2X, value:0x%4.4X index:0x%4.4X, datasize:%d",
1201*5113495bSYour Name 			 req, value, index, size);
1202*5113495bSYour Name 
1203*5113495bSYour Name 		result = usb_control_msg(device->udev,
1204*5113495bSYour Name 					usb_rcvctrlpipe(device->udev, 0),
1205*5113495bSYour Name 					req,
1206*5113495bSYour Name 					USB_DIR_IN | USB_TYPE_VENDOR |
1207*5113495bSYour Name 					USB_RECIP_DEVICE, value, index, buf,
1208*5113495bSYour Name 					size, 2 * HZ);
1209*5113495bSYour Name 
1210*5113495bSYour Name 		if (result < 0) {
1211*5113495bSYour Name 			hif_err("usb_control_msg failed, (result=%d)", result);
1212*5113495bSYour Name 			ret = QDF_STATUS_E_FAILURE;
1213*5113495bSYour Name 			break;
1214*5113495bSYour Name 		}
1215*5113495bSYour Name 
1216*5113495bSYour Name 		qdf_mem_copy((uint8_t *) data, buf, size);
1217*5113495bSYour Name 
1218*5113495bSYour Name 	} while (false);
1219*5113495bSYour Name 
1220*5113495bSYour Name 	if (buf)
1221*5113495bSYour Name 		qdf_mem_free(buf);
1222*5113495bSYour Name 
1223*5113495bSYour Name 	return ret;
1224*5113495bSYour Name }
1225*5113495bSYour Name 
1226*5113495bSYour Name /**
1227*5113495bSYour Name  * usb_hif_io_complete() - transmit call back for tx urb
1228*5113495bSYour Name  * @pipe: pointer to struct HIF_USB_PIPE
1229*5113495bSYour Name  *
1230*5113495bSYour Name  * Return: none
1231*5113495bSYour Name  */
usb_hif_io_complete(struct HIF_USB_PIPE * pipe)1232*5113495bSYour Name static void usb_hif_io_complete(struct HIF_USB_PIPE *pipe)
1233*5113495bSYour Name {
1234*5113495bSYour Name 	qdf_nbuf_t buf;
1235*5113495bSYour Name 	struct HIF_DEVICE_USB *device;
1236*5113495bSYour Name 	HTC_FRAME_HDR *HtcHdr;
1237*5113495bSYour Name 	uint8_t *data;
1238*5113495bSYour Name 	uint32_t len;
1239*5113495bSYour Name 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(pipe->device);
1240*5113495bSYour Name 
1241*5113495bSYour Name 	device = pipe->device;
1242*5113495bSYour Name 	HIF_ENTER();
1243*5113495bSYour Name 	while ((buf = skb_dequeue(&pipe->io_comp_queue))) {
1244*5113495bSYour Name 		if (pipe->flags & HIF_USB_PIPE_FLAG_TX) {
1245*5113495bSYour Name 			hif_debug("+athusb xmit callback buf:0x%pK", buf);
1246*5113495bSYour Name 			HtcHdr = (HTC_FRAME_HDR *)
1247*5113495bSYour Name 					qdf_nbuf_get_frag_vaddr(buf, 0);
1248*5113495bSYour Name 
1249*5113495bSYour Name #ifdef ATH_11AC_TXCOMPACT
1250*5113495bSYour Name /* ATH_11AC_TXCOMPACT does not support High Latency mode */
1251*5113495bSYour Name #else
1252*5113495bSYour Name 			device->htc_callbacks.txCompletionHandler(device->
1253*5113495bSYour Name 								htc_callbacks.
1254*5113495bSYour Name 								Context, buf,
1255*5113495bSYour Name 								HtcHdr->
1256*5113495bSYour Name 								EndpointID, 0);
1257*5113495bSYour Name #endif
1258*5113495bSYour Name 			hif_debug("-athusb xmit callback");
1259*5113495bSYour Name 		} else {
1260*5113495bSYour Name 			hif_debug("+athusb recv callback buf: 0x%pK", buf);
1261*5113495bSYour Name 			qdf_nbuf_peek_header(buf, &data, &len);
1262*5113495bSYour Name 
1263*5113495bSYour Name 			if (IS_FW_CRASH_DUMP(*((uint32_t *) data))) {
1264*5113495bSYour Name 				sc->fw_data = data;
1265*5113495bSYour Name 				sc->fw_data_len = len;
1266*5113495bSYour Name 				device->htc_callbacks.fwEventHandler(
1267*5113495bSYour Name 					device->htc_callbacks.Context,
1268*5113495bSYour Name 					QDF_STATUS_E_USB_ERROR);
1269*5113495bSYour Name 				qdf_nbuf_free(buf);
1270*5113495bSYour Name 			} else {
1271*5113495bSYour Name 				device->htc_callbacks.rxCompletionHandler(
1272*5113495bSYour Name 				device->htc_callbacks.Context, buf,
1273*5113495bSYour Name 				pipe->logical_pipe_num);
1274*5113495bSYour Name 			}
1275*5113495bSYour Name 			hif_debug("-athusb recv callback");
1276*5113495bSYour Name 		}
1277*5113495bSYour Name 	}
1278*5113495bSYour Name 
1279*5113495bSYour Name 	HIF_EXIT();
1280*5113495bSYour Name }
1281*5113495bSYour Name 
1282*5113495bSYour Name #ifdef HIF_USB_TASKLET
1283*5113495bSYour Name /**
1284*5113495bSYour Name  * usb_hif_io_comp_tasklet() - per pipe tasklet routine
1285*5113495bSYour Name  * @context: pointer to HIF USB pipe
1286*5113495bSYour Name  *
1287*5113495bSYour Name  * Return: none
1288*5113495bSYour Name  */
usb_hif_io_comp_tasklet(unsigned long context)1289*5113495bSYour Name void usb_hif_io_comp_tasklet(unsigned long context)
1290*5113495bSYour Name {
1291*5113495bSYour Name 	struct HIF_USB_PIPE *pipe = (struct HIF_USB_PIPE *) context;
1292*5113495bSYour Name 
1293*5113495bSYour Name 	usb_hif_io_complete(pipe);
1294*5113495bSYour Name }
1295*5113495bSYour Name 
1296*5113495bSYour Name #else
1297*5113495bSYour Name /**
1298*5113495bSYour Name  * usb_hif_io_comp_work() - per pipe work queue
1299*5113495bSYour Name  * @work: pointer to struct work_struct
1300*5113495bSYour Name  *
1301*5113495bSYour Name  * Return: none
1302*5113495bSYour Name  */
usb_hif_io_comp_work(struct work_struct * work)1303*5113495bSYour Name void usb_hif_io_comp_work(struct work_struct *work)
1304*5113495bSYour Name {
1305*5113495bSYour Name 	struct HIF_USB_PIPE *pipe = container_of(work, struct HIF_USB_PIPE,
1306*5113495bSYour Name 						 io_complete_work);
1307*5113495bSYour Name 
1308*5113495bSYour Name 	usb_hif_io_complete(pipe);
1309*5113495bSYour Name }
1310*5113495bSYour Name #endif
1311