1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "main.h"
21#include "wmm.h"
22#include "cfg80211.h"
23#include "11n.h"
24
25#define VERSION "1.0"
26
27const char driver_version[] = "mwifiex " VERSION " (%s) ";
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
45 void **padapter)
46{
47 struct mwifiex_adapter *adapter;
48 int i;
49
50 adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL);
51 if (!adapter)
52 return -ENOMEM;
53
54 *padapter = adapter;
55 adapter->card = card;
56
57
58 memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops));
59
60
61 if (adapter->if_ops.init_if(adapter))
62 goto error;
63
64 adapter->priv_num = 0;
65
66
67 adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private),
68 GFP_KERNEL);
69 if (!adapter->priv[0]) {
70 dev_err(adapter->dev, "%s: failed to alloc priv[0]\n",
71 __func__);
72 goto error;
73 }
74
75 adapter->priv_num++;
76
77 adapter->priv[0]->adapter = adapter;
78 mwifiex_init_lock_list(adapter);
79
80 init_timer(&adapter->cmd_timer);
81 adapter->cmd_timer.function = mwifiex_cmd_timeout_func;
82 adapter->cmd_timer.data = (unsigned long) adapter;
83
84 return 0;
85
86error:
87 dev_dbg(adapter->dev, "info: leave mwifiex_register with error\n");
88
89 for (i = 0; i < adapter->priv_num; i++)
90 kfree(adapter->priv[i]);
91
92 kfree(adapter);
93
94 return -1;
95}
96
97
98
99
100
101
102
103
104
105
106
107static int mwifiex_unregister(struct mwifiex_adapter *adapter)
108{
109 s32 i;
110
111 del_timer(&adapter->cmd_timer);
112
113
114 for (i = 0; i < adapter->priv_num; i++) {
115 if (adapter->priv[i]) {
116 mwifiex_free_curr_bcn(adapter->priv[i]);
117 kfree(adapter->priv[i]);
118 }
119 }
120
121 kfree(adapter);
122 return 0;
123}
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140int mwifiex_main_process(struct mwifiex_adapter *adapter)
141{
142 int ret = 0;
143 unsigned long flags;
144
145 spin_lock_irqsave(&adapter->main_proc_lock, flags);
146
147
148 if (adapter->mwifiex_processing) {
149 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
150 goto exit_main_proc;
151 } else {
152 adapter->mwifiex_processing = true;
153 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
154 }
155process_start:
156 do {
157 if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) ||
158 (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
159 break;
160
161
162 if (adapter->int_status) {
163 if (adapter->hs_activated)
164 mwifiex_process_hs_config(adapter);
165 adapter->if_ops.process_int_status(adapter);
166 }
167
168
169 if ((adapter->ps_state == PS_STATE_SLEEP) &&
170 (adapter->pm_wakeup_card_req &&
171 !adapter->pm_wakeup_fw_try) &&
172 (is_command_pending(adapter)
173 || !mwifiex_wmm_lists_empty(adapter))) {
174 adapter->pm_wakeup_fw_try = true;
175 adapter->if_ops.wakeup(adapter);
176 continue;
177 }
178 if (IS_CARD_RX_RCVD(adapter)) {
179 adapter->pm_wakeup_fw_try = false;
180 if (adapter->ps_state == PS_STATE_SLEEP)
181 adapter->ps_state = PS_STATE_AWAKE;
182 } else {
183
184 if (adapter->pm_wakeup_fw_try)
185 break;
186 if (adapter->ps_state != PS_STATE_AWAKE ||
187 adapter->tx_lock_flag)
188 break;
189
190 if (adapter->scan_processing || adapter->data_sent
191 || mwifiex_wmm_lists_empty(adapter)) {
192 if (adapter->cmd_sent || adapter->curr_cmd
193 || (!is_command_pending(adapter)))
194 break;
195 }
196 }
197
198
199 if (adapter->cmd_resp_received) {
200 adapter->cmd_resp_received = false;
201 mwifiex_process_cmdresp(adapter);
202
203
204 if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) {
205 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
206 mwifiex_init_fw_complete(adapter);
207 }
208 }
209
210
211 if (adapter->event_received) {
212 adapter->event_received = false;
213 mwifiex_process_event(adapter);
214 }
215
216
217
218 if (adapter->ps_state == PS_STATE_PRE_SLEEP) {
219 if (!adapter->cmd_sent && !adapter->curr_cmd)
220 mwifiex_check_ps_cond(adapter);
221 }
222
223
224
225
226 if ((adapter->ps_state == PS_STATE_SLEEP)
227 || (adapter->ps_state == PS_STATE_PRE_SLEEP)
228 || (adapter->ps_state == PS_STATE_SLEEP_CFM)
229 || adapter->tx_lock_flag)
230 continue;
231
232 if (!adapter->cmd_sent && !adapter->curr_cmd) {
233 if (mwifiex_exec_next_cmd(adapter) == -1) {
234 ret = -1;
235 break;
236 }
237 }
238
239 if (!adapter->scan_processing && !adapter->data_sent &&
240 !mwifiex_wmm_lists_empty(adapter)) {
241 mwifiex_wmm_process_tx(adapter);
242 if (adapter->hs_activated) {
243 adapter->is_hs_configured = false;
244 mwifiex_hs_activated_event
245 (mwifiex_get_priv
246 (adapter, MWIFIEX_BSS_ROLE_ANY),
247 false);
248 }
249 }
250
251 if (adapter->delay_null_pkt && !adapter->cmd_sent &&
252 !adapter->curr_cmd && !is_command_pending(adapter)
253 && mwifiex_wmm_lists_empty(adapter)) {
254 if (!mwifiex_send_null_packet
255 (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
256 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
257 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) {
258 adapter->delay_null_pkt = false;
259 adapter->ps_state = PS_STATE_SLEEP;
260 }
261 break;
262 }
263 } while (true);
264
265 if ((adapter->int_status) || IS_CARD_RX_RCVD(adapter))
266 goto process_start;
267
268 spin_lock_irqsave(&adapter->main_proc_lock, flags);
269 adapter->mwifiex_processing = false;
270 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
271
272exit_main_proc:
273 if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING)
274 mwifiex_shutdown_drv(adapter);
275 return ret;
276}
277
278
279
280
281
282
283
284static void mwifiex_free_adapter(struct mwifiex_adapter *adapter)
285{
286 if (!adapter) {
287 pr_err("%s: adapter is NULL\n", __func__);
288 return;
289 }
290
291 mwifiex_unregister(adapter);
292 pr_debug("info: %s: free adapter\n", __func__);
293}
294
295
296
297
298
299
300
301
302
303
304static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter)
305{
306 int ret, err;
307 struct mwifiex_fw_image fw;
308
309 memset(&fw, 0, sizeof(struct mwifiex_fw_image));
310
311 err = request_firmware(&adapter->firmware, adapter->fw_name,
312 adapter->dev);
313 if (err < 0) {
314 dev_err(adapter->dev, "request_firmware() returned"
315 " error code %#x\n", err);
316 ret = -1;
317 goto done;
318 }
319 fw.fw_buf = (u8 *) adapter->firmware->data;
320 fw.fw_len = adapter->firmware->size;
321
322 ret = mwifiex_dnld_fw(adapter, &fw);
323 if (ret == -1)
324 goto done;
325
326 dev_notice(adapter->dev, "WLAN FW is active\n");
327
328 adapter->init_wait_q_woken = false;
329 ret = mwifiex_init_fw(adapter);
330 if (ret == -1) {
331 goto done;
332 } else if (!ret) {
333 adapter->hw_status = MWIFIEX_HW_STATUS_READY;
334 goto done;
335 }
336
337 wait_event_interruptible(adapter->init_wait_q,
338 adapter->init_wait_q_woken);
339 if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) {
340 ret = -1;
341 goto done;
342 }
343 ret = 0;
344
345done:
346 if (adapter->firmware)
347 release_firmware(adapter->firmware);
348 if (ret)
349 ret = -1;
350 return ret;
351}
352
353
354
355
356
357
358
359
360static void
361mwifiex_fill_buffer(struct sk_buff *skb)
362{
363 struct ethhdr *eth;
364 struct iphdr *iph;
365 struct timeval tv;
366 u8 tid = 0;
367
368 eth = (struct ethhdr *) skb->data;
369 switch (eth->h_proto) {
370 case __constant_htons(ETH_P_IP):
371 iph = ip_hdr(skb);
372 tid = IPTOS_PREC(iph->tos);
373 pr_debug("data: packet type ETH_P_IP: %04x, tid=%#x prio=%#x\n",
374 eth->h_proto, tid, skb->priority);
375 break;
376 case __constant_htons(ETH_P_ARP):
377 pr_debug("data: ARP packet: %04x\n", eth->h_proto);
378 default:
379 break;
380 }
381
382#define IPTOS_OFFSET 5
383 tid = (tid >> IPTOS_OFFSET);
384 skb->priority = tid;
385
386
387
388
389
390
391
392 do_gettimeofday(&tv);
393 skb->tstamp = timeval_to_ktime(tv);
394}
395
396
397
398
399
400
401static int
402mwifiex_open(struct net_device *dev)
403{
404 netif_start_queue(dev);
405 return 0;
406}
407
408
409
410
411static int
412mwifiex_close(struct net_device *dev)
413{
414 return 0;
415}
416
417
418
419
420static int
421mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
422{
423 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
424 struct sk_buff *new_skb;
425 struct mwifiex_txinfo *tx_info;
426
427 dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n",
428 jiffies, priv->bss_index);
429
430 if (priv->adapter->surprise_removed) {
431 kfree_skb(skb);
432 priv->stats.tx_dropped++;
433 return 0;
434 }
435 if (!skb->len || (skb->len > ETH_FRAME_LEN)) {
436 dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len);
437 kfree_skb(skb);
438 priv->stats.tx_dropped++;
439 return 0;
440 }
441 if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
442 dev_dbg(priv->adapter->dev,
443 "data: Tx: insufficient skb headroom %d\n",
444 skb_headroom(skb));
445
446 new_skb =
447 skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
448 if (unlikely(!new_skb)) {
449 dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n");
450 kfree_skb(skb);
451 priv->stats.tx_dropped++;
452 return 0;
453 }
454 kfree_skb(skb);
455 skb = new_skb;
456 dev_dbg(priv->adapter->dev, "info: new skb headroomd %d\n",
457 skb_headroom(skb));
458 }
459
460 tx_info = MWIFIEX_SKB_TXCB(skb);
461 tx_info->bss_index = priv->bss_index;
462 mwifiex_fill_buffer(skb);
463
464 mwifiex_wmm_add_buf_txqueue(priv->adapter, skb);
465 atomic_inc(&priv->adapter->tx_pending);
466
467 if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
468 netif_stop_queue(priv->netdev);
469 dev->trans_start = jiffies;
470 }
471
472 queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
473
474 return 0;
475}
476
477
478
479
480static int
481mwifiex_set_mac_address(struct net_device *dev, void *addr)
482{
483 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
484 struct sockaddr *hw_addr = addr;
485 int ret;
486
487 memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
488
489
490 ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
491 HostCmd_ACT_GEN_SET, 0, NULL);
492
493 if (!ret)
494 memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN);
495 else
496 dev_err(priv->adapter->dev, "set mac address failed: ret=%d"
497 "\n", ret);
498
499 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
500
501 return ret;
502}
503
504
505
506
507static void mwifiex_set_multicast_list(struct net_device *dev)
508{
509 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
510 struct mwifiex_multicast_list mcast_list;
511
512 if (dev->flags & IFF_PROMISC) {
513 mcast_list.mode = MWIFIEX_PROMISC_MODE;
514 } else if (dev->flags & IFF_ALLMULTI ||
515 netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) {
516 mcast_list.mode = MWIFIEX_ALL_MULTI_MODE;
517 } else {
518 mcast_list.mode = MWIFIEX_MULTICAST_MODE;
519 if (netdev_mc_count(dev))
520 mcast_list.num_multicast_addr =
521 mwifiex_copy_mcast_addr(&mcast_list, dev);
522 }
523 mwifiex_request_set_multicast_list(priv, &mcast_list);
524}
525
526
527
528
529static void
530mwifiex_tx_timeout(struct net_device *dev)
531{
532 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
533
534 dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_index=%d\n",
535 jiffies, priv->bss_index);
536 dev->trans_start = jiffies;
537 priv->num_tx_timeout++;
538}
539
540
541
542
543static struct net_device_stats *mwifiex_get_stats(struct net_device *dev)
544{
545 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
546
547 return &priv->stats;
548}
549
550
551static const struct net_device_ops mwifiex_netdev_ops = {
552 .ndo_open = mwifiex_open,
553 .ndo_stop = mwifiex_close,
554 .ndo_start_xmit = mwifiex_hard_start_xmit,
555 .ndo_set_mac_address = mwifiex_set_mac_address,
556 .ndo_tx_timeout = mwifiex_tx_timeout,
557 .ndo_get_stats = mwifiex_get_stats,
558 .ndo_set_rx_mode = mwifiex_set_multicast_list,
559};
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580void mwifiex_init_priv_params(struct mwifiex_private *priv,
581 struct net_device *dev)
582{
583 dev->netdev_ops = &mwifiex_netdev_ops;
584
585 priv->current_key_index = 0;
586 priv->media_connected = false;
587 memset(&priv->nick_name, 0, sizeof(priv->nick_name));
588 priv->num_tx_timeout = 0;
589 priv->workqueue = create_singlethread_workqueue("cfg80211_wq");
590 INIT_WORK(&priv->cfg_workqueue, mwifiex_cfg80211_results);
591 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
592}
593
594
595
596
597int is_command_pending(struct mwifiex_adapter *adapter)
598{
599 unsigned long flags;
600 int is_cmd_pend_q_empty;
601
602 spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags);
603 is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q);
604 spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags);
605
606 return !is_cmd_pend_q_empty;
607}
608
609
610
611
612
613struct mwifiex_private *
614mwifiex_bss_index_to_priv(struct mwifiex_adapter *adapter, u8 bss_index)
615{
616 if (!adapter || (bss_index >= adapter->priv_num))
617 return NULL;
618 return adapter->priv[bss_index];
619}
620
621
622
623
624
625
626
627static void mwifiex_main_work_queue(struct work_struct *work)
628{
629 struct mwifiex_adapter *adapter =
630 container_of(work, struct mwifiex_adapter, main_work);
631
632 if (adapter->surprise_removed)
633 return;
634 mwifiex_main_process(adapter);
635}
636
637
638
639
640
641static void
642mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter)
643{
644 flush_workqueue(adapter->workqueue);
645 destroy_workqueue(adapter->workqueue);
646 adapter->workqueue = NULL;
647}
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662int
663mwifiex_add_card(void *card, struct semaphore *sem,
664 struct mwifiex_if_ops *if_ops, u8 iface_type)
665{
666 struct mwifiex_adapter *adapter;
667 char fmt[64];
668 struct mwifiex_private *priv;
669
670 if (down_interruptible(sem))
671 goto exit_sem_err;
672
673 if (mwifiex_register(card, if_ops, (void **)&adapter)) {
674 pr_err("%s: software init failed\n", __func__);
675 goto err_init_sw;
676 }
677
678 adapter->iface_type = iface_type;
679
680 adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
681 adapter->surprise_removed = false;
682 init_waitqueue_head(&adapter->init_wait_q);
683 adapter->is_suspended = false;
684 adapter->hs_activated = false;
685 init_waitqueue_head(&adapter->hs_activate_wait_q);
686 adapter->cmd_wait_q_required = false;
687 init_waitqueue_head(&adapter->cmd_wait_q.wait);
688 adapter->cmd_wait_q.status = 0;
689 adapter->scan_wait_q_woken = false;
690
691 adapter->workqueue = create_workqueue("MWIFIEX_WORK_QUEUE");
692 if (!adapter->workqueue)
693 goto err_kmalloc;
694
695 INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
696
697
698
699 if (adapter->if_ops.register_dev(adapter)) {
700 pr_err("%s: failed to register mwifiex device\n", __func__);
701 goto err_registerdev;
702 }
703
704 if (mwifiex_init_hw_fw(adapter)) {
705 pr_err("%s: firmware init failed\n", __func__);
706 goto err_init_fw;
707 }
708
709 priv = adapter->priv[0];
710
711 if (mwifiex_register_cfg80211(priv) != 0) {
712 dev_err(adapter->dev, "cannot register netdevice"
713 " with cfg80211\n");
714 goto err_init_fw;
715 }
716
717 rtnl_lock();
718
719 if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d",
720 NL80211_IFTYPE_STATION, NULL, NULL)) {
721 rtnl_unlock();
722 dev_err(adapter->dev, "cannot create default station"
723 " interface\n");
724 goto err_add_intf;
725 }
726
727 rtnl_unlock();
728
729 up(sem);
730
731 mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
732 dev_notice(adapter->dev, "driver_version = %s\n", fmt);
733
734 return 0;
735
736err_add_intf:
737 rtnl_lock();
738 mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
739 rtnl_unlock();
740err_init_fw:
741 pr_debug("info: %s: unregister device\n", __func__);
742 adapter->if_ops.unregister_dev(adapter);
743err_registerdev:
744 adapter->surprise_removed = true;
745 mwifiex_terminate_workqueue(adapter);
746err_kmalloc:
747 if ((adapter->hw_status == MWIFIEX_HW_STATUS_FW_READY) ||
748 (adapter->hw_status == MWIFIEX_HW_STATUS_READY)) {
749 pr_debug("info: %s: shutdown mwifiex\n", __func__);
750 adapter->init_wait_q_woken = false;
751
752 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
753 wait_event_interruptible(adapter->init_wait_q,
754 adapter->init_wait_q_woken);
755 }
756
757 mwifiex_free_adapter(adapter);
758
759err_init_sw:
760 up(sem);
761
762exit_sem_err:
763 return -1;
764}
765EXPORT_SYMBOL_GPL(mwifiex_add_card);
766
767
768
769
770
771
772
773
774
775
776
777
778int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
779{
780 struct mwifiex_private *priv = NULL;
781 int i;
782
783 if (down_interruptible(sem))
784 goto exit_sem_err;
785
786 if (!adapter)
787 goto exit_remove;
788
789 adapter->surprise_removed = true;
790
791
792 for (i = 0; i < adapter->priv_num; i++) {
793 priv = adapter->priv[i];
794 if (priv && priv->netdev) {
795 if (!netif_queue_stopped(priv->netdev))
796 netif_stop_queue(priv->netdev);
797 if (netif_carrier_ok(priv->netdev))
798 netif_carrier_off(priv->netdev);
799 }
800 }
801
802 dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
803 adapter->init_wait_q_woken = false;
804
805 if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
806 wait_event_interruptible(adapter->init_wait_q,
807 adapter->init_wait_q_woken);
808 dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
809 if (atomic_read(&adapter->rx_pending) ||
810 atomic_read(&adapter->tx_pending) ||
811 atomic_read(&adapter->cmd_pending)) {
812 dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
813 "cmd_pending=%d\n",
814 atomic_read(&adapter->rx_pending),
815 atomic_read(&adapter->tx_pending),
816 atomic_read(&adapter->cmd_pending));
817 }
818
819 for (i = 0; i < adapter->priv_num; i++) {
820 priv = adapter->priv[i];
821
822 if (!priv)
823 continue;
824
825 rtnl_lock();
826 mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev);
827 rtnl_unlock();
828 }
829
830 priv = adapter->priv[0];
831 if (!priv)
832 goto exit_remove;
833
834 wiphy_unregister(priv->wdev->wiphy);
835 wiphy_free(priv->wdev->wiphy);
836 kfree(priv->wdev);
837
838 mwifiex_terminate_workqueue(adapter);
839
840
841 dev_dbg(adapter->dev, "info: unregister device\n");
842 adapter->if_ops.unregister_dev(adapter);
843
844 dev_dbg(adapter->dev, "info: free adapter\n");
845 mwifiex_free_adapter(adapter);
846
847exit_remove:
848 up(sem);
849exit_sem_err:
850 return 0;
851}
852EXPORT_SYMBOL_GPL(mwifiex_remove_card);
853
854
855
856
857
858
859static int
860mwifiex_init_module(void)
861{
862#ifdef CONFIG_DEBUG_FS
863 mwifiex_debugfs_init();
864#endif
865 return 0;
866}
867
868
869
870
871
872
873static void
874mwifiex_cleanup_module(void)
875{
876#ifdef CONFIG_DEBUG_FS
877 mwifiex_debugfs_remove();
878#endif
879}
880
881module_init(mwifiex_init_module);
882module_exit(mwifiex_cleanup_module);
883
884MODULE_AUTHOR("Marvell International Ltd.");
885MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION);
886MODULE_VERSION(VERSION);
887MODULE_LICENSE("GPL v2");
888