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