Root/drivers/net/wireless/mwl8k.c

1/*
2 * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards
3 *
4 * Copyright (C) 2008 Marvell Semiconductor Inc.
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/init.h>
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/spinlock.h>
15#include <linux/list.h>
16#include <linux/pci.h>
17#include <linux/delay.h>
18#include <linux/completion.h>
19#include <linux/etherdevice.h>
20#include <net/mac80211.h>
21#include <linux/moduleparam.h>
22#include <linux/firmware.h>
23#include <linux/workqueue.h>
24
25#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver"
26#define MWL8K_NAME KBUILD_MODNAME
27#define MWL8K_VERSION "0.9.1"
28
29MODULE_DESCRIPTION(MWL8K_DESC);
30MODULE_VERSION(MWL8K_VERSION);
31MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>");
32MODULE_LICENSE("GPL");
33
34static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = {
35    { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, },
36    { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, },
37    { }
38};
39MODULE_DEVICE_TABLE(pci, mwl8k_table);
40
41#define IEEE80211_ADDR_LEN ETH_ALEN
42
43/* Register definitions */
44#define MWL8K_HIU_GEN_PTR 0x00000c10
45#define MWL8K_MODE_STA 0x0000005a
46#define MWL8K_MODE_AP 0x000000a5
47#define MWL8K_HIU_INT_CODE 0x00000c14
48#define MWL8K_FWSTA_READY 0xf0f1f2f4
49#define MWL8K_FWAP_READY 0xf1f2f4a5
50#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005
51#define MWL8K_HIU_SCRATCH 0x00000c40
52
53/* Host->device communications */
54#define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18
55#define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c
56#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20
57#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24
58#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28
59#define MWL8K_H2A_INT_DUMMY (1 << 20)
60#define MWL8K_H2A_INT_RESET (1 << 15)
61#define MWL8K_H2A_INT_PS (1 << 2)
62#define MWL8K_H2A_INT_DOORBELL (1 << 1)
63#define MWL8K_H2A_INT_PPA_READY (1 << 0)
64
65/* Device->host communications */
66#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c
67#define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30
68#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34
69#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38
70#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c
71#define MWL8K_A2H_INT_DUMMY (1 << 20)
72#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11)
73#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10)
74#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7)
75#define MWL8K_A2H_INT_RADIO_ON (1 << 6)
76#define MWL8K_A2H_INT_RADIO_OFF (1 << 5)
77#define MWL8K_A2H_INT_MAC_EVENT (1 << 3)
78#define MWL8K_A2H_INT_OPC_DONE (1 << 2)
79#define MWL8K_A2H_INT_RX_READY (1 << 1)
80#define MWL8K_A2H_INT_TX_DONE (1 << 0)
81
82#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \
83                 MWL8K_A2H_INT_CHNL_SWITCHED | \
84                 MWL8K_A2H_INT_QUEUE_EMPTY | \
85                 MWL8K_A2H_INT_RADAR_DETECT | \
86                 MWL8K_A2H_INT_RADIO_ON | \
87                 MWL8K_A2H_INT_RADIO_OFF | \
88                 MWL8K_A2H_INT_MAC_EVENT | \
89                 MWL8K_A2H_INT_OPC_DONE | \
90                 MWL8K_A2H_INT_RX_READY | \
91                 MWL8K_A2H_INT_TX_DONE)
92
93/* WME stream classes */
94#define WME_AC_BE 0 /* best effort */
95#define WME_AC_BK 1 /* background */
96#define WME_AC_VI 2 /* video */
97#define WME_AC_VO 3 /* voice */
98
99#define MWL8K_RX_QUEUES 1
100#define MWL8K_TX_QUEUES 4
101
102struct mwl8k_rx_queue {
103    int rx_desc_count;
104
105    /* hw receives here */
106    int rx_head;
107
108    /* refill descs here */
109    int rx_tail;
110
111    struct mwl8k_rx_desc *rx_desc_area;
112    dma_addr_t rx_desc_dma;
113    struct sk_buff **rx_skb;
114};
115
116struct mwl8k_skb {
117    /*
118     * The DMA engine requires a modification to the payload.
119     * If the skbuff is shared/cloned, it needs to be unshared.
120     * This method is used to ensure the stack always gets back
121     * the skbuff it sent for transmission.
122     */
123    struct sk_buff *clone;
124    struct sk_buff *skb;
125};
126
127struct mwl8k_tx_queue {
128    /* hw transmits here */
129    int tx_head;
130
131    /* sw appends here */
132    int tx_tail;
133
134    struct ieee80211_tx_queue_stats tx_stats;
135    struct mwl8k_tx_desc *tx_desc_area;
136    dma_addr_t tx_desc_dma;
137    struct mwl8k_skb *tx_skb;
138};
139
140/* Pointers to the firmware data and meta information about it. */
141struct mwl8k_firmware {
142    /* Microcode */
143    struct firmware *ucode;
144
145    /* Boot helper code */
146    struct firmware *helper;
147};
148
149struct mwl8k_priv {
150    void __iomem *regs;
151    struct ieee80211_hw *hw;
152
153    struct pci_dev *pdev;
154    u8 name[16];
155    /* firmware access lock */
156    spinlock_t fw_lock;
157
158    /* firmware files and meta data */
159    struct mwl8k_firmware fw;
160    u32 part_num;
161
162    /* lock held over TX and TX reap */
163    spinlock_t tx_lock;
164    u32 int_mask;
165
166    struct ieee80211_vif *vif;
167    struct list_head vif_list;
168
169    struct ieee80211_channel *current_channel;
170
171    /* power management status cookie from firmware */
172    u32 *cookie;
173    dma_addr_t cookie_dma;
174
175    u16 num_mcaddrs;
176    u16 region_code;
177    u8 hw_rev;
178    __le32 fw_rev;
179    u32 wep_enabled;
180
181    /*
182     * Running count of TX packets in flight, to avoid
183     * iterating over the transmit rings each time.
184     */
185    int pending_tx_pkts;
186
187    struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
188    struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES];
189
190    /* PHY parameters */
191    struct ieee80211_supported_band band;
192    struct ieee80211_channel channels[14];
193    struct ieee80211_rate rates[12];
194
195    /* RF preamble: Short, Long or Auto */
196    u8 radio_preamble;
197    u8 radio_state;
198
199    /* WMM MODE 1 for enabled; 0 for disabled */
200    bool wmm_mode;
201
202    /* Set if PHY config is in progress */
203    bool inconfig;
204
205    /* XXX need to convert this to handle multiple interfaces */
206    bool capture_beacon;
207    u8 capture_bssid[IEEE80211_ADDR_LEN];
208    struct sk_buff *beacon_skb;
209
210    /*
211     * This FJ worker has to be global as it is scheduled from the
212     * RX handler. At this point we don't know which interface it
213     * belongs to until the list of bssids waiting to complete join
214     * is checked.
215     */
216    struct work_struct finalize_join_worker;
217
218    /* Tasklet to reclaim TX descriptors and buffers after tx */
219    struct tasklet_struct tx_reclaim_task;
220
221    /* Work thread to serialize configuration requests */
222    struct workqueue_struct *config_wq;
223    struct completion *hostcmd_wait;
224    struct completion *tx_wait;
225};
226
227/* Per interface specific private data */
228struct mwl8k_vif {
229    struct list_head node;
230
231    /* backpointer to parent config block */
232    struct mwl8k_priv *priv;
233
234    /* BSS config of AP or IBSS from mac80211*/
235    struct ieee80211_bss_conf bss_info;
236
237    /* BSSID of AP or IBSS */
238    u8 bssid[IEEE80211_ADDR_LEN];
239    u8 mac_addr[IEEE80211_ADDR_LEN];
240
241    /*
242     * Subset of supported legacy rates.
243     * Intersection of AP and STA supported rates.
244     */
245    struct ieee80211_rate legacy_rates[12];
246
247    /* number of supported legacy rates */
248    u8 legacy_nrates;
249
250    /* Number of supported MCS rates. Work in progress */
251    u8 mcs_nrates;
252
253     /* Index into station database.Returned by update_sta_db call */
254    u8 peer_id;
255
256    /* Non AMPDU sequence number assigned by driver */
257    u16 seqno;
258
259    /* Note:There is no channel info,
260     * refer to the master channel info in priv
261     */
262};
263
264#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
265
266static const struct ieee80211_channel mwl8k_channels[] = {
267    { .center_freq = 2412, .hw_value = 1, },
268    { .center_freq = 2417, .hw_value = 2, },
269    { .center_freq = 2422, .hw_value = 3, },
270    { .center_freq = 2427, .hw_value = 4, },
271    { .center_freq = 2432, .hw_value = 5, },
272    { .center_freq = 2437, .hw_value = 6, },
273    { .center_freq = 2442, .hw_value = 7, },
274    { .center_freq = 2447, .hw_value = 8, },
275    { .center_freq = 2452, .hw_value = 9, },
276    { .center_freq = 2457, .hw_value = 10, },
277    { .center_freq = 2462, .hw_value = 11, },
278};
279
280static const struct ieee80211_rate mwl8k_rates[] = {
281    { .bitrate = 10, .hw_value = 2, },
282    { .bitrate = 20, .hw_value = 4, },
283    { .bitrate = 55, .hw_value = 11, },
284    { .bitrate = 60, .hw_value = 12, },
285    { .bitrate = 90, .hw_value = 18, },
286    { .bitrate = 110, .hw_value = 22, },
287    { .bitrate = 120, .hw_value = 24, },
288    { .bitrate = 180, .hw_value = 36, },
289    { .bitrate = 240, .hw_value = 48, },
290    { .bitrate = 360, .hw_value = 72, },
291    { .bitrate = 480, .hw_value = 96, },
292    { .bitrate = 540, .hw_value = 108, },
293};
294
295/* Radio settings */
296#define MWL8K_RADIO_FORCE 0x2
297#define MWL8K_RADIO_ENABLE 0x1
298#define MWL8K_RADIO_DISABLE 0x0
299#define MWL8K_RADIO_AUTO_PREAMBLE 0x0005
300#define MWL8K_RADIO_SHORT_PREAMBLE 0x0003
301#define MWL8K_RADIO_LONG_PREAMBLE 0x0001
302
303/* WMM */
304#define MWL8K_WMM_ENABLE 1
305#define MWL8K_WMM_DISABLE 0
306
307#define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE
308
309/* Slot time */
310
311/* Short Slot: 9us slot time */
312#define MWL8K_SHORT_SLOTTIME 1
313
314/* Long slot: 20us slot time */
315#define MWL8K_LONG_SLOTTIME 0
316
317/* Set or get info from Firmware */
318#define MWL8K_CMD_SET 0x0001
319#define MWL8K_CMD_GET 0x0000
320
321/* Firmware command codes */
322#define MWL8K_CMD_CODE_DNLD 0x0001
323#define MWL8K_CMD_GET_HW_SPEC 0x0003
324#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010
325#define MWL8K_CMD_GET_STAT 0x0014
326#define MWL8K_CMD_RADIO_CONTROL 0x001C
327#define MWL8K_CMD_RF_TX_POWER 0x001E
328#define MWL8K_CMD_SET_PRE_SCAN 0x0107
329#define MWL8K_CMD_SET_POST_SCAN 0x0108
330#define MWL8K_CMD_SET_RF_CHANNEL 0x010A
331#define MWL8K_CMD_SET_SLOT 0x0114
332#define MWL8K_CMD_MIMO_CONFIG 0x0125
333#define MWL8K_CMD_ENABLE_SNIFFER 0x0150
334#define MWL8K_CMD_SET_WMM_MODE 0x0123
335#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115
336#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111
337#define MWL8K_CMD_UPDATE_STADB 0x1123
338#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
339#define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129
340#define MWL8K_CMD_SET_AID 0x010d
341#define MWL8K_CMD_SET_RATE 0x0110
342#define MWL8K_CMD_USE_FIXED_RATE 0x0126
343#define MWL8K_CMD_RTS_THRESHOLD 0x0113
344#define MWL8K_CMD_ENCRYPTION 0x1122
345
346static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
347{
348#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\
349                    snprintf(buf, bufsize, "%s", #x);\
350                    return buf;\
351                    } while (0)
352    switch (cmd & (~0x8000)) {
353        MWL8K_CMDNAME(CODE_DNLD);
354        MWL8K_CMDNAME(GET_HW_SPEC);
355        MWL8K_CMDNAME(MAC_MULTICAST_ADR);
356        MWL8K_CMDNAME(GET_STAT);
357        MWL8K_CMDNAME(RADIO_CONTROL);
358        MWL8K_CMDNAME(RF_TX_POWER);
359        MWL8K_CMDNAME(SET_PRE_SCAN);
360        MWL8K_CMDNAME(SET_POST_SCAN);
361        MWL8K_CMDNAME(SET_RF_CHANNEL);
362        MWL8K_CMDNAME(SET_SLOT);
363        MWL8K_CMDNAME(MIMO_CONFIG);
364        MWL8K_CMDNAME(ENABLE_SNIFFER);
365        MWL8K_CMDNAME(SET_WMM_MODE);
366        MWL8K_CMDNAME(SET_EDCA_PARAMS);
367        MWL8K_CMDNAME(SET_FINALIZE_JOIN);
368        MWL8K_CMDNAME(UPDATE_STADB);
369        MWL8K_CMDNAME(SET_RATEADAPT_MODE);
370        MWL8K_CMDNAME(SET_LINKADAPT_MODE);
371        MWL8K_CMDNAME(SET_AID);
372        MWL8K_CMDNAME(SET_RATE);
373        MWL8K_CMDNAME(USE_FIXED_RATE);
374        MWL8K_CMDNAME(RTS_THRESHOLD);
375        MWL8K_CMDNAME(ENCRYPTION);
376    default:
377        snprintf(buf, bufsize, "0x%x", cmd);
378    }
379#undef MWL8K_CMDNAME
380
381    return buf;
382}
383
384/* Hardware and firmware reset */
385static void mwl8k_hw_reset(struct mwl8k_priv *priv)
386{
387    iowrite32(MWL8K_H2A_INT_RESET,
388        priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
389    iowrite32(MWL8K_H2A_INT_RESET,
390        priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
391    msleep(20);
392}
393
394/* Release fw image */
395static void mwl8k_release_fw(struct firmware **fw)
396{
397    if (*fw == NULL)
398        return;
399    release_firmware(*fw);
400    *fw = NULL;
401}
402
403static void mwl8k_release_firmware(struct mwl8k_priv *priv)
404{
405    mwl8k_release_fw(&priv->fw.ucode);
406    mwl8k_release_fw(&priv->fw.helper);
407}
408
409/* Request fw image */
410static int mwl8k_request_fw(struct mwl8k_priv *priv,
411                const char *fname, struct firmware **fw)
412{
413    /* release current image */
414    if (*fw != NULL)
415        mwl8k_release_fw(fw);
416
417    return request_firmware((const struct firmware **)fw,
418                        fname, &priv->pdev->dev);
419}
420
421static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num)
422{
423    u8 filename[64];
424    int rc;
425
426    priv->part_num = part_num;
427
428    snprintf(filename, sizeof(filename),
429         "mwl8k/helper_%u.fw", priv->part_num);
430
431    rc = mwl8k_request_fw(priv, filename, &priv->fw.helper);
432    if (rc) {
433        printk(KERN_ERR
434            "%s Error requesting helper firmware file %s\n",
435            pci_name(priv->pdev), filename);
436        return rc;
437    }
438
439    snprintf(filename, sizeof(filename),
440         "mwl8k/fmimage_%u.fw", priv->part_num);
441
442    rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode);
443    if (rc) {
444        printk(KERN_ERR "%s Error requesting firmware file %s\n",
445                    pci_name(priv->pdev), filename);
446        mwl8k_release_fw(&priv->fw.helper);
447        return rc;
448    }
449
450    return 0;
451}
452
453struct mwl8k_cmd_pkt {
454    __le16 code;
455    __le16 length;
456    __le16 seq_num;
457    __le16 result;
458    char payload[0];
459} __attribute__((packed));
460
461/*
462 * Firmware loading.
463 */
464static int
465mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
466{
467    void __iomem *regs = priv->regs;
468    dma_addr_t dma_addr;
469    int rc;
470    int loops;
471
472    dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE);
473    if (pci_dma_mapping_error(priv->pdev, dma_addr))
474        return -ENOMEM;
475
476    iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
477    iowrite32(0, regs + MWL8K_HIU_INT_CODE);
478    iowrite32(MWL8K_H2A_INT_DOORBELL,
479        regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
480    iowrite32(MWL8K_H2A_INT_DUMMY,
481        regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
482
483    rc = -ETIMEDOUT;
484    loops = 1000;
485    do {
486        u32 int_code;
487
488        int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
489        if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
490            iowrite32(0, regs + MWL8K_HIU_INT_CODE);
491            rc = 0;
492            break;
493        }
494
495        udelay(1);
496    } while (--loops);
497
498    pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE);
499
500    /*
501     * Clear 'command done' interrupt bit.
502     */
503    loops = 1000;
504    do {
505        u32 status;
506
507        status = ioread32(priv->regs +
508                MWL8K_HIU_A2H_INTERRUPT_STATUS);
509        if (status & MWL8K_A2H_INT_OPC_DONE) {
510            iowrite32(~MWL8K_A2H_INT_OPC_DONE,
511                priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
512            ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
513            break;
514        }
515
516        udelay(1);
517    } while (--loops);
518
519    return rc;
520}
521
522static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
523                const u8 *data, size_t length)
524{
525    struct mwl8k_cmd_pkt *cmd;
526    int done;
527    int rc = 0;
528
529    cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL);
530    if (cmd == NULL)
531        return -ENOMEM;
532
533    cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD);
534    cmd->seq_num = 0;
535    cmd->result = 0;
536
537    done = 0;
538    while (length) {
539        int block_size = length > 256 ? 256 : length;
540
541        memcpy(cmd->payload, data + done, block_size);
542        cmd->length = cpu_to_le16(block_size);
543
544        rc = mwl8k_send_fw_load_cmd(priv, cmd,
545                        sizeof(*cmd) + block_size);
546        if (rc)
547            break;
548
549        done += block_size;
550        length -= block_size;
551    }
552
553    if (!rc) {
554        cmd->length = 0;
555        rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd));
556    }
557
558    kfree(cmd);
559
560    return rc;
561}
562
563static int mwl8k_feed_fw_image(struct mwl8k_priv *priv,
564                const u8 *data, size_t length)
565{
566    unsigned char *buffer;
567    int may_continue, rc = 0;
568    u32 done, prev_block_size;
569
570    buffer = kmalloc(1024, GFP_KERNEL);
571    if (buffer == NULL)
572        return -ENOMEM;
573
574    done = 0;
575    prev_block_size = 0;
576    may_continue = 1000;
577    while (may_continue > 0) {
578        u32 block_size;
579
580        block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH);
581        if (block_size & 1) {
582            block_size &= ~1;
583            may_continue--;
584        } else {
585            done += prev_block_size;
586            length -= prev_block_size;
587        }
588
589        if (block_size > 1024 || block_size > length) {
590            rc = -EOVERFLOW;
591            break;
592        }
593
594        if (length == 0) {
595            rc = 0;
596            break;
597        }
598
599        if (block_size == 0) {
600            rc = -EPROTO;
601            may_continue--;
602            udelay(1);
603            continue;
604        }
605
606        prev_block_size = block_size;
607        memcpy(buffer, data + done, block_size);
608
609        rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size);
610        if (rc)
611            break;
612    }
613
614    if (!rc && length != 0)
615        rc = -EREMOTEIO;
616
617    kfree(buffer);
618
619    return rc;
620}
621
622static int mwl8k_load_firmware(struct mwl8k_priv *priv)
623{
624    int loops, rc;
625
626    const u8 *ucode = priv->fw.ucode->data;
627    size_t ucode_len = priv->fw.ucode->size;
628    const u8 *helper = priv->fw.helper->data;
629    size_t helper_len = priv->fw.helper->size;
630
631    if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) {
632        rc = mwl8k_load_fw_image(priv, helper, helper_len);
633        if (rc) {
634            printk(KERN_ERR "%s: unable to load firmware "
635                "helper image\n", pci_name(priv->pdev));
636            return rc;
637        }
638        msleep(1);
639
640        rc = mwl8k_feed_fw_image(priv, ucode, ucode_len);
641    } else {
642        rc = mwl8k_load_fw_image(priv, ucode, ucode_len);
643    }
644
645    if (rc) {
646        printk(KERN_ERR "%s: unable to load firmware data\n",
647            pci_name(priv->pdev));
648        return rc;
649    }
650
651    iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
652    msleep(1);
653
654    loops = 200000;
655    do {
656        if (ioread32(priv->regs + MWL8K_HIU_INT_CODE)
657                        == MWL8K_FWSTA_READY)
658            break;
659        udelay(1);
660    } while (--loops);
661
662    return loops ? 0 : -ETIMEDOUT;
663}
664
665
666/*
667 * Defines shared between transmission and reception.
668 */
669/* HT control fields for firmware */
670struct ewc_ht_info {
671    __le16 control1;
672    __le16 control2;
673    __le16 control3;
674} __attribute__((packed));
675
676/* Firmware Station database operations */
677#define MWL8K_STA_DB_ADD_ENTRY 0
678#define MWL8K_STA_DB_MODIFY_ENTRY 1
679#define MWL8K_STA_DB_DEL_ENTRY 2
680#define MWL8K_STA_DB_FLUSH 3
681
682/* Peer Entry flags - used to define the type of the peer node */
683#define MWL8K_PEER_TYPE_ACCESSPOINT 2
684#define MWL8K_PEER_TYPE_ADHOC_STATION 4
685
686#define MWL8K_IEEE_LEGACY_DATA_RATES 12
687#define MWL8K_MCS_BITMAP_SIZE 16
688#define pad_size 16
689
690struct peer_capability_info {
691    /* Peer type - AP vs. STA. */
692    __u8 peer_type;
693
694    /* Basic 802.11 capabilities from assoc resp. */
695    __le16 basic_caps;
696
697    /* Set if peer supports 802.11n high throughput (HT). */
698    __u8 ht_support;
699
700    /* Valid if HT is supported. */
701    __le16 ht_caps;
702    __u8 extended_ht_caps;
703    struct ewc_ht_info ewc_info;
704
705    /* Legacy rate table. Intersection of our rates and peer rates. */
706    __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES];
707
708    /* HT rate table. Intersection of our rates and peer rates. */
709    __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE];
710    __u8 pad[pad_size];
711
712    /* If set, interoperability mode, no proprietary extensions. */
713    __u8 interop;
714    __u8 pad2;
715    __u8 station_id;
716    __le16 amsdu_enabled;
717} __attribute__((packed));
718
719/* Inline functions to manipulate QoS field in data descriptor. */
720static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid)
721{
722    u16 val_mask = 0x000f;
723    u16 qos_mask = ~val_mask;
724
725    /* TID bits 0-3 */
726    return (qos & qos_mask) | (tid & val_mask);
727}
728
729static inline u16 mwl8k_qos_setbit_eosp(u16 qos)
730{
731    u16 val_mask = 1 << 4;
732
733    /* End of Service Period Bit 4 */
734    return qos | val_mask;
735}
736
737static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy)
738{
739    u16 val_mask = 0x3;
740    u8 shift = 5;
741    u16 qos_mask = ~(val_mask << shift);
742
743    /* Ack Policy Bit 5-6 */
744    return (qos & qos_mask) | ((ack_policy & val_mask) << shift);
745}
746
747static inline u16 mwl8k_qos_setbit_amsdu(u16 qos)
748{
749    u16 val_mask = 1 << 7;
750
751    /* AMSDU present Bit 7 */
752    return qos | val_mask;
753}
754
755static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len)
756{
757    u16 val_mask = 0xff;
758    u8 shift = 8;
759    u16 qos_mask = ~(val_mask << shift);
760
761    /* Queue Length Bits 8-15 */
762    return (qos & qos_mask) | ((len & val_mask) << shift);
763}
764
765/* DMA header used by firmware and hardware. */
766struct mwl8k_dma_data {
767    __le16 fwlen;
768    struct ieee80211_hdr wh;
769} __attribute__((packed));
770
771/* Routines to add/remove DMA header from skb. */
772static inline int mwl8k_remove_dma_header(struct sk_buff *skb)
773{
774    struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data);
775    void *dst, *src = &tr->wh;
776    __le16 fc = tr->wh.frame_control;
777    int hdrlen = ieee80211_hdrlen(fc);
778    u16 space = sizeof(struct mwl8k_dma_data) - hdrlen;
779
780    dst = (void *)tr + space;
781    if (dst != src) {
782        memmove(dst, src, hdrlen);
783        skb_pull(skb, space);
784    }
785
786    return 0;
787}
788
789static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb)
790{
791    struct ieee80211_hdr *wh;
792    u32 hdrlen, pktlen;
793    struct mwl8k_dma_data *tr;
794
795    wh = (struct ieee80211_hdr *)skb->data;
796    hdrlen = ieee80211_hdrlen(wh->frame_control);
797    pktlen = skb->len;
798
799    /*
800     * Copy up/down the 802.11 header; the firmware requires
801     * we present a 2-byte payload length followed by a
802     * 4-address header (w/o QoS), followed (optionally) by
803     * any WEP/ExtIV header (but only filled in for CCMP).
804     */
805    if (hdrlen != sizeof(struct mwl8k_dma_data))
806        skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen);
807
808    tr = (struct mwl8k_dma_data *)skb->data;
809    if (wh != &tr->wh)
810        memmove(&tr->wh, wh, hdrlen);
811
812    /* Clear addr4 */
813    memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN);
814
815    /*
816     * Firmware length is the length of the fully formed "802.11
817     * payload". That is, everything except for the 802.11 header.
818     * This includes all crypto material including the MIC.
819     */
820    tr->fwlen = cpu_to_le16(pktlen - hdrlen);
821
822    return skb;
823}
824
825
826/*
827 * Packet reception.
828 */
829#define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30
830#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02
831#define MWL8K_RX_CTRL_AMPDU 0x01
832
833struct mwl8k_rx_desc {
834    __le16 pkt_len;
835    __u8 link_quality;
836    __u8 noise_level;
837    __le32 pkt_phys_addr;
838    __le32 next_rx_desc_phys_addr;
839    __le16 qos_control;
840    __le16 rate_info;
841    __le32 pad0[4];
842    __u8 rssi;
843    __u8 channel;
844    __le16 pad1;
845    __u8 rx_ctrl;
846    __u8 rx_status;
847    __u8 pad2[2];
848} __attribute__((packed));
849
850#define MWL8K_RX_DESCS 256
851#define MWL8K_RX_MAXSZ 3800
852
853static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
854{
855    struct mwl8k_priv *priv = hw->priv;
856    struct mwl8k_rx_queue *rxq = priv->rxq + index;
857    int size;
858    int i;
859
860    rxq->rx_desc_count = 0;
861    rxq->rx_head = 0;
862    rxq->rx_tail = 0;
863
864    size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc);
865
866    rxq->rx_desc_area =
867        pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma);
868    if (rxq->rx_desc_area == NULL) {
869        printk(KERN_ERR "%s: failed to alloc RX descriptors\n",
870               priv->name);
871        return -ENOMEM;
872    }
873    memset(rxq->rx_desc_area, 0, size);
874
875    rxq->rx_skb = kmalloc(MWL8K_RX_DESCS *
876                sizeof(*rxq->rx_skb), GFP_KERNEL);
877    if (rxq->rx_skb == NULL) {
878        printk(KERN_ERR "%s: failed to alloc RX skbuff list\n",
879            priv->name);
880        pci_free_consistent(priv->pdev, size,
881                    rxq->rx_desc_area, rxq->rx_desc_dma);
882        return -ENOMEM;
883    }
884    memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb));
885
886    for (i = 0; i < MWL8K_RX_DESCS; i++) {
887        struct mwl8k_rx_desc *rx_desc;
888        int nexti;
889
890        rx_desc = rxq->rx_desc_area + i;
891        nexti = (i + 1) % MWL8K_RX_DESCS;
892
893        rx_desc->next_rx_desc_phys_addr =
894            cpu_to_le32(rxq->rx_desc_dma
895                        + nexti * sizeof(*rx_desc));
896        rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST;
897    }
898
899    return 0;
900}
901
902static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
903{
904    struct mwl8k_priv *priv = hw->priv;
905    struct mwl8k_rx_queue *rxq = priv->rxq + index;
906    int refilled;
907
908    refilled = 0;
909    while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) {
910        struct sk_buff *skb;
911        int rx;
912
913        skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
914        if (skb == NULL)
915            break;
916
917        rxq->rx_desc_count++;
918
919        rx = rxq->rx_tail;
920        rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS;
921
922        rxq->rx_desc_area[rx].pkt_phys_addr =
923            cpu_to_le32(pci_map_single(priv->pdev, skb->data,
924                    MWL8K_RX_MAXSZ, DMA_FROM_DEVICE));
925
926        rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ);
927        rxq->rx_skb[rx] = skb;
928        wmb();
929        rxq->rx_desc_area[rx].rx_ctrl = 0;
930
931        refilled++;
932    }
933
934    return refilled;
935}
936
937/* Must be called only when the card's reception is completely halted */
938static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
939{
940    struct mwl8k_priv *priv = hw->priv;
941    struct mwl8k_rx_queue *rxq = priv->rxq + index;
942    int i;
943
944    for (i = 0; i < MWL8K_RX_DESCS; i++) {
945        if (rxq->rx_skb[i] != NULL) {
946            unsigned long addr;
947
948            addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr);
949            pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ,
950                     PCI_DMA_FROMDEVICE);
951            kfree_skb(rxq->rx_skb[i]);
952            rxq->rx_skb[i] = NULL;
953        }
954    }
955
956    kfree(rxq->rx_skb);
957    rxq->rx_skb = NULL;
958
959    pci_free_consistent(priv->pdev,
960                MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc),
961                rxq->rx_desc_area, rxq->rx_desc_dma);
962    rxq->rx_desc_area = NULL;
963}
964
965
966/*
967 * Scan a list of BSSIDs to process for finalize join.
968 * Allows for extension to process multiple BSSIDs.
969 */
970static inline int
971mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh)
972{
973    return priv->capture_beacon &&
974        ieee80211_is_beacon(wh->frame_control) &&
975        !compare_ether_addr(wh->addr3, priv->capture_bssid);
976}
977
978static inline void mwl8k_save_beacon(struct mwl8k_priv *priv,
979                            struct sk_buff *skb)
980{
981    priv->capture_beacon = false;
982    memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN);
983
984    /*
985     * Use GFP_ATOMIC as rxq_process is called from
986     * the primary interrupt handler, memory allocation call
987     * must not sleep.
988     */
989    priv->beacon_skb = skb_copy(skb, GFP_ATOMIC);
990    if (priv->beacon_skb != NULL)
991        queue_work(priv->config_wq,
992                &priv->finalize_join_worker);
993}
994
995static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
996{
997    struct mwl8k_priv *priv = hw->priv;
998    struct mwl8k_rx_queue *rxq = priv->rxq + index;
999    int processed;
1000
1001    processed = 0;
1002    while (rxq->rx_desc_count && limit--) {
1003        struct mwl8k_rx_desc *rx_desc;
1004        struct sk_buff *skb;
1005        struct ieee80211_rx_status status;
1006        unsigned long addr;
1007        struct ieee80211_hdr *wh;
1008
1009        rx_desc = rxq->rx_desc_area + rxq->rx_head;
1010        if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST))
1011            break;
1012        rmb();
1013
1014        skb = rxq->rx_skb[rxq->rx_head];
1015        if (skb == NULL)
1016            break;
1017        rxq->rx_skb[rxq->rx_head] = NULL;
1018
1019        rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS;
1020        rxq->rx_desc_count--;
1021
1022        addr = le32_to_cpu(rx_desc->pkt_phys_addr);
1023        pci_unmap_single(priv->pdev, addr,
1024                    MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
1025
1026        skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
1027        if (mwl8k_remove_dma_header(skb)) {
1028            dev_kfree_skb(skb);
1029            continue;
1030        }
1031
1032        wh = (struct ieee80211_hdr *)skb->data;
1033
1034        /*
1035         * Check for pending join operation. save a copy of
1036         * the beacon and schedule a tasklet to send finalize
1037         * join command to the firmware.
1038         */
1039        if (mwl8k_capture_bssid(priv, wh))
1040            mwl8k_save_beacon(priv, skb);
1041
1042        memset(&status, 0, sizeof(status));
1043        status.mactime = 0;
1044        status.signal = -rx_desc->rssi;
1045        status.noise = -rx_desc->noise_level;
1046        status.qual = rx_desc->link_quality;
1047        status.antenna = 1;
1048        status.rate_idx = 1;
1049        status.flag = 0;
1050        status.band = IEEE80211_BAND_2GHZ;
1051        status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
1052        ieee80211_rx_irqsafe(hw, skb, &status);
1053
1054        processed++;
1055    }
1056
1057    return processed;
1058}
1059
1060
1061/*
1062 * Packet transmission.
1063 */
1064
1065/* Transmit queue assignment. */
1066enum {
1067    MWL8K_WME_AC_BK = 0, /* background access */
1068    MWL8K_WME_AC_BE = 1, /* best effort access */
1069    MWL8K_WME_AC_VI = 2, /* video access */
1070    MWL8K_WME_AC_VO = 3, /* voice access */
1071};
1072
1073/* Transmit packet ACK policy */
1074#define MWL8K_TXD_ACK_POLICY_NORMAL 0
1075#define MWL8K_TXD_ACK_POLICY_NONE 1
1076#define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2
1077#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3
1078
1079#define GET_TXQ(_ac) (\
1080        ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \
1081        ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \
1082        ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \
1083        MWL8K_WME_AC_BE)
1084
1085#define MWL8K_TXD_STATUS_IDLE 0x00000000
1086#define MWL8K_TXD_STATUS_USED 0x00000001
1087#define MWL8K_TXD_STATUS_OK 0x00000001
1088#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
1089#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
1090#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008
1091#define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010
1092#define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020
1093#define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040
1094#define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080
1095#define MWL8K_TXD_STATUS_HOST_CMD 0x40000000
1096#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000
1097#define MWL8K_TXD_SOFTSTALE 0x80
1098#define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01
1099
1100struct mwl8k_tx_desc {
1101    __le32 status;
1102    __u8 data_rate;
1103    __u8 tx_priority;
1104    __le16 qos_control;
1105    __le32 pkt_phys_addr;
1106    __le16 pkt_len;
1107    __u8 dest_MAC_addr[IEEE80211_ADDR_LEN];
1108    __le32 next_tx_desc_phys_addr;
1109    __le32 reserved;
1110    __le16 rate_info;
1111    __u8 peer_id;
1112    __u8 tx_frag_cnt;
1113} __attribute__((packed));
1114
1115#define MWL8K_TX_DESCS 128
1116
1117static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
1118{
1119    struct mwl8k_priv *priv = hw->priv;
1120    struct mwl8k_tx_queue *txq = priv->txq + index;
1121    int size;
1122    int i;
1123
1124    memset(&txq->tx_stats, 0,
1125        sizeof(struct ieee80211_tx_queue_stats));
1126    txq->tx_stats.limit = MWL8K_TX_DESCS;
1127    txq->tx_head = 0;
1128    txq->tx_tail = 0;
1129
1130    size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
1131
1132    txq->tx_desc_area =
1133        pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma);
1134    if (txq->tx_desc_area == NULL) {
1135        printk(KERN_ERR "%s: failed to alloc TX descriptors\n",
1136               priv->name);
1137        return -ENOMEM;
1138    }
1139    memset(txq->tx_desc_area, 0, size);
1140
1141    txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb),
1142                                GFP_KERNEL);
1143    if (txq->tx_skb == NULL) {
1144        printk(KERN_ERR "%s: failed to alloc TX skbuff list\n",
1145               priv->name);
1146        pci_free_consistent(priv->pdev, size,
1147                    txq->tx_desc_area, txq->tx_desc_dma);
1148        return -ENOMEM;
1149    }
1150    memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb));
1151
1152    for (i = 0; i < MWL8K_TX_DESCS; i++) {
1153        struct mwl8k_tx_desc *tx_desc;
1154        int nexti;
1155
1156        tx_desc = txq->tx_desc_area + i;
1157        nexti = (i + 1) % MWL8K_TX_DESCS;
1158
1159        tx_desc->status = 0;
1160        tx_desc->next_tx_desc_phys_addr =
1161            cpu_to_le32(txq->tx_desc_dma +
1162                        nexti * sizeof(*tx_desc));
1163    }
1164
1165    return 0;
1166}
1167
1168static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
1169{
1170    iowrite32(MWL8K_H2A_INT_PPA_READY,
1171        priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1172    iowrite32(MWL8K_H2A_INT_DUMMY,
1173        priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1174    ioread32(priv->regs + MWL8K_HIU_INT_CODE);
1175}
1176
1177static inline int mwl8k_txq_busy(struct mwl8k_priv *priv)
1178{
1179    return priv->pending_tx_pkts;
1180}
1181
1182struct mwl8k_txq_info {
1183    u32 fw_owned;
1184    u32 drv_owned;
1185    u32 unused;
1186    u32 len;
1187    u32 head;
1188    u32 tail;
1189};
1190
1191static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
1192                struct mwl8k_txq_info txinfo[],
1193                u32 num_queues)
1194{
1195    int count, desc, status;
1196    struct mwl8k_tx_queue *txq;
1197    struct mwl8k_tx_desc *tx_desc;
1198    int ndescs = 0;
1199
1200    memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info));
1201    spin_lock_bh(&priv->tx_lock);
1202    for (count = 0; count < num_queues; count++) {
1203        txq = priv->txq + count;
1204        txinfo[count].len = txq->tx_stats.len;
1205        txinfo[count].head = txq->tx_head;
1206        txinfo[count].tail = txq->tx_tail;
1207        for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
1208            tx_desc = txq->tx_desc_area + desc;
1209            status = le32_to_cpu(tx_desc->status);
1210
1211            if (status & MWL8K_TXD_STATUS_FW_OWNED)
1212                txinfo[count].fw_owned++;
1213            else
1214                txinfo[count].drv_owned++;
1215
1216            if (tx_desc->pkt_len == 0)
1217                txinfo[count].unused++;
1218        }
1219    }
1220    spin_unlock_bh(&priv->tx_lock);
1221
1222    return ndescs;
1223}
1224
1225static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms)
1226{
1227    u32 count = 0;
1228    unsigned long timeout = 0;
1229    struct mwl8k_priv *priv = hw->priv;
1230    DECLARE_COMPLETION_ONSTACK(cmd_wait);
1231
1232    might_sleep();
1233
1234    if (priv->tx_wait != NULL)
1235        printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n");
1236
1237    spin_lock_bh(&priv->tx_lock);
1238    count = mwl8k_txq_busy(priv);
1239    if (count) {
1240        priv->tx_wait = &cmd_wait;
1241        if (priv->radio_state)
1242            mwl8k_tx_start(priv);
1243    }
1244    spin_unlock_bh(&priv->tx_lock);
1245
1246    if (count) {
1247        struct mwl8k_txq_info txinfo[4];
1248        int index;
1249        int newcount;
1250
1251        timeout = wait_for_completion_timeout(&cmd_wait,
1252                    msecs_to_jiffies(delay_ms));
1253        if (timeout)
1254            return 0;
1255
1256        spin_lock_bh(&priv->tx_lock);
1257        priv->tx_wait = NULL;
1258        newcount = mwl8k_txq_busy(priv);
1259        spin_unlock_bh(&priv->tx_lock);
1260
1261        printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n",
1262               __func__, __LINE__, delay_ms, count, newcount);
1263
1264        mwl8k_scan_tx_ring(priv, txinfo, 4);
1265        for (index = 0 ; index < 4; index++)
1266            printk(KERN_ERR
1267                "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
1268                    index,
1269                    txinfo[index].len,
1270                    txinfo[index].head,
1271                    txinfo[index].tail,
1272                    txinfo[index].fw_owned,
1273                    txinfo[index].drv_owned,
1274                    txinfo[index].unused);
1275        return -ETIMEDOUT;
1276    }
1277
1278    return 0;
1279}
1280
1281#define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \
1282             MWL8K_TXD_STATUS_OK_RETRY | \
1283             MWL8K_TXD_STATUS_OK_MORE_RETRY)
1284#define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK)
1285#define MWL8K_TXD_FAIL_RETRY(stat) \
1286    ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT))
1287
1288static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
1289{
1290    struct mwl8k_priv *priv = hw->priv;
1291    struct mwl8k_tx_queue *txq = priv->txq + index;
1292    int wake = 0;
1293
1294    while (txq->tx_stats.len > 0) {
1295        int tx;
1296        int rc;
1297        struct mwl8k_tx_desc *tx_desc;
1298        unsigned long addr;
1299        size_t size;
1300        struct sk_buff *skb;
1301        struct ieee80211_tx_info *info;
1302        u32 status;
1303
1304        rc = 0;
1305        tx = txq->tx_head;
1306        tx_desc = txq->tx_desc_area + tx;
1307
1308        status = le32_to_cpu(tx_desc->status);
1309
1310        if (status & MWL8K_TXD_STATUS_FW_OWNED) {
1311            if (!force)
1312                break;
1313            tx_desc->status &=
1314                ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED);
1315        }
1316
1317        txq->tx_head = (tx + 1) % MWL8K_TX_DESCS;
1318        BUG_ON(txq->tx_stats.len == 0);
1319        txq->tx_stats.len--;
1320        priv->pending_tx_pkts--;
1321
1322        addr = le32_to_cpu(tx_desc->pkt_phys_addr);
1323        size = (u32)(le16_to_cpu(tx_desc->pkt_len));
1324        skb = txq->tx_skb[tx].skb;
1325        txq->tx_skb[tx].skb = NULL;
1326
1327        BUG_ON(skb == NULL);
1328        pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
1329
1330        rc = mwl8k_remove_dma_header(skb);
1331
1332        /* Mark descriptor as unused */
1333        tx_desc->pkt_phys_addr = 0;
1334        tx_desc->pkt_len = 0;
1335
1336        if (txq->tx_skb[tx].clone) {
1337            /* Replace with original skb
1338             * before returning to stack
1339             * as buffer has been cloned
1340             */
1341            dev_kfree_skb(skb);
1342            skb = txq->tx_skb[tx].clone;
1343            txq->tx_skb[tx].clone = NULL;
1344        }
1345
1346        if (rc) {
1347            /* Something has gone wrong here.
1348             * Failed to remove DMA header.
1349             * Print error message and drop packet.
1350             */
1351            printk(KERN_ERR "%s: Error removing DMA header from "
1352                    "tx skb 0x%p.\n", priv->name, skb);
1353
1354            dev_kfree_skb(skb);
1355            continue;
1356        }
1357
1358        info = IEEE80211_SKB_CB(skb);
1359        ieee80211_tx_info_clear_status(info);
1360
1361        /* Convert firmware status stuff into tx_status */
1362        if (MWL8K_TXD_SUCCESS(status)) {
1363            /* Transmit OK */
1364            info->flags |= IEEE80211_TX_STAT_ACK;
1365        }
1366
1367        ieee80211_tx_status_irqsafe(hw, skb);
1368
1369        wake = !priv->inconfig && priv->radio_state;
1370    }
1371
1372    if (wake)
1373        ieee80211_wake_queue(hw, index);
1374}
1375
1376/* must be called only when the card's transmit is completely halted */
1377static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
1378{
1379    struct mwl8k_priv *priv = hw->priv;
1380    struct mwl8k_tx_queue *txq = priv->txq + index;
1381
1382    mwl8k_txq_reclaim(hw, index, 1);
1383
1384    kfree(txq->tx_skb);
1385    txq->tx_skb = NULL;
1386
1387    pci_free_consistent(priv->pdev,
1388                MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc),
1389                txq->tx_desc_area, txq->tx_desc_dma);
1390    txq->tx_desc_area = NULL;
1391}
1392
1393static int
1394mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1395{
1396    struct mwl8k_priv *priv = hw->priv;
1397    struct ieee80211_tx_info *tx_info;
1398    struct ieee80211_hdr *wh;
1399    struct mwl8k_tx_queue *txq;
1400    struct mwl8k_tx_desc *tx;
1401    struct mwl8k_dma_data *tr;
1402    struct mwl8k_vif *mwl8k_vif;
1403    struct sk_buff *org_skb = skb;
1404    dma_addr_t dma;
1405    u16 qos = 0;
1406    bool qosframe = false, ampduframe = false;
1407    bool mcframe = false, eapolframe = false;
1408    bool amsduframe = false;
1409    __le16 fc;
1410
1411    txq = priv->txq + index;
1412    tx = txq->tx_desc_area + txq->tx_tail;
1413
1414    BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL);
1415
1416    /*
1417     * Append HW DMA header to start of packet. Drop packet if
1418     * there is not enough space or a failure to unshare/unclone
1419     * the skb.
1420     */
1421    skb = mwl8k_add_dma_header(skb);
1422
1423    if (skb == NULL) {
1424        printk(KERN_DEBUG "%s: failed to prepend HW DMA "
1425            "header, dropping TX frame.\n", priv->name);
1426        dev_kfree_skb(org_skb);
1427        return NETDEV_TX_OK;
1428    }
1429
1430    tx_info = IEEE80211_SKB_CB(skb);
1431    mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
1432    tr = (struct mwl8k_dma_data *)skb->data;
1433    wh = &tr->wh;
1434    fc = wh->frame_control;
1435    qosframe = ieee80211_is_data_qos(fc);
1436    mcframe = is_multicast_ether_addr(wh->addr1);
1437    ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
1438
1439    if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
1440        u16 seqno = mwl8k_vif->seqno;
1441        wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
1442        wh->seq_ctrl |= cpu_to_le16(seqno << 4);
1443        mwl8k_vif->seqno = seqno++ % 4096;
1444    }
1445
1446    if (qosframe)
1447        qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
1448
1449    dma = pci_map_single(priv->pdev, skb->data,
1450                skb->len, PCI_DMA_TODEVICE);
1451
1452    if (pci_dma_mapping_error(priv->pdev, dma)) {
1453        printk(KERN_DEBUG "%s: failed to dma map skb, "
1454            "dropping TX frame.\n", priv->name);
1455
1456        if (org_skb != NULL)
1457            dev_kfree_skb(org_skb);
1458        if (skb != NULL)
1459            dev_kfree_skb(skb);
1460        return NETDEV_TX_OK;
1461    }
1462
1463    /* Set desc header, cpu bit order. */
1464    tx->status = 0;
1465    tx->data_rate = 0;
1466    tx->tx_priority = index;
1467    tx->qos_control = 0;
1468    tx->rate_info = 0;
1469    tx->peer_id = mwl8k_vif->peer_id;
1470
1471    amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT);
1472
1473    /* Setup firmware control bit fields for each frame type. */
1474    if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
1475        tx->data_rate = 0;
1476        qos = mwl8k_qos_setbit_eosp(qos);
1477        /* Set Queue size to unspecified */
1478        qos = mwl8k_qos_setbit_qlen(qos, 0xff);
1479    } else if (ieee80211_is_data(fc)) {
1480        tx->data_rate = 1;
1481        if (mcframe)
1482            tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX;
1483
1484        /*
1485         * Tell firmware to not send EAPOL pkts in an
1486         * aggregate. Verify against mac80211 tx path. If
1487         * stack turns off AMPDU for an EAPOL frame this
1488         * check will be removed.
1489         */
1490        if (eapolframe) {
1491            qos = mwl8k_qos_setbit_ack(qos,
1492                MWL8K_TXD_ACK_POLICY_NORMAL);
1493        } else {
1494            /* Send pkt in an aggregate if AMPDU frame. */
1495            if (ampduframe)
1496                qos = mwl8k_qos_setbit_ack(qos,
1497                    MWL8K_TXD_ACK_POLICY_BLOCKACK);
1498            else
1499                qos = mwl8k_qos_setbit_ack(qos,
1500                    MWL8K_TXD_ACK_POLICY_NORMAL);
1501
1502            if (amsduframe)
1503                qos = mwl8k_qos_setbit_amsdu(qos);
1504        }
1505    }
1506
1507    /* Convert to little endian */
1508    tx->qos_control = cpu_to_le16(qos);
1509    tx->status = cpu_to_le32(tx->status);
1510    tx->pkt_phys_addr = cpu_to_le32(dma);
1511    tx->pkt_len = cpu_to_le16(skb->len);
1512
1513    txq->tx_skb[txq->tx_tail].skb = skb;
1514    txq->tx_skb[txq->tx_tail].clone =
1515        skb == org_skb ? NULL : org_skb;
1516
1517    spin_lock_bh(&priv->tx_lock);
1518
1519    tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK |
1520                    MWL8K_TXD_STATUS_FW_OWNED);
1521    wmb();
1522    txq->tx_stats.len++;
1523    priv->pending_tx_pkts++;
1524    txq->tx_stats.count++;
1525    txq->tx_tail++;
1526
1527    if (txq->tx_tail == MWL8K_TX_DESCS)
1528        txq->tx_tail = 0;
1529    if (txq->tx_head == txq->tx_tail)
1530        ieee80211_stop_queue(hw, index);
1531
1532    if (priv->inconfig) {
1533        /*
1534         * Silently queue packet when we are in the middle of
1535         * a config cycle. Notify firmware only if we are
1536         * waiting for TXQs to empty. If a packet is sent
1537         * before .config() is complete, perhaps it is better
1538         * to drop the packet, as the channel is being changed
1539         * and the packet will end up on the wrong channel.
1540         */
1541        printk(KERN_ERR "%s(): WARNING TX activity while "
1542            "in config\n", __func__);
1543
1544        if (priv->tx_wait != NULL)
1545            mwl8k_tx_start(priv);
1546    } else
1547        mwl8k_tx_start(priv);
1548
1549    spin_unlock_bh(&priv->tx_lock);
1550
1551    return NETDEV_TX_OK;
1552}
1553
1554
1555/*
1556 * Command processing.
1557 */
1558
1559/* Timeout firmware commands after 2000ms */
1560#define MWL8K_CMD_TIMEOUT_MS 2000
1561
1562static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
1563{
1564    DECLARE_COMPLETION_ONSTACK(cmd_wait);
1565    struct mwl8k_priv *priv = hw->priv;
1566    void __iomem *regs = priv->regs;
1567    dma_addr_t dma_addr;
1568    unsigned int dma_size;
1569    int rc;
1570    u16 __iomem *result;
1571    unsigned long timeout = 0;
1572    u8 buf[32];
1573
1574    cmd->result = 0xFFFF;
1575    dma_size = le16_to_cpu(cmd->length);
1576    dma_addr = pci_map_single(priv->pdev, cmd, dma_size,
1577                  PCI_DMA_BIDIRECTIONAL);
1578    if (pci_dma_mapping_error(priv->pdev, dma_addr))
1579        return -ENOMEM;
1580
1581    if (priv->hostcmd_wait != NULL)
1582        printk(KERN_ERR "WARNING host command in progress\n");
1583
1584    spin_lock_irq(&priv->fw_lock);
1585    priv->hostcmd_wait = &cmd_wait;
1586    iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
1587    iowrite32(MWL8K_H2A_INT_DOORBELL,
1588        regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1589    iowrite32(MWL8K_H2A_INT_DUMMY,
1590        regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1591    spin_unlock_irq(&priv->fw_lock);
1592
1593    timeout = wait_for_completion_timeout(&cmd_wait,
1594                msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
1595
1596    pci_unmap_single(priv->pdev, dma_addr, dma_size,
1597                    PCI_DMA_BIDIRECTIONAL);
1598
1599    result = &cmd->result;
1600    if (!timeout) {
1601        spin_lock_irq(&priv->fw_lock);
1602        priv->hostcmd_wait = NULL;
1603        spin_unlock_irq(&priv->fw_lock);
1604        printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
1605               priv->name,
1606               mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1607               MWL8K_CMD_TIMEOUT_MS);
1608        rc = -ETIMEDOUT;
1609    } else {
1610        rc = *result ? -EINVAL : 0;
1611        if (rc)
1612            printk(KERN_ERR "%s: Command %s error 0x%x\n",
1613                   priv->name,
1614                   mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1615                   *result);
1616    }
1617
1618    return rc;
1619}
1620
1621/*
1622 * GET_HW_SPEC.
1623 */
1624struct mwl8k_cmd_get_hw_spec {
1625    struct mwl8k_cmd_pkt header;
1626    __u8 hw_rev;
1627    __u8 host_interface;
1628    __le16 num_mcaddrs;
1629    __u8 perm_addr[IEEE80211_ADDR_LEN];
1630    __le16 region_code;
1631    __le32 fw_rev;
1632    __le32 ps_cookie;
1633    __le32 caps;
1634    __u8 mcs_bitmap[16];
1635    __le32 rx_queue_ptr;
1636    __le32 num_tx_queues;
1637    __le32 tx_queue_ptrs[MWL8K_TX_QUEUES];
1638    __le32 caps2;
1639    __le32 num_tx_desc_per_queue;
1640    __le32 total_rx_desc;
1641} __attribute__((packed));
1642
1643static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
1644{
1645    struct mwl8k_priv *priv = hw->priv;
1646    struct mwl8k_cmd_get_hw_spec *cmd;
1647    int rc;
1648    int i;
1649
1650    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1651    if (cmd == NULL)
1652        return -ENOMEM;
1653
1654    cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
1655    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1656
1657    memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
1658    cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
1659    cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma);
1660    cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
1661    for (i = 0; i < MWL8K_TX_QUEUES; i++)
1662        cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma);
1663    cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
1664    cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS);
1665
1666    rc = mwl8k_post_cmd(hw, &cmd->header);
1667
1668    if (!rc) {
1669        SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
1670        priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
1671        priv->fw_rev = le32_to_cpu(cmd->fw_rev);
1672        priv->hw_rev = cmd->hw_rev;
1673        priv->region_code = le16_to_cpu(cmd->region_code);
1674    }
1675
1676    kfree(cmd);
1677    return rc;
1678}
1679
1680/*
1681 * CMD_MAC_MULTICAST_ADR.
1682 */
1683struct mwl8k_cmd_mac_multicast_adr {
1684    struct mwl8k_cmd_pkt header;
1685    __le16 action;
1686    __le16 numaddr;
1687    __u8 addr[1][IEEE80211_ADDR_LEN];
1688};
1689
1690#define MWL8K_ENABLE_RX_MULTICAST 0x000F
1691static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
1692                    int mc_count,
1693                    struct dev_addr_list *mclist)
1694{
1695    struct mwl8k_cmd_mac_multicast_adr *cmd;
1696    int index = 0;
1697    int rc;
1698    int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN);
1699    cmd = kzalloc(size, GFP_KERNEL);
1700    if (cmd == NULL)
1701        return -ENOMEM;
1702
1703    cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
1704    cmd->header.length = cpu_to_le16(size);
1705    cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
1706    cmd->numaddr = cpu_to_le16(mc_count);
1707    while ((index < mc_count) && mclist) {
1708        if (mclist->da_addrlen != IEEE80211_ADDR_LEN) {
1709            rc = -EINVAL;
1710            goto mwl8k_cmd_mac_multicast_adr_exit;
1711        }
1712        memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN);
1713        index++;
1714        mclist = mclist->next;
1715    }
1716
1717    rc = mwl8k_post_cmd(hw, &cmd->header);
1718
1719mwl8k_cmd_mac_multicast_adr_exit:
1720    kfree(cmd);
1721    return rc;
1722}
1723
1724/*
1725 * CMD_802_11_GET_STAT.
1726 */
1727struct mwl8k_cmd_802_11_get_stat {
1728    struct mwl8k_cmd_pkt header;
1729    __le16 action;
1730    __le32 stats[64];
1731} __attribute__((packed));
1732
1733#define MWL8K_STAT_ACK_FAILURE 9
1734#define MWL8K_STAT_RTS_FAILURE 12
1735#define MWL8K_STAT_FCS_ERROR 24
1736#define MWL8K_STAT_RTS_SUCCESS 11
1737
1738static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw,
1739                struct ieee80211_low_level_stats *stats)
1740{
1741    struct mwl8k_cmd_802_11_get_stat *cmd;
1742    int rc;
1743
1744    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1745    if (cmd == NULL)
1746        return -ENOMEM;
1747
1748    cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT);
1749    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1750    cmd->action = cpu_to_le16(MWL8K_CMD_GET);
1751
1752    rc = mwl8k_post_cmd(hw, &cmd->header);
1753    if (!rc) {
1754        stats->dot11ACKFailureCount =
1755            le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]);
1756        stats->dot11RTSFailureCount =
1757            le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]);
1758        stats->dot11FCSErrorCount =
1759            le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]);
1760        stats->dot11RTSSuccessCount =
1761            le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]);
1762    }
1763    kfree(cmd);
1764
1765    return rc;
1766}
1767
1768/*
1769 * CMD_802_11_RADIO_CONTROL.
1770 */
1771struct mwl8k_cmd_802_11_radio_control {
1772    struct mwl8k_cmd_pkt header;
1773    __le16 action;
1774    __le16 control;
1775    __le16 radio_on;
1776} __attribute__((packed));
1777
1778static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable)
1779{
1780    struct mwl8k_priv *priv = hw->priv;
1781    struct mwl8k_cmd_802_11_radio_control *cmd;
1782    int rc;
1783
1784    if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) &&
1785        !(enable & MWL8K_RADIO_FORCE))
1786        return 0;
1787
1788    enable &= MWL8K_RADIO_ENABLE;
1789
1790    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1791    if (cmd == NULL)
1792        return -ENOMEM;
1793
1794    cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL);
1795    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1796    cmd->action = cpu_to_le16(MWL8K_CMD_SET);
1797    cmd->control = cpu_to_le16(priv->radio_preamble);
1798    cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000);
1799
1800    rc = mwl8k_post_cmd(hw, &cmd->header);
1801    kfree(cmd);
1802
1803    if (!rc)
1804        priv->radio_state = enable;
1805
1806    return rc;
1807}
1808
1809static int
1810mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
1811{
1812    struct mwl8k_priv *priv;
1813
1814    if (hw == NULL || hw->priv == NULL)
1815        return -EINVAL;
1816    priv = hw->priv;
1817
1818    priv->radio_preamble = (short_preamble ?
1819        MWL8K_RADIO_SHORT_PREAMBLE :
1820        MWL8K_RADIO_LONG_PREAMBLE);
1821
1822    return mwl8k_cmd_802_11_radio_control(hw,
1823            MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE);
1824}
1825
1826/*
1827 * CMD_802_11_RF_TX_POWER.
1828 */
1829#define MWL8K_TX_POWER_LEVEL_TOTAL 8
1830
1831struct mwl8k_cmd_802_11_rf_tx_power {
1832    struct mwl8k_cmd_pkt header;
1833    __le16 action;
1834    __le16 support_level;
1835    __le16 current_level;
1836    __le16 reserved;
1837    __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
1838} __attribute__((packed));
1839
1840static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm)
1841{
1842    struct mwl8k_cmd_802_11_rf_tx_power *cmd;
1843    int rc;
1844
1845    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1846    if (cmd == NULL)
1847        return -ENOMEM;
1848
1849    cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER);
1850    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1851    cmd->action = cpu_to_le16(MWL8K_CMD_SET);
1852    cmd->support_level = cpu_to_le16(dBm);
1853
1854    rc = mwl8k_post_cmd(hw, &cmd->header);
1855    kfree(cmd);
1856
1857    return rc;
1858}
1859
1860/*
1861 * CMD_SET_PRE_SCAN.
1862 */
1863struct mwl8k_cmd_set_pre_scan {
1864    struct mwl8k_cmd_pkt header;
1865} __attribute__((packed));
1866
1867static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
1868{
1869    struct mwl8k_cmd_set_pre_scan *cmd;
1870    int rc;
1871
1872    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1873    if (cmd == NULL)
1874        return -ENOMEM;
1875
1876    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN);
1877    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1878
1879    rc = mwl8k_post_cmd(hw, &cmd->header);
1880    kfree(cmd);
1881
1882    return rc;
1883}
1884
1885/*
1886 * CMD_SET_POST_SCAN.
1887 */
1888struct mwl8k_cmd_set_post_scan {
1889    struct mwl8k_cmd_pkt header;
1890    __le32 isibss;
1891    __u8 bssid[IEEE80211_ADDR_LEN];
1892} __attribute__((packed));
1893
1894static int
1895mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN])
1896{
1897    struct mwl8k_cmd_set_post_scan *cmd;
1898    int rc;
1899
1900    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1901    if (cmd == NULL)
1902        return -ENOMEM;
1903
1904    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN);
1905    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1906    cmd->isibss = 0;
1907    memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN);
1908
1909    rc = mwl8k_post_cmd(hw, &cmd->header);
1910    kfree(cmd);
1911
1912    return rc;
1913}
1914
1915/*
1916 * CMD_SET_RF_CHANNEL.
1917 */
1918struct mwl8k_cmd_set_rf_channel {
1919    struct mwl8k_cmd_pkt header;
1920    __le16 action;
1921    __u8 current_channel;
1922    __le32 channel_flags;
1923} __attribute__((packed));
1924
1925static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
1926                    struct ieee80211_channel *channel)
1927{
1928    struct mwl8k_cmd_set_rf_channel *cmd;
1929    int rc;
1930
1931    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1932    if (cmd == NULL)
1933        return -ENOMEM;
1934
1935    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL);
1936    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1937    cmd->action = cpu_to_le16(MWL8K_CMD_SET);
1938    cmd->current_channel = channel->hw_value;
1939    if (channel->band == IEEE80211_BAND_2GHZ)
1940        cmd->channel_flags = cpu_to_le32(0x00000081);
1941    else
1942        cmd->channel_flags = cpu_to_le32(0x00000000);
1943
1944    rc = mwl8k_post_cmd(hw, &cmd->header);
1945    kfree(cmd);
1946
1947    return rc;
1948}
1949
1950/*
1951 * CMD_SET_SLOT.
1952 */
1953struct mwl8k_cmd_set_slot {
1954    struct mwl8k_cmd_pkt header;
1955    __le16 action;
1956    __u8 short_slot;
1957} __attribute__((packed));
1958
1959static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time)
1960{
1961    struct mwl8k_cmd_set_slot *cmd;
1962    int rc;
1963
1964    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1965    if (cmd == NULL)
1966        return -ENOMEM;
1967
1968    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
1969    cmd->header.length = cpu_to_le16(sizeof(*cmd));
1970    cmd->action = cpu_to_le16(MWL8K_CMD_SET);
1971    cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0;
1972
1973    rc = mwl8k_post_cmd(hw, &cmd->header);
1974    kfree(cmd);
1975
1976    return rc;
1977}
1978
1979/*
1980 * CMD_MIMO_CONFIG.
1981 */
1982struct mwl8k_cmd_mimo_config {
1983    struct mwl8k_cmd_pkt header;
1984    __le32 action;
1985    __u8 rx_antenna_map;
1986    __u8 tx_antenna_map;
1987} __attribute__((packed));
1988
1989static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
1990{
1991    struct mwl8k_cmd_mimo_config *cmd;
1992    int rc;
1993
1994    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1995    if (cmd == NULL)
1996        return -ENOMEM;
1997
1998    cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG);
1999    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2000    cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET);
2001    cmd->rx_antenna_map = rx;
2002    cmd->tx_antenna_map = tx;
2003
2004    rc = mwl8k_post_cmd(hw, &cmd->header);
2005    kfree(cmd);
2006
2007    return rc;
2008}
2009
2010/*
2011 * CMD_ENABLE_SNIFFER.
2012 */
2013struct mwl8k_cmd_enable_sniffer {
2014    struct mwl8k_cmd_pkt header;
2015    __le32 action;
2016} __attribute__((packed));
2017
2018static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
2019{
2020    struct mwl8k_cmd_enable_sniffer *cmd;
2021    int rc;
2022
2023    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2024    if (cmd == NULL)
2025        return -ENOMEM;
2026
2027    cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
2028    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2029    cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0;
2030
2031    rc = mwl8k_post_cmd(hw, &cmd->header);
2032    kfree(cmd);
2033
2034    return rc;
2035}
2036
2037/*
2038 * CMD_SET_RATE_ADAPT_MODE.
2039 */
2040struct mwl8k_cmd_set_rate_adapt_mode {
2041    struct mwl8k_cmd_pkt header;
2042    __le16 action;
2043    __le16 mode;
2044} __attribute__((packed));
2045
2046static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode)
2047{
2048    struct mwl8k_cmd_set_rate_adapt_mode *cmd;
2049    int rc;
2050
2051    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2052    if (cmd == NULL)
2053        return -ENOMEM;
2054
2055    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE);
2056    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2057    cmd->action = cpu_to_le16(MWL8K_CMD_SET);
2058    cmd->mode = cpu_to_le16(mode);
2059
2060    rc = mwl8k_post_cmd(hw, &cmd->header);
2061    kfree(cmd);
2062
2063    return rc;
2064}
2065
2066/*
2067 * CMD_SET_WMM_MODE.
2068 */
2069struct mwl8k_cmd_set_wmm {
2070    struct mwl8k_cmd_pkt header;
2071    __le16 action;
2072} __attribute__((packed));
2073
2074static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable)
2075{
2076    struct mwl8k_priv *priv = hw->priv;
2077    struct mwl8k_cmd_set_wmm *cmd;
2078    int rc;
2079
2080    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2081    if (cmd == NULL)
2082        return -ENOMEM;
2083
2084    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
2085    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2086    cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0;
2087
2088    rc = mwl8k_post_cmd(hw, &cmd->header);
2089    kfree(cmd);
2090
2091    if (!rc)
2092        priv->wmm_mode = enable;
2093
2094    return rc;
2095}
2096
2097/*
2098 * CMD_SET_RTS_THRESHOLD.
2099 */
2100struct mwl8k_cmd_rts_threshold {
2101    struct mwl8k_cmd_pkt header;
2102    __le16 action;
2103    __le16 threshold;
2104} __attribute__((packed));
2105
2106static int mwl8k_rts_threshold(struct ieee80211_hw *hw,
2107                   u16 action, u16 *threshold)
2108{
2109    struct mwl8k_cmd_rts_threshold *cmd;
2110    int rc;
2111
2112    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2113    if (cmd == NULL)
2114        return -ENOMEM;
2115
2116    cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD);
2117    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2118    cmd->action = cpu_to_le16(action);
2119    cmd->threshold = cpu_to_le16(*threshold);
2120
2121    rc = mwl8k_post_cmd(hw, &cmd->header);
2122    kfree(cmd);
2123
2124    return rc;
2125}
2126
2127/*
2128 * CMD_SET_EDCA_PARAMS.
2129 */
2130struct mwl8k_cmd_set_edca_params {
2131    struct mwl8k_cmd_pkt header;
2132
2133    /* See MWL8K_SET_EDCA_XXX below */
2134    __le16 action;
2135
2136    /* TX opportunity in units of 32 us */
2137    __le16 txop;
2138
2139    /* Log exponent of max contention period: 0...15*/
2140    __u8 log_cw_max;
2141
2142    /* Log exponent of min contention period: 0...15 */
2143    __u8 log_cw_min;
2144
2145    /* Adaptive interframe spacing in units of 32us */
2146    __u8 aifs;
2147
2148    /* TX queue to configure */
2149    __u8 txq;
2150} __attribute__((packed));
2151
2152#define MWL8K_GET_EDCA_ALL 0
2153#define MWL8K_SET_EDCA_CW 0x01
2154#define MWL8K_SET_EDCA_TXOP 0x02
2155#define MWL8K_SET_EDCA_AIFS 0x04
2156
2157#define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \
2158                 MWL8K_SET_EDCA_TXOP | \
2159                 MWL8K_SET_EDCA_AIFS)
2160
2161static int
2162mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
2163        __u16 cw_min, __u16 cw_max,
2164        __u8 aifs, __u16 txop)
2165{
2166    struct mwl8k_cmd_set_edca_params *cmd;
2167    u32 log_cw_min, log_cw_max;
2168    int rc;
2169
2170    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2171    if (cmd == NULL)
2172        return -ENOMEM;
2173
2174    log_cw_min = ilog2(cw_min+1);
2175    log_cw_max = ilog2(cw_max+1);
2176    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
2177    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2178
2179    cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
2180    cmd->txop = cpu_to_le16(txop);
2181    cmd->log_cw_max = (u8)log_cw_max;
2182    cmd->log_cw_min = (u8)log_cw_min;
2183    cmd->aifs = aifs;
2184    cmd->txq = qnum;
2185
2186    rc = mwl8k_post_cmd(hw, &cmd->header);
2187    kfree(cmd);
2188
2189    return rc;
2190}
2191
2192/*
2193 * CMD_FINALIZE_JOIN.
2194 */
2195
2196/* FJ beacon buffer size is compiled into the firmware. */
2197#define MWL8K_FJ_BEACON_MAXLEN 128
2198
2199struct mwl8k_cmd_finalize_join {
2200    struct mwl8k_cmd_pkt header;
2201    __le32 sleep_interval; /* Number of beacon periods to sleep */
2202    __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
2203} __attribute__((packed));
2204
2205static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
2206                __u16 framelen, __u16 dtim)
2207{
2208    struct mwl8k_cmd_finalize_join *cmd;
2209    struct ieee80211_mgmt *payload = frame;
2210    u16 hdrlen;
2211    u32 payload_len;
2212    int rc;
2213
2214    if (frame == NULL)
2215        return -EINVAL;
2216
2217    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2218    if (cmd == NULL)
2219        return -ENOMEM;
2220
2221    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
2222    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2223
2224    if (dtim)
2225        cmd->sleep_interval = cpu_to_le32(dtim);
2226    else
2227        cmd->sleep_interval = cpu_to_le32(1);
2228
2229    hdrlen = ieee80211_hdrlen(payload->frame_control);
2230
2231    payload_len = framelen > hdrlen ? framelen - hdrlen : 0;
2232
2233    /* XXX TBD Might just have to abort and return an error */
2234    if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
2235        printk(KERN_ERR "%s(): WARNING: Incomplete beacon "
2236            "sent to firmware. Sz=%u MAX=%u\n", __func__,
2237            payload_len, MWL8K_FJ_BEACON_MAXLEN);
2238
2239    payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ?
2240                MWL8K_FJ_BEACON_MAXLEN : payload_len;
2241
2242    if (payload && payload_len)
2243        memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
2244
2245    rc = mwl8k_post_cmd(hw, &cmd->header);
2246    kfree(cmd);
2247    return rc;
2248}
2249
2250/*
2251 * CMD_UPDATE_STADB.
2252 */
2253struct mwl8k_cmd_update_sta_db {
2254    struct mwl8k_cmd_pkt header;
2255
2256    /* See STADB_ACTION_TYPE */
2257    __le32 action;
2258
2259    /* Peer MAC address */
2260    __u8 peer_addr[IEEE80211_ADDR_LEN];
2261
2262    __le32 reserved;
2263
2264    /* Peer info - valid during add/update. */
2265    struct peer_capability_info peer_info;
2266} __attribute__((packed));
2267
2268static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw,
2269        struct ieee80211_vif *vif, __u32 action)
2270{
2271    struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2272    struct ieee80211_bss_conf *info = &mv_vif->bss_info;
2273    struct mwl8k_cmd_update_sta_db *cmd;
2274    struct peer_capability_info *peer_info;
2275    struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2276    DECLARE_MAC_BUF(mac);
2277    int rc;
2278    __u8 count, *rates;
2279
2280    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2281    if (cmd == NULL)
2282        return -ENOMEM;
2283
2284    cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
2285    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2286
2287    cmd->action = cpu_to_le32(action);
2288    peer_info = &cmd->peer_info;
2289    memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN);
2290
2291    switch (action) {
2292    case MWL8K_STA_DB_ADD_ENTRY:
2293    case MWL8K_STA_DB_MODIFY_ENTRY:
2294        /* Build peer_info block */
2295        peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
2296        peer_info->basic_caps = cpu_to_le16(info->assoc_capability);
2297        peer_info->interop = 1;
2298        peer_info->amsdu_enabled = 0;
2299
2300        rates = peer_info->legacy_rates;
2301        for (count = 0 ; count < mv_vif->legacy_nrates; count++)
2302            rates[count] = bitrates[count].hw_value;
2303
2304        rc = mwl8k_post_cmd(hw, &cmd->header);
2305        if (rc == 0)
2306            mv_vif->peer_id = peer_info->station_id;
2307
2308        break;
2309
2310    case MWL8K_STA_DB_DEL_ENTRY:
2311    case MWL8K_STA_DB_FLUSH:
2312    default:
2313        rc = mwl8k_post_cmd(hw, &cmd->header);
2314        if (rc == 0)
2315            mv_vif->peer_id = 0;
2316        break;
2317    }
2318    kfree(cmd);
2319
2320    return rc;
2321}
2322
2323/*
2324 * CMD_SET_AID.
2325 */
2326#define IEEE80211_OPMODE_DISABLED 0x00
2327#define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01
2328#define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02
2329#define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03
2330
2331#define MWL8K_RATE_INDEX_MAX_ARRAY 14
2332
2333#define MWL8K_FRAME_PROT_DISABLED 0x00
2334#define MWL8K_FRAME_PROT_11G 0x07
2335#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
2336#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
2337#define MWL8K_FRAME_PROT_MASK 0x07
2338
2339struct mwl8k_cmd_update_set_aid {
2340    struct mwl8k_cmd_pkt header;
2341    __le16 aid;
2342
2343     /* AP's MAC address (BSSID) */
2344    __u8 bssid[IEEE80211_ADDR_LEN];
2345    __le16 protection_mode;
2346    __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
2347} __attribute__((packed));
2348
2349static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2350                    struct ieee80211_vif *vif)
2351{
2352    struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2353    struct ieee80211_bss_conf *info = &mv_vif->bss_info;
2354    struct mwl8k_cmd_update_set_aid *cmd;
2355    struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2356    int count;
2357    u16 prot_mode;
2358    int rc;
2359
2360    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2361    if (cmd == NULL)
2362        return -ENOMEM;
2363
2364    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
2365    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2366    cmd->aid = cpu_to_le16(info->aid);
2367
2368    memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN);
2369
2370    prot_mode = MWL8K_FRAME_PROT_DISABLED;
2371
2372    if (info->use_cts_prot) {
2373        prot_mode = MWL8K_FRAME_PROT_11G;
2374    } else {
2375        switch (info->ht_operation_mode &
2376            IEEE80211_HT_OP_MODE_PROTECTION) {
2377        case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
2378            prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
2379            break;
2380        case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
2381            prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL;
2382            break;
2383        default:
2384            prot_mode = MWL8K_FRAME_PROT_DISABLED;
2385            break;
2386        }
2387    }
2388
2389    cmd->protection_mode = cpu_to_le16(prot_mode);
2390
2391    for (count = 0; count < mv_vif->legacy_nrates; count++)
2392        cmd->supp_rates[count] = bitrates[count].hw_value;
2393
2394    rc = mwl8k_post_cmd(hw, &cmd->header);
2395    kfree(cmd);
2396
2397    return rc;
2398}
2399
2400/*
2401 * CMD_SET_RATE.
2402 */
2403struct mwl8k_cmd_update_rateset {
2404    struct mwl8k_cmd_pkt header;
2405    __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY];
2406
2407    /* Bitmap for supported MCS codes. */
2408    __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES];
2409    __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES];
2410} __attribute__((packed));
2411
2412static int mwl8k_update_rateset(struct ieee80211_hw *hw,
2413        struct ieee80211_vif *vif)
2414{
2415    struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
2416    struct mwl8k_cmd_update_rateset *cmd;
2417    struct ieee80211_rate *bitrates = mv_vif->legacy_rates;
2418    int count;
2419    int rc;
2420
2421    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2422    if (cmd == NULL)
2423        return -ENOMEM;
2424
2425    cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
2426    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2427
2428    for (count = 0; count < mv_vif->legacy_nrates; count++)
2429        cmd->legacy_rates[count] = bitrates[count].hw_value;
2430
2431    rc = mwl8k_post_cmd(hw, &cmd->header);
2432    kfree(cmd);
2433
2434    return rc;
2435}
2436
2437/*
2438 * CMD_USE_FIXED_RATE.
2439 */
2440#define MWL8K_RATE_TABLE_SIZE 8
2441#define MWL8K_UCAST_RATE 0
2442#define MWL8K_MCAST_RATE 1
2443#define MWL8K_BCAST_RATE 2
2444
2445#define MWL8K_USE_FIXED_RATE 0x0001
2446#define MWL8K_USE_AUTO_RATE 0x0002
2447
2448struct mwl8k_rate_entry {
2449    /* Set to 1 if HT rate, 0 if legacy. */
2450    __le32 is_ht_rate;
2451
2452    /* Set to 1 to use retry_count field. */
2453    __le32 enable_retry;
2454
2455    /* Specified legacy rate or MCS. */
2456    __le32 rate;
2457
2458    /* Number of allowed retries. */
2459    __le32 retry_count;
2460} __attribute__((packed));
2461
2462struct mwl8k_rate_table {
2463    /* 1 to allow specified rate and below */
2464    __le32 allow_rate_drop;
2465    __le32 num_rates;
2466    struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE];
2467} __attribute__((packed));
2468
2469struct mwl8k_cmd_use_fixed_rate {
2470    struct mwl8k_cmd_pkt header;
2471    __le32 action;
2472    struct mwl8k_rate_table rate_table;
2473
2474    /* Unicast, Broadcast or Multicast */
2475    __le32 rate_type;
2476    __le32 reserved1;
2477    __le32 reserved2;
2478} __attribute__((packed));
2479
2480static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw,
2481    u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table)
2482{
2483    struct mwl8k_cmd_use_fixed_rate *cmd;
2484    int count;
2485    int rc;
2486
2487    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2488    if (cmd == NULL)
2489        return -ENOMEM;
2490
2491    cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
2492    cmd->header.length = cpu_to_le16(sizeof(*cmd));
2493
2494    cmd->action = cpu_to_le32(action);
2495    cmd->rate_type = cpu_to_le32(rate_type);
2496
2497    if (rate_table != NULL) {
2498        /* Copy over each field manually so
2499        * that bitflipping can be done
2500        */
2501        cmd->rate_table.allow_rate_drop =
2502                cpu_to_le32(rate_table->allow_rate_drop);
2503        cmd->rate_table.num_rates =
2504                cpu_to_le32(rate_table->num_rates);
2505
2506        for (count = 0; count < rate_table->num_rates; count++) {
2507            struct mwl8k_rate_entry *dst =
2508                &cmd->rate_table.rate_entry[count];
2509            struct mwl8k_rate_entry *src =
2510                &rate_table->rate_entry[count];
2511
2512            dst->is_ht_rate = cpu_to_le32(src->is_ht_rate);
2513            dst->enable_retry = cpu_to_le32(src->enable_retry);
2514            dst->rate = cpu_to_le32(src->rate);
2515            dst->retry_count = cpu_to_le32(src->retry_count);
2516        }
2517    }
2518
2519    rc = mwl8k_post_cmd(hw, &cmd->header);
2520    kfree(cmd);
2521
2522    return rc;
2523}
2524
2525
2526/*
2527 * Interrupt handling.
2528 */
2529static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
2530{
2531    struct ieee80211_hw *hw = dev_id;
2532    struct mwl8k_priv *priv = hw->priv;
2533    u32 status;
2534
2535    status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
2536    iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
2537
2538    status &= priv->int_mask;
2539    if (!status)
2540        return IRQ_NONE;
2541
2542    if (status & MWL8K_A2H_INT_TX_DONE)
2543        tasklet_schedule(&priv->tx_reclaim_task);
2544
2545    if (status & MWL8K_A2H_INT_RX_READY) {
2546        while (rxq_process(hw, 0, 1))
2547            rxq_refill(hw, 0, 1);
2548    }
2549
2550    if (status & MWL8K_A2H_INT_OPC_DONE) {
2551        if (priv->hostcmd_wait != NULL) {
2552            complete(priv->hostcmd_wait);
2553            priv->hostcmd_wait = NULL;
2554        }
2555    }
2556
2557    if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
2558        if (!priv->inconfig &&
2559            priv->radio_state &&
2560            mwl8k_txq_busy(priv))
2561                mwl8k_tx_start(priv);
2562    }
2563
2564    return IRQ_HANDLED;
2565}
2566
2567
2568/*
2569 * Core driver operations.
2570 */
2571static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2572{
2573    struct mwl8k_priv *priv = hw->priv;
2574    int index = skb_get_queue_mapping(skb);
2575    int rc;
2576
2577    if (priv->current_channel == NULL) {
2578        printk(KERN_DEBUG "%s: dropped TX frame since radio "
2579               "disabled\n", priv->name);
2580        dev_kfree_skb(skb);
2581        return NETDEV_TX_OK;
2582    }
2583
2584    rc = mwl8k_txq_xmit(hw, index, skb);
2585
2586    return rc;
2587}
2588
2589struct mwl8k_work_struct {
2590    /* Initialized by mwl8k_queue_work(). */
2591    struct work_struct wt;
2592
2593    /* Required field passed in to mwl8k_queue_work(). */
2594    struct ieee80211_hw *hw;
2595
2596    /* Required field passed in to mwl8k_queue_work(). */
2597    int (*wfunc)(struct work_struct *w);
2598
2599    /* Initialized by mwl8k_queue_work(). */
2600    struct completion *cmd_wait;
2601
2602    /* Result code. */
2603    int rc;
2604
2605    /*
2606     * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX
2607     * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS.
2608     */
2609    u32 options;
2610
2611    /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */
2612    unsigned long timeout_ms;
2613
2614    /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */
2615    u32 txwait_attempts;
2616
2617    /* Optional field. Defaults to MWL8K_TXWAIT_MS. */
2618    u32 tx_timeout_ms;
2619    u32 step;
2620};
2621
2622/* Flags controlling behavior of config queue requests */
2623
2624/* Caller spins while waiting for completion. */
2625#define MWL8K_WQ_SPIN 0x00000001
2626
2627/* Wait for TX queues to empty before proceeding with configuration. */
2628#define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002
2629
2630/* Queue request and return immediately. */
2631#define MWL8K_WQ_POST_REQUEST 0x00000004
2632
2633/*
2634 * Caller sleeps and waits for task complete notification.
2635 * Do not use in atomic context.
2636 */
2637#define MWL8K_WQ_SLEEP 0x00000008
2638
2639/* Free work struct when task is done. */
2640#define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010
2641
2642/*
2643 * Config request is queued and returns to caller imediately. Use
2644 * this in atomic context. Work struct is freed by mwl8k_queue_work()
2645 * when this flag is set.
2646 */
2647#define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \
2648                 MWL8K_WQ_FREE_WORKSTRUCT)
2649
2650/* Default work queue behavior is to sleep and wait for tx completion. */
2651#define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY)
2652
2653/*
2654 * Default config request timeout. Add adjustments to make sure the
2655 * config thread waits long enough for both tx wait and cmd wait before
2656 * timing out.
2657 */
2658
2659/* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */
2660#define MWL8K_TXWAIT_TIMEOUT_MS 1000
2661
2662/* Default number of TX wait attempts. */
2663#define MWL8K_WQ_TXWAIT_ATTEMPTS 4
2664
2665/* Total time to wait for TXQ to drain. */
2666#define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \
2667                        MWL8K_WQ_TXWAIT_ATTEMPTS)
2668
2669/* Scheduling slop. */
2670#define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200
2671
2672#define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \
2673                 MWL8K_TXWAIT_MS + \
2674                 MWL8K_OS_SCHEDULE_OVERHEAD_MS)
2675
2676static void mwl8k_config_thread(struct work_struct *wt)
2677{
2678    struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt;
2679    struct ieee80211_hw *hw = worker->hw;
2680    struct mwl8k_priv *priv = hw->priv;
2681    int rc = 0;
2682
2683    spin_lock_irq(&priv->tx_lock);
2684    priv->inconfig = true;
2685    spin_unlock_irq(&priv->tx_lock);
2686
2687    ieee80211_stop_queues(hw);
2688
2689    /*
2690     * Wait for host queues to drain before doing PHY
2691     * reconfiguration. This avoids interrupting any in-flight
2692     * DMA transfers to the hardware.
2693     */
2694    if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) {
2695        u32 timeout;
2696        u32 time_remaining;
2697        u32 iter;
2698        u32 tx_wait_attempts = worker->txwait_attempts;
2699
2700        time_remaining = worker->tx_timeout_ms;
2701        if (!tx_wait_attempts)
2702            tx_wait_attempts = 1;
2703
2704        timeout = worker->tx_timeout_ms/tx_wait_attempts;
2705        if (!timeout)
2706            timeout = 1;
2707
2708        iter = tx_wait_attempts;
2709        do {
2710            int wait_time;
2711
2712            if (time_remaining > timeout) {
2713                time_remaining -= timeout;
2714                wait_time = timeout;
2715            } else
2716                wait_time = time_remaining;
2717
2718            if (!wait_time)
2719                wait_time = 1;
2720
2721            rc = mwl8k_tx_wait_empty(hw, wait_time);
2722            if (rc)
2723                printk(KERN_ERR "%s() txwait timeout=%ums "
2724                    "Retry:%u/%u\n", __func__, timeout,
2725                    tx_wait_attempts - iter + 1,
2726                    tx_wait_attempts);
2727
2728        } while (rc && --iter);
2729
2730        rc = iter ? 0 : -ETIMEDOUT;
2731    }
2732    if (!rc)
2733        rc = worker->wfunc(wt);
2734
2735    spin_lock_irq(&priv->tx_lock);
2736    priv->inconfig = false;
2737    if (priv->pending_tx_pkts && priv->radio_state)
2738        mwl8k_tx_start(priv);
2739    spin_unlock_irq(&priv->tx_lock);
2740    ieee80211_wake_queues(hw);
2741
2742    worker->rc = rc;
2743    if (worker->options & MWL8K_WQ_SLEEP)
2744        complete(worker->cmd_wait);
2745
2746    if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT)
2747        kfree(wt);
2748}
2749
2750static int mwl8k_queue_work(struct ieee80211_hw *hw,
2751                struct mwl8k_work_struct *worker,
2752                struct workqueue_struct *wqueue,
2753                int (*wfunc)(struct work_struct *w))
2754{
2755    unsigned long timeout = 0;
2756    int rc = 0;
2757
2758    DECLARE_COMPLETION_ONSTACK(cmd_wait);
2759
2760    if (!worker->timeout_ms)
2761        worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS;
2762
2763    if (!worker->options)
2764        worker->options = MWL8K_WQ_DEFAULT_OPTIONS;
2765
2766    if (!worker->txwait_attempts)
2767        worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS;
2768
2769    if (!worker->tx_timeout_ms)
2770        worker->tx_timeout_ms = MWL8K_TXWAIT_MS;
2771
2772    worker->hw = hw;
2773    worker->cmd_wait = &cmd_wait;
2774    worker->rc = 1;
2775    worker->wfunc = wfunc;
2776
2777    INIT_WORK(&worker->wt, mwl8k_config_thread);
2778    queue_work(wqueue, &worker->wt);
2779
2780    if (worker->options & MWL8K_WQ_POST_REQUEST) {
2781        rc = 0;
2782    } else {
2783        if (worker->options & MWL8K_WQ_SPIN) {
2784            timeout = worker->timeout_ms;
2785            while (timeout && (worker->rc > 0)) {
2786                mdelay(1);
2787                timeout--;
2788            }
2789        } else if (worker->options & MWL8K_WQ_SLEEP)
2790            timeout = wait_for_completion_timeout(&cmd_wait,
2791                msecs_to_jiffies(worker->timeout_ms));
2792
2793        if (timeout)
2794            rc = worker->rc;
2795        else {
2796            cancel_work_sync(&worker->wt);
2797            rc = -ETIMEDOUT;
2798        }
2799    }
2800
2801    return rc;
2802}
2803
2804struct mwl8k_start_worker {
2805    struct mwl8k_work_struct header;
2806};
2807
2808static int mwl8k_start_wt(struct work_struct *wt)
2809{
2810    struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt;
2811    struct ieee80211_hw *hw = worker->header.hw;
2812    struct mwl8k_priv *priv = hw->priv;
2813    int rc = 0;
2814
2815    if (priv->vif != NULL) {
2816        rc = -EIO;
2817        goto mwl8k_start_exit;
2818    }
2819
2820    /* Turn on radio */
2821    if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
2822        rc = -EIO;
2823        goto mwl8k_start_exit;
2824    }
2825
2826    /* Purge TX/RX HW queues */
2827    if (mwl8k_cmd_set_pre_scan(hw)) {
2828        rc = -EIO;
2829        goto mwl8k_start_exit;
2830    }
2831
2832    if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) {
2833        rc = -EIO;
2834        goto mwl8k_start_exit;
2835    }
2836
2837    /* Enable firmware rate adaptation */
2838    if (mwl8k_cmd_setrateadaptmode(hw, 0)) {
2839        rc = -EIO;
2840        goto mwl8k_start_exit;
2841    }
2842
2843    /* Disable WMM. WMM gets enabled when stack sends WMM parms */
2844    if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) {
2845        rc = -EIO;
2846        goto mwl8k_start_exit;
2847    }
2848
2849    /* Disable sniffer mode */
2850    if (mwl8k_enable_sniffer(hw, 0))
2851        rc = -EIO;
2852
2853mwl8k_start_exit:
2854    return rc;
2855}
2856
2857static int mwl8k_start(struct ieee80211_hw *hw)
2858{
2859    struct mwl8k_start_worker *worker;
2860    struct mwl8k_priv *priv = hw->priv;
2861    int rc;
2862
2863    /* Enable tx reclaim tasklet */
2864    tasklet_enable(&priv->tx_reclaim_task);
2865
2866    rc = request_irq(priv->pdev->irq, &mwl8k_interrupt,
2867             IRQF_SHARED, MWL8K_NAME, hw);
2868    if (rc) {
2869        printk(KERN_ERR "%s: failed to register IRQ handler\n",
2870               priv->name);
2871        rc = -EIO;
2872        goto mwl8k_start_disable_tasklet;
2873    }
2874
2875    /* Enable interrupts */
2876    iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
2877
2878    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
2879    if (worker == NULL) {
2880        rc = -ENOMEM;
2881        goto mwl8k_start_disable_irq;
2882    }
2883
2884    rc = mwl8k_queue_work(hw, &worker->header,
2885                  priv->config_wq, mwl8k_start_wt);
2886    kfree(worker);
2887    if (!rc)
2888        return rc;
2889
2890    if (rc == -ETIMEDOUT)
2891        printk(KERN_ERR "%s() timed out\n", __func__);
2892
2893    rc = -EIO;
2894
2895mwl8k_start_disable_irq:
2896    spin_lock_irq(&priv->tx_lock);
2897    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
2898    spin_unlock_irq(&priv->tx_lock);
2899    free_irq(priv->pdev->irq, hw);
2900
2901mwl8k_start_disable_tasklet:
2902    tasklet_disable(&priv->tx_reclaim_task);
2903
2904    return rc;
2905}
2906
2907struct mwl8k_stop_worker {
2908    struct mwl8k_work_struct header;
2909};
2910
2911static int mwl8k_stop_wt(struct work_struct *wt)
2912{
2913    struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt;
2914    struct ieee80211_hw *hw = worker->header.hw;
2915    int rc;
2916
2917    rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
2918
2919    return rc;
2920}
2921
2922static void mwl8k_stop(struct ieee80211_hw *hw)
2923{
2924    int rc;
2925    struct mwl8k_stop_worker *worker;
2926    struct mwl8k_priv *priv = hw->priv;
2927    int i;
2928
2929    if (priv->vif != NULL)
2930        return;
2931
2932    ieee80211_stop_queues(hw);
2933
2934    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
2935    if (worker == NULL)
2936        return;
2937
2938    rc = mwl8k_queue_work(hw, &worker->header,
2939                  priv->config_wq, mwl8k_stop_wt);
2940    kfree(worker);
2941    if (rc == -ETIMEDOUT)
2942        printk(KERN_ERR "%s() timed out\n", __func__);
2943
2944    /* Disable interrupts */
2945    spin_lock_irq(&priv->tx_lock);
2946    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
2947    spin_unlock_irq(&priv->tx_lock);
2948    free_irq(priv->pdev->irq, hw);
2949
2950    /* Stop finalize join worker */
2951    cancel_work_sync(&priv->finalize_join_worker);
2952    if (priv->beacon_skb != NULL)
2953        dev_kfree_skb(priv->beacon_skb);
2954
2955    /* Stop tx reclaim tasklet */
2956    tasklet_disable(&priv->tx_reclaim_task);
2957
2958    /* Stop config thread */
2959    flush_workqueue(priv->config_wq);
2960
2961    /* Return all skbs to mac80211 */
2962    for (i = 0; i < MWL8K_TX_QUEUES; i++)
2963        mwl8k_txq_reclaim(hw, i, 1);
2964}
2965
2966static int mwl8k_add_interface(struct ieee80211_hw *hw,
2967                struct ieee80211_if_init_conf *conf)
2968{
2969    struct mwl8k_priv *priv = hw->priv;
2970    struct mwl8k_vif *mwl8k_vif;
2971
2972    /*
2973     * We only support one active interface at a time.
2974     */
2975    if (priv->vif != NULL)
2976        return -EBUSY;
2977
2978    /*
2979     * We only support managed interfaces for now.
2980     */
2981    if (conf->type != NL80211_IFTYPE_STATION &&
2982        conf->type != NL80211_IFTYPE_MONITOR)
2983        return -EINVAL;
2984
2985    /* Clean out driver private area */
2986    mwl8k_vif = MWL8K_VIF(conf->vif);
2987    memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
2988
2989    /* Save the mac address */
2990    memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN);
2991
2992    /* Back pointer to parent config block */
2993    mwl8k_vif->priv = priv;
2994
2995    /* Setup initial PHY parameters */
2996    memcpy(mwl8k_vif->legacy_rates ,
2997        priv->rates, sizeof(mwl8k_vif->legacy_rates));
2998    mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates);
2999
3000    /* Set Initial sequence number to zero */
3001    mwl8k_vif->seqno = 0;
3002
3003    priv->vif = conf->vif;
3004    priv->current_channel = NULL;
3005
3006    return 0;
3007}
3008
3009static void mwl8k_remove_interface(struct ieee80211_hw *hw,
3010                   struct ieee80211_if_init_conf *conf)
3011{
3012    struct mwl8k_priv *priv = hw->priv;
3013
3014    if (priv->vif == NULL)
3015        return;
3016
3017    priv->vif = NULL;
3018}
3019
3020struct mwl8k_config_worker {
3021    struct mwl8k_work_struct header;
3022    u32 changed;
3023};
3024
3025static int mwl8k_config_wt(struct work_struct *wt)
3026{
3027    struct mwl8k_config_worker *worker =
3028        (struct mwl8k_config_worker *)wt;
3029    struct ieee80211_hw *hw = worker->header.hw;
3030    struct ieee80211_conf *conf = &hw->conf;
3031    struct mwl8k_priv *priv = hw->priv;
3032    int rc = 0;
3033
3034    if (!conf->radio_enabled) {
3035        mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
3036        priv->current_channel = NULL;
3037        rc = 0;
3038        goto mwl8k_config_exit;
3039    }
3040
3041    if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) {
3042        rc = -EINVAL;
3043        goto mwl8k_config_exit;
3044    }
3045
3046    priv->current_channel = conf->channel;
3047
3048    if (mwl8k_cmd_set_rf_channel(hw, conf->channel)) {
3049        rc = -EINVAL;
3050        goto mwl8k_config_exit;
3051    }
3052
3053    if (conf->power_level > 18)
3054        conf->power_level = 18;
3055    if (mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level)) {
3056        rc = -EINVAL;
3057        goto mwl8k_config_exit;
3058    }
3059
3060    if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7))
3061        rc = -EINVAL;
3062
3063mwl8k_config_exit:
3064    return rc;
3065}
3066
3067static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
3068{
3069    int rc = 0;
3070    struct mwl8k_config_worker *worker;
3071    struct mwl8k_priv *priv = hw->priv;
3072
3073    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
3074    if (worker == NULL)
3075        return -ENOMEM;
3076
3077    worker->changed = changed;
3078    rc = mwl8k_queue_work(hw, &worker->header,
3079                  priv->config_wq, mwl8k_config_wt);
3080    if (rc == -ETIMEDOUT) {
3081        printk(KERN_ERR "%s() timed out.\n", __func__);
3082        rc = -EINVAL;
3083    }
3084
3085    kfree(worker);
3086
3087    /*
3088     * mac80211 will crash on anything other than -EINVAL on
3089     * error. Looks like wireless extensions which calls mac80211
3090     * may be the actual culprit...
3091     */
3092    return rc ? -EINVAL : 0;
3093}
3094
3095struct mwl8k_bss_info_changed_worker {
3096    struct mwl8k_work_struct header;
3097    struct ieee80211_vif *vif;
3098    struct ieee80211_bss_conf *info;
3099    u32 changed;
3100};
3101
3102static int mwl8k_bss_info_changed_wt(struct work_struct *wt)
3103{
3104    struct mwl8k_bss_info_changed_worker *worker =
3105        (struct mwl8k_bss_info_changed_worker *)wt;
3106    struct ieee80211_hw *hw = worker->header.hw;
3107    struct ieee80211_vif *vif = worker->vif;
3108    struct ieee80211_bss_conf *info = worker->info;
3109    u32 changed;
3110    int rc;
3111
3112    struct mwl8k_priv *priv = hw->priv;
3113    struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
3114
3115    changed = worker->changed;
3116    priv->capture_beacon = false;
3117
3118    if (info->assoc) {
3119        memcpy(&mwl8k_vif->bss_info, info,
3120            sizeof(struct ieee80211_bss_conf));
3121
3122        /* Install rates */
3123        if (mwl8k_update_rateset(hw, vif))
3124            goto mwl8k_bss_info_changed_exit;
3125
3126        /* Turn on rate adaptation */
3127        if (mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE,
3128            MWL8K_UCAST_RATE, NULL))
3129            goto mwl8k_bss_info_changed_exit;
3130
3131        /* Set radio preamble */
3132        if (mwl8k_set_radio_preamble(hw,
3133                info->use_short_preamble))
3134            goto mwl8k_bss_info_changed_exit;
3135
3136        /* Set slot time */
3137        if (mwl8k_cmd_set_slot(hw, info->use_short_slot ?
3138                MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME))
3139            goto mwl8k_bss_info_changed_exit;
3140
3141        /* Update peer rate info */
3142        if (mwl8k_cmd_update_sta_db(hw, vif,
3143                MWL8K_STA_DB_MODIFY_ENTRY))
3144            goto mwl8k_bss_info_changed_exit;
3145
3146        /* Set AID */
3147        if (mwl8k_cmd_set_aid(hw, vif))
3148            goto mwl8k_bss_info_changed_exit;
3149
3150        /*
3151         * Finalize the join. Tell rx handler to process
3152         * next beacon from our BSSID.
3153         */
3154        memcpy(priv->capture_bssid,
3155                mwl8k_vif->bssid, IEEE80211_ADDR_LEN);
3156        priv->capture_beacon = true;
3157    } else {
3158        mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY);
3159        memset(&mwl8k_vif->bss_info, 0,
3160            sizeof(struct ieee80211_bss_conf));
3161        memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN);
3162    }
3163
3164mwl8k_bss_info_changed_exit:
3165    rc = 0;
3166    return rc;
3167}
3168
3169static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
3170                   struct ieee80211_vif *vif,
3171                   struct ieee80211_bss_conf *info,
3172                   u32 changed)
3173{
3174    struct mwl8k_bss_info_changed_worker *worker;
3175    struct mwl8k_priv *priv = hw->priv;
3176    struct mwl8k_vif *mv_vif = MWL8K_VIF(vif);
3177    int rc;
3178
3179    if (changed & BSS_CHANGED_BSSID)
3180        memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN);
3181
3182    if ((changed & BSS_CHANGED_ASSOC) == 0)
3183        return;
3184
3185    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
3186    if (worker == NULL)
3187        return;
3188
3189    worker->vif = vif;
3190    worker->info = info;
3191    worker->changed = changed;
3192    rc = mwl8k_queue_work(hw, &worker->header,
3193                  priv->config_wq,
3194                  mwl8k_bss_info_changed_wt);
3195    kfree(worker);
3196    if (rc == -ETIMEDOUT)
3197        printk(KERN_ERR "%s() timed out\n", __func__);
3198}
3199
3200struct mwl8k_configure_filter_worker {
3201    struct mwl8k_work_struct header;
3202    unsigned int changed_flags;
3203    unsigned int *total_flags;
3204    int mc_count;
3205    struct dev_addr_list *mclist;
3206};
3207
3208#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC
3209
3210static int mwl8k_configure_filter_wt(struct work_struct *wt)
3211{
3212    struct mwl8k_configure_filter_worker *worker =
3213        (struct mwl8k_configure_filter_worker *)wt;
3214
3215    struct ieee80211_hw *hw = worker->header.hw;
3216    unsigned int changed_flags = worker->changed_flags;
3217    unsigned int *total_flags = worker->total_flags;
3218    int mc_count = worker->mc_count;
3219    struct dev_addr_list *mclist = worker->mclist;
3220
3221    struct mwl8k_priv *priv = hw->priv;
3222    int rc = 0;
3223
3224    if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
3225        if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
3226            rc = mwl8k_cmd_set_pre_scan(hw);
3227        else {
3228            u8 *bssid;
3229
3230            bssid = "\x00\x00\x00\x00\x00\x00";
3231            if (priv->vif != NULL)
3232                bssid = MWL8K_VIF(priv->vif)->bssid;
3233
3234            rc = mwl8k_cmd_set_post_scan(hw, bssid);
3235        }
3236    }
3237
3238    if (rc)
3239        goto mwl8k_configure_filter_exit;
3240    if (mc_count) {
3241        mc_count = mc_count < priv->num_mcaddrs ?
3242                mc_count : priv->num_mcaddrs;
3243        rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
3244        if (rc)
3245            printk(KERN_ERR
3246            "%s()Error setting multicast addresses\n",
3247            __func__);
3248    }
3249
3250mwl8k_configure_filter_exit:
3251    return rc;
3252}
3253
3254static void mwl8k_configure_filter(struct ieee80211_hw *hw,
3255                   unsigned int changed_flags,
3256                   unsigned int *total_flags,
3257                   int mc_count,
3258                   struct dev_addr_list *mclist)
3259{
3260
3261    struct mwl8k_configure_filter_worker *worker;
3262    struct mwl8k_priv *priv = hw->priv;
3263
3264    /* Clear unsupported feature flags */
3265    *total_flags &= MWL8K_SUPPORTED_IF_FLAGS;
3266
3267    if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count)
3268        return;
3269
3270    worker = kzalloc(sizeof(*worker), GFP_ATOMIC);
3271    if (worker == NULL)
3272        return;
3273
3274    worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
3275    worker->changed_flags = changed_flags;
3276    worker->total_flags = total_flags;
3277    worker->mc_count = mc_count;
3278    worker->mclist = mclist;
3279
3280    mwl8k_queue_work(hw, &worker->header, priv->config_wq,
3281             mwl8k_configure_filter_wt);
3282}
3283
3284struct mwl8k_set_rts_threshold_worker {
3285    struct mwl8k_work_struct header;
3286    u32 value;
3287};
3288
3289static int mwl8k_set_rts_threshold_wt(struct work_struct *wt)
3290{
3291    struct mwl8k_set_rts_threshold_worker *worker =
3292        (struct mwl8k_set_rts_threshold_worker *)wt;
3293
3294    struct ieee80211_hw *hw = worker->header.hw;
3295    u16 threshold = (u16)(worker->value);
3296    int rc;
3297
3298    rc = mwl8k_rts_threshold(hw, MWL8K_CMD_SET, &threshold);
3299
3300    return rc;
3301}
3302
3303static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
3304{
3305    int rc;
3306    struct mwl8k_set_rts_threshold_worker *worker;
3307    struct mwl8k_priv *priv = hw->priv;
3308
3309    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
3310    if (worker == NULL)
3311        return -ENOMEM;
3312
3313    worker->value = value;
3314
3315    rc = mwl8k_queue_work(hw, &worker->header,
3316                  priv->config_wq,
3317                  mwl8k_set_rts_threshold_wt);
3318    kfree(worker);
3319
3320    if (rc == -ETIMEDOUT) {
3321        printk(KERN_ERR "%s() timed out\n", __func__);
3322        rc = -EINVAL;
3323    }
3324
3325    return rc;
3326}
3327
3328struct mwl8k_conf_tx_worker {
3329    struct mwl8k_work_struct header;
3330    u16 queue;
3331    const struct ieee80211_tx_queue_params *params;
3332};
3333
3334static int mwl8k_conf_tx_wt(struct work_struct *wt)
3335{
3336    struct mwl8k_conf_tx_worker *worker =
3337    (struct mwl8k_conf_tx_worker *)wt;
3338
3339    struct ieee80211_hw *hw = worker->header.hw;
3340    u16 queue = worker->queue;
3341    const struct ieee80211_tx_queue_params *params = worker->params;
3342
3343    struct mwl8k_priv *priv = hw->priv;
3344    int rc = 0;
3345
3346    if (priv->wmm_mode == MWL8K_WMM_DISABLE)
3347        if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) {
3348            rc = -EINVAL;
3349            goto mwl8k_conf_tx_exit;
3350    }
3351
3352    if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min,
3353        params->cw_max, params->aifs, params->txop))
3354            rc = -EINVAL;
3355mwl8k_conf_tx_exit:
3356    return rc;
3357}
3358
3359static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
3360             const struct ieee80211_tx_queue_params *params)
3361{
3362    int rc;
3363    struct mwl8k_conf_tx_worker *worker;
3364    struct mwl8k_priv *priv = hw->priv;
3365
3366    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
3367    if (worker == NULL)
3368        return -ENOMEM;
3369
3370    worker->queue = queue;
3371    worker->params = params;
3372    rc = mwl8k_queue_work(hw, &worker->header,
3373                  priv->config_wq, mwl8k_conf_tx_wt);
3374    kfree(worker);
3375    if (rc == -ETIMEDOUT) {
3376        printk(KERN_ERR "%s() timed out\n", __func__);
3377        rc = -EINVAL;
3378    }
3379    return rc;
3380}
3381
3382static int mwl8k_get_tx_stats(struct ieee80211_hw *hw,
3383                  struct ieee80211_tx_queue_stats *stats)
3384{
3385    struct mwl8k_priv *priv = hw->priv;
3386    struct mwl8k_tx_queue *txq;
3387    int index;
3388
3389    spin_lock_bh(&priv->tx_lock);
3390    for (index = 0; index < MWL8K_TX_QUEUES; index++) {
3391        txq = priv->txq + index;
3392        memcpy(&stats[index], &txq->tx_stats,
3393            sizeof(struct ieee80211_tx_queue_stats));
3394    }
3395    spin_unlock_bh(&priv->tx_lock);
3396    return 0;
3397}
3398
3399struct mwl8k_get_stats_worker {
3400    struct mwl8k_work_struct header;
3401    struct ieee80211_low_level_stats *stats;
3402};
3403
3404static int mwl8k_get_stats_wt(struct work_struct *wt)
3405{
3406    struct mwl8k_get_stats_worker *worker =
3407        (struct mwl8k_get_stats_worker *)wt;
3408
3409    return mwl8k_cmd_802_11_get_stat(worker->header.hw, worker->stats);
3410}
3411
3412static int mwl8k_get_stats(struct ieee80211_hw *hw,
3413               struct ieee80211_low_level_stats *stats)
3414{
3415    int rc;
3416    struct mwl8k_get_stats_worker *worker;
3417    struct mwl8k_priv *priv = hw->priv;
3418
3419    worker = kzalloc(sizeof(*worker), GFP_KERNEL);
3420    if (worker == NULL)
3421        return -ENOMEM;
3422
3423    worker->stats = stats;
3424    rc = mwl8k_queue_work(hw, &worker->header,
3425                  priv->config_wq, mwl8k_get_stats_wt);
3426
3427    kfree(worker);
3428    if (rc == -ETIMEDOUT) {
3429        printk(KERN_ERR "%s() timed out\n", __func__);
3430        rc = -EINVAL;
3431    }
3432
3433    return rc;
3434}
3435
3436static const struct ieee80211_ops mwl8k_ops = {
3437    .tx = mwl8k_tx,
3438    .start = mwl8k_start,
3439    .stop = mwl8k_stop,
3440    .add_interface = mwl8k_add_interface,
3441    .remove_interface = mwl8k_remove_interface,
3442    .config = mwl8k_config,
3443    .bss_info_changed = mwl8k_bss_info_changed,
3444    .configure_filter = mwl8k_configure_filter,
3445    .set_rts_threshold = mwl8k_set_rts_threshold,
3446    .conf_tx = mwl8k_conf_tx,
3447    .get_tx_stats = mwl8k_get_tx_stats,
3448    .get_stats = mwl8k_get_stats,
3449};
3450
3451static void mwl8k_tx_reclaim_handler(unsigned long data)
3452{
3453    int i;
3454    struct ieee80211_hw *hw = (struct ieee80211_hw *) data;
3455    struct mwl8k_priv *priv = hw->priv;
3456
3457    spin_lock_bh(&priv->tx_lock);
3458    for (i = 0; i < MWL8K_TX_QUEUES; i++)
3459        mwl8k_txq_reclaim(hw, i, 0);
3460
3461    if (priv->tx_wait != NULL) {
3462        int count = mwl8k_txq_busy(priv);
3463        if (count == 0) {
3464            complete(priv->tx_wait);
3465            priv->tx_wait = NULL;
3466        }
3467    }
3468    spin_unlock_bh(&priv->tx_lock);
3469}
3470
3471static void mwl8k_finalize_join_worker(struct work_struct *work)
3472{
3473    struct mwl8k_priv *priv =
3474        container_of(work, struct mwl8k_priv, finalize_join_worker);
3475    struct sk_buff *skb = priv->beacon_skb;
3476    u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period;
3477
3478    mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim);
3479    dev_kfree_skb(skb);
3480
3481    priv->beacon_skb = NULL;
3482}
3483
3484static int __devinit mwl8k_probe(struct pci_dev *pdev,
3485                 const struct pci_device_id *id)
3486{
3487    struct ieee80211_hw *hw;
3488    struct mwl8k_priv *priv;
3489    DECLARE_MAC_BUF(mac);
3490    int rc;
3491    int i;
3492    u8 *fw;
3493
3494    rc = pci_enable_device(pdev);
3495    if (rc) {
3496        printk(KERN_ERR "%s: Cannot enable new PCI device\n",
3497               MWL8K_NAME);
3498        return rc;
3499    }
3500
3501    rc = pci_request_regions(pdev, MWL8K_NAME);
3502    if (rc) {
3503        printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
3504               MWL8K_NAME);
3505        return rc;
3506    }
3507
3508    pci_set_master(pdev);
3509
3510    hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
3511    if (hw == NULL) {
3512        printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
3513        rc = -ENOMEM;
3514        goto err_free_reg;
3515    }
3516
3517    priv = hw->priv;
3518    priv->hw = hw;
3519    priv->pdev = pdev;
3520    priv->hostcmd_wait = NULL;
3521    priv->tx_wait = NULL;
3522    priv->inconfig = false;
3523    priv->wep_enabled = 0;
3524    priv->wmm_mode = false;
3525    priv->pending_tx_pkts = 0;
3526    strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
3527
3528    spin_lock_init(&priv->fw_lock);
3529
3530    SET_IEEE80211_DEV(hw, &pdev->dev);
3531    pci_set_drvdata(pdev, hw);
3532
3533    priv->regs = pci_iomap(pdev, 1, 0x10000);
3534    if (priv->regs == NULL) {
3535        printk(KERN_ERR "%s: Cannot map device memory\n", priv->name);
3536        goto err_iounmap;
3537    }
3538
3539    memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels));
3540    priv->band.band = IEEE80211_BAND_2GHZ;
3541    priv->band.channels = priv->channels;
3542    priv->band.n_channels = ARRAY_SIZE(mwl8k_channels);
3543    priv->band.bitrates = priv->rates;
3544    priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates);
3545    hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
3546
3547    BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates));
3548    memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates));
3549
3550    /*
3551     * Extra headroom is the size of the required DMA header
3552     * minus the size of the smallest 802.11 frame (CTS frame).
3553     */
3554    hw->extra_tx_headroom =
3555        sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
3556
3557    hw->channel_change_time = 10;
3558
3559    hw->queues = MWL8K_TX_QUEUES;
3560
3561    hw->wiphy->interface_modes =
3562        BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR);
3563
3564    /* Set rssi and noise values to dBm */
3565    hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM);
3566    hw->vif_data_size = sizeof(struct mwl8k_vif);
3567    priv->vif = NULL;
3568
3569    /* Set default radio state and preamble */
3570    priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE;
3571    priv->radio_state = MWL8K_RADIO_DISABLE;
3572
3573    /* Finalize join worker */
3574    INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
3575
3576    /* TX reclaim tasklet */
3577    tasklet_init(&priv->tx_reclaim_task,
3578            mwl8k_tx_reclaim_handler, (unsigned long)hw);
3579    tasklet_disable(&priv->tx_reclaim_task);
3580
3581    /* Config workthread */
3582    priv->config_wq = create_singlethread_workqueue("mwl8k_config");
3583    if (priv->config_wq == NULL)
3584        goto err_iounmap;
3585
3586    /* Power management cookie */
3587    priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
3588    if (priv->cookie == NULL)
3589        goto err_iounmap;
3590
3591    rc = mwl8k_rxq_init(hw, 0);
3592    if (rc)
3593        goto err_iounmap;
3594    rxq_refill(hw, 0, INT_MAX);
3595
3596    spin_lock_init(&priv->tx_lock);
3597
3598    for (i = 0; i < MWL8K_TX_QUEUES; i++) {
3599        rc = mwl8k_txq_init(hw, i);
3600        if (rc)
3601            goto err_free_queues;
3602    }
3603
3604    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3605    priv->int_mask = 0;
3606    iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3607    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
3608    iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
3609
3610    rc = request_irq(priv->pdev->irq, &mwl8k_interrupt,
3611             IRQF_SHARED, MWL8K_NAME, hw);
3612    if (rc) {
3613        printk(KERN_ERR "%s: failed to register IRQ handler\n",
3614               priv->name);
3615        goto err_free_queues;
3616    }
3617
3618    /* Reset firmware and hardware */
3619    mwl8k_hw_reset(priv);
3620
3621    /* Ask userland hotplug daemon for the device firmware */
3622    rc = mwl8k_request_firmware(priv, (u32)id->driver_data);
3623    if (rc) {
3624        printk(KERN_ERR "%s: Firmware files not found\n", priv->name);
3625        goto err_free_irq;
3626    }
3627
3628    /* Load firmware into hardware */
3629    rc = mwl8k_load_firmware(priv);
3630    if (rc) {
3631        printk(KERN_ERR "%s: Cannot start firmware\n", priv->name);
3632        goto err_stop_firmware;
3633    }
3634
3635    /* Reclaim memory once firmware is successfully loaded */
3636    mwl8k_release_firmware(priv);
3637
3638    /*
3639     * Temporarily enable interrupts. Initial firmware host
3640     * commands use interrupts and avoids polling. Disable
3641     * interrupts when done.
3642     */
3643    priv->int_mask |= MWL8K_A2H_EVENTS;
3644
3645    iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3646
3647    /* Get config data, mac addrs etc */
3648    rc = mwl8k_cmd_get_hw_spec(hw);
3649    if (rc) {
3650        printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name);
3651        goto err_stop_firmware;
3652    }
3653
3654    /* Turn radio off */
3655    rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE);
3656    if (rc) {
3657        printk(KERN_ERR "%s: Cannot disable\n", priv->name);
3658        goto err_stop_firmware;
3659    }
3660
3661    /* Disable interrupts */
3662    spin_lock_irq(&priv->tx_lock);
3663    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3664    spin_unlock_irq(&priv->tx_lock);
3665    free_irq(priv->pdev->irq, hw);
3666
3667    rc = ieee80211_register_hw(hw);
3668    if (rc) {
3669        printk(KERN_ERR "%s: Cannot register device\n", priv->name);
3670        goto err_stop_firmware;
3671    }
3672
3673    fw = (u8 *)&priv->fw_rev;
3674    printk(KERN_INFO "%s: 88W%u %s\n", priv->name, priv->part_num,
3675        MWL8K_DESC);
3676    printk(KERN_INFO "%s: Driver Ver:%s Firmware Ver:%u.%u.%u.%u\n",
3677        priv->name, MWL8K_VERSION, fw[3], fw[2], fw[1], fw[0]);
3678    printk(KERN_INFO "%s: MAC Address: %s\n", priv->name,
3679           print_mac(mac, hw->wiphy->perm_addr));
3680
3681    return 0;
3682
3683err_stop_firmware:
3684    mwl8k_hw_reset(priv);
3685    mwl8k_release_firmware(priv);
3686
3687err_free_irq:
3688    spin_lock_irq(&priv->tx_lock);
3689    iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3690    spin_unlock_irq(&priv->tx_lock);
3691    free_irq(priv->pdev->irq, hw);
3692
3693err_free_queues:
3694    for (i = 0; i < MWL8K_TX_QUEUES; i++)
3695        mwl8k_txq_deinit(hw, i);
3696    mwl8k_rxq_deinit(hw, 0);
3697
3698err_iounmap:
3699    if (priv->cookie != NULL)
3700        pci_free_consistent(priv->pdev, 4,
3701                priv->cookie, priv->cookie_dma);
3702
3703    if (priv->regs != NULL)
3704        pci_iounmap(pdev, priv->regs);
3705
3706    if (priv->config_wq != NULL)
3707        destroy_workqueue(priv->config_wq);
3708
3709    pci_set_drvdata(pdev, NULL);
3710    ieee80211_free_hw(hw);
3711
3712err_free_reg:
3713    pci_release_regions(pdev);
3714    pci_disable_device(pdev);
3715
3716    return rc;
3717}
3718
3719static void __devexit mwl8k_shutdown(struct pci_dev *pdev)
3720{
3721    printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__);
3722}
3723
3724static void __devexit mwl8k_remove(struct pci_dev *pdev)
3725{
3726    struct ieee80211_hw *hw = pci_get_drvdata(pdev);
3727    struct mwl8k_priv *priv;
3728    int i;
3729
3730    if (hw == NULL)
3731        return;
3732    priv = hw->priv;
3733
3734    ieee80211_stop_queues(hw);
3735
3736    ieee80211_unregister_hw(hw);
3737
3738    /* Remove tx reclaim tasklet */
3739    tasklet_kill(&priv->tx_reclaim_task);
3740
3741    /* Stop config thread */
3742    destroy_workqueue(priv->config_wq);
3743
3744    /* Stop hardware */
3745    mwl8k_hw_reset(priv);
3746
3747    /* Return all skbs to mac80211 */
3748    for (i = 0; i < MWL8K_TX_QUEUES; i++)
3749        mwl8k_txq_reclaim(hw, i, 1);
3750
3751    for (i = 0; i < MWL8K_TX_QUEUES; i++)
3752        mwl8k_txq_deinit(hw, i);
3753
3754    mwl8k_rxq_deinit(hw, 0);
3755
3756    pci_free_consistent(priv->pdev, 4,
3757                priv->cookie, priv->cookie_dma);
3758
3759    pci_iounmap(pdev, priv->regs);
3760    pci_set_drvdata(pdev, NULL);
3761    ieee80211_free_hw(hw);
3762    pci_release_regions(pdev);
3763    pci_disable_device(pdev);
3764}
3765
3766static struct pci_driver mwl8k_driver = {
3767    .name = MWL8K_NAME,
3768    .id_table = mwl8k_table,
3769    .probe = mwl8k_probe,
3770    .remove = __devexit_p(mwl8k_remove),
3771    .shutdown = __devexit_p(mwl8k_shutdown),
3772};
3773
3774static int __init mwl8k_init(void)
3775{
3776    return pci_register_driver(&mwl8k_driver);
3777}
3778
3779static void __exit mwl8k_exit(void)
3780{
3781    pci_unregister_driver(&mwl8k_driver);
3782}
3783
3784module_init(mwl8k_init);
3785module_exit(mwl8k_exit);
3786

Archive Download this file



interactive