1 /** @file moal_usb.c
2 *
3 * @brief This file contains the interfaceing to USB bus
4 * driver.
5 *
6 *
7 * Copyright 2008-2021 NXP
8 *
9 * This software file (the File) is distributed by NXP
10 * under the terms of the GNU General Public License Version 2, June 1991
11 * (the License). You may use, redistribute and/or modify the File in
12 * accordance with the terms and conditions of the License, a copy of which
13 * is available by writing to the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16 *
17 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
20 * this warranty disclaimer.
21 *
22 */
23
24 /********************************************************
25 Change log:
26 10/21/2008: initial version
27 ********************************************************/
28
29 #include "moal_main.h"
30 #include "moal_usb.h"
31 extern struct semaphore AddRemoveCardSem;
32
33 /********************************************************
34 Local Variables
35 ********************************************************/
36
37 #if defined(USB8997) || defined(USB9098) || defined(USB9097) || \
38 defined(USB8978) || defined(USBNW62X)
39 /** Card-type detection frame response */
40 typedef struct {
41 /** 32-bit ACK+WINNER field */
42 t_u32 ack_winner;
43 /** 32-bit Sequence number */
44 t_u32 seq;
45 /** 32-bit extend */
46 t_u32 extend;
47 /** 32-bit chip-revision code */
48 t_u32 chip_rev;
49 /** 32-bit strap setting */
50 t_u32 strap;
51 } usb_ack_pkt;
52 #endif
53
54 /** NXP USB device */
55 #define NXP_USB_DEVICE(vid, pid, name) \
56 USB_DEVICE(vid, pid), .driver_info = (t_ptr)name
57
58 /** Name of the USB driver */
59 static const char usbdriver_name[] = "usbxxx";
60
61 /** This structure contains the device signature */
62 static struct usb_device_id woal_usb_table[] = {
63 /* Enter the device signature inside */
64 #ifdef USB8801
65 {NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_1, "NXP WLAN USB Adapter")},
66 {NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_2, "NXP WLAN USB Adapter")},
67 #endif
68 #ifdef USB8897
69 {NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_1, "NXP WLAN USB Adapter")},
70 {NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_2, "NXP WLAN USB Adapter")},
71 #endif
72 #ifdef USB8997
73 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_1, "NXP WLAN USB Adapter")},
74 {NXP_USB_DEVICE(USB8997_VID_1, USB8997V2_PID_1,
75 "NXP WLAN USB Adapter")},
76 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_2, "NXP WLAN USB Adapter")},
77 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_3, "NXP WLAN USB Adapter")},
78 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_4, "NXP WLAN USB Adapter")},
79 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_5, "NXP WLAN USB Adapter")},
80 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_6, "NXP WLAN USB Adapter")},
81 #endif
82 #ifdef USB8978
83 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_1, "NXP WLAN USB Adapter")},
84 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_1_BT,
85 "NXP WLAN USB Adapter")},
86 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2, "NXP WLAN USB Adapter")},
87 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2_BT,
88 "NXP WLAN USB Adapter")},
89 #endif
90 #ifdef USB9098
91 {NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_1, "NXP WLAN USB Adapter")},
92 {NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_2, "NXP WLAN USB Adapter")},
93 #endif
94 #ifdef USB9097
95 {NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_1, "NXP WLAN USB Adapter")},
96 {NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_2, "NXP WLAN USB Adapter")},
97 #endif
98 #ifdef USBNW62X
99 {NXP_USB_DEVICE(USBNW62X_VID_1, USBNW62X_PID_1,
100 "NXP WLAN USB Adapter")},
101 {NXP_USB_DEVICE(USBNW62X_VID_1, USBNW62X_PID_2,
102 "NXP WLAN USB Adapter")},
103 #endif
104 /* Terminating entry */
105 {},
106 };
107
108 /** This structure contains the device signature */
109 static struct usb_device_id woal_usb_table_skip_fwdnld[] = {
110 /* Enter the device signature inside */
111 #ifdef USB8801
112 {NXP_USB_DEVICE(USB8801_VID_1, USB8801_PID_2, "NXP WLAN USB Adapter")},
113 #endif
114 #ifdef USB8897
115 {NXP_USB_DEVICE(USB8897_VID_1, USB8897_PID_2, "NXP WLAN USB Adapter")},
116 #endif
117 #ifdef USB8997
118 {NXP_USB_DEVICE(USB8997_VID_1, USB8997_PID_2, "NXP WLAN USB Adapter")},
119 #endif
120 #ifdef USB8978
121 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2, "NXP WLAN USB Adapter")},
122 {NXP_USB_DEVICE(USB8978_VID_1, USB8978_PID_2_BT,
123 "NXP WLAN USB Adapter")},
124 #endif
125 #ifdef USB9098
126 {NXP_USB_DEVICE(USB9098_VID_1, USB9098_PID_2, "NXP WLAN USB Adapter")},
127 #endif
128 #ifdef USB9097
129 {NXP_USB_DEVICE(USB9097_VID_1, USB9097_PID_2, "NXP WLAN USB Adapter")},
130 #endif
131 #ifdef USBNW62X
132 {NXP_USB_DEVICE(USBNW62X_VID_1, USBNW62X_PID_2,
133 "NXP WLAN USB Adapter")},
134 #endif
135 /* Terminating entry */
136 {},
137 };
138
139 static mlan_status woal_usb_submit_rx_urb(urb_context *ctx, int size);
140 static int woal_usb_probe(struct usb_interface *intf,
141 const struct usb_device_id *id);
142 static void woal_usb_disconnect(struct usb_interface *intf);
143 static mlan_status woal_usb_write_data_sync(moal_handle *handle,
144 mlan_buffer *pmbuf, t_u32 endpoint,
145 t_u32 timeout);
146 static mlan_status woal_usb_read_data_sync(moal_handle *handle,
147 mlan_buffer *pmbuf, t_u32 endpoint,
148 t_u32 timeout);
149 #ifdef CONFIG_PM
150 static int woal_usb_suspend(struct usb_interface *intf, pm_message_t message);
151 static int woal_usb_resume(struct usb_interface *intf);
152 #endif /* CONFIG_PM */
153
154 /** woal_usb_driver */
155 static struct usb_driver REFDATA woal_usb_driver = {
156 /* Driver name */
157 .name = usbdriver_name,
158
159 /* Probe function name */
160 .probe = woal_usb_probe,
161
162 /* Disconnect function name */
163 .disconnect = woal_usb_disconnect,
164
165 /* Device signature table */
166 .id_table = woal_usb_table,
167 #ifdef CONFIG_PM
168 /* Suspend function name */
169 .suspend = woal_usb_suspend,
170
171 /* Resume function name */
172 .resume = woal_usb_resume,
173
174 /* Reset resume function name */
175 .reset_resume = woal_usb_resume,
176
177 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
178 /* Driver supports autosuspend */
179 .supports_autosuspend = 1,
180 #endif
181 #endif /* CONFIG_PM */
182 };
183
184 MODULE_DEVICE_TABLE(usb, woal_usb_table);
185 MODULE_DEVICE_TABLE(usb, woal_usb_table_skip_fwdnld);
186
187 /* moal interface ops */
188 static moal_if_ops usb_ops;
189
190 /********************************************************
191 Global Variables
192 ********************************************************/
193
194 /********************************************************
195 Local Functions
196 ********************************************************/
197
198 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
199 /**
200 * @brief This function receive packet of the data/cmd/event packet
201 * and pass to MLAN
202 *
203 * @param urb Pointer to struct urb
204 * @param regs Registers
205 *
206 * @return N/A
207 */
woal_usb_receive(struct urb * urb,struct pt_regs * regs)208 static void woal_usb_receive(struct urb *urb, struct pt_regs *regs)
209 #else
210 /**
211 * @brief This function receive packet of the data/cmd/event packet
212 * and pass to MLAN
213 *
214 * @param urb Pointer to struct urb
215 *
216 * @return N/A
217 */
218 static void woal_usb_receive(struct urb *urb)
219 #endif
220 {
221 urb_context *context = NULL;
222 moal_handle *handle = NULL;
223 mlan_buffer *pmbuf = NULL;
224 struct usb_card_rec *cardp = NULL;
225 int recv_length;
226 int size;
227 mlan_status status = MLAN_STATUS_SUCCESS;
228
229 ENTER();
230
231 if (!urb || !urb->context) {
232 PRINTM(MERROR, "URB or URB context is not valid in USB Rx\n");
233 LEAVE();
234 return;
235 }
236 context = (urb_context *)urb->context;
237 handle = context->handle;
238 pmbuf = context->pmbuf;
239 recv_length = urb->actual_length;
240
241 if (!handle || !handle->card || !pmbuf) {
242 PRINTM(MERROR,
243 "moal handle, card structure or mlan_buffer is not valid in USB Rx\n");
244 LEAVE();
245 return;
246 }
247 cardp = (struct usb_card_rec *)handle->card;
248 if (cardp->rx_cmd_ep == context->ep)
249 atomic_dec(&cardp->rx_cmd_urb_pending);
250 else
251 atomic_dec(&cardp->rx_data_urb_pending);
252
253 if (recv_length) {
254 if (urb->status || (handle->surprise_removed == MTRUE)) {
255 if (handle->surprise_removed || handle->is_suspended) {
256 woal_free_mlan_buffer(handle, pmbuf);
257 context->pmbuf = NULL;
258 goto rx_exit;
259 } else {
260 PRINTM(MERROR,
261 "EP %d Rx URB status failure: %d\n",
262 context->ep, urb->status);
263 /* Do not free mlan_buffer in case of command ep
264 */
265 if (cardp->rx_cmd_ep != context->ep)
266 woal_free_mlan_buffer(handle, pmbuf);
267 goto setup_for_next;
268 }
269 }
270 pmbuf->data_len = recv_length;
271 pmbuf->flags |= MLAN_BUF_FLAG_RX_DEAGGR;
272 /* Send packet to MLAN */
273 atomic_inc(&handle->rx_pending);
274 status = mlan_recv(handle->pmlan_adapter, pmbuf, context->ep);
275 PRINTM(MINFO, "Receive length = 0x%x, status=%d\n", recv_length,
276 status);
277 if (status == MLAN_STATUS_PENDING) {
278 queue_work(handle->workqueue, &handle->main_work);
279 /* urb for data_ep is re-submitted now, unless we reach
280 * USB_HIGH_RX_PENDING */
281 /* urb for cmd_ep will be re-submitted in callback
282 * moal_recv_complete */
283 if (cardp->rx_cmd_ep == context->ep)
284 goto rx_exit;
285 else if (atomic_read(&handle->rx_pending) >=
286 USB_HIGH_RX_PENDING) {
287 context->pmbuf = NULL;
288 goto rx_exit;
289 }
290 } else {
291 atomic_dec(&handle->rx_pending);
292 if (status == MLAN_STATUS_FAILURE) {
293 PRINTM(MERROR,
294 "MLAN fail to process the receive data\n");
295 } else if ((status == MLAN_STATUS_SUCCESS) &&
296 (pmbuf->flags &
297 MLAN_BUF_FLAG_SLEEPCFM_RESP)) {
298 pmbuf->flags &= ~MLAN_BUF_FLAG_SLEEPCFM_RESP;
299 queue_work(handle->workqueue,
300 &handle->main_work);
301 }
302 /* Do not free mlan_buffer in case of command ep */
303 if (cardp->rx_cmd_ep != context->ep)
304 woal_free_mlan_buffer(handle, pmbuf);
305 }
306 } else if (urb->status) {
307 if (!((cardp->rx_data_ep == context->ep) &&
308 (cardp->resubmit_urbs == 1))) {
309 if (!handle->is_suspended) {
310 PRINTM(MMSG, "Card is removed: %d\n",
311 urb->status);
312 handle->surprise_removed = MTRUE;
313 }
314 }
315 woal_free_mlan_buffer(handle, pmbuf);
316 context->pmbuf = NULL;
317 goto rx_exit;
318 } else {
319 /* Do not free mlan_buffer in case of command ep */
320 if (cardp->rx_cmd_ep != context->ep)
321 woal_free_mlan_buffer(handle, pmbuf);
322 goto setup_for_next;
323 }
324
325 setup_for_next:
326 if (cardp->rx_cmd_ep == context->ep) {
327 size = MLAN_RX_CMD_BUF_SIZE;
328 } else {
329 if (cardp->rx_deaggr_ctrl.enable) {
330 size = cardp->rx_deaggr_ctrl.aggr_max;
331 if (cardp->rx_deaggr_ctrl.aggr_mode ==
332 MLAN_USB_AGGR_MODE_NUM) {
333 size *= MAX(MLAN_USB_MAX_PKT_SIZE,
334 cardp->rx_deaggr_ctrl.aggr_align);
335 size = MAX(size, MLAN_RX_DATA_BUF_SIZE);
336 }
337 } else
338 size = MLAN_RX_DATA_BUF_SIZE;
339 }
340 woal_usb_submit_rx_urb(context, size);
341
342 rx_exit:
343 LEAVE();
344 return;
345 }
346
347 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
348 /**
349 * @brief Call back function to handle the status of the Tx data URB
350 *
351 * @param urb Pointer to urb structure
352 * @param regs Registers
353 *
354 * @return N/A
355 */
woal_usb_tx_complete(struct urb * urb,struct pt_regs * regs)356 static void woal_usb_tx_complete(struct urb *urb, struct pt_regs *regs)
357 #else
358 /**
359 * @brief Call back function to handle the status of the Tx data URB
360 *
361 * @param urb Pointer to urb structure
362 *
363 * @return N/A
364 */
365 static void woal_usb_tx_complete(struct urb *urb)
366 #endif
367 {
368 urb_context *context = NULL;
369 moal_handle *handle = NULL;
370 struct usb_card_rec *cardp = NULL;
371
372 ENTER();
373
374 if (!urb || !urb->context) {
375 PRINTM(MERROR,
376 "URB or URB context is not valid in USB Tx complete\n");
377 LEAVE();
378 return;
379 }
380 context = (urb_context *)urb->context;
381 handle = context->handle;
382
383 if (!handle || !handle->card || !context->pmbuf) {
384 PRINTM(MERROR,
385 "moal handle, card structure or mlan_buffer is not valid in USB Tx complete\n");
386 LEAVE();
387 return;
388 }
389 cardp = handle->card;
390
391 /* Handle the transmission complete validations */
392 if (urb->status) {
393 PRINTM(MERROR, "EP %d Tx URB status failure: %d\n", context->ep,
394 urb->status);
395 mlan_write_data_async_complete(handle->pmlan_adapter,
396 context->pmbuf, context->ep,
397 MLAN_STATUS_FAILURE);
398 } else {
399 mlan_write_data_async_complete(handle->pmlan_adapter,
400 context->pmbuf, context->ep,
401 MLAN_STATUS_SUCCESS);
402 }
403
404 /* Decrease pending URB counter */
405 if (context->ep == cardp->tx_cmd_ep)
406 atomic_dec(&cardp->tx_cmd_urb_pending);
407 else if (context->ep == cardp->tx_data_ep)
408 atomic_dec(&cardp->tx_data_urb_pending);
409
410 queue_work(handle->workqueue, &handle->main_work);
411
412 LEAVE();
413 return;
414 }
415
416 /**
417 * @brief This function sets up the data to receive
418 *
419 * @param ctx Pointer to urb_context structure
420 * @param size Skb size
421 *
422 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
423 */
woal_usb_submit_rx_urb(urb_context * ctx,int size)424 static mlan_status woal_usb_submit_rx_urb(urb_context *ctx, int size)
425 {
426 moal_handle *handle = ctx->handle;
427 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
428 mlan_status ret = MLAN_STATUS_FAILURE;
429 t_u8 *data = NULL;
430
431 ENTER();
432
433 if (handle->surprise_removed || handle->is_suspended) {
434 if ((cardp->rx_cmd_ep == ctx->ep) && ctx->pmbuf) {
435 woal_free_mlan_buffer(handle, ctx->pmbuf);
436 ctx->pmbuf = NULL;
437 }
438 PRINTM(MERROR,
439 "Card removed/suspended, EP %d Rx URB submit skipped\n",
440 ctx->ep);
441 goto rx_ret;
442 }
443
444 if (cardp->rx_cmd_ep != ctx->ep) {
445 ctx->pmbuf = woal_alloc_mlan_buffer(handle, size);
446 if (!ctx->pmbuf) {
447 PRINTM(MERROR,
448 "Fail to submit Rx URB due to no memory/skb\n");
449 goto rx_ret;
450 }
451 ctx->pmbuf->data_offset = MLAN_RX_HEADER_LEN;
452 data = ctx->pmbuf->pbuf + ctx->pmbuf->data_offset;
453 } else {
454 ctx->pmbuf->data_offset = 0;
455 data = ctx->pmbuf->pbuf + ctx->pmbuf->data_offset;
456 }
457
458 if (cardp->rx_cmd_ep == ctx->ep &&
459 cardp->rx_cmd_ep_type == USB_ENDPOINT_XFER_INT)
460 usb_fill_int_urb(ctx->urb, cardp->udev,
461 usb_rcvintpipe(cardp->udev, ctx->ep), data,
462 size - ctx->pmbuf->data_offset,
463 woal_usb_receive, (void *)ctx,
464 cardp->rx_cmd_interval);
465 else
466 usb_fill_bulk_urb(ctx->urb, cardp->udev,
467 usb_rcvbulkpipe(cardp->udev, ctx->ep), data,
468 size - ctx->pmbuf->data_offset,
469 woal_usb_receive, (void *)ctx);
470 if (cardp->rx_cmd_ep == ctx->ep)
471 atomic_inc(&cardp->rx_cmd_urb_pending);
472 else
473 atomic_inc(&cardp->rx_data_urb_pending);
474 if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) {
475 /* Submit URB failure */
476 PRINTM(MERROR, "Submit EP %d Rx URB failed: %d\n", ctx->ep,
477 ret);
478 woal_free_mlan_buffer(handle, ctx->pmbuf);
479 if (cardp->rx_cmd_ep == ctx->ep)
480 atomic_dec(&cardp->rx_cmd_urb_pending);
481 else
482 atomic_dec(&cardp->rx_data_urb_pending);
483 ctx->pmbuf = NULL;
484 ret = MLAN_STATUS_FAILURE;
485 } else {
486 ret = MLAN_STATUS_SUCCESS;
487 }
488 rx_ret:
489 LEAVE();
490 return ret;
491 }
492
493 /********************************************************
494 Global Functions
495 ********************************************************/
496
497 #if defined(USB8997) || defined(USB9098) || defined(USB9097) || \
498 defined(USB8978) || defined(USBNW62X)
499 /**
500 * @brief Check chip revision
501 *
502 * @param handle A pointer to moal_handle structure
503 * @param usb_chip_rev A pointer to usb_chip_rev variable
504 * @param usb_strap A pointer to usb_strap
505 *
506 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
507 */
woal_check_chip_revision(moal_handle * handle,t_u32 * usb_chip_rev,t_u32 * usb_strap)508 static mlan_status woal_check_chip_revision(moal_handle *handle,
509 t_u32 *usb_chip_rev,
510 t_u32 *usb_strap)
511 {
512 mlan_status ret = MLAN_STATUS_SUCCESS;
513 mlan_buffer mbuf;
514 t_u8 *tx_buff = NULL;
515 t_u8 *recv_buff = NULL;
516 usb_ack_pkt ack_pkt;
517 t_u32 extend_ver;
518 t_u8 tx_size = CHIP_REV_TX_BUF_SIZE;
519 struct usb_card_rec *cardp = handle->card;
520
521 ENTER();
522
523 /* Allocate memory for transmit */
524 tx_buff = kzalloc(tx_size, GFP_ATOMIC | GFP_DMA);
525 if (tx_buff == NULL) {
526 PRINTM(MERROR,
527 "Could not allocate buffer for chip revision check frame transmission\n");
528 ret = MLAN_STATUS_FAILURE;
529 goto cleanup;
530 }
531
532 /* Allocate memory for receive */
533 recv_buff = kzalloc(CHIP_REV_RX_BUF_SIZE, GFP_ATOMIC | GFP_DMA);
534 if (recv_buff == NULL) {
535 PRINTM(MERROR,
536 "Could not allocate buffer for chip revision check frame response\n");
537 ret = MLAN_STATUS_FAILURE;
538 goto cleanup;
539 }
540
541 /* The struct is initialised to all zero */
542 memset(&ack_pkt, 0, sizeof(usb_ack_pkt));
543
544 /* Send pseudo data to check winner status first */
545 memset(&mbuf, 0, sizeof(mlan_buffer));
546 mbuf.pbuf = (t_u8 *)tx_buff;
547 mbuf.data_len = tx_size;
548
549 /* Send the chip revision check frame */
550 ret = woal_usb_write_data_sync(handle, &mbuf, cardp->tx_cmd_ep,
551 MLAN_USB_BULK_MSG_TIMEOUT);
552 if (ret != MLAN_STATUS_SUCCESS) {
553 PRINTM(MERROR,
554 "Chip revision check frame dnld: write_data failed, ret %d\n",
555 ret);
556 ret = MLAN_STATUS_FAILURE;
557 goto cleanup;
558 }
559
560 memset(&mbuf, 0, sizeof(mlan_buffer));
561 mbuf.pbuf = (t_u8 *)recv_buff;
562 mbuf.data_len = CHIP_REV_RX_BUF_SIZE;
563
564 /* Receive the chip revision check frame response */
565 ret = woal_usb_read_data_sync(handle, &mbuf, cardp->rx_cmd_ep,
566 MLAN_USB_BULK_MSG_TIMEOUT);
567 if (ret != MLAN_STATUS_SUCCESS) {
568 PRINTM(MERROR,
569 "Chip revision check frame response: read_data failed, ret %d\n",
570 ret);
571 ret = MLAN_STATUS_FAILURE;
572 goto cleanup;
573 }
574 moal_memcpy_ext(handle, &ack_pkt, recv_buff, sizeof(usb_ack_pkt),
575 sizeof(ack_pkt));
576 ack_pkt.ack_winner = woal_le32_to_cpu(ack_pkt.ack_winner);
577 ack_pkt.seq = woal_le32_to_cpu(ack_pkt.seq);
578 ack_pkt.extend = woal_le32_to_cpu(ack_pkt.extend);
579 ack_pkt.chip_rev = woal_le32_to_cpu(ack_pkt.chip_rev);
580 ack_pkt.strap = woal_le32_to_cpu(ack_pkt.strap);
581
582 if ((ack_pkt.extend & 0xffff0000) == EXTEND_HDR) {
583 extend_ver = ack_pkt.extend & 0x0000ffff;
584 *usb_chip_rev = ack_pkt.chip_rev & 0x000000ff;
585 if (extend_ver >= EXTEND_V2) {
586 PRINTM(MINFO, "chip_rev=0x%x, strap=0x%x\n",
587 *usb_chip_rev, ack_pkt.strap);
588 *usb_strap = ack_pkt.strap & 0x7;
589 } else
590 PRINTM(MINFO, "chip_rev=0x%x\n", *usb_chip_rev);
591 }
592 cleanup:
593 kfree(recv_buff);
594 kfree(tx_buff);
595
596 LEAVE();
597 return ret;
598 }
599 #endif
600
601 /**
602 * @brief This function unlink urb
603 *
604 * @param handle A pointer to moal_handle structure
605 * @return N/A
606 */
woal_usb_unlink_urb(void * card_desc)607 static void woal_usb_unlink_urb(void *card_desc)
608 {
609 struct usb_card_rec *cardp = (struct usb_card_rec *)card_desc;
610 int i;
611 ENTER();
612 if (cardp) {
613 /* Unlink Rx cmd URB */
614 if (atomic_read(&cardp->rx_cmd_urb_pending) &&
615 cardp->rx_cmd.urb) {
616 usb_kill_urb(cardp->rx_cmd.urb);
617 }
618 /* Unlink Rx data URBs */
619 if (atomic_read(&cardp->rx_data_urb_pending)) {
620 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
621 if (cardp->rx_data_list[i].urb)
622 usb_kill_urb(
623 cardp->rx_data_list[i].urb);
624 }
625 }
626 /* Unlink Tx cmd URB */
627 if (atomic_read(&cardp->tx_cmd_urb_pending) &&
628 cardp->tx_cmd.urb) {
629 usb_kill_urb(cardp->tx_cmd.urb);
630 }
631 /* Unlink Tx data URBs */
632 if (atomic_read(&cardp->tx_data_urb_pending)) {
633 for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
634 if (cardp->tx_data_list[i].urb) {
635 usb_kill_urb(
636 cardp->tx_data_list[i].urb);
637 }
638 }
639 }
640 }
641 LEAVE();
642 }
643
644 /**
645 * @brief Free Tx/Rx urb, skb and Rx buffer
646 *
647 * @param cardp Pointer usb_card_rec
648 *
649 * @return N/A
650 */
woal_usb_free(struct usb_card_rec * cardp)651 void woal_usb_free(struct usb_card_rec *cardp)
652 {
653 int i;
654
655 ENTER();
656
657 woal_usb_unlink_urb(cardp);
658 /* Free Rx data URBs */
659 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
660 if (cardp->rx_data_list[i].urb) {
661 usb_free_urb(cardp->rx_data_list[i].urb);
662 cardp->rx_data_list[i].urb = NULL;
663 }
664 }
665 /* Free Rx cmd URB */
666 if (cardp->rx_cmd.urb) {
667 usb_free_urb(cardp->rx_cmd.urb);
668 cardp->rx_cmd.urb = NULL;
669 }
670
671 /* Free Tx data URBs */
672 for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
673 if (cardp->tx_data_list[i].urb) {
674 usb_free_urb(cardp->tx_data_list[i].urb);
675 cardp->tx_data_list[i].urb = NULL;
676 }
677 }
678 /* Free Tx cmd URB */
679 if (cardp->tx_cmd.urb) {
680 usb_free_urb(cardp->tx_cmd.urb);
681 cardp->tx_cmd.urb = NULL;
682 }
683
684 LEAVE();
685 return;
686 }
687
woal_update_card_type(t_void * card)688 static t_u16 woal_update_card_type(t_void *card)
689 {
690 struct usb_card_rec *cardp_usb = (struct usb_card_rec *)card;
691 t_u16 card_type = 0;
692
693 /* Update card type */
694 #ifdef USB8801
695 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
696 (__force __le16)USB8801_PID_1 ||
697 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
698 (__force __le16)USB8801_PID_2) {
699 card_type = CARD_TYPE_USB8801;
700 moal_memcpy_ext(NULL, driver_version, CARD_USB8801,
701 strlen(CARD_USB8801), strlen(driver_version));
702 moal_memcpy_ext(NULL,
703 driver_version + strlen(INTF_CARDTYPE) +
704 strlen(KERN_VERSION),
705 V14, strlen(V14),
706 strlen(driver_version) - strlen(INTF_CARDTYPE) -
707 strlen(KERN_VERSION));
708 }
709 #endif
710 #ifdef USB8897
711 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
712 (__force __le16)USB8897_PID_1 ||
713 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
714 (__force __le16)USB8897_PID_2) {
715 card_type = CARD_TYPE_USB8897;
716 moal_memcpy_ext(NULL, driver_version, CARD_USB8897,
717 strlen(CARD_USB8897), strlen(driver_version));
718 moal_memcpy_ext(NULL,
719 driver_version + strlen(INTF_CARDTYPE) +
720 strlen(KERN_VERSION),
721 V15, strlen(V15),
722 strlen(driver_version) - strlen(INTF_CARDTYPE) -
723 strlen(KERN_VERSION));
724 }
725 #endif
726 #ifdef USB8997
727 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
728 (__force __le16)USB8997_PID_1 ||
729 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
730 (__force __le16)USB8997_PID_2 ||
731 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
732 (__force __le16)USB8997_PID_3 ||
733 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
734 (__force __le16)USB8997_PID_4 ||
735 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
736 (__force __le16)USB8997_PID_5 ||
737 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
738 (__force __le16)USB8997_PID_6 ||
739 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
740 (__force __le16)USB8997V2_PID_1) {
741 card_type = CARD_TYPE_USB8997;
742 moal_memcpy_ext(NULL, driver_version, CARD_USB8997,
743 strlen(CARD_USB8997), strlen(driver_version));
744 moal_memcpy_ext(NULL,
745 driver_version + strlen(INTF_CARDTYPE) +
746 strlen(KERN_VERSION),
747 V16, strlen(V16),
748 strlen(driver_version) - strlen(INTF_CARDTYPE) -
749 strlen(KERN_VERSION));
750 }
751 #endif
752 #ifdef USB8978
753 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
754 (__force __le16)USB8978_PID_1 ||
755 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
756 (__force __le16)USB8978_PID_2) {
757 card_type = CARD_TYPE_USB8978;
758 moal_memcpy_ext(NULL, driver_version, "USBIW416",
759 strlen("USBIW416"), strlen(driver_version));
760 moal_memcpy_ext(NULL,
761 driver_version + strlen(INTF_CARDTYPE) +
762 strlen(KERN_VERSION),
763 V16, strlen(V16),
764 strlen(driver_version) - strlen(INTF_CARDTYPE) -
765 strlen(KERN_VERSION));
766 }
767 #endif
768 #ifdef USB9098
769 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
770 (__force __le16)USB9098_PID_1 ||
771 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
772 (__force __le16)USB9098_PID_2) {
773 card_type = CARD_TYPE_USB9098;
774 moal_memcpy_ext(NULL, driver_version, CARD_USB9098,
775 strlen(CARD_USB9098), strlen(driver_version));
776 moal_memcpy_ext(NULL,
777 driver_version + strlen(INTF_CARDTYPE) +
778 strlen(KERN_VERSION),
779 V17, strlen(V17),
780 strlen(driver_version) - strlen(INTF_CARDTYPE) -
781 strlen(KERN_VERSION));
782 }
783 #endif
784 #ifdef USB9097
785 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
786 (__force __le16)USB9097_PID_1 ||
787 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
788 (__force __le16)USB9097_PID_2) {
789 card_type = CARD_TYPE_USB9097;
790 moal_memcpy_ext(NULL, driver_version, CARD_USB9097,
791 strlen(CARD_USB9097), strlen(driver_version));
792 moal_memcpy_ext(NULL,
793 driver_version + strlen(INTF_CARDTYPE) +
794 strlen(KERN_VERSION),
795 V17, strlen(V17),
796 strlen(driver_version) - strlen(INTF_CARDTYPE) -
797 strlen(KERN_VERSION));
798 }
799 #endif
800 #ifdef USBNW62X
801 if (woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
802 (__force __le16)USBNW62X_PID_1 ||
803 woal_cpu_to_le16(cardp_usb->udev->descriptor.idProduct) ==
804 (__force __le16)USBNW62X_PID_2) {
805 card_type = CARD_TYPE_USBNW62X;
806 moal_memcpy_ext(NULL, driver_version, CARD_USBNW62X,
807 strlen(CARD_USBNW62X), strlen(driver_version));
808 moal_memcpy_ext(NULL,
809 driver_version + strlen(INTF_CARDTYPE) +
810 strlen(KERN_VERSION),
811 V17, strlen(V17),
812 strlen(driver_version) - strlen(INTF_CARDTYPE) -
813 strlen(KERN_VERSION));
814 }
815 #endif
816 return card_type;
817 }
818
819 /**
820 * @brief Sets the configuration values
821 *
822 * @param intf Pointer to usb_interface
823 * @param id Pointer to usb_device_id
824 *
825 * @return Address of variable usb_cardp, error code otherwise
826 */
woal_usb_probe(struct usb_interface * intf,const struct usb_device_id * id)827 static int woal_usb_probe(struct usb_interface *intf,
828 const struct usb_device_id *id)
829 {
830 struct usb_device *udev;
831 struct usb_host_interface *iface_desc;
832 struct usb_endpoint_descriptor *endpoint;
833 int i;
834 struct usb_card_rec *usb_cardp = NULL;
835 t_u16 card_type = 0;
836
837 ENTER();
838
839 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
840 PRINTM(MMSG,
841 "USB probe: idVendor=%x idProduct=%x bInterfaceNumber=%d\n",
842 id->idVendor, id->idProduct, id->bInterfaceNumber);
843 #endif
844
845 udev = interface_to_usbdev(intf);
846 usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
847 if (!usb_cardp) {
848 LEAVE();
849 return -ENOMEM;
850 }
851
852 /* Check probe is for our device */
853 for (i = 0; woal_usb_table[i].idVendor; i++) {
854 if (woal_cpu_to_le16(udev->descriptor.idVendor) ==
855 (__force __le16)woal_usb_table[i].idVendor &&
856 woal_cpu_to_le16(udev->descriptor.idProduct) ==
857 (__force __le16)woal_usb_table[i].idProduct) {
858 PRINTM(MMSG, "VID/PID = %X/%X, Boot2 version = %X\n",
859 woal_cpu_to_le16(udev->descriptor.idVendor),
860 woal_cpu_to_le16(udev->descriptor.idProduct),
861 woal_cpu_to_le16(udev->descriptor.bcdDevice));
862 switch (woal_cpu_to_le16(udev->descriptor.idProduct)) {
863 #ifdef USB8801
864 case (__force __le16)USB8801_PID_1:
865 #endif /* USB8801 */
866 #ifdef USB8897
867 case (__force __le16)USB8897_PID_1:
868 #endif /* USB8897 */
869 #ifdef USB8997
870 case (__force __le16)USB8997_PID_1:
871 case (__force __le16)USB8997V2_PID_1:
872 #endif /* USB8997 */
873 #ifdef USB8978
874 case (__force __le16)USB8978_PID_1:
875 case (__force __le16)USB8978_PID_1_BT:
876 #endif /* USB8978 */
877 #ifdef USB9098
878 case (__force __le16)USB9098_PID_1:
879 #endif /* USB9098 */
880 #ifdef USB9097
881 case (__force __le16)USB9097_PID_1:
882 #endif /* USB9097 */
883 #ifdef USBNW62X
884 case (__force __le16)USBNW62X_PID_1:
885 #endif /* USBNW62X */
886
887 /* If skip FW is set, we must return error so
888 * the next driver can download the FW */
889 if (skip_fwdnld)
890 goto error;
891 else
892 usb_cardp->boot_state = USB_FW_DNLD;
893 break;
894 #ifdef USB8801
895 case (__force __le16)USB8801_PID_2:
896 #endif /* USB8801 */
897 #ifdef USB8897
898 case (__force __le16)USB8897_PID_2:
899 #endif /* USB8897 */
900 #ifdef USB8997
901 case (__force __le16)USB8997_PID_2:
902 #endif /* USB8997 */
903 #ifdef USB8978
904 case (__force __le16)USB8978_PID_2:
905 case (__force __le16)USB8978_PID_2_BT:
906 #endif /* USB8978 */
907 #ifdef USB9098
908 case (__force __le16)USB9098_PID_2:
909 #endif /* USB9098 */
910 #ifdef USB9097
911 case (__force __le16)USB9097_PID_2:
912 #endif /* USB9097 */
913 #ifdef USBNW62X
914 case (__force __le16)USBNW62X_PID_2:
915 #endif /* USBNW62X */
916
917 usb_cardp->boot_state = USB_FW_READY;
918 break;
919 }
920 /*To do, get card type*/
921 /* if
922 (woal_cpu_to_le16(udev->descriptor.idProduct) ==
923 USB8897_PID_2) usb_cardp->card_type =
924 CARD_TYPE_USB8897; else if
925 (woal_cpu_to_le16(udev->descriptor.idProduct) ==
926 USB8997_PID_2) usb_cardp->card_type =
927 CARD_TYPE_USB997;
928 */
929 break;
930 }
931 }
932
933 if (woal_usb_table[i].idVendor) {
934 usb_cardp->udev = udev;
935 iface_desc = intf->cur_altsetting;
936 usb_cardp->intf = intf;
937
938 PRINTM(MINFO,
939 "bcdUSB = 0x%X bDeviceClass = 0x%X"
940 " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
941 woal_cpu_to_le16(udev->descriptor.bcdUSB),
942 udev->descriptor.bDeviceClass,
943 udev->descriptor.bDeviceSubClass,
944 udev->descriptor.bDeviceProtocol);
945
946 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
947 endpoint = &iface_desc->endpoint[i].desc;
948 if ((usb_endpoint_is_bulk_in(endpoint) ||
949 usb_endpoint_is_int_in(endpoint)) &&
950 (usb_endpoint_num(endpoint) ==
951 MLAN_USB_EP_CMD_EVENT ||
952 usb_endpoint_num(endpoint) ==
953 MLAN_USB_EP_CMD_EVENT_IF2)) {
954 usb_cardp->rx_cmd_ep_type =
955 usb_endpoint_type(endpoint);
956 usb_cardp->rx_cmd_interval =
957 endpoint->bInterval;
958 /* We found a bulk in command/event endpoint */
959 PRINTM(MCMND,
960 "Rx CMD/EVT: max packet size = %d, address = %d ep_type=%d\n",
961 woal_le16_to_cpu(
962 endpoint->wMaxPacketSize),
963 endpoint->bEndpointAddress,
964 usb_cardp->rx_cmd_ep_type);
965 usb_cardp->rx_cmd_ep =
966 (endpoint->bEndpointAddress &
967 USB_ENDPOINT_NUMBER_MASK);
968
969 atomic_set(&usb_cardp->rx_cmd_urb_pending, 0);
970 if (usb_endpoint_num(endpoint) ==
971 MLAN_USB_EP_CMD_EVENT_IF2)
972 usb_cardp->second_mac = MTRUE;
973 }
974 if (usb_endpoint_is_bulk_in(endpoint) &&
975 (usb_endpoint_num(endpoint) == MLAN_USB_EP_DATA ||
976 usb_endpoint_num(endpoint) ==
977 MLAN_USB_EP_DATA_IF2)) {
978 /* We found a bulk in data endpoint */
979 PRINTM(MINFO,
980 "Bulk IN: max packet size = %d, address = %d\n",
981 woal_le16_to_cpu(
982 endpoint->wMaxPacketSize),
983 endpoint->bEndpointAddress);
984 usb_cardp->rx_data_ep =
985 (endpoint->bEndpointAddress &
986 USB_ENDPOINT_NUMBER_MASK);
987 atomic_set(&usb_cardp->rx_data_urb_pending, 0);
988 }
989 if (usb_endpoint_is_bulk_out(endpoint) &&
990 (usb_endpoint_num(endpoint) == MLAN_USB_EP_DATA ||
991 usb_endpoint_num(endpoint) ==
992 MLAN_USB_EP_DATA_IF2)) {
993 /* We found a bulk out data endpoint */
994 PRINTM(MCMND,
995 "Bulk OUT: max packet size = %d, address = %d\n",
996 woal_le16_to_cpu(
997 endpoint->wMaxPacketSize),
998 endpoint->bEndpointAddress);
999 usb_cardp->tx_data_ep =
1000 endpoint->bEndpointAddress;
1001 atomic_set(&usb_cardp->tx_data_urb_pending, 0);
1002 usb_cardp->tx_data_maxpktsize =
1003 (__force int)woal_le16_to_cpu(
1004 endpoint->wMaxPacketSize);
1005 }
1006
1007 if ((usb_endpoint_is_bulk_out(endpoint) ||
1008 usb_endpoint_is_int_out(endpoint)) &&
1009 (usb_endpoint_num(endpoint) ==
1010 MLAN_USB_EP_CMD_EVENT ||
1011 usb_endpoint_num(endpoint) ==
1012 MLAN_USB_EP_CMD_EVENT_IF2)) {
1013 usb_cardp->tx_cmd_ep_type =
1014 usb_endpoint_type(endpoint);
1015 usb_cardp->tx_cmd_interval =
1016 endpoint->bInterval;
1017 /* We found a bulk out command/event endpoint */
1018 PRINTM(MCMND,
1019 "Tx CMD: max packet size = %d, address = %d ep_type=%d\n",
1020 woal_le16_to_cpu(
1021 endpoint->wMaxPacketSize),
1022 endpoint->bEndpointAddress,
1023 usb_cardp->tx_cmd_ep_type);
1024 usb_cardp->tx_cmd_ep =
1025 endpoint->bEndpointAddress;
1026 atomic_set(&usb_cardp->tx_cmd_urb_pending, 0);
1027 usb_cardp->tx_cmd_maxpktsize =
1028 (__force int)woal_le16_to_cpu(
1029 endpoint->wMaxPacketSize);
1030 }
1031 }
1032
1033 if (usb_cardp->boot_state == USB_FW_DNLD) {
1034 if (!usb_cardp->tx_cmd_ep || !usb_cardp->rx_cmd_ep)
1035 goto error;
1036 } else if (usb_cardp->boot_state == USB_FW_READY) {
1037 if (!usb_cardp->tx_cmd_ep || !usb_cardp->tx_data_ep ||
1038 !usb_cardp->rx_cmd_ep || !usb_cardp->rx_data_ep) {
1039 PRINTM(MERROR,
1040 "%s: invalid endpoint assignment\n",
1041 __FUNCTION__);
1042 goto error;
1043 }
1044 }
1045
1046 usb_cardp->tx_aggr_ctrl.enable = MFALSE;
1047 usb_cardp->tx_aggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
1048 usb_cardp->tx_aggr_ctrl.aggr_align =
1049 MAX(max_tx_buf, MLAN_USB_TX_AGGR_ALIGN);
1050 usb_cardp->tx_aggr_ctrl.aggr_max = MLAN_USB_TX_MAX_AGGR_NUM;
1051 usb_cardp->tx_aggr_ctrl.aggr_tmo =
1052 MLAN_USB_TX_AGGR_TIMEOUT_MSEC * 1000;
1053 usb_cardp->rx_deaggr_ctrl.enable = MFALSE;
1054 usb_cardp->rx_deaggr_ctrl.aggr_mode = MLAN_USB_AGGR_MODE_NUM;
1055 usb_cardp->rx_deaggr_ctrl.aggr_align = MLAN_USB_RX_ALIGN_SIZE;
1056 usb_cardp->rx_deaggr_ctrl.aggr_max = MLAN_USB_RX_MAX_AGGR_NUM;
1057 usb_cardp->rx_deaggr_ctrl.aggr_tmo =
1058 MLAN_USB_RX_DEAGGR_TIMEOUT_USEC;
1059 usb_set_intfdata(intf, usb_cardp);
1060
1061 card_type = woal_update_card_type(usb_cardp);
1062 if (!card_type) {
1063 PRINTM(MERROR,
1064 "usb probe: woal_update_card_type() failed\n");
1065 goto error;
1066 }
1067
1068 /* At this point wlan_add_card() will be called */
1069 if (!(woal_add_card(usb_cardp, &usb_cardp->udev->dev, &usb_ops,
1070 card_type))) {
1071 PRINTM(MERROR, "%s: woal_add_card failed\n",
1072 __FUNCTION__);
1073 goto error;
1074 }
1075 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
1076 /* Note: From 2.6.34.2 onwards, remote wakeup is NOT enabled by
1077 * default. So drivers wanting remote wakeup will have to enable
1078 * this using -
1079 * device_set_wakeup_enable(&udev->dev, 1);
1080 * It has been observed that some cards having device attr =
1081 * 0xa0 do not support remote wakeup. These cards come
1082 * immediately out of the suspend when power/wakeup file is set
1083 * to 'enabled'. To support all types of cards i.e. with/without
1084 * remote wakeup, we are NOT setting the 'power/wakeup' file
1085 * from here. Also in principle, we are not supposed to change
1086 * the wakeup policy, which is purely a userspace decision.
1087 */
1088 /* if (udev->actconfig->desc.bmAttributes &
1089 USB_CONFIG_ATT_WAKEUP) intf->needs_remote_wakeup = 1; */
1090 #endif
1091 usb_get_dev(udev);
1092 LEAVE();
1093 return 0;
1094 } else {
1095 PRINTM(MINFO, "Discard the Probe request\n");
1096 PRINTM(MINFO, "VID = 0x%X PID = 0x%X\n",
1097 woal_cpu_to_le16(udev->descriptor.idVendor),
1098 woal_cpu_to_le16(udev->descriptor.idProduct));
1099 }
1100 error:
1101 kfree(usb_cardp);
1102 usb_cardp = NULL;
1103 LEAVE();
1104 return -ENXIO;
1105 }
1106
1107 /**
1108 * @brief Free resource and cleanup
1109 *
1110 * @param intf Pointer to usb_interface
1111 *
1112 * @return N/A
1113 */
woal_usb_disconnect(struct usb_interface * intf)1114 static void woal_usb_disconnect(struct usb_interface *intf)
1115 {
1116 struct usb_card_rec *cardp = usb_get_intfdata(intf);
1117 moal_handle *phandle = NULL;
1118 ENTER();
1119 if (!cardp || !cardp->phandle) {
1120 PRINTM(MERROR, "Card or phandle is not valid\n");
1121 LEAVE();
1122 return;
1123 }
1124 phandle = (moal_handle *)cardp->phandle;
1125
1126 /*
1127 * Update Surprise removed to TRUE
1128 * Free all the URB's allocated
1129 */
1130 phandle->surprise_removed = MTRUE;
1131
1132 /* Card is removed and we can call wlan_remove_card */
1133 PRINTM(MINFO, "Call remove card\n");
1134 woal_remove_card(cardp);
1135
1136 usb_set_intfdata(intf, NULL);
1137 usb_put_dev(interface_to_usbdev(intf));
1138 kfree(cardp);
1139 LEAVE();
1140 return;
1141 }
1142
1143 /**
1144 * @brief killall pending urbs
1145 *
1146 * @param handle Pointer to moal_handle
1147 *
1148 *
1149 * @return N/A
1150 */
woal_kill_urbs(moal_handle * handle)1151 void woal_kill_urbs(moal_handle *handle)
1152 {
1153 ENTER();
1154 handle->is_suspended = MTRUE;
1155 woal_usb_unlink_urb(handle->card);
1156 LEAVE();
1157 }
1158
1159 /**
1160 * @brief resubmit urbs
1161 *
1162 * @param handle Pointer to moal_handle
1163 *
1164 *
1165 * @return N/A
1166 */
woal_resubmit_urbs(moal_handle * handle)1167 void woal_resubmit_urbs(moal_handle *handle)
1168 {
1169 struct usb_card_rec *cardp = handle->card;
1170
1171 ENTER();
1172 handle->is_suspended = MFALSE;
1173
1174 if (!atomic_read(&cardp->rx_data_urb_pending)) {
1175 /* Submit multiple Rx data URBs */
1176 woal_usb_submit_rx_data_urbs(handle);
1177 }
1178 if (!atomic_read(&cardp->rx_cmd_urb_pending)) {
1179 cardp->rx_cmd.pmbuf =
1180 woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
1181 if (cardp->rx_cmd.pmbuf)
1182 woal_usb_submit_rx_urb(&cardp->rx_cmd,
1183 MLAN_RX_CMD_BUF_SIZE);
1184 }
1185 LEAVE();
1186 }
1187
1188 #ifdef CONFIG_PM
1189 /**
1190 * @brief Handle suspend
1191 *
1192 * @param intf Pointer to usb_interface
1193 * @param message Pointer to pm_message_t structure
1194 *
1195 * @return MLAN_STATUS_SUCCESS
1196 */
woal_usb_suspend(struct usb_interface * intf,pm_message_t message)1197 static int woal_usb_suspend(struct usb_interface *intf, pm_message_t message)
1198 {
1199 struct usb_card_rec *cardp = usb_get_intfdata(intf);
1200 moal_handle *handle = NULL;
1201 int i;
1202 int ret = 0;
1203
1204 ENTER();
1205
1206 PRINTM(MCMND, "<--- Enter woal_usb_suspend --->\n");
1207 if (!cardp || !cardp->phandle) {
1208 PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
1209 ret = 0;
1210 goto done;
1211 }
1212 handle = cardp->phandle;
1213 if (handle->is_suspended == MTRUE) {
1214 PRINTM(MWARN, "Device already suspended\n");
1215 ret = 0;
1216 goto done;
1217 }
1218 #ifdef STA_SUPPORT
1219 for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
1220 if (handle->priv[i] &&
1221 (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
1222 woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
1223 }
1224 #endif
1225 /* Enable Host Sleep */
1226 woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
1227
1228 /* Indicate device suspended */
1229 /* The flag must be set here before the usb_kill_urb() calls.
1230 * Reason: In the complete handlers, urb->status(= -ENOENT) and
1231 * 'is_suspended' flag is used in combination to distinguish
1232 * between a suspended state and a 'disconnect' one.
1233 */
1234 handle->is_suspended = MTRUE;
1235 for (i = 0; i < handle->priv_num; i++)
1236 netif_carrier_off(handle->priv[i]->netdev);
1237
1238 /* Unlink Rx cmd URB */
1239 if (atomic_read(&cardp->rx_cmd_urb_pending) && cardp->rx_cmd.urb) {
1240 usb_kill_urb(cardp->rx_cmd.urb);
1241 }
1242 /* Unlink Rx data URBs */
1243 if (atomic_read(&cardp->rx_data_urb_pending)) {
1244 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
1245 if (cardp->rx_data_list[i].urb) {
1246 usb_kill_urb(cardp->rx_data_list[i].urb);
1247 usb_init_urb(cardp->rx_data_list[i].urb);
1248 }
1249 }
1250 }
1251
1252 /* Unlink Tx data URBs */
1253 for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
1254 if (cardp->tx_data_list[i].urb) {
1255 usb_kill_urb(cardp->tx_data_list[i].urb);
1256 }
1257 }
1258 /* Unlink Tx cmd URB */
1259 if (cardp->tx_cmd.urb) {
1260 usb_kill_urb(cardp->tx_cmd.urb);
1261 }
1262
1263 handle->suspend_wait_q_woken = MTRUE;
1264 wake_up_interruptible(&handle->suspend_wait_q);
1265
1266 done:
1267 PRINTM(MCMND, "<--- Leave woal_usb_suspend --->\n");
1268 LEAVE();
1269 return ret;
1270 }
1271
1272 /**
1273 * @brief Handle resume
1274 *
1275 * @param intf Pointer to usb_interface
1276 *
1277 * @return MLAN_STATUS_SUCCESS
1278 */
woal_usb_resume(struct usb_interface * intf)1279 static int woal_usb_resume(struct usb_interface *intf)
1280 {
1281 struct usb_card_rec *cardp = usb_get_intfdata(intf);
1282 moal_handle *handle = NULL;
1283 int i;
1284
1285 ENTER();
1286
1287 PRINTM(MCMND, "<--- Enter woal_usb_resume --->\n");
1288 if (!cardp || !cardp->phandle) {
1289 PRINTM(MERROR, "Card or adapter structure is not valid\n");
1290 goto done;
1291 }
1292 handle = cardp->phandle;
1293
1294 if (handle->is_suspended == MFALSE) {
1295 PRINTM(MWARN, "Device already resumed\n");
1296 goto done;
1297 }
1298
1299 /* Indicate device resumed.
1300 * The netdev queue will be resumed only after the urbs
1301 * have been resubmitted */
1302 handle->is_suspended = MFALSE;
1303
1304 if (!atomic_read(&cardp->rx_data_urb_pending)) {
1305 /* Submit multiple Rx data URBs */
1306 woal_usb_submit_rx_data_urbs(handle);
1307 }
1308 if (!atomic_read(&cardp->rx_cmd_urb_pending)) {
1309 cardp->rx_cmd.pmbuf =
1310 woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
1311 if (cardp->rx_cmd.pmbuf)
1312 woal_usb_submit_rx_urb(&cardp->rx_cmd,
1313 MLAN_RX_CMD_BUF_SIZE);
1314 }
1315
1316 for (i = 0; i < handle->priv_num; i++)
1317 if (handle->priv[i]->media_connected == MTRUE)
1318 netif_carrier_on(handle->priv[i]->netdev);
1319
1320 /* Disable Host Sleep */
1321 if (handle->hs_activated)
1322 woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
1323 MOAL_NO_WAIT);
1324
1325 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1326 /* Resume handler may be called due to remote wakeup,
1327 force to exit suspend anyway */
1328 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
1329 cardp->udev->autosuspend_disabled = 1;
1330 #else
1331 #ifdef CONFIG_PM_RUNTIME
1332 cardp->udev->dev.power.runtime_auto = 0;
1333 #endif
1334 #endif /* < 2.6.35 */
1335 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
1336 cardp->udev->autoresume_disabled = 0;
1337 #endif /* < 2.6.33 */
1338 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
1339 #ifdef CONFIG_PM_RUNTIME
1340 atomic_inc(&(cardp->udev)->dev.power.usage_count);
1341 #endif
1342 #endif /* >= 2.6.34 */
1343 #endif /* >= 2.6.24 */
1344
1345 done:
1346 PRINTM(MCMND, "<--- Leave woal_usb_resume --->\n");
1347 LEAVE();
1348 return 0;
1349 }
1350 #endif /* CONFIG_PM */
1351
1352 /**
1353 * @brief This function initialize the tx URBs
1354 *
1355 * @param handle Pointer to moal_handle structure
1356 *
1357 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1358 */
woal_usb_tx_init(moal_handle * handle)1359 mlan_status woal_usb_tx_init(moal_handle *handle)
1360 {
1361 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1362 int i;
1363 mlan_status ret = MLAN_STATUS_SUCCESS;
1364
1365 ENTER();
1366
1367 cardp->tx_cmd.handle = handle;
1368 cardp->tx_cmd.ep = cardp->tx_cmd_ep;
1369 /* Allocate URB for command */
1370 cardp->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
1371 if (!cardp->tx_cmd.urb) {
1372 PRINTM(MERROR, "Tx command URB allocation failed\n");
1373 ret = MLAN_STATUS_FAILURE;
1374 goto init_exit;
1375 }
1376
1377 cardp->tx_data_ix = 0;
1378 for (i = 0; i < MVUSB_TX_HIGH_WMARK; i++) {
1379 cardp->tx_data_list[i].handle = handle;
1380 cardp->tx_data_list[i].ep = cardp->tx_data_ep;
1381 /* Allocate URB for data */
1382 cardp->tx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
1383 if (!cardp->tx_data_list[i].urb) {
1384 PRINTM(MERROR, "Tx data URB allocation failed\n");
1385 ret = MLAN_STATUS_FAILURE;
1386 goto init_exit;
1387 }
1388 }
1389
1390 init_exit:
1391 LEAVE();
1392 return ret;
1393 }
1394
1395 /**
1396 * @brief This function submits the rx data URBs
1397 *
1398 * @param handle Pointer to moal_handle structure
1399 *
1400 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1401 */
woal_usb_submit_rx_data_urbs(moal_handle * handle)1402 mlan_status woal_usb_submit_rx_data_urbs(moal_handle *handle)
1403 {
1404 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1405 int i;
1406 mlan_status ret = MLAN_STATUS_FAILURE;
1407 t_u32 buffer_len = MLAN_RX_DATA_BUF_SIZE;
1408
1409 ENTER();
1410
1411 if (cardp->rx_deaggr_ctrl.enable) {
1412 buffer_len = cardp->rx_deaggr_ctrl.aggr_max;
1413 if (cardp->rx_deaggr_ctrl.aggr_mode == MLAN_USB_AGGR_MODE_NUM) {
1414 buffer_len *= MAX(MLAN_USB_MAX_PKT_SIZE,
1415 cardp->rx_deaggr_ctrl.aggr_align);
1416 buffer_len = MAX(buffer_len, MLAN_RX_DATA_BUF_SIZE);
1417 }
1418 }
1419
1420 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
1421 /* Submit Rx data URB */
1422 if (!cardp->rx_data_list[i].pmbuf) {
1423 if (woal_usb_submit_rx_urb(&cardp->rx_data_list[i],
1424 buffer_len))
1425 continue;
1426 }
1427 ret = MLAN_STATUS_SUCCESS;
1428 }
1429 LEAVE();
1430 return ret;
1431 }
1432
1433 /**
1434 * @brief This function initialize the rx URBs and submit them
1435 *
1436 * @param handle Pointer to moal_handle structure
1437 *
1438 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1439 */
woal_usb_rx_init(moal_handle * handle)1440 mlan_status woal_usb_rx_init(moal_handle *handle)
1441 {
1442 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1443 int i;
1444 mlan_status ret = MLAN_STATUS_SUCCESS;
1445
1446 ENTER();
1447
1448 cardp->rx_cmd.handle = handle;
1449 cardp->rx_cmd.ep = cardp->rx_cmd_ep;
1450 /* Allocate URB for command/event */
1451 cardp->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL);
1452 if (!cardp->rx_cmd.urb) {
1453 PRINTM(MERROR, "Rx command URB allocation failed\n");
1454 ret = MLAN_STATUS_FAILURE;
1455 goto init_exit;
1456 }
1457
1458 cardp->rx_cmd.pmbuf =
1459 woal_alloc_mlan_buffer(handle, MLAN_RX_CMD_BUF_SIZE);
1460 if (cardp->rx_cmd.pmbuf) {
1461 /* Submit Rx command URB */
1462 if (woal_usb_submit_rx_urb(&cardp->rx_cmd,
1463 MLAN_RX_CMD_BUF_SIZE)) {
1464 ret = MLAN_STATUS_FAILURE;
1465 goto init_exit;
1466 }
1467 }
1468 for (i = 0; i < MVUSB_RX_DATA_URB; i++) {
1469 cardp->rx_data_list[i].handle = handle;
1470 cardp->rx_data_list[i].ep = cardp->rx_data_ep;
1471 /* Allocate URB for data */
1472 cardp->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL);
1473 if (!cardp->rx_data_list[i].urb) {
1474 PRINTM(MERROR, "Rx data URB allocation failed\n");
1475 ret = MLAN_STATUS_FAILURE;
1476 goto init_exit;
1477 }
1478 }
1479 ret = woal_usb_submit_rx_data_urbs(handle);
1480 if (ret) {
1481 PRINTM(MERROR, "Rx data URB submission failed\n");
1482 goto init_exit;
1483 }
1484
1485 init_exit:
1486 LEAVE();
1487 return ret;
1488 }
1489
1490 /**
1491 * @brief This function downloads data blocks to device
1492 *
1493 * @param handle Pointer to moal_handle structure
1494 * @param pmbuf Pointer to mlan_buffer structure
1495 * @param ep Endpoint to send
1496 * @param timeout Timeout value in milliseconds (if 0 the wait is forever)
1497 *
1498 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1499 */
woal_usb_write_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 endpoint,t_u32 timeout)1500 static mlan_status woal_usb_write_data_sync(moal_handle *handle,
1501 mlan_buffer *pmbuf, t_u32 endpoint,
1502 t_u32 timeout)
1503 {
1504 struct usb_card_rec *cardp = handle->card;
1505 t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1506 t_u8 ep = endpoint;
1507 t_u32 length = pmbuf->data_len;
1508 int actual_length;
1509 mlan_status ret = MLAN_STATUS_SUCCESS;
1510 int bulk_out_maxpktsize = 512;
1511
1512 if (ep == cardp->tx_cmd_ep)
1513 bulk_out_maxpktsize = cardp->tx_cmd_maxpktsize;
1514 else if (ep == cardp->tx_data_ep)
1515 bulk_out_maxpktsize = cardp->tx_data_maxpktsize;
1516
1517 if (length % bulk_out_maxpktsize == 0)
1518 length++;
1519
1520 /* Send the data block */
1521 ret = usb_bulk_msg(cardp->udev, usb_sndbulkpipe(cardp->udev, ep),
1522 (t_u8 *)data, length, &actual_length, timeout);
1523 if (ret) {
1524 PRINTM(MERROR, "usb_blk_msg for send failed, ret %d\n", ret);
1525 ret = MLAN_STATUS_FAILURE;
1526 }
1527
1528 pmbuf->data_len = actual_length;
1529 DBG_HEXDUMP(MIF_D, "write sync", data, actual_length);
1530
1531 return ret;
1532 }
1533
1534 /**
1535 * @brief This function read data blocks to device
1536 *
1537 * @param handle Pointer to moal_handle structure
1538 * @param pmbuf Pointer to mlan_buffer structure
1539 * @param ep Endpoint to receive
1540 * @param timeout Timeout value in milliseconds (if 0 the wait is forever)
1541 *
1542 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1543 */
woal_usb_read_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 endpoint,t_u32 timeout)1544 static mlan_status woal_usb_read_data_sync(moal_handle *handle,
1545 mlan_buffer *pmbuf, t_u32 endpoint,
1546 t_u32 timeout)
1547 {
1548 struct usb_card_rec *cardp = handle->card;
1549 t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1550 t_u8 ep = endpoint;
1551 t_u32 buf_len = pmbuf->data_len;
1552 int actual_length;
1553 mlan_status ret = MLAN_STATUS_SUCCESS;
1554 ENTER();
1555 /* Receive the data response */
1556 ret = usb_bulk_msg(cardp->udev, usb_rcvbulkpipe(cardp->udev, ep), data,
1557 buf_len, &actual_length, timeout);
1558 if (ret) {
1559 PRINTM(MERROR, "usb_bulk_msg failed: %d\n", ret);
1560 ret = MLAN_STATUS_FAILURE;
1561 }
1562 pmbuf->data_len = actual_length;
1563 DBG_HEXDUMP(MIF_D, "read sync", data, actual_length);
1564 LEAVE();
1565 return ret;
1566 }
1567
1568 /**
1569 * @brief This function downloads data/command packet to device
1570 *
1571 * @param handle Pointer to moal_handle structure
1572 * @param pmbuf Pointer to mlan_buffer structure
1573 * @param ep Endpoint to send
1574 *
1575 * @return MLAN_STATUS_PENDING or MLAN_STATUS_FAILURE or
1576 * MLAN_STATUS_RESOURCE
1577 */
woal_write_data_async(moal_handle * handle,mlan_buffer * pmbuf,t_u8 ep)1578 mlan_status woal_write_data_async(moal_handle *handle, mlan_buffer *pmbuf,
1579 t_u8 ep)
1580 {
1581 struct usb_card_rec *cardp = handle->card;
1582 urb_context *context = NULL;
1583 t_u8 *data = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1584 struct urb *tx_urb = NULL;
1585 mlan_status ret = MLAN_STATUS_SUCCESS;
1586 t_u32 data_len = pmbuf->data_len;
1587 int bulk_out_maxpktsize = 512;
1588
1589 ENTER();
1590
1591 /* Check if device is removed */
1592 if (handle->surprise_removed) {
1593 PRINTM(MERROR, "Device removed\n");
1594 ret = MLAN_STATUS_FAILURE;
1595 goto tx_ret;
1596 }
1597
1598 if ((ep == cardp->tx_data_ep) &&
1599 (atomic_read(&cardp->tx_data_urb_pending) >= MVUSB_TX_HIGH_WMARK)) {
1600 ret = MLAN_STATUS_RESOURCE;
1601 goto tx_ret;
1602 }
1603 PRINTM(MINFO, "woal_write_data_async: ep=%d\n", ep);
1604
1605 if (ep == cardp->tx_cmd_ep) {
1606 context = &cardp->tx_cmd;
1607 bulk_out_maxpktsize = cardp->tx_cmd_maxpktsize;
1608 } else {
1609 if (ep == cardp->tx_data_ep) {
1610 bulk_out_maxpktsize = cardp->tx_data_maxpktsize;
1611 if (cardp->tx_data_ix >= MVUSB_TX_HIGH_WMARK)
1612 cardp->tx_data_ix = 0;
1613 context = &cardp->tx_data_list[cardp->tx_data_ix++];
1614 }
1615 }
1616
1617 if (!context) {
1618 PRINTM(MERROR, "Cannot allocate Tx urb_context\n");
1619 ret = MLAN_STATUS_FAILURE;
1620 goto tx_ret;
1621 }
1622 context->handle = handle;
1623 context->ep = ep;
1624 context->pmbuf = pmbuf;
1625
1626 tx_urb = context->urb;
1627
1628 if (data_len % bulk_out_maxpktsize == 0)
1629 data_len++;
1630
1631 /*
1632 * Use USB API usb_fill_bulk_urb() to set the
1633 * configuration information of the Tx bulk URB
1634 * and initialize the Tx callback
1635 */
1636
1637 if (ep == cardp->tx_cmd_ep &&
1638 cardp->tx_cmd_ep_type == USB_ENDPOINT_XFER_INT) {
1639 usb_fill_int_urb(tx_urb, cardp->udev,
1640 usb_sndintpipe(cardp->udev, ep), data,
1641 data_len, woal_usb_tx_complete,
1642 (void *)context, cardp->tx_cmd_interval);
1643 } else
1644 usb_fill_bulk_urb(tx_urb, cardp->udev,
1645 usb_sndbulkpipe(cardp->udev, ep), data,
1646 data_len, woal_usb_tx_complete,
1647 (void *)context);
1648 /* We find on Ubuntu 12.10 this flag does not work */
1649 // tx_urb->transfer_flags |= URB_ZERO_PACKET;
1650
1651 if (ep == cardp->tx_cmd_ep)
1652 atomic_inc(&cardp->tx_cmd_urb_pending);
1653 else if (ep == cardp->tx_data_ep)
1654 atomic_inc(&cardp->tx_data_urb_pending);
1655 if (usb_submit_urb(tx_urb, GFP_ATOMIC)) {
1656 /* Submit URB failure */
1657 PRINTM(MERROR, "Submit EP %d Tx URB failed: %d\n", ep, ret);
1658 if (ep == cardp->tx_cmd_ep)
1659 atomic_dec(&cardp->tx_cmd_urb_pending);
1660 else {
1661 if (ep == cardp->tx_data_ep) {
1662 atomic_dec(&cardp->tx_data_urb_pending);
1663 if (cardp->tx_data_ix)
1664 cardp->tx_data_ix--;
1665 else
1666 cardp->tx_data_ix = MVUSB_TX_HIGH_WMARK;
1667 }
1668 }
1669 ret = MLAN_STATUS_FAILURE;
1670 } else {
1671 if (ep == cardp->tx_data_ep &&
1672 (atomic_read(&cardp->tx_data_urb_pending) ==
1673 MVUSB_TX_HIGH_WMARK))
1674 ret = MLAN_STATUS_PRESOURCE;
1675 else
1676 ret = MLAN_STATUS_SUCCESS;
1677 }
1678
1679 tx_ret:
1680
1681 if (!ret)
1682 ret = MLAN_STATUS_PENDING;
1683
1684 LEAVE();
1685 return ret;
1686 }
1687
1688 /**
1689 * @brief This function register usb device and initialize parameter
1690 *
1691 * @param handle Pointer to moal_handle structure
1692 *
1693 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1694 */
woal_usb_register_dev(moal_handle * handle)1695 static mlan_status woal_usb_register_dev(moal_handle *handle)
1696 {
1697 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1698 mlan_status ret = MLAN_STATUS_SUCCESS;
1699
1700 ENTER();
1701
1702 cardp->phandle = handle;
1703 LEAVE();
1704 return ret;
1705 }
1706
woal_usb_unregister_dev(moal_handle * handle)1707 static void woal_usb_unregister_dev(moal_handle *handle)
1708 {
1709 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1710 PRINTM(MMSG, "USB: unregister device\n");
1711 woal_usb_free(cardp);
1712 cardp->phandle = NULL;
1713 return;
1714 }
1715
1716 /**
1717 * @brief This function registers driver.
1718 *
1719 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1720 */
woal_usb_bus_register(void)1721 mlan_status woal_usb_bus_register(void)
1722 {
1723 mlan_status ret = MLAN_STATUS_SUCCESS;
1724 ENTER();
1725
1726 if (skip_fwdnld) {
1727 woal_usb_driver.id_table = woal_usb_table_skip_fwdnld;
1728 }
1729 /*
1730 * API registers the NXP USB driver
1731 * to the USB system
1732 */
1733 if (usb_register(&woal_usb_driver)) {
1734 PRINTM(MFATAL, "USB Driver Registration Failed \n");
1735 ret = MLAN_STATUS_FAILURE;
1736 }
1737 LEAVE();
1738 return ret;
1739 }
1740
1741 /**
1742 * @brief This function removes usb driver.
1743 *
1744 * @return N/A
1745 */
woal_usb_bus_unregister(void)1746 void woal_usb_bus_unregister(void)
1747 {
1748 ENTER();
1749 /* API unregisters the driver from USB subsystem */
1750 usb_deregister(&woal_usb_driver);
1751 LEAVE();
1752 return;
1753 }
1754
1755 /**
1756 * @brief This function check if this is second mac
1757 *
1758 * @param handle A pointer to moal_handle structure
1759 * @return MTRUE/MFALSE
1760 *
1761 */
woal_usb_is_second_mac(moal_handle * handle)1762 static t_u8 woal_usb_is_second_mac(moal_handle *handle)
1763 {
1764 return ((struct usb_card_rec *)(handle->card))->second_mac;
1765 }
1766
1767 #ifdef CONFIG_USB_SUSPEND
1768 /**
1769 * @brief This function makes USB device to suspend.
1770 *
1771 * @param handle A pointer to moal_handle structure
1772 *
1773 * @return 0 --success, otherwise fail
1774 */
woal_enter_usb_suspend(moal_handle * handle)1775 int woal_enter_usb_suspend(moal_handle *handle)
1776 {
1777 struct usb_device *udev = ((struct usb_card_rec *)(handle->card))->udev;
1778 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1779 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1780 struct usb_interface *intf =
1781 ((struct usb_card_rec *)(handle->card))->intf;
1782 #endif /* < 2.6.34 */
1783 #endif /* >= 2.6.24 */
1784
1785 ENTER();
1786
1787 PRINTM(MIOCTL, "USB suspend ioctl (state %d)\n", udev->state);
1788
1789 if (handle->is_suspended == MTRUE) {
1790 PRINTM(MERROR, "Device already suspended\n");
1791 LEAVE();
1792 return -EFAULT;
1793 }
1794
1795 handle->suspend_wait_q_woken = MFALSE;
1796
1797 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1798 /* Enter into USB suspend */
1799 usb_lock_device(udev);
1800 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
1801 udev->autosuspend_delay = 0; /* Autosuspend delay in jiffies */
1802 #else
1803 pm_runtime_set_autosuspend_delay(&udev->dev, 0); /* Autosuspend delay in
1804 jiffies */
1805 #endif /* < 2.6.38 */
1806 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1807 udev->autosuspend_disabled = 0; /* /sys/bus/usb/devices/.../power/level
1808 < auto */
1809 #endif /* < 2.6.34 */
1810 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
1811 udev->autoresume_disabled = 0;
1812 #endif /* < 2.6.33 */
1813 usb_unlock_device(udev);
1814 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1815 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1816 intf->pm_usage_cnt = 1;
1817 #else
1818 atomic_set(&intf->pm_usage_cnt, 1);
1819 #endif /* < 2.6.32 */
1820 usb_autopm_put_interface(intf);
1821 #else
1822 usb_lock_device(udev);
1823 atomic_set(&udev->dev.power.usage_count, 1);
1824 usb_enable_autosuspend(udev);
1825 usb_unlock_device(udev);
1826 #endif /* < 2.6.34 */
1827 #endif /* >= 2.6.24 */
1828
1829 /* Wait for suspend to complete */
1830 wait_event_interruptible(handle->suspend_wait_q,
1831 handle->suspend_wait_q_woken);
1832
1833 LEAVE();
1834 return 0;
1835 }
1836
1837 /**
1838 * @brief This function makes USB device to resume.
1839 *
1840 * @param handle A pointer to moal_handle structure
1841 *
1842 * @return 0 --success, otherwise fail
1843 */
woal_exit_usb_suspend(moal_handle * handle)1844 int woal_exit_usb_suspend(moal_handle *handle)
1845 {
1846 struct usb_device *udev = ((struct usb_card_rec *)(handle->card))->udev;
1847 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1848 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1849 struct usb_interface *intf =
1850 ((struct usb_card_rec *)(handle->card))->intf;
1851 #endif /* < 2.6.34 */
1852 #endif /* >= 2.6.24 */
1853
1854 ENTER();
1855
1856 PRINTM(MIOCTL, "USB resume ioctl (state %d)\n", udev->state);
1857
1858 if (handle->is_suspended == MFALSE ||
1859 udev->state != USB_STATE_SUSPENDED) {
1860 PRINTM(MERROR, "Device already resumed\n");
1861 LEAVE();
1862 return -EFAULT;
1863 }
1864
1865 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1866 /* Exit from USB suspend */
1867 usb_lock_device(udev);
1868 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1869 udev->autosuspend_disabled = 1; /* /sys/bus/usb/devices/.../power/level
1870 < on */
1871 #endif /* < 2.6.34 */
1872 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
1873 udev->autoresume_disabled = 0;
1874 #endif /* < 2.6.33 */
1875 usb_unlock_device(udev);
1876 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
1877 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1878 intf->pm_usage_cnt = 0;
1879 #else
1880 atomic_set(&intf->pm_usage_cnt, 0);
1881 #endif /* < 2.6.32 */
1882 usb_autopm_get_interface(intf);
1883 #else
1884 usb_lock_device(udev);
1885 atomic_set(&udev->dev.power.usage_count, 0);
1886 usb_disable_autosuspend(udev);
1887 usb_unlock_device(udev);
1888 #endif /* < 2.6.34 */
1889 #endif /* >= 2.6.24 */
1890
1891 LEAVE();
1892 return 0;
1893 }
1894 #endif /* CONFIG_USB_SUSPEND */
1895
1896 /**
1897 * @brief This function will submit rx urb.
1898 *
1899 * @param handle Pointer to moal_handle
1900 * @param ep Endpoint to re-submit urb
1901 *
1902 * @return N/A
1903 */
woal_submit_rx_urb(moal_handle * handle,t_u8 ep)1904 void woal_submit_rx_urb(moal_handle *handle, t_u8 ep)
1905 {
1906 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1907
1908 ENTER();
1909
1910 if ((ep == cardp->rx_cmd_ep) &&
1911 (!atomic_read(&cardp->rx_cmd_urb_pending))) {
1912 woal_usb_submit_rx_urb(&cardp->rx_cmd, MLAN_RX_CMD_BUF_SIZE);
1913 }
1914
1915 LEAVE();
1916 return;
1917 }
1918
1919 /**
1920 * @brief This function dump firmware memory to file
1921 *
1922 * @param phandle A pointer to moal_handle
1923 *
1924 * @return N/A
1925 */
woal_usb_dump_fw_info(moal_handle * phandle)1926 static void woal_usb_dump_fw_info(moal_handle *phandle)
1927 {
1928 moal_private *priv = NULL;
1929 mlan_ioctl_req *req = NULL;
1930 mlan_ds_misc_cfg *pcfg_misc = NULL;
1931 mlan_status status = MLAN_STATUS_SUCCESS;
1932
1933 ENTER();
1934
1935 priv = woal_get_priv(phandle, MLAN_BSS_ROLE_ANY);
1936 if (!priv) {
1937 PRINTM(MERROR, "woal_usb_dump_fw_info: priv is NULL!\n");
1938 goto done;
1939 }
1940 /* Allocate an IOCTL request buffer */
1941 req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg));
1942 if (req == NULL) {
1943 PRINTM(MERROR, "woal_usb_dump_fw_info: alloc req fail!\n");
1944 goto done;
1945 }
1946
1947 /* Fill request buffer */
1948 pcfg_misc = (mlan_ds_misc_cfg *)req->pbuf;
1949 pcfg_misc->sub_command = MLAN_OID_MISC_FW_DUMP_EVENT;
1950 req->req_id = MLAN_IOCTL_MISC_CFG;
1951 req->action = MLAN_ACT_GET;
1952
1953 /* Send IOCTL request to MLAN */
1954 status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1955
1956 if (status != MLAN_STATUS_PENDING)
1957 kfree(req);
1958 phandle->is_fw_dump_timer_set = MTRUE;
1959 woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
1960
1961 done:
1962 LEAVE();
1963 return;
1964 }
1965
woal_usb_get_fw_name(moal_handle * handle)1966 static mlan_status woal_usb_get_fw_name(moal_handle *handle)
1967 {
1968 mlan_status ret = MLAN_STATUS_SUCCESS;
1969 #if defined(USB8997) || defined(USB9098) || defined(USB9097) || \
1970 defined(USB8978) || defined(USBNW62X)
1971 t_u32 revision_id = 0;
1972 t_u32 strap = 0;
1973 #endif
1974 struct usb_card_rec *cardp = (struct usb_card_rec *)handle->card;
1975 #if defined(USB9098)
1976 moal_handle *ref_handle = NULL;
1977 #endif
1978
1979 ENTER();
1980 if (handle->params.fw_name)
1981 goto done;
1982 if (cardp->boot_state == USB_FW_READY)
1983 goto done;
1984 #ifdef USB8801
1985 if (IS_USB8801(handle->card_type))
1986 goto done;
1987 #endif
1988
1989 #if defined(USB8997) || defined(USB9098) || defined(USB9097) || \
1990 defined(USB8978) || defined(USBNW62X)
1991 ret = woal_check_chip_revision(handle, &revision_id, &strap);
1992 if (ret != MLAN_STATUS_SUCCESS) {
1993 PRINTM(MFATAL, "Chip revision check failure!\n");
1994 ret = MLAN_STATUS_FAILURE;
1995 goto done;
1996 }
1997 PRINTM(MCMND, "revision=0x%x, strap=0x%x\n", revision_id, strap);
1998 #endif
1999
2000 #ifdef USB8997
2001 if (IS_USB8997(handle->card_type)) {
2002 if (strap == CARD_TYPE_USB_UART)
2003 strcpy(handle->card_info->fw_name,
2004 USBUART8997_DEFAULT_COMBO_FW_NAME);
2005 else if (strap != 0)
2006 strcpy(handle->card_info->fw_name,
2007 USBUSB8997_DEFAULT_COMBO_FW_NAME);
2008 }
2009 #endif
2010
2011 #ifdef USB8978
2012 if (IS_USB8978(handle->card_type)) {
2013 if (strap == CARD_TYPE_USB_UART)
2014 strcpy(handle->card_info->fw_name,
2015 USBUART8978_DEFAULT_COMBO_FW_NAME);
2016 else if (strap != 0)
2017 strcpy(handle->card_info->fw_name,
2018 USBUSB8978_DEFAULT_COMBO_FW_NAME);
2019 }
2020 #endif
2021
2022 #ifdef USB9098
2023 if (IS_USB9098(handle->card_type)) {
2024 if (cardp->second_mac) {
2025 ref_handle = (moal_handle *)handle->pref_mac;
2026 if (ref_handle) {
2027 strcpy(handle->card_info->fw_name,
2028 ref_handle->card_info->fw_name);
2029 strcpy(handle->card_info->fw_name_wlan,
2030 ref_handle->card_info->fw_name_wlan);
2031 }
2032 goto done;
2033 }
2034 switch (revision_id) {
2035 case USB9098_Z1Z2:
2036 if (strap != 0) {
2037 if (strap == CARD_TYPE_USB_UART)
2038 strcpy(handle->card_info->fw_name,
2039 USBUART9098_DEFAULT_COMBO_FW_NAME);
2040 else
2041 strcpy(handle->card_info->fw_name,
2042 USBUSB9098_DEFAULT_COMBO_FW_NAME);
2043 }
2044 strcpy(handle->card_info->fw_name_wlan,
2045 USB9098_DEFAULT_WLAN_FW_NAME);
2046 break;
2047 case USB9098_A0:
2048 case USB9098_A1:
2049 case USB9098_A2:
2050 if (strap != 0) {
2051 if (strap == CARD_TYPE_USB_UART)
2052 strcpy(handle->card_info->fw_name,
2053 USBUART9098_COMBO_V1_FW_NAME);
2054 else
2055 strcpy(handle->card_info->fw_name,
2056 USBUSB9098_COMBO_V1_FW_NAME);
2057 }
2058 strcpy(handle->card_info->fw_name_wlan,
2059 USB9098_WLAN_V1_FW_NAME);
2060 break;
2061 }
2062 }
2063 #endif
2064 #ifdef USB9097
2065 if (IS_USB9097(handle->card_type)) {
2066 switch (revision_id) {
2067 case USB9097_B0:
2068 case USB9097_B1:
2069 if (strap != 0) {
2070 if (strap == CARD_TYPE_USB_UART)
2071 strcpy(handle->card_info->fw_name,
2072 USBUART9097_COMBO_V1_FW_NAME);
2073 else
2074 strcpy(handle->card_info->fw_name,
2075 USBUSB9097_COMBO_V1_FW_NAME);
2076 }
2077 strcpy(handle->card_info->fw_name_wlan,
2078 USB9097_WLAN_V1_FW_NAME);
2079 break;
2080 }
2081 }
2082 #endif
2083 #ifdef USBNW62X
2084 if (IS_USBNW62X(handle->card_type)) {
2085 if (strap == CARD_TYPE_USB_UART)
2086 strcpy(handle->card_info->fw_name,
2087 USBUARTNW62X_COMBO_FW_NAME);
2088 else
2089 strcpy(handle->card_info->fw_name,
2090 USBUSBNW62X_COMBO_FW_NAME);
2091 }
2092 #endif
2093
2094 done:
2095 PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
2096 handle->card_info->fw_name_wlan);
2097 LEAVE();
2098 return ret;
2099 }
2100
2101 static moal_if_ops usb_ops = {
2102 .register_dev = woal_usb_register_dev,
2103 .unregister_dev = woal_usb_unregister_dev,
2104 .read_data_sync = woal_usb_read_data_sync,
2105 .write_data_sync = woal_usb_write_data_sync,
2106 .get_fw_name = woal_usb_get_fw_name,
2107 .dump_fw_info = woal_usb_dump_fw_info,
2108 .is_second_mac = woal_usb_is_second_mac,
2109 };
2110