]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/wireless/mwl8k.c
mwl8k: differentiate between WMM queues and AMPDU queues
[mirror_ubuntu-artful-kernel.git] / drivers / net / wireless / mwl8k.c
CommitLineData
a66098da 1/*
ce9e2e1b
LB
2 * drivers/net/wireless/mwl8k.c
3 * Driver for Marvell TOPDOG 802.11 Wireless cards
a66098da 4 *
a5fb297d 5 * Copyright (C) 2008, 2009, 2010 Marvell Semiconductor Inc.
a66098da
LB
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
3d76e82c 15#include <linux/sched.h>
a66098da
LB
16#include <linux/spinlock.h>
17#include <linux/list.h>
18#include <linux/pci.h>
19#include <linux/delay.h>
20#include <linux/completion.h>
21#include <linux/etherdevice.h>
5a0e3ad6 22#include <linux/slab.h>
a66098da
LB
23#include <net/mac80211.h>
24#include <linux/moduleparam.h>
25#include <linux/firmware.h>
26#include <linux/workqueue.h>
27
28#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver"
29#define MWL8K_NAME KBUILD_MODNAME
a5fb297d 30#define MWL8K_VERSION "0.12"
a66098da 31
0863ade8
BC
32/* Module parameters */
33static unsigned ap_mode_default;
34module_param(ap_mode_default, bool, 0);
35MODULE_PARM_DESC(ap_mode_default,
36 "Set to 1 to make ap mode the default instead of sta mode");
37
a66098da
LB
38/* Register definitions */
39#define MWL8K_HIU_GEN_PTR 0x00000c10
ce9e2e1b
LB
40#define MWL8K_MODE_STA 0x0000005a
41#define MWL8K_MODE_AP 0x000000a5
a66098da 42#define MWL8K_HIU_INT_CODE 0x00000c14
ce9e2e1b
LB
43#define MWL8K_FWSTA_READY 0xf0f1f2f4
44#define MWL8K_FWAP_READY 0xf1f2f4a5
45#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005
a66098da
LB
46#define MWL8K_HIU_SCRATCH 0x00000c40
47
48/* Host->device communications */
49#define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18
50#define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c
51#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20
52#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24
53#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28
ce9e2e1b
LB
54#define MWL8K_H2A_INT_DUMMY (1 << 20)
55#define MWL8K_H2A_INT_RESET (1 << 15)
56#define MWL8K_H2A_INT_DOORBELL (1 << 1)
57#define MWL8K_H2A_INT_PPA_READY (1 << 0)
a66098da
LB
58
59/* Device->host communications */
60#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c
61#define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30
62#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34
63#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38
64#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c
ce9e2e1b
LB
65#define MWL8K_A2H_INT_DUMMY (1 << 20)
66#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11)
67#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10)
68#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7)
69#define MWL8K_A2H_INT_RADIO_ON (1 << 6)
70#define MWL8K_A2H_INT_RADIO_OFF (1 << 5)
71#define MWL8K_A2H_INT_MAC_EVENT (1 << 3)
72#define MWL8K_A2H_INT_OPC_DONE (1 << 2)
73#define MWL8K_A2H_INT_RX_READY (1 << 1)
74#define MWL8K_A2H_INT_TX_DONE (1 << 0)
a66098da
LB
75
76#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \
77 MWL8K_A2H_INT_CHNL_SWITCHED | \
78 MWL8K_A2H_INT_QUEUE_EMPTY | \
79 MWL8K_A2H_INT_RADAR_DETECT | \
80 MWL8K_A2H_INT_RADIO_ON | \
81 MWL8K_A2H_INT_RADIO_OFF | \
82 MWL8K_A2H_INT_MAC_EVENT | \
83 MWL8K_A2H_INT_OPC_DONE | \
84 MWL8K_A2H_INT_RX_READY | \
85 MWL8K_A2H_INT_TX_DONE)
86
a66098da 87#define MWL8K_RX_QUEUES 1
e600707b 88#define MWL8K_TX_WMM_QUEUES 4
8a7a578c 89#define MWL8K_MAX_AMPDU_QUEUES 8
e600707b
BC
90#define MWL8K_MAX_TX_QUEUES (MWL8K_TX_WMM_QUEUES + MWL8K_MAX_AMPDU_QUEUES)
91#define mwl8k_tx_queues(priv) (MWL8K_TX_WMM_QUEUES + (priv)->num_ampdu_queues)
a66098da 92
54bc3a0d
LB
93struct rxd_ops {
94 int rxd_size;
95 void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
96 void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
20f09c3d 97 int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status,
0d462bbb 98 __le16 *qos, s8 *noise);
54bc3a0d
LB
99};
100
45a390dd 101struct mwl8k_device_info {
a74b295e
LB
102 char *part_name;
103 char *helper_image;
0863ade8
BC
104 char *fw_image_sta;
105 char *fw_image_ap;
89a91f4f 106 struct rxd_ops *ap_rxd_ops;
952a0e96 107 u32 fw_api_ap;
45a390dd
LB
108};
109
a66098da 110struct mwl8k_rx_queue {
45eb400d 111 int rxd_count;
a66098da
LB
112
113 /* hw receives here */
45eb400d 114 int head;
a66098da
LB
115
116 /* refill descs here */
45eb400d 117 int tail;
a66098da 118
54bc3a0d 119 void *rxd;
45eb400d 120 dma_addr_t rxd_dma;
788838eb
LB
121 struct {
122 struct sk_buff *skb;
53b1b3e1 123 DEFINE_DMA_UNMAP_ADDR(dma);
788838eb 124 } *buf;
a66098da
LB
125};
126
a66098da
LB
127struct mwl8k_tx_queue {
128 /* hw transmits here */
45eb400d 129 int head;
a66098da
LB
130
131 /* sw appends here */
45eb400d 132 int tail;
a66098da 133
8ccbc3b8 134 unsigned int len;
45eb400d
LB
135 struct mwl8k_tx_desc *txd;
136 dma_addr_t txd_dma;
137 struct sk_buff **skb;
a66098da
LB
138};
139
5faa1aff
NS
140struct mwl8k_ampdu_stream {
141 struct ieee80211_sta *sta;
142 u8 tid;
143 u8 state;
144 u8 idx;
145 u8 txq_idx; /* index of this stream in priv->txq */
146};
147
a66098da 148struct mwl8k_priv {
a66098da 149 struct ieee80211_hw *hw;
a66098da 150 struct pci_dev *pdev;
a66098da 151
45a390dd
LB
152 struct mwl8k_device_info *device_info;
153
be695fc4
LB
154 void __iomem *sram;
155 void __iomem *regs;
156
157 /* firmware */
d1f9e41d
BC
158 const struct firmware *fw_helper;
159 const struct firmware *fw_ucode;
a66098da 160
be695fc4
LB
161 /* hardware/firmware parameters */
162 bool ap_fw;
163 struct rxd_ops *rxd_ops;
777ad375
LB
164 struct ieee80211_supported_band band_24;
165 struct ieee80211_channel channels_24[14];
166 struct ieee80211_rate rates_24[14];
4eae9edd
LB
167 struct ieee80211_supported_band band_50;
168 struct ieee80211_channel channels_50[4];
169 struct ieee80211_rate rates_50[9];
ee0ddf18
LB
170 u32 ap_macids_supported;
171 u32 sta_macids_supported;
be695fc4 172
8a7a578c
BC
173 /* Ampdu stream information */
174 u8 num_ampdu_queues;
175
618952a7
LB
176 /* firmware access */
177 struct mutex fw_mutex;
178 struct task_struct *fw_mutex_owner;
179 int fw_mutex_depth;
618952a7
LB
180 struct completion *hostcmd_wait;
181
a66098da
LB
182 /* lock held over TX and TX reap */
183 spinlock_t tx_lock;
a66098da 184
88de754a
LB
185 /* TX quiesce completion, protected by fw_mutex and tx_lock */
186 struct completion *tx_wait;
187
f5bb87cf 188 /* List of interfaces. */
ee0ddf18 189 u32 macids_used;
f5bb87cf 190 struct list_head vif_list;
a66098da 191
a66098da
LB
192 /* power management status cookie from firmware */
193 u32 *cookie;
194 dma_addr_t cookie_dma;
195
196 u16 num_mcaddrs;
a66098da 197 u8 hw_rev;
2aa7b01f 198 u32 fw_rev;
a66098da
LB
199
200 /*
201 * Running count of TX packets in flight, to avoid
202 * iterating over the transmit rings each time.
203 */
204 int pending_tx_pkts;
205
206 struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES];
e600707b
BC
207 struct mwl8k_tx_queue txq[MWL8K_MAX_TX_QUEUES];
208 u32 txq_offset[MWL8K_MAX_TX_QUEUES];
a66098da 209
c46563b7 210 bool radio_on;
68ce3884 211 bool radio_short_preamble;
a43c49a8 212 bool sniffer_enabled;
0439b1f5 213 bool wmm_enabled;
a66098da 214
a66098da
LB
215 /* XXX need to convert this to handle multiple interfaces */
216 bool capture_beacon;
d89173f2 217 u8 capture_bssid[ETH_ALEN];
a66098da
LB
218 struct sk_buff *beacon_skb;
219
220 /*
221 * This FJ worker has to be global as it is scheduled from the
222 * RX handler. At this point we don't know which interface it
223 * belongs to until the list of bssids waiting to complete join
224 * is checked.
225 */
226 struct work_struct finalize_join_worker;
227
1e9f9de3
LB
228 /* Tasklet to perform TX reclaim. */
229 struct tasklet_struct poll_tx_task;
67e2eb27
LB
230
231 /* Tasklet to perform RX. */
232 struct tasklet_struct poll_rx_task;
0d462bbb
JL
233
234 /* Most recently reported noise in dBm */
235 s8 noise;
0863ade8
BC
236
237 /*
238 * preserve the queue configurations so they can be restored if/when
239 * the firmware image is swapped.
240 */
e600707b 241 struct ieee80211_tx_queue_params wmm_params[MWL8K_TX_WMM_QUEUES];
99020471
BC
242
243 /* async firmware loading state */
244 unsigned fw_state;
245 char *fw_pref;
246 char *fw_alt;
247 struct completion firmware_loading_complete;
a66098da
LB
248};
249
e53d9b96
NS
250#define MAX_WEP_KEY_LEN 13
251#define NUM_WEP_KEYS 4
252
a66098da
LB
253/* Per interface specific private data */
254struct mwl8k_vif {
f5bb87cf
LB
255 struct list_head list;
256 struct ieee80211_vif *vif;
257
f57ca9c1
LB
258 /* Firmware macid for this vif. */
259 int macid;
260
c2c2b12a 261 /* Non AMPDU sequence number assigned by driver. */
a680400e 262 u16 seqno;
e53d9b96
NS
263
264 /* Saved WEP keys */
265 struct {
266 u8 enabled;
267 u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
268 } wep_key_conf[NUM_WEP_KEYS];
d9a07d49
NS
269
270 /* BSSID */
271 u8 bssid[ETH_ALEN];
272
273 /* A flag to indicate is HW crypto is enabled for this bssid */
274 bool is_hw_crypto_enabled;
a66098da 275};
a94cc97e 276#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
fcdc403c 277#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
a66098da 278
a680400e
LB
279struct mwl8k_sta {
280 /* Index into station database. Returned by UPDATE_STADB. */
281 u8 peer_id;
282};
283#define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv))
284
777ad375 285static const struct ieee80211_channel mwl8k_channels_24[] = {
a66098da
LB
286 { .center_freq = 2412, .hw_value = 1, },
287 { .center_freq = 2417, .hw_value = 2, },
288 { .center_freq = 2422, .hw_value = 3, },
289 { .center_freq = 2427, .hw_value = 4, },
290 { .center_freq = 2432, .hw_value = 5, },
291 { .center_freq = 2437, .hw_value = 6, },
292 { .center_freq = 2442, .hw_value = 7, },
293 { .center_freq = 2447, .hw_value = 8, },
294 { .center_freq = 2452, .hw_value = 9, },
295 { .center_freq = 2457, .hw_value = 10, },
296 { .center_freq = 2462, .hw_value = 11, },
647ca6b0
LB
297 { .center_freq = 2467, .hw_value = 12, },
298 { .center_freq = 2472, .hw_value = 13, },
299 { .center_freq = 2484, .hw_value = 14, },
a66098da
LB
300};
301
777ad375 302static const struct ieee80211_rate mwl8k_rates_24[] = {
a66098da
LB
303 { .bitrate = 10, .hw_value = 2, },
304 { .bitrate = 20, .hw_value = 4, },
305 { .bitrate = 55, .hw_value = 11, },
5dfd3e2c
LB
306 { .bitrate = 110, .hw_value = 22, },
307 { .bitrate = 220, .hw_value = 44, },
a66098da
LB
308 { .bitrate = 60, .hw_value = 12, },
309 { .bitrate = 90, .hw_value = 18, },
a66098da
LB
310 { .bitrate = 120, .hw_value = 24, },
311 { .bitrate = 180, .hw_value = 36, },
312 { .bitrate = 240, .hw_value = 48, },
313 { .bitrate = 360, .hw_value = 72, },
314 { .bitrate = 480, .hw_value = 96, },
315 { .bitrate = 540, .hw_value = 108, },
140eb5e2
LB
316 { .bitrate = 720, .hw_value = 144, },
317};
318
4eae9edd
LB
319static const struct ieee80211_channel mwl8k_channels_50[] = {
320 { .center_freq = 5180, .hw_value = 36, },
321 { .center_freq = 5200, .hw_value = 40, },
322 { .center_freq = 5220, .hw_value = 44, },
323 { .center_freq = 5240, .hw_value = 48, },
324};
325
326static const struct ieee80211_rate mwl8k_rates_50[] = {
327 { .bitrate = 60, .hw_value = 12, },
328 { .bitrate = 90, .hw_value = 18, },
329 { .bitrate = 120, .hw_value = 24, },
330 { .bitrate = 180, .hw_value = 36, },
331 { .bitrate = 240, .hw_value = 48, },
332 { .bitrate = 360, .hw_value = 72, },
333 { .bitrate = 480, .hw_value = 96, },
334 { .bitrate = 540, .hw_value = 108, },
335 { .bitrate = 720, .hw_value = 144, },
336};
337
a66098da 338/* Set or get info from Firmware */
a66098da 339#define MWL8K_CMD_GET 0x0000
41fdf097
NS
340#define MWL8K_CMD_SET 0x0001
341#define MWL8K_CMD_SET_LIST 0x0002
a66098da
LB
342
343/* Firmware command codes */
344#define MWL8K_CMD_CODE_DNLD 0x0001
345#define MWL8K_CMD_GET_HW_SPEC 0x0003
42fba21d 346#define MWL8K_CMD_SET_HW_SPEC 0x0004
a66098da
LB
347#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010
348#define MWL8K_CMD_GET_STAT 0x0014
ff45fc60
LB
349#define MWL8K_CMD_RADIO_CONTROL 0x001c
350#define MWL8K_CMD_RF_TX_POWER 0x001e
41fdf097 351#define MWL8K_CMD_TX_POWER 0x001f
08b06347 352#define MWL8K_CMD_RF_ANTENNA 0x0020
aa21d0f6 353#define MWL8K_CMD_SET_BEACON 0x0100 /* per-vif */
a66098da
LB
354#define MWL8K_CMD_SET_PRE_SCAN 0x0107
355#define MWL8K_CMD_SET_POST_SCAN 0x0108
ff45fc60
LB
356#define MWL8K_CMD_SET_RF_CHANNEL 0x010a
357#define MWL8K_CMD_SET_AID 0x010d
358#define MWL8K_CMD_SET_RATE 0x0110
359#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111
360#define MWL8K_CMD_RTS_THRESHOLD 0x0113
a66098da 361#define MWL8K_CMD_SET_SLOT 0x0114
ff45fc60
LB
362#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115
363#define MWL8K_CMD_SET_WMM_MODE 0x0123
a66098da 364#define MWL8K_CMD_MIMO_CONFIG 0x0125
ff45fc60 365#define MWL8K_CMD_USE_FIXED_RATE 0x0126
a66098da 366#define MWL8K_CMD_ENABLE_SNIFFER 0x0150
aa21d0f6 367#define MWL8K_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
a66098da 368#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
aa21d0f6
LB
369#define MWL8K_CMD_BSS_START 0x1100 /* per-vif */
370#define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */
fcdc403c 371#define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
ff45fc60 372#define MWL8K_CMD_UPDATE_STADB 0x1123
5faa1aff 373#define MWL8K_CMD_BASTREAM 0x1125
a66098da 374
b603742f 375static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
a66098da 376{
b603742f
JL
377 u16 command = le16_to_cpu(cmd);
378
a66098da
LB
379#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\
380 snprintf(buf, bufsize, "%s", #x);\
381 return buf;\
382 } while (0)
b603742f 383 switch (command & ~0x8000) {
a66098da
LB
384 MWL8K_CMDNAME(CODE_DNLD);
385 MWL8K_CMDNAME(GET_HW_SPEC);
42fba21d 386 MWL8K_CMDNAME(SET_HW_SPEC);
a66098da
LB
387 MWL8K_CMDNAME(MAC_MULTICAST_ADR);
388 MWL8K_CMDNAME(GET_STAT);
389 MWL8K_CMDNAME(RADIO_CONTROL);
390 MWL8K_CMDNAME(RF_TX_POWER);
41fdf097 391 MWL8K_CMDNAME(TX_POWER);
08b06347 392 MWL8K_CMDNAME(RF_ANTENNA);
b64fe619 393 MWL8K_CMDNAME(SET_BEACON);
a66098da
LB
394 MWL8K_CMDNAME(SET_PRE_SCAN);
395 MWL8K_CMDNAME(SET_POST_SCAN);
396 MWL8K_CMDNAME(SET_RF_CHANNEL);
ff45fc60
LB
397 MWL8K_CMDNAME(SET_AID);
398 MWL8K_CMDNAME(SET_RATE);
399 MWL8K_CMDNAME(SET_FINALIZE_JOIN);
400 MWL8K_CMDNAME(RTS_THRESHOLD);
a66098da 401 MWL8K_CMDNAME(SET_SLOT);
ff45fc60
LB
402 MWL8K_CMDNAME(SET_EDCA_PARAMS);
403 MWL8K_CMDNAME(SET_WMM_MODE);
a66098da 404 MWL8K_CMDNAME(MIMO_CONFIG);
ff45fc60 405 MWL8K_CMDNAME(USE_FIXED_RATE);
a66098da 406 MWL8K_CMDNAME(ENABLE_SNIFFER);
32060e1b 407 MWL8K_CMDNAME(SET_MAC_ADDR);
a66098da 408 MWL8K_CMDNAME(SET_RATEADAPT_MODE);
b64fe619 409 MWL8K_CMDNAME(BSS_START);
3f5610ff 410 MWL8K_CMDNAME(SET_NEW_STN);
fcdc403c 411 MWL8K_CMDNAME(UPDATE_ENCRYPTION);
ff45fc60 412 MWL8K_CMDNAME(UPDATE_STADB);
5faa1aff 413 MWL8K_CMDNAME(BASTREAM);
a66098da
LB
414 default:
415 snprintf(buf, bufsize, "0x%x", cmd);
416 }
417#undef MWL8K_CMDNAME
418
419 return buf;
420}
421
422/* Hardware and firmware reset */
423static void mwl8k_hw_reset(struct mwl8k_priv *priv)
424{
425 iowrite32(MWL8K_H2A_INT_RESET,
426 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
427 iowrite32(MWL8K_H2A_INT_RESET,
428 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
429 msleep(20);
430}
431
432/* Release fw image */
d1f9e41d 433static void mwl8k_release_fw(const struct firmware **fw)
a66098da
LB
434{
435 if (*fw == NULL)
436 return;
437 release_firmware(*fw);
438 *fw = NULL;
439}
440
441static void mwl8k_release_firmware(struct mwl8k_priv *priv)
442{
22be40d9
LB
443 mwl8k_release_fw(&priv->fw_ucode);
444 mwl8k_release_fw(&priv->fw_helper);
a66098da
LB
445}
446
99020471
BC
447/* states for asynchronous f/w loading */
448static void mwl8k_fw_state_machine(const struct firmware *fw, void *context);
449enum {
450 FW_STATE_INIT = 0,
451 FW_STATE_LOADING_PREF,
452 FW_STATE_LOADING_ALT,
453 FW_STATE_ERROR,
454};
455
a66098da
LB
456/* Request fw image */
457static int mwl8k_request_fw(struct mwl8k_priv *priv,
d1f9e41d 458 const char *fname, const struct firmware **fw,
99020471 459 bool nowait)
a66098da
LB
460{
461 /* release current image */
462 if (*fw != NULL)
463 mwl8k_release_fw(fw);
464
99020471
BC
465 if (nowait)
466 return request_firmware_nowait(THIS_MODULE, 1, fname,
467 &priv->pdev->dev, GFP_KERNEL,
468 priv, mwl8k_fw_state_machine);
469 else
d1f9e41d 470 return request_firmware(fw, fname, &priv->pdev->dev);
a66098da
LB
471}
472
99020471
BC
473static int mwl8k_request_firmware(struct mwl8k_priv *priv, char *fw_image,
474 bool nowait)
a66098da 475{
a74b295e 476 struct mwl8k_device_info *di = priv->device_info;
a66098da
LB
477 int rc;
478
a74b295e 479 if (di->helper_image != NULL) {
99020471
BC
480 if (nowait)
481 rc = mwl8k_request_fw(priv, di->helper_image,
482 &priv->fw_helper, true);
483 else
484 rc = mwl8k_request_fw(priv, di->helper_image,
485 &priv->fw_helper, false);
486 if (rc)
487 printk(KERN_ERR "%s: Error requesting helper fw %s\n",
488 pci_name(priv->pdev), di->helper_image);
489
490 if (rc || nowait)
a74b295e 491 return rc;
a66098da
LB
492 }
493
99020471
BC
494 if (nowait) {
495 /*
496 * if we get here, no helper image is needed. Skip the
497 * FW_STATE_INIT state.
498 */
499 priv->fw_state = FW_STATE_LOADING_PREF;
500 rc = mwl8k_request_fw(priv, fw_image,
501 &priv->fw_ucode,
502 true);
503 } else
504 rc = mwl8k_request_fw(priv, fw_image,
505 &priv->fw_ucode, false);
a66098da 506 if (rc) {
c2c357ce 507 printk(KERN_ERR "%s: Error requesting firmware file %s\n",
0863ade8 508 pci_name(priv->pdev), fw_image);
22be40d9 509 mwl8k_release_fw(&priv->fw_helper);
a66098da
LB
510 return rc;
511 }
512
513 return 0;
514}
515
516struct mwl8k_cmd_pkt {
517 __le16 code;
518 __le16 length;
f57ca9c1
LB
519 __u8 seq_num;
520 __u8 macid;
a66098da
LB
521 __le16 result;
522 char payload[0];
ba2d3587 523} __packed;
a66098da
LB
524
525/*
526 * Firmware loading.
527 */
528static int
529mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
530{
531 void __iomem *regs = priv->regs;
532 dma_addr_t dma_addr;
a66098da
LB
533 int loops;
534
535 dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE);
536 if (pci_dma_mapping_error(priv->pdev, dma_addr))
537 return -ENOMEM;
538
539 iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
540 iowrite32(0, regs + MWL8K_HIU_INT_CODE);
541 iowrite32(MWL8K_H2A_INT_DOORBELL,
542 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
543 iowrite32(MWL8K_H2A_INT_DUMMY,
544 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
545
a66098da
LB
546 loops = 1000;
547 do {
548 u32 int_code;
549
550 int_code = ioread32(regs + MWL8K_HIU_INT_CODE);
551 if (int_code == MWL8K_INT_CODE_CMD_FINISHED) {
552 iowrite32(0, regs + MWL8K_HIU_INT_CODE);
a66098da
LB
553 break;
554 }
555
3d76e82c 556 cond_resched();
a66098da
LB
557 udelay(1);
558 } while (--loops);
559
560 pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE);
561
d4b70570 562 return loops ? 0 : -ETIMEDOUT;
a66098da
LB
563}
564
565static int mwl8k_load_fw_image(struct mwl8k_priv *priv,
566 const u8 *data, size_t length)
567{
568 struct mwl8k_cmd_pkt *cmd;
569 int done;
570 int rc = 0;
571
572 cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL);
573 if (cmd == NULL)
574 return -ENOMEM;
575
576 cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD);
577 cmd->seq_num = 0;
f57ca9c1 578 cmd->macid = 0;
a66098da
LB
579 cmd->result = 0;
580
581 done = 0;
582 while (length) {
583 int block_size = length > 256 ? 256 : length;
584
585 memcpy(cmd->payload, data + done, block_size);
586 cmd->length = cpu_to_le16(block_size);
587
588 rc = mwl8k_send_fw_load_cmd(priv, cmd,
589 sizeof(*cmd) + block_size);
590 if (rc)
591 break;
592
593 done += block_size;
594 length -= block_size;
595 }
596
597 if (!rc) {
598 cmd->length = 0;
599 rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd));
600 }
601
602 kfree(cmd);
603
604 return rc;
605}
606
607static int mwl8k_feed_fw_image(struct mwl8k_priv *priv,
608 const u8 *data, size_t length)
609{
610 unsigned char *buffer;
611 int may_continue, rc = 0;
612 u32 done, prev_block_size;
613
614 buffer = kmalloc(1024, GFP_KERNEL);
615 if (buffer == NULL)
616 return -ENOMEM;
617
618 done = 0;
619 prev_block_size = 0;
620 may_continue = 1000;
621 while (may_continue > 0) {
622 u32 block_size;
623
624 block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH);
625 if (block_size & 1) {
626 block_size &= ~1;
627 may_continue--;
628 } else {
629 done += prev_block_size;
630 length -= prev_block_size;
631 }
632
633 if (block_size > 1024 || block_size > length) {
634 rc = -EOVERFLOW;
635 break;
636 }
637
638 if (length == 0) {
639 rc = 0;
640 break;
641 }
642
643 if (block_size == 0) {
644 rc = -EPROTO;
645 may_continue--;
646 udelay(1);
647 continue;
648 }
649
650 prev_block_size = block_size;
651 memcpy(buffer, data + done, block_size);
652
653 rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size);
654 if (rc)
655 break;
656 }
657
658 if (!rc && length != 0)
659 rc = -EREMOTEIO;
660
661 kfree(buffer);
662
663 return rc;
664}
665
c2c357ce 666static int mwl8k_load_firmware(struct ieee80211_hw *hw)
a66098da 667{
c2c357ce 668 struct mwl8k_priv *priv = hw->priv;
d1f9e41d 669 const struct firmware *fw = priv->fw_ucode;
c2c357ce
LB
670 int rc;
671 int loops;
672
673 if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
d1f9e41d 674 const struct firmware *helper = priv->fw_helper;
a66098da 675
c2c357ce
LB
676 if (helper == NULL) {
677 printk(KERN_ERR "%s: helper image needed but none "
678 "given\n", pci_name(priv->pdev));
679 return -EINVAL;
680 }
a66098da 681
c2c357ce 682 rc = mwl8k_load_fw_image(priv, helper->data, helper->size);
a66098da
LB
683 if (rc) {
684 printk(KERN_ERR "%s: unable to load firmware "
c2c357ce 685 "helper image\n", pci_name(priv->pdev));
a66098da
LB
686 return rc;
687 }
89b872e2 688 msleep(5);
a66098da 689
c2c357ce 690 rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
a66098da 691 } else {
c2c357ce 692 rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
a66098da
LB
693 }
694
695 if (rc) {
c2c357ce
LB
696 printk(KERN_ERR "%s: unable to load firmware image\n",
697 pci_name(priv->pdev));
a66098da
LB
698 return rc;
699 }
700
89a91f4f 701 iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
a66098da 702
89b872e2 703 loops = 500000;
a66098da 704 do {
eae74e65
LB
705 u32 ready_code;
706
707 ready_code = ioread32(priv->regs + MWL8K_HIU_INT_CODE);
708 if (ready_code == MWL8K_FWAP_READY) {
709 priv->ap_fw = 1;
710 break;
711 } else if (ready_code == MWL8K_FWSTA_READY) {
712 priv->ap_fw = 0;
a66098da 713 break;
eae74e65
LB
714 }
715
716 cond_resched();
a66098da
LB
717 udelay(1);
718 } while (--loops);
719
720 return loops ? 0 : -ETIMEDOUT;
721}
722
723
a66098da
LB
724/* DMA header used by firmware and hardware. */
725struct mwl8k_dma_data {
726 __le16 fwlen;
727 struct ieee80211_hdr wh;
20f09c3d 728 char data[0];
ba2d3587 729} __packed;
a66098da
LB
730
731/* Routines to add/remove DMA header from skb. */
20f09c3d 732static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
a66098da 733{
20f09c3d
LB
734 struct mwl8k_dma_data *tr;
735 int hdrlen;
736
737 tr = (struct mwl8k_dma_data *)skb->data;
738 hdrlen = ieee80211_hdrlen(tr->wh.frame_control);
739
740 if (hdrlen != sizeof(tr->wh)) {
741 if (ieee80211_is_data_qos(tr->wh.frame_control)) {
742 memmove(tr->data - hdrlen, &tr->wh, hdrlen - 2);
743 *((__le16 *)(tr->data - 2)) = qos;
744 } else {
745 memmove(tr->data - hdrlen, &tr->wh, hdrlen);
746 }
a66098da 747 }
20f09c3d
LB
748
749 if (hdrlen != sizeof(*tr))
750 skb_pull(skb, sizeof(*tr) - hdrlen);
a66098da
LB
751}
752
252486a1
NS
753static void
754mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
a66098da
LB
755{
756 struct ieee80211_hdr *wh;
ca009301 757 int hdrlen;
252486a1 758 int reqd_hdrlen;
a66098da
LB
759 struct mwl8k_dma_data *tr;
760
ca009301
LB
761 /*
762 * Add a firmware DMA header; the firmware requires that we
763 * present a 2-byte payload length followed by a 4-address
764 * header (without QoS field), followed (optionally) by any
765 * WEP/ExtIV header (but only filled in for CCMP).
766 */
a66098da 767 wh = (struct ieee80211_hdr *)skb->data;
ca009301 768
a66098da 769 hdrlen = ieee80211_hdrlen(wh->frame_control);
252486a1
NS
770 reqd_hdrlen = sizeof(*tr);
771
772 if (hdrlen != reqd_hdrlen)
773 skb_push(skb, reqd_hdrlen - hdrlen);
a66098da 774
ca009301 775 if (ieee80211_is_data_qos(wh->frame_control))
252486a1 776 hdrlen -= IEEE80211_QOS_CTL_LEN;
a66098da
LB
777
778 tr = (struct mwl8k_dma_data *)skb->data;
779 if (wh != &tr->wh)
780 memmove(&tr->wh, wh, hdrlen);
ca009301
LB
781 if (hdrlen != sizeof(tr->wh))
782 memset(((void *)&tr->wh) + hdrlen, 0, sizeof(tr->wh) - hdrlen);
a66098da
LB
783
784 /*
785 * Firmware length is the length of the fully formed "802.11
786 * payload". That is, everything except for the 802.11 header.
787 * This includes all crypto material including the MIC.
788 */
252486a1 789 tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
a66098da
LB
790}
791
e53d9b96
NS
792static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
793{
794 struct ieee80211_hdr *wh;
795 struct ieee80211_tx_info *tx_info;
796 struct ieee80211_key_conf *key_conf;
797 int data_pad;
798
799 wh = (struct ieee80211_hdr *)skb->data;
800
801 tx_info = IEEE80211_SKB_CB(skb);
802
803 key_conf = NULL;
804 if (ieee80211_is_data(wh->frame_control))
805 key_conf = tx_info->control.hw_key;
806
807 /*
808 * Make sure the packet header is in the DMA header format (4-address
809 * without QoS), the necessary crypto padding between the header and the
810 * payload has already been provided by mac80211, but it doesn't add tail
811 * padding when HW crypto is enabled.
812 *
813 * We have the following trailer padding requirements:
814 * - WEP: 4 trailer bytes (ICV)
815 * - TKIP: 12 trailer bytes (8 MIC + 4 ICV)
816 * - CCMP: 8 trailer bytes (MIC)
817 */
818 data_pad = 0;
819 if (key_conf != NULL) {
820 switch (key_conf->cipher) {
821 case WLAN_CIPHER_SUITE_WEP40:
822 case WLAN_CIPHER_SUITE_WEP104:
823 data_pad = 4;
824 break;
825 case WLAN_CIPHER_SUITE_TKIP:
826 data_pad = 12;
827 break;
828 case WLAN_CIPHER_SUITE_CCMP:
829 data_pad = 8;
830 break;
831 }
832 }
833 mwl8k_add_dma_header(skb, data_pad);
834}
a66098da
LB
835
836/*
89a91f4f 837 * Packet reception for 88w8366 AP firmware.
6f6d1e9a 838 */
89a91f4f 839struct mwl8k_rxd_8366_ap {
6f6d1e9a
LB
840 __le16 pkt_len;
841 __u8 sq2;
842 __u8 rate;
843 __le32 pkt_phys_addr;
844 __le32 next_rxd_phys_addr;
845 __le16 qos_control;
846 __le16 htsig2;
847 __le32 hw_rssi_info;
848 __le32 hw_noise_floor_info;
849 __u8 noise_floor;
850 __u8 pad0[3];
851 __u8 rssi;
852 __u8 rx_status;
853 __u8 channel;
854 __u8 rx_ctrl;
ba2d3587 855} __packed;
6f6d1e9a 856
89a91f4f
LB
857#define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80
858#define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40
859#define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f)
8e9f33f0 860
89a91f4f 861#define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80
6f6d1e9a 862
d9a07d49
NS
863/* 8366 AP rx_status bits */
864#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80
865#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF
866#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02
867#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04
868#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08
869
89a91f4f 870static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
6f6d1e9a 871{
89a91f4f 872 struct mwl8k_rxd_8366_ap *rxd = _rxd;
6f6d1e9a
LB
873
874 rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
89a91f4f 875 rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST;
6f6d1e9a
LB
876}
877
89a91f4f 878static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len)
6f6d1e9a 879{
89a91f4f 880 struct mwl8k_rxd_8366_ap *rxd = _rxd;
6f6d1e9a
LB
881
882 rxd->pkt_len = cpu_to_le16(len);
883 rxd->pkt_phys_addr = cpu_to_le32(addr);
884 wmb();
885 rxd->rx_ctrl = 0;
886}
887
888static int
89a91f4f 889mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
0d462bbb 890 __le16 *qos, s8 *noise)
6f6d1e9a 891{
89a91f4f 892 struct mwl8k_rxd_8366_ap *rxd = _rxd;
6f6d1e9a 893
89a91f4f 894 if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST))
6f6d1e9a
LB
895 return -1;
896 rmb();
897
898 memset(status, 0, sizeof(*status));
899
900 status->signal = -rxd->rssi;
0d462bbb 901 *noise = -rxd->noise_floor;
6f6d1e9a 902
89a91f4f 903 if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
6f6d1e9a 904 status->flag |= RX_FLAG_HT;
89a91f4f 905 if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ)
8e9f33f0 906 status->flag |= RX_FLAG_40MHZ;
89a91f4f 907 status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate);
6f6d1e9a
LB
908 } else {
909 int i;
910
777ad375
LB
911 for (i = 0; i < ARRAY_SIZE(mwl8k_rates_24); i++) {
912 if (mwl8k_rates_24[i].hw_value == rxd->rate) {
6f6d1e9a
LB
913 status->rate_idx = i;
914 break;
915 }
916 }
917 }
918
85478344
LB
919 if (rxd->channel > 14) {
920 status->band = IEEE80211_BAND_5GHZ;
921 if (!(status->flag & RX_FLAG_HT))
922 status->rate_idx -= 5;
923 } else {
924 status->band = IEEE80211_BAND_2GHZ;
925 }
59eb21a6
BR
926 status->freq = ieee80211_channel_to_frequency(rxd->channel,
927 status->band);
6f6d1e9a 928
20f09c3d
LB
929 *qos = rxd->qos_control;
930
d9a07d49
NS
931 if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
932 (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
933 (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
934 status->flag |= RX_FLAG_MMIC_ERROR;
935
6f6d1e9a
LB
936 return le16_to_cpu(rxd->pkt_len);
937}
938
89a91f4f
LB
939static struct rxd_ops rxd_8366_ap_ops = {
940 .rxd_size = sizeof(struct mwl8k_rxd_8366_ap),
941 .rxd_init = mwl8k_rxd_8366_ap_init,
942 .rxd_refill = mwl8k_rxd_8366_ap_refill,
943 .rxd_process = mwl8k_rxd_8366_ap_process,
6f6d1e9a
LB
944};
945
946/*
89a91f4f 947 * Packet reception for STA firmware.
a66098da 948 */
89a91f4f 949struct mwl8k_rxd_sta {
a66098da
LB
950 __le16 pkt_len;
951 __u8 link_quality;
952 __u8 noise_level;
953 __le32 pkt_phys_addr;
45eb400d 954 __le32 next_rxd_phys_addr;
a66098da
LB
955 __le16 qos_control;
956 __le16 rate_info;
957 __le32 pad0[4];
958 __u8 rssi;
959 __u8 channel;
960 __le16 pad1;
961 __u8 rx_ctrl;
962 __u8 rx_status;
963 __u8 pad2[2];
ba2d3587 964} __packed;
a66098da 965
89a91f4f
LB
966#define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000
967#define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
968#define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
969#define MWL8K_STA_RATE_INFO_40MHZ 0x0004
970#define MWL8K_STA_RATE_INFO_SHORTGI 0x0002
971#define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001
54bc3a0d 972
89a91f4f 973#define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02
d9a07d49
NS
974#define MWL8K_STA_RX_CTRL_DECRYPT_ERROR 0x04
975/* ICV=0 or MIC=1 */
976#define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE 0x08
977/* Key is uploaded only in failure case */
978#define MWL8K_STA_RX_CTRL_KEY_INDEX 0x30
54bc3a0d 979
89a91f4f 980static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
54bc3a0d 981{
89a91f4f 982 struct mwl8k_rxd_sta *rxd = _rxd;
54bc3a0d
LB
983
984 rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
89a91f4f 985 rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST;
54bc3a0d
LB
986}
987
89a91f4f 988static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len)
54bc3a0d 989{
89a91f4f 990 struct mwl8k_rxd_sta *rxd = _rxd;
54bc3a0d
LB
991
992 rxd->pkt_len = cpu_to_le16(len);
993 rxd->pkt_phys_addr = cpu_to_le32(addr);
994 wmb();
995 rxd->rx_ctrl = 0;
996}
997
998static int
89a91f4f 999mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
0d462bbb 1000 __le16 *qos, s8 *noise)
54bc3a0d 1001{
89a91f4f 1002 struct mwl8k_rxd_sta *rxd = _rxd;
54bc3a0d
LB
1003 u16 rate_info;
1004
89a91f4f 1005 if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST))
54bc3a0d
LB
1006 return -1;
1007 rmb();
1008
1009 rate_info = le16_to_cpu(rxd->rate_info);
1010
1011 memset(status, 0, sizeof(*status));
1012
1013 status->signal = -rxd->rssi;
0d462bbb 1014 *noise = -rxd->noise_level;
89a91f4f
LB
1015 status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
1016 status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
54bc3a0d 1017
89a91f4f 1018 if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE)
54bc3a0d 1019 status->flag |= RX_FLAG_SHORTPRE;
89a91f4f 1020 if (rate_info & MWL8K_STA_RATE_INFO_40MHZ)
54bc3a0d 1021 status->flag |= RX_FLAG_40MHZ;
89a91f4f 1022 if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI)
54bc3a0d 1023 status->flag |= RX_FLAG_SHORT_GI;
89a91f4f 1024 if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT)
54bc3a0d
LB
1025 status->flag |= RX_FLAG_HT;
1026
85478344
LB
1027 if (rxd->channel > 14) {
1028 status->band = IEEE80211_BAND_5GHZ;
1029 if (!(status->flag & RX_FLAG_HT))
1030 status->rate_idx -= 5;
1031 } else {
1032 status->band = IEEE80211_BAND_2GHZ;
1033 }
59eb21a6
BR
1034 status->freq = ieee80211_channel_to_frequency(rxd->channel,
1035 status->band);
54bc3a0d 1036
20f09c3d 1037 *qos = rxd->qos_control;
d9a07d49
NS
1038 if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
1039 (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
1040 status->flag |= RX_FLAG_MMIC_ERROR;
20f09c3d 1041
54bc3a0d
LB
1042 return le16_to_cpu(rxd->pkt_len);
1043}
1044
89a91f4f
LB
1045static struct rxd_ops rxd_sta_ops = {
1046 .rxd_size = sizeof(struct mwl8k_rxd_sta),
1047 .rxd_init = mwl8k_rxd_sta_init,
1048 .rxd_refill = mwl8k_rxd_sta_refill,
1049 .rxd_process = mwl8k_rxd_sta_process,
54bc3a0d
LB
1050};
1051
1052
a66098da
LB
1053#define MWL8K_RX_DESCS 256
1054#define MWL8K_RX_MAXSZ 3800
1055
1056static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
1057{
1058 struct mwl8k_priv *priv = hw->priv;
1059 struct mwl8k_rx_queue *rxq = priv->rxq + index;
1060 int size;
1061 int i;
1062
45eb400d
LB
1063 rxq->rxd_count = 0;
1064 rxq->head = 0;
1065 rxq->tail = 0;
a66098da 1066
54bc3a0d 1067 size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
a66098da 1068
45eb400d
LB
1069 rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
1070 if (rxq->rxd == NULL) {
5db55844 1071 wiphy_err(hw->wiphy, "failed to alloc RX descriptors\n");
a66098da
LB
1072 return -ENOMEM;
1073 }
45eb400d 1074 memset(rxq->rxd, 0, size);
a66098da 1075
b9ede5f1 1076 rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
788838eb 1077 if (rxq->buf == NULL) {
5db55844 1078 wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
45eb400d 1079 pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
a66098da
LB
1080 return -ENOMEM;
1081 }
a66098da
LB
1082
1083 for (i = 0; i < MWL8K_RX_DESCS; i++) {
54bc3a0d
LB
1084 int desc_size;
1085 void *rxd;
a66098da 1086 int nexti;
54bc3a0d
LB
1087 dma_addr_t next_dma_addr;
1088
1089 desc_size = priv->rxd_ops->rxd_size;
1090 rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size);
a66098da 1091
54bc3a0d
LB
1092 nexti = i + 1;
1093 if (nexti == MWL8K_RX_DESCS)
1094 nexti = 0;
1095 next_dma_addr = rxq->rxd_dma + (nexti * desc_size);
a66098da 1096
54bc3a0d 1097 priv->rxd_ops->rxd_init(rxd, next_dma_addr);
a66098da
LB
1098 }
1099
1100 return 0;
1101}
1102
1103static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
1104{
1105 struct mwl8k_priv *priv = hw->priv;
1106 struct mwl8k_rx_queue *rxq = priv->rxq + index;
1107 int refilled;
1108
1109 refilled = 0;
45eb400d 1110 while (rxq->rxd_count < MWL8K_RX_DESCS && limit--) {
a66098da 1111 struct sk_buff *skb;
788838eb 1112 dma_addr_t addr;
a66098da 1113 int rx;
54bc3a0d 1114 void *rxd;
a66098da
LB
1115
1116 skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
1117 if (skb == NULL)
1118 break;
1119
788838eb
LB
1120 addr = pci_map_single(priv->pdev, skb->data,
1121 MWL8K_RX_MAXSZ, DMA_FROM_DEVICE);
a66098da 1122
54bc3a0d
LB
1123 rxq->rxd_count++;
1124 rx = rxq->tail++;
1125 if (rxq->tail == MWL8K_RX_DESCS)
1126 rxq->tail = 0;
788838eb 1127 rxq->buf[rx].skb = skb;
53b1b3e1 1128 dma_unmap_addr_set(&rxq->buf[rx], dma, addr);
54bc3a0d
LB
1129
1130 rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size);
1131 priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ);
a66098da
LB
1132
1133 refilled++;
1134 }
1135
1136 return refilled;
1137}
1138
1139/* Must be called only when the card's reception is completely halted */
1140static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
1141{
1142 struct mwl8k_priv *priv = hw->priv;
1143 struct mwl8k_rx_queue *rxq = priv->rxq + index;
1144 int i;
1145
73b46320
BC
1146 if (rxq->rxd == NULL)
1147 return;
1148
a66098da 1149 for (i = 0; i < MWL8K_RX_DESCS; i++) {
788838eb
LB
1150 if (rxq->buf[i].skb != NULL) {
1151 pci_unmap_single(priv->pdev,
53b1b3e1 1152 dma_unmap_addr(&rxq->buf[i], dma),
788838eb 1153 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
53b1b3e1 1154 dma_unmap_addr_set(&rxq->buf[i], dma, 0);
788838eb
LB
1155
1156 kfree_skb(rxq->buf[i].skb);
1157 rxq->buf[i].skb = NULL;
a66098da
LB
1158 }
1159 }
1160
788838eb
LB
1161 kfree(rxq->buf);
1162 rxq->buf = NULL;
a66098da
LB
1163
1164 pci_free_consistent(priv->pdev,
54bc3a0d 1165 MWL8K_RX_DESCS * priv->rxd_ops->rxd_size,
45eb400d
LB
1166 rxq->rxd, rxq->rxd_dma);
1167 rxq->rxd = NULL;
a66098da
LB
1168}
1169
1170
1171/*
1172 * Scan a list of BSSIDs to process for finalize join.
1173 * Allows for extension to process multiple BSSIDs.
1174 */
1175static inline int
1176mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh)
1177{
1178 return priv->capture_beacon &&
1179 ieee80211_is_beacon(wh->frame_control) &&
1180 !compare_ether_addr(wh->addr3, priv->capture_bssid);
1181}
1182
3779752d
LB
1183static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
1184 struct sk_buff *skb)
a66098da 1185{
3779752d
LB
1186 struct mwl8k_priv *priv = hw->priv;
1187
a66098da 1188 priv->capture_beacon = false;
d89173f2 1189 memset(priv->capture_bssid, 0, ETH_ALEN);
a66098da
LB
1190
1191 /*
1192 * Use GFP_ATOMIC as rxq_process is called from
1193 * the primary interrupt handler, memory allocation call
1194 * must not sleep.
1195 */
1196 priv->beacon_skb = skb_copy(skb, GFP_ATOMIC);
1197 if (priv->beacon_skb != NULL)
3779752d 1198 ieee80211_queue_work(hw, &priv->finalize_join_worker);
a66098da
LB
1199}
1200
d9a07d49
NS
1201static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
1202 u8 *bssid)
1203{
1204 struct mwl8k_vif *mwl8k_vif;
1205
1206 list_for_each_entry(mwl8k_vif,
1207 vif_list, list) {
1208 if (memcmp(bssid, mwl8k_vif->bssid,
1209 ETH_ALEN) == 0)
1210 return mwl8k_vif;
1211 }
1212
1213 return NULL;
1214}
1215
a66098da
LB
1216static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
1217{
1218 struct mwl8k_priv *priv = hw->priv;
d9a07d49 1219 struct mwl8k_vif *mwl8k_vif = NULL;
a66098da
LB
1220 struct mwl8k_rx_queue *rxq = priv->rxq + index;
1221 int processed;
1222
1223 processed = 0;
45eb400d 1224 while (rxq->rxd_count && limit--) {
a66098da 1225 struct sk_buff *skb;
54bc3a0d
LB
1226 void *rxd;
1227 int pkt_len;
a66098da 1228 struct ieee80211_rx_status status;
d9a07d49 1229 struct ieee80211_hdr *wh;
20f09c3d 1230 __le16 qos;
a66098da 1231
788838eb 1232 skb = rxq->buf[rxq->head].skb;
d25f9f13
LB
1233 if (skb == NULL)
1234 break;
54bc3a0d
LB
1235
1236 rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
1237
0d462bbb
JL
1238 pkt_len = priv->rxd_ops->rxd_process(rxd, &status, &qos,
1239 &priv->noise);
54bc3a0d
LB
1240 if (pkt_len < 0)
1241 break;
1242
788838eb
LB
1243 rxq->buf[rxq->head].skb = NULL;
1244
1245 pci_unmap_single(priv->pdev,
53b1b3e1 1246 dma_unmap_addr(&rxq->buf[rxq->head], dma),
788838eb 1247 MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
53b1b3e1 1248 dma_unmap_addr_set(&rxq->buf[rxq->head], dma, 0);
a66098da 1249
54bc3a0d
LB
1250 rxq->head++;
1251 if (rxq->head == MWL8K_RX_DESCS)
1252 rxq->head = 0;
1253
45eb400d 1254 rxq->rxd_count--;
a66098da 1255
d9a07d49 1256 wh = &((struct mwl8k_dma_data *)skb->data)->wh;
a66098da 1257
a66098da 1258 /*
c2c357ce
LB
1259 * Check for a pending join operation. Save a
1260 * copy of the beacon and schedule a tasklet to
1261 * send a FINALIZE_JOIN command to the firmware.
a66098da 1262 */
54bc3a0d 1263 if (mwl8k_capture_bssid(priv, (void *)skb->data))
3779752d 1264 mwl8k_save_beacon(hw, skb);
a66098da 1265
d9a07d49
NS
1266 if (ieee80211_has_protected(wh->frame_control)) {
1267
1268 /* Check if hw crypto has been enabled for
1269 * this bss. If yes, set the status flags
1270 * accordingly
1271 */
1272 mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
1273 wh->addr1);
1274
1275 if (mwl8k_vif != NULL &&
1276 mwl8k_vif->is_hw_crypto_enabled == true) {
1277 /*
1278 * When MMIC ERROR is encountered
1279 * by the firmware, payload is
1280 * dropped and only 32 bytes of
1281 * mwl8k Firmware header is sent
1282 * to the host.
1283 *
1284 * We need to add four bytes of
1285 * key information. In it
1286 * MAC80211 expects keyidx set to
1287 * 0 for triggering Counter
1288 * Measure of MMIC failure.
1289 */
1290 if (status.flag & RX_FLAG_MMIC_ERROR) {
1291 struct mwl8k_dma_data *tr;
1292 tr = (struct mwl8k_dma_data *)skb->data;
1293 memset((void *)&(tr->data), 0, 4);
1294 pkt_len += 4;
1295 }
1296
1297 if (!ieee80211_is_auth(wh->frame_control))
1298 status.flag |= RX_FLAG_IV_STRIPPED |
1299 RX_FLAG_DECRYPTED |
1300 RX_FLAG_MMIC_STRIPPED;
1301 }
1302 }
1303
1304 skb_put(skb, pkt_len);
1305 mwl8k_remove_dma_header(skb, qos);
f1d58c25
JB
1306 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
1307 ieee80211_rx_irqsafe(hw, skb);
a66098da
LB
1308
1309 processed++;
1310 }
1311
1312 return processed;
1313}
1314
1315
1316/*
1317 * Packet transmission.
1318 */
1319
a66098da
LB
1320#define MWL8K_TXD_STATUS_OK 0x00000001
1321#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
1322#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
1323#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008
a66098da 1324#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000
a66098da 1325
e0493a8d
LB
1326#define MWL8K_QOS_QLEN_UNSPEC 0xff00
1327#define MWL8K_QOS_ACK_POLICY_MASK 0x0060
1328#define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000
1329#define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060
1330#define MWL8K_QOS_EOSP 0x0010
1331
a66098da
LB
1332struct mwl8k_tx_desc {
1333 __le32 status;
1334 __u8 data_rate;
1335 __u8 tx_priority;
1336 __le16 qos_control;
1337 __le32 pkt_phys_addr;
1338 __le16 pkt_len;
d89173f2 1339 __u8 dest_MAC_addr[ETH_ALEN];
45eb400d 1340 __le32 next_txd_phys_addr;
8a7a578c 1341 __le32 timestamp;
a66098da
LB
1342 __le16 rate_info;
1343 __u8 peer_id;
a1fe24b0 1344 __u8 tx_frag_cnt;
ba2d3587 1345} __packed;
a66098da
LB
1346
1347#define MWL8K_TX_DESCS 128
1348
1349static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
1350{
1351 struct mwl8k_priv *priv = hw->priv;
1352 struct mwl8k_tx_queue *txq = priv->txq + index;
1353 int size;
1354 int i;
1355
8ccbc3b8 1356 txq->len = 0;
45eb400d
LB
1357 txq->head = 0;
1358 txq->tail = 0;
a66098da
LB
1359
1360 size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
1361
45eb400d
LB
1362 txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
1363 if (txq->txd == NULL) {
5db55844 1364 wiphy_err(hw->wiphy, "failed to alloc TX descriptors\n");
a66098da
LB
1365 return -ENOMEM;
1366 }
45eb400d 1367 memset(txq->txd, 0, size);
a66098da 1368
b9ede5f1 1369 txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
45eb400d 1370 if (txq->skb == NULL) {
5db55844 1371 wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
45eb400d 1372 pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
a66098da
LB
1373 return -ENOMEM;
1374 }
a66098da
LB
1375
1376 for (i = 0; i < MWL8K_TX_DESCS; i++) {
1377 struct mwl8k_tx_desc *tx_desc;
1378 int nexti;
1379
45eb400d 1380 tx_desc = txq->txd + i;
a66098da
LB
1381 nexti = (i + 1) % MWL8K_TX_DESCS;
1382
1383 tx_desc->status = 0;
45eb400d
LB
1384 tx_desc->next_txd_phys_addr =
1385 cpu_to_le32(txq->txd_dma + nexti * sizeof(*tx_desc));
a66098da
LB
1386 }
1387
1388 return 0;
1389}
1390
1391static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
1392{
1393 iowrite32(MWL8K_H2A_INT_PPA_READY,
1394 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1395 iowrite32(MWL8K_H2A_INT_DUMMY,
1396 priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1397 ioread32(priv->regs + MWL8K_HIU_INT_CODE);
1398}
1399
7e1112d3 1400static void mwl8k_dump_tx_rings(struct ieee80211_hw *hw)
a66098da 1401{
7e1112d3
LB
1402 struct mwl8k_priv *priv = hw->priv;
1403 int i;
1404
e600707b 1405 for (i = 0; i < mwl8k_tx_queues(priv); i++) {
7e1112d3
LB
1406 struct mwl8k_tx_queue *txq = priv->txq + i;
1407 int fw_owned = 0;
1408 int drv_owned = 0;
1409 int unused = 0;
1410 int desc;
1411
a66098da 1412 for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
7e1112d3
LB
1413 struct mwl8k_tx_desc *tx_desc = txq->txd + desc;
1414 u32 status;
a66098da 1415
7e1112d3 1416 status = le32_to_cpu(tx_desc->status);
a66098da 1417 if (status & MWL8K_TXD_STATUS_FW_OWNED)
7e1112d3 1418 fw_owned++;
a66098da 1419 else
7e1112d3 1420 drv_owned++;
a66098da
LB
1421
1422 if (tx_desc->pkt_len == 0)
7e1112d3 1423 unused++;
a66098da 1424 }
a66098da 1425
c96c31e4
JP
1426 wiphy_err(hw->wiphy,
1427 "txq[%d] len=%d head=%d tail=%d "
1428 "fw_owned=%d drv_owned=%d unused=%d\n",
1429 i,
1430 txq->len, txq->head, txq->tail,
1431 fw_owned, drv_owned, unused);
7e1112d3 1432 }
a66098da
LB
1433}
1434
618952a7 1435/*
88de754a 1436 * Must be called with priv->fw_mutex held and tx queues stopped.
618952a7 1437 */
62abd3cf 1438#define MWL8K_TX_WAIT_TIMEOUT_MS 5000
7e1112d3 1439
950d5b01 1440static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
a66098da 1441{
a66098da 1442 struct mwl8k_priv *priv = hw->priv;
88de754a 1443 DECLARE_COMPLETION_ONSTACK(tx_wait);
7e1112d3
LB
1444 int retry;
1445 int rc;
a66098da
LB
1446
1447 might_sleep();
1448
7e1112d3
LB
1449 /*
1450 * The TX queues are stopped at this point, so this test
1451 * doesn't need to take ->tx_lock.
1452 */
1453 if (!priv->pending_tx_pkts)
1454 return 0;
1455
1456 retry = 0;
1457 rc = 0;
1458
a66098da 1459 spin_lock_bh(&priv->tx_lock);
7e1112d3
LB
1460 priv->tx_wait = &tx_wait;
1461 while (!rc) {
1462 int oldcount;
1463 unsigned long timeout;
a66098da 1464
7e1112d3 1465 oldcount = priv->pending_tx_pkts;
a66098da 1466
7e1112d3 1467 spin_unlock_bh(&priv->tx_lock);
88de754a 1468 timeout = wait_for_completion_timeout(&tx_wait,
7e1112d3 1469 msecs_to_jiffies(MWL8K_TX_WAIT_TIMEOUT_MS));
a66098da 1470 spin_lock_bh(&priv->tx_lock);
7e1112d3
LB
1471
1472 if (timeout) {
1473 WARN_ON(priv->pending_tx_pkts);
1474 if (retry) {
c96c31e4 1475 wiphy_notice(hw->wiphy, "tx rings drained\n");
7e1112d3
LB
1476 }
1477 break;
1478 }
1479
1480 if (priv->pending_tx_pkts < oldcount) {
c96c31e4
JP
1481 wiphy_notice(hw->wiphy,
1482 "waiting for tx rings to drain (%d -> %d pkts)\n",
1483 oldcount, priv->pending_tx_pkts);
7e1112d3
LB
1484 retry = 1;
1485 continue;
1486 }
1487
a66098da 1488 priv->tx_wait = NULL;
a66098da 1489
c96c31e4
JP
1490 wiphy_err(hw->wiphy, "tx rings stuck for %d ms\n",
1491 MWL8K_TX_WAIT_TIMEOUT_MS);
7e1112d3
LB
1492 mwl8k_dump_tx_rings(hw);
1493
1494 rc = -ETIMEDOUT;
a66098da 1495 }
7e1112d3 1496 spin_unlock_bh(&priv->tx_lock);
a66098da 1497
7e1112d3 1498 return rc;
a66098da
LB
1499}
1500
c23b5a69
LB
1501#define MWL8K_TXD_SUCCESS(status) \
1502 ((status) & (MWL8K_TXD_STATUS_OK | \
1503 MWL8K_TXD_STATUS_OK_RETRY | \
1504 MWL8K_TXD_STATUS_OK_MORE_RETRY))
a66098da 1505
efb7c49a
LB
1506static int
1507mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
a66098da
LB
1508{
1509 struct mwl8k_priv *priv = hw->priv;
1510 struct mwl8k_tx_queue *txq = priv->txq + index;
efb7c49a 1511 int processed;
a66098da 1512
efb7c49a 1513 processed = 0;
8ccbc3b8 1514 while (txq->len > 0 && limit--) {
a66098da 1515 int tx;
a66098da
LB
1516 struct mwl8k_tx_desc *tx_desc;
1517 unsigned long addr;
ce9e2e1b 1518 int size;
a66098da
LB
1519 struct sk_buff *skb;
1520 struct ieee80211_tx_info *info;
1521 u32 status;
1522
45eb400d
LB
1523 tx = txq->head;
1524 tx_desc = txq->txd + tx;
a66098da
LB
1525
1526 status = le32_to_cpu(tx_desc->status);
1527
1528 if (status & MWL8K_TXD_STATUS_FW_OWNED) {
1529 if (!force)
1530 break;
1531 tx_desc->status &=
1532 ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED);
1533 }
1534
45eb400d 1535 txq->head = (tx + 1) % MWL8K_TX_DESCS;
8ccbc3b8
KV
1536 BUG_ON(txq->len == 0);
1537 txq->len--;
a66098da
LB
1538 priv->pending_tx_pkts--;
1539
1540 addr = le32_to_cpu(tx_desc->pkt_phys_addr);
ce9e2e1b 1541 size = le16_to_cpu(tx_desc->pkt_len);
45eb400d
LB
1542 skb = txq->skb[tx];
1543 txq->skb[tx] = NULL;
a66098da
LB
1544
1545 BUG_ON(skb == NULL);
1546 pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
1547
20f09c3d 1548 mwl8k_remove_dma_header(skb, tx_desc->qos_control);
a66098da
LB
1549
1550 /* Mark descriptor as unused */
1551 tx_desc->pkt_phys_addr = 0;
1552 tx_desc->pkt_len = 0;
1553
a66098da
LB
1554 info = IEEE80211_SKB_CB(skb);
1555 ieee80211_tx_info_clear_status(info);
0bf22c37
NS
1556
1557 /* Rate control is happening in the firmware.
1558 * Ensure no tx rate is being reported.
1559 */
1560 info->status.rates[0].idx = -1;
1561 info->status.rates[0].count = 1;
1562
ce9e2e1b 1563 if (MWL8K_TXD_SUCCESS(status))
a66098da 1564 info->flags |= IEEE80211_TX_STAT_ACK;
a66098da
LB
1565
1566 ieee80211_tx_status_irqsafe(hw, skb);
1567
efb7c49a 1568 processed++;
a66098da
LB
1569 }
1570
efb7c49a 1571 if (processed && priv->radio_on && !mutex_is_locked(&priv->fw_mutex))
a66098da 1572 ieee80211_wake_queue(hw, index);
efb7c49a
LB
1573
1574 return processed;
a66098da
LB
1575}
1576
1577/* must be called only when the card's transmit is completely halted */
1578static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
1579{
1580 struct mwl8k_priv *priv = hw->priv;
1581 struct mwl8k_tx_queue *txq = priv->txq + index;
1582
73b46320
BC
1583 if (txq->txd == NULL)
1584 return;
1585
efb7c49a 1586 mwl8k_txq_reclaim(hw, index, INT_MAX, 1);
a66098da 1587
45eb400d
LB
1588 kfree(txq->skb);
1589 txq->skb = NULL;
a66098da
LB
1590
1591 pci_free_consistent(priv->pdev,
1592 MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc),
45eb400d
LB
1593 txq->txd, txq->txd_dma);
1594 txq->txd = NULL;
a66098da
LB
1595}
1596
7bb45683 1597static void
a66098da
LB
1598mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
1599{
1600 struct mwl8k_priv *priv = hw->priv;
1601 struct ieee80211_tx_info *tx_info;
23b33906 1602 struct mwl8k_vif *mwl8k_vif;
a66098da
LB
1603 struct ieee80211_hdr *wh;
1604 struct mwl8k_tx_queue *txq;
1605 struct mwl8k_tx_desc *tx;
a66098da 1606 dma_addr_t dma;
23b33906
LB
1607 u32 txstatus;
1608 u8 txdatarate;
1609 u16 qos;
a66098da 1610
23b33906
LB
1611 wh = (struct ieee80211_hdr *)skb->data;
1612 if (ieee80211_is_data_qos(wh->frame_control))
1613 qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
1614 else
1615 qos = 0;
a66098da 1616
d9a07d49
NS
1617 if (priv->ap_fw)
1618 mwl8k_encapsulate_tx_frame(skb);
1619 else
1620 mwl8k_add_dma_header(skb, 0);
1621
23b33906 1622 wh = &((struct mwl8k_dma_data *)skb->data)->wh;
a66098da
LB
1623
1624 tx_info = IEEE80211_SKB_CB(skb);
1625 mwl8k_vif = MWL8K_VIF(tx_info->control.vif);
a66098da
LB
1626
1627 if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
a66098da 1628 wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
657232b6
LB
1629 wh->seq_ctrl |= cpu_to_le16(mwl8k_vif->seqno);
1630 mwl8k_vif->seqno += 0x10;
a66098da
LB
1631 }
1632
23b33906
LB
1633 /* Setup firmware control bit fields for each frame type. */
1634 txstatus = 0;
1635 txdatarate = 0;
1636 if (ieee80211_is_mgmt(wh->frame_control) ||
1637 ieee80211_is_ctl(wh->frame_control)) {
1638 txdatarate = 0;
e0493a8d 1639 qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP;
23b33906
LB
1640 } else if (ieee80211_is_data(wh->frame_control)) {
1641 txdatarate = 1;
1642 if (is_multicast_ether_addr(wh->addr1))
1643 txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX;
1644
e0493a8d 1645 qos &= ~MWL8K_QOS_ACK_POLICY_MASK;
23b33906 1646 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU)
e0493a8d 1647 qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK;
23b33906 1648 else
e0493a8d 1649 qos |= MWL8K_QOS_ACK_POLICY_NORMAL;
23b33906 1650 }
a66098da
LB
1651
1652 dma = pci_map_single(priv->pdev, skb->data,
1653 skb->len, PCI_DMA_TODEVICE);
1654
1655 if (pci_dma_mapping_error(priv->pdev, dma)) {
c96c31e4
JP
1656 wiphy_debug(hw->wiphy,
1657 "failed to dma map skb, dropping TX frame.\n");
23b33906 1658 dev_kfree_skb(skb);
7bb45683 1659 return;
a66098da
LB
1660 }
1661
23b33906 1662 spin_lock_bh(&priv->tx_lock);
a66098da 1663
23b33906 1664 txq = priv->txq + index;
a66098da 1665
45eb400d
LB
1666 BUG_ON(txq->skb[txq->tail] != NULL);
1667 txq->skb[txq->tail] = skb;
a66098da 1668
45eb400d 1669 tx = txq->txd + txq->tail;
23b33906
LB
1670 tx->data_rate = txdatarate;
1671 tx->tx_priority = index;
a66098da 1672 tx->qos_control = cpu_to_le16(qos);
a66098da
LB
1673 tx->pkt_phys_addr = cpu_to_le32(dma);
1674 tx->pkt_len = cpu_to_le16(skb->len);
23b33906 1675 tx->rate_info = 0;
a680400e
LB
1676 if (!priv->ap_fw && tx_info->control.sta != NULL)
1677 tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
1678 else
1679 tx->peer_id = 0;
a66098da 1680 wmb();
23b33906
LB
1681 tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
1682
8ccbc3b8 1683 txq->len++;
a66098da 1684 priv->pending_tx_pkts++;
a66098da 1685
45eb400d
LB
1686 txq->tail++;
1687 if (txq->tail == MWL8K_TX_DESCS)
1688 txq->tail = 0;
23b33906 1689
45eb400d 1690 if (txq->head == txq->tail)
a66098da
LB
1691 ieee80211_stop_queue(hw, index);
1692
23b33906 1693 mwl8k_tx_start(priv);
a66098da
LB
1694
1695 spin_unlock_bh(&priv->tx_lock);
a66098da
LB
1696}
1697
1698
618952a7
LB
1699/*
1700 * Firmware access.
1701 *
1702 * We have the following requirements for issuing firmware commands:
1703 * - Some commands require that the packet transmit path is idle when
1704 * the command is issued. (For simplicity, we'll just quiesce the
1705 * transmit path for every command.)
1706 * - There are certain sequences of commands that need to be issued to
1707 * the hardware sequentially, with no other intervening commands.
1708 *
1709 * This leads to an implementation of a "firmware lock" as a mutex that
1710 * can be taken recursively, and which is taken by both the low-level
1711 * command submission function (mwl8k_post_cmd) as well as any users of
1712 * that function that require issuing of an atomic sequence of commands,
1713 * and quiesces the transmit path whenever it's taken.
1714 */
1715static int mwl8k_fw_lock(struct ieee80211_hw *hw)
1716{
1717 struct mwl8k_priv *priv = hw->priv;
1718
1719 if (priv->fw_mutex_owner != current) {
1720 int rc;
1721
1722 mutex_lock(&priv->fw_mutex);
1723 ieee80211_stop_queues(hw);
1724
1725 rc = mwl8k_tx_wait_empty(hw);
1726 if (rc) {
1727 ieee80211_wake_queues(hw);
1728 mutex_unlock(&priv->fw_mutex);
1729
1730 return rc;
1731 }
1732
1733 priv->fw_mutex_owner = current;
1734 }
1735
1736 priv->fw_mutex_depth++;
1737
1738 return 0;
1739}
1740
1741static void mwl8k_fw_unlock(struct ieee80211_hw *hw)
1742{
1743 struct mwl8k_priv *priv = hw->priv;
1744
1745 if (!--priv->fw_mutex_depth) {
1746 ieee80211_wake_queues(hw);
1747 priv->fw_mutex_owner = NULL;
1748 mutex_unlock(&priv->fw_mutex);
1749 }
1750}
1751
1752
a66098da
LB
1753/*
1754 * Command processing.
1755 */
1756
0c9cc640
LB
1757/* Timeout firmware commands after 10s */
1758#define MWL8K_CMD_TIMEOUT_MS 10000
a66098da
LB
1759
1760static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
1761{
1762 DECLARE_COMPLETION_ONSTACK(cmd_wait);
1763 struct mwl8k_priv *priv = hw->priv;
1764 void __iomem *regs = priv->regs;
1765 dma_addr_t dma_addr;
1766 unsigned int dma_size;
1767 int rc;
a66098da
LB
1768 unsigned long timeout = 0;
1769 u8 buf[32];
1770
b603742f 1771 cmd->result = (__force __le16) 0xffff;
a66098da
LB
1772 dma_size = le16_to_cpu(cmd->length);
1773 dma_addr = pci_map_single(priv->pdev, cmd, dma_size,
1774 PCI_DMA_BIDIRECTIONAL);
1775 if (pci_dma_mapping_error(priv->pdev, dma_addr))
1776 return -ENOMEM;
1777
618952a7 1778 rc = mwl8k_fw_lock(hw);
39a1e42e
LB
1779 if (rc) {
1780 pci_unmap_single(priv->pdev, dma_addr, dma_size,
1781 PCI_DMA_BIDIRECTIONAL);
618952a7 1782 return rc;
39a1e42e 1783 }
a66098da 1784
a66098da
LB
1785 priv->hostcmd_wait = &cmd_wait;
1786 iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR);
1787 iowrite32(MWL8K_H2A_INT_DOORBELL,
1788 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
1789 iowrite32(MWL8K_H2A_INT_DUMMY,
1790 regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS);
a66098da
LB
1791
1792 timeout = wait_for_completion_timeout(&cmd_wait,
1793 msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS));
1794
618952a7
LB
1795 priv->hostcmd_wait = NULL;
1796
1797 mwl8k_fw_unlock(hw);
1798
37055bd4
LB
1799 pci_unmap_single(priv->pdev, dma_addr, dma_size,
1800 PCI_DMA_BIDIRECTIONAL);
1801
a66098da 1802 if (!timeout) {
5db55844 1803 wiphy_err(hw->wiphy, "Command %s timeout after %u ms\n",
c96c31e4
JP
1804 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1805 MWL8K_CMD_TIMEOUT_MS);
a66098da
LB
1806 rc = -ETIMEDOUT;
1807 } else {
0c9cc640
LB
1808 int ms;
1809
1810 ms = MWL8K_CMD_TIMEOUT_MS - jiffies_to_msecs(timeout);
1811
ce9e2e1b 1812 rc = cmd->result ? -EINVAL : 0;
a66098da 1813 if (rc)
5db55844 1814 wiphy_err(hw->wiphy, "Command %s error 0x%x\n",
c96c31e4
JP
1815 mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
1816 le16_to_cpu(cmd->result));
0c9cc640 1817 else if (ms > 2000)
5db55844 1818 wiphy_notice(hw->wiphy, "Command %s took %d ms\n",
c96c31e4
JP
1819 mwl8k_cmd_name(cmd->code,
1820 buf, sizeof(buf)),
1821 ms);
a66098da
LB
1822 }
1823
a66098da
LB
1824 return rc;
1825}
1826
f57ca9c1
LB
1827static int mwl8k_post_pervif_cmd(struct ieee80211_hw *hw,
1828 struct ieee80211_vif *vif,
1829 struct mwl8k_cmd_pkt *cmd)
1830{
1831 if (vif != NULL)
1832 cmd->macid = MWL8K_VIF(vif)->macid;
1833 return mwl8k_post_cmd(hw, cmd);
1834}
1835
1349ad2f
LB
1836/*
1837 * Setup code shared between STA and AP firmware images.
1838 */
1839static void mwl8k_setup_2ghz_band(struct ieee80211_hw *hw)
1840{
1841 struct mwl8k_priv *priv = hw->priv;
1842
1843 BUILD_BUG_ON(sizeof(priv->channels_24) != sizeof(mwl8k_channels_24));
1844 memcpy(priv->channels_24, mwl8k_channels_24, sizeof(mwl8k_channels_24));
1845
1846 BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl8k_rates_24));
1847 memcpy(priv->rates_24, mwl8k_rates_24, sizeof(mwl8k_rates_24));
1848
1849 priv->band_24.band = IEEE80211_BAND_2GHZ;
1850 priv->band_24.channels = priv->channels_24;
1851 priv->band_24.n_channels = ARRAY_SIZE(mwl8k_channels_24);
1852 priv->band_24.bitrates = priv->rates_24;
1853 priv->band_24.n_bitrates = ARRAY_SIZE(mwl8k_rates_24);
1854
1855 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24;
1856}
1857
4eae9edd
LB
1858static void mwl8k_setup_5ghz_band(struct ieee80211_hw *hw)
1859{
1860 struct mwl8k_priv *priv = hw->priv;
1861
1862 BUILD_BUG_ON(sizeof(priv->channels_50) != sizeof(mwl8k_channels_50));
1863 memcpy(priv->channels_50, mwl8k_channels_50, sizeof(mwl8k_channels_50));
1864
1865 BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl8k_rates_50));
1866 memcpy(priv->rates_50, mwl8k_rates_50, sizeof(mwl8k_rates_50));
1867
1868 priv->band_50.band = IEEE80211_BAND_5GHZ;
1869 priv->band_50.channels = priv->channels_50;
1870 priv->band_50.n_channels = ARRAY_SIZE(mwl8k_channels_50);
1871 priv->band_50.bitrates = priv->rates_50;
1872 priv->band_50.n_bitrates = ARRAY_SIZE(mwl8k_rates_50);
1873
1874 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50;
1875}
1876
a66098da 1877/*
04b147b1 1878 * CMD_GET_HW_SPEC (STA version).
a66098da 1879 */
04b147b1 1880struct mwl8k_cmd_get_hw_spec_sta {
a66098da
LB
1881 struct mwl8k_cmd_pkt header;
1882 __u8 hw_rev;
1883 __u8 host_interface;
1884 __le16 num_mcaddrs;
d89173f2 1885 __u8 perm_addr[ETH_ALEN];
a66098da
LB
1886 __le16 region_code;
1887 __le32 fw_rev;
1888 __le32 ps_cookie;
1889 __le32 caps;
1890 __u8 mcs_bitmap[16];
1891 __le32 rx_queue_ptr;
1892 __le32 num_tx_queues;
e600707b 1893 __le32 tx_queue_ptrs[MWL8K_TX_WMM_QUEUES];
a66098da
LB
1894 __le32 caps2;
1895 __le32 num_tx_desc_per_queue;
45eb400d 1896 __le32 total_rxd;
ba2d3587 1897} __packed;
a66098da 1898
341c9791
LB
1899#define MWL8K_CAP_MAX_AMSDU 0x20000000
1900#define MWL8K_CAP_GREENFIELD 0x08000000
1901#define MWL8K_CAP_AMPDU 0x04000000
1902#define MWL8K_CAP_RX_STBC 0x01000000
1903#define MWL8K_CAP_TX_STBC 0x00800000
1904#define MWL8K_CAP_SHORTGI_40MHZ 0x00400000
1905#define MWL8K_CAP_SHORTGI_20MHZ 0x00200000
1906#define MWL8K_CAP_RX_ANTENNA_MASK 0x000e0000
1907#define MWL8K_CAP_TX_ANTENNA_MASK 0x0001c000
1908#define MWL8K_CAP_DELAY_BA 0x00003000
1909#define MWL8K_CAP_MIMO 0x00000200
1910#define MWL8K_CAP_40MHZ 0x00000100
06953235
LB
1911#define MWL8K_CAP_BAND_MASK 0x00000007
1912#define MWL8K_CAP_5GHZ 0x00000004
1913#define MWL8K_CAP_2GHZ4 0x00000001
341c9791 1914
06953235
LB
1915static void
1916mwl8k_set_ht_caps(struct ieee80211_hw *hw,
1917 struct ieee80211_supported_band *band, u32 cap)
341c9791 1918{
341c9791
LB
1919 int rx_streams;
1920 int tx_streams;
1921
777ad375 1922 band->ht_cap.ht_supported = 1;
341c9791
LB
1923
1924 if (cap & MWL8K_CAP_MAX_AMSDU)
777ad375 1925 band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
341c9791 1926 if (cap & MWL8K_CAP_GREENFIELD)
777ad375 1927 band->ht_cap.cap |= IEEE80211_HT_CAP_GRN_FLD;
341c9791
LB
1928 if (cap & MWL8K_CAP_AMPDU) {
1929 hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
777ad375
LB
1930 band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
1931 band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
341c9791
LB
1932 }
1933 if (cap & MWL8K_CAP_RX_STBC)
777ad375 1934 band->ht_cap.cap |= IEEE80211_HT_CAP_RX_STBC;
341c9791 1935 if (cap & MWL8K_CAP_TX_STBC)
777ad375 1936 band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
341c9791 1937 if (cap & MWL8K_CAP_SHORTGI_40MHZ)
777ad375 1938 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
341c9791 1939 if (cap & MWL8K_CAP_SHORTGI_20MHZ)
777ad375 1940 band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
341c9791 1941 if (cap & MWL8K_CAP_DELAY_BA)
777ad375 1942 band->ht_cap.cap |= IEEE80211_HT_CAP_DELAY_BA;
341c9791 1943 if (cap & MWL8K_CAP_40MHZ)
777ad375 1944 band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
341c9791
LB
1945
1946 rx_streams = hweight32(cap & MWL8K_CAP_RX_ANTENNA_MASK);
1947 tx_streams = hweight32(cap & MWL8K_CAP_TX_ANTENNA_MASK);
1948
777ad375 1949 band->ht_cap.mcs.rx_mask[0] = 0xff;
341c9791 1950 if (rx_streams >= 2)
777ad375 1951 band->ht_cap.mcs.rx_mask[1] = 0xff;
341c9791 1952 if (rx_streams >= 3)
777ad375
LB
1953 band->ht_cap.mcs.rx_mask[2] = 0xff;
1954 band->ht_cap.mcs.rx_mask[4] = 0x01;
1955 band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
341c9791
LB
1956
1957 if (rx_streams != tx_streams) {
777ad375
LB
1958 band->ht_cap.mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
1959 band->ht_cap.mcs.tx_params |= (tx_streams - 1) <<
341c9791
LB
1960 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
1961 }
1962}
1963
06953235
LB
1964static void
1965mwl8k_set_caps(struct ieee80211_hw *hw, u32 caps)
1966{
1967 struct mwl8k_priv *priv = hw->priv;
1968
1969 if ((caps & MWL8K_CAP_2GHZ4) || !(caps & MWL8K_CAP_BAND_MASK)) {
1970 mwl8k_setup_2ghz_band(hw);
1971 if (caps & MWL8K_CAP_MIMO)
1972 mwl8k_set_ht_caps(hw, &priv->band_24, caps);
1973 }
1974
1975 if (caps & MWL8K_CAP_5GHZ) {
1976 mwl8k_setup_5ghz_band(hw);
1977 if (caps & MWL8K_CAP_MIMO)
1978 mwl8k_set_ht_caps(hw, &priv->band_50, caps);
1979 }
1980}
1981
04b147b1 1982static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
a66098da
LB
1983{
1984 struct mwl8k_priv *priv = hw->priv;
04b147b1 1985 struct mwl8k_cmd_get_hw_spec_sta *cmd;
a66098da
LB
1986 int rc;
1987 int i;
1988
1989 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
1990 if (cmd == NULL)
1991 return -ENOMEM;
1992
1993 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
1994 cmd->header.length = cpu_to_le16(sizeof(*cmd));
1995
1996 memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
1997 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
45eb400d 1998 cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
e600707b
BC
1999 cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv));
2000 for (i = 0; i < mwl8k_tx_queues(priv); i++)
45eb400d 2001 cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
4ff6432e 2002 cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
45eb400d 2003 cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
a66098da
LB
2004
2005 rc = mwl8k_post_cmd(hw, &cmd->header);
2006
2007 if (!rc) {
2008 SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
2009 priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
4ff6432e 2010 priv->fw_rev = le32_to_cpu(cmd->fw_rev);
a66098da 2011 priv->hw_rev = cmd->hw_rev;
06953235 2012 mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
ee0ddf18
LB
2013 priv->ap_macids_supported = 0x00000000;
2014 priv->sta_macids_supported = 0x00000001;
a66098da
LB
2015 }
2016
2017 kfree(cmd);
2018 return rc;
2019}
2020
42fba21d
LB
2021/*
2022 * CMD_GET_HW_SPEC (AP version).
2023 */
2024struct mwl8k_cmd_get_hw_spec_ap {
2025 struct mwl8k_cmd_pkt header;
2026 __u8 hw_rev;
2027 __u8 host_interface;
2028 __le16 num_wcb;
2029 __le16 num_mcaddrs;
2030 __u8 perm_addr[ETH_ALEN];
2031 __le16 region_code;
2032 __le16 num_antenna;
2033 __le32 fw_rev;
2034 __le32 wcbbase0;
2035 __le32 rxwrptr;
2036 __le32 rxrdptr;
2037 __le32 ps_cookie;
2038 __le32 wcbbase1;
2039 __le32 wcbbase2;
2040 __le32 wcbbase3;
952a0e96 2041 __le32 fw_api_version;
8a7a578c
BC
2042 __le32 caps;
2043 __le32 num_of_ampdu_queues;
2044 __le32 wcbbase_ampdu[MWL8K_MAX_AMPDU_QUEUES];
ba2d3587 2045} __packed;
42fba21d
LB
2046
2047static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
2048{
2049 struct mwl8k_priv *priv = hw->priv;
2050 struct mwl8k_cmd_get_hw_spec_ap *cmd;
8a7a578c 2051 int rc, i;
952a0e96 2052 u32 api_version;
42fba21d
LB
2053
2054 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2055 if (cmd == NULL)
2056 return -ENOMEM;
2057
2058 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
2059 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2060
2061 memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
2062 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
2063
2064 rc = mwl8k_post_cmd(hw, &cmd->header);
2065
2066 if (!rc) {
2067 int off;
2068
952a0e96
BC
2069 api_version = le32_to_cpu(cmd->fw_api_version);
2070 if (priv->device_info->fw_api_ap != api_version) {
2071 printk(KERN_ERR "%s: Unsupported fw API version for %s."
2072 " Expected %d got %d.\n", MWL8K_NAME,
2073 priv->device_info->part_name,
2074 priv->device_info->fw_api_ap,
2075 api_version);
2076 rc = -EINVAL;
2077 goto done;
2078 }
42fba21d
LB
2079 SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
2080 priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
2081 priv->fw_rev = le32_to_cpu(cmd->fw_rev);
2082 priv->hw_rev = cmd->hw_rev;
8a7a578c 2083 mwl8k_set_caps(hw, le32_to_cpu(cmd->caps));
ee0ddf18
LB
2084 priv->ap_macids_supported = 0x000000ff;
2085 priv->sta_macids_supported = 0x00000000;
8a7a578c
BC
2086 priv->num_ampdu_queues = le32_to_cpu(cmd->num_of_ampdu_queues);
2087 if (priv->num_ampdu_queues > MWL8K_MAX_AMPDU_QUEUES) {
2088 wiphy_warn(hw->wiphy, "fw reported %d ampdu queues"
2089 " but we only support %d.\n",
2090 priv->num_ampdu_queues,
2091 MWL8K_MAX_AMPDU_QUEUES);
2092 priv->num_ampdu_queues = MWL8K_MAX_AMPDU_QUEUES;
2093 }
42fba21d 2094 off = le32_to_cpu(cmd->rxwrptr) & 0xffff;
b603742f 2095 iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
42fba21d
LB
2096
2097 off = le32_to_cpu(cmd->rxrdptr) & 0xffff;
b603742f 2098 iowrite32(priv->rxq[0].rxd_dma, priv->sram + off);
42fba21d 2099
73b46320
BC
2100 priv->txq_offset[0] = le32_to_cpu(cmd->wcbbase0) & 0xffff;
2101 priv->txq_offset[1] = le32_to_cpu(cmd->wcbbase1) & 0xffff;
2102 priv->txq_offset[2] = le32_to_cpu(cmd->wcbbase2) & 0xffff;
2103 priv->txq_offset[3] = le32_to_cpu(cmd->wcbbase3) & 0xffff;
8a7a578c
BC
2104
2105 for (i = 0; i < priv->num_ampdu_queues; i++)
e600707b 2106 priv->txq_offset[i + MWL8K_TX_WMM_QUEUES] =
8a7a578c 2107 le32_to_cpu(cmd->wcbbase_ampdu[i]) & 0xffff;
42fba21d
LB
2108 }
2109
952a0e96 2110done:
42fba21d
LB
2111 kfree(cmd);
2112 return rc;
2113}
2114
2115/*
2116 * CMD_SET_HW_SPEC.
2117 */
2118struct mwl8k_cmd_set_hw_spec {
2119 struct mwl8k_cmd_pkt header;
2120 __u8 hw_rev;
2121 __u8 host_interface;
2122 __le16 num_mcaddrs;
2123 __u8 perm_addr[ETH_ALEN];
2124 __le16 region_code;
2125 __le32 fw_rev;
2126 __le32 ps_cookie;
2127 __le32 caps;
2128 __le32 rx_queue_ptr;
2129 __le32 num_tx_queues;
e600707b 2130 __le32 tx_queue_ptrs[MWL8K_MAX_TX_QUEUES];
42fba21d
LB
2131 __le32 flags;
2132 __le32 num_tx_desc_per_queue;
2133 __le32 total_rxd;
ba2d3587 2134} __packed;
42fba21d 2135
8a7a578c
BC
2136/* If enabled, MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY will cause
2137 * packets to expire 500 ms after the timestamp in the tx descriptor. That is,
2138 * the packets that are queued for more than 500ms, will be dropped in the
2139 * hardware. This helps minimizing the issues caused due to head-of-line
2140 * blocking where a slow client can hog the bandwidth and affect traffic to a
2141 * faster client.
2142 */
2143#define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400
b64fe619
LB
2144#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
2145#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP 0x00000020
2146#define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON 0x00000010
42fba21d
LB
2147
2148static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
2149{
2150 struct mwl8k_priv *priv = hw->priv;
2151 struct mwl8k_cmd_set_hw_spec *cmd;
2152 int rc;
2153 int i;
2154
2155 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2156 if (cmd == NULL)
2157 return -ENOMEM;
2158
2159 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC);
2160 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2161
2162 cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
2163 cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
e600707b 2164 cmd->num_tx_queues = cpu_to_le32(mwl8k_tx_queues(priv));
85c9205c
NS
2165
2166 /*
2167 * Mac80211 stack has Q0 as highest priority and Q3 as lowest in
2168 * that order. Firmware has Q3 as highest priority and Q0 as lowest
2169 * in that order. Map Q3 of mac80211 to Q0 of firmware so that the
2170 * priority is interpreted the right way in firmware.
2171 */
e600707b
BC
2172 for (i = 0; i < mwl8k_tx_queues(priv); i++) {
2173 int j = mwl8k_tx_queues(priv) - 1 - i;
85c9205c
NS
2174 cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma);
2175 }
2176
b64fe619
LB
2177 cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
2178 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
2179 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON);
42fba21d
LB
2180 cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
2181 cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
2182
2183 rc = mwl8k_post_cmd(hw, &cmd->header);
2184 kfree(cmd);
2185
2186 return rc;
2187}
2188
a66098da
LB
2189/*
2190 * CMD_MAC_MULTICAST_ADR.
2191 */
2192struct mwl8k_cmd_mac_multicast_adr {
2193 struct mwl8k_cmd_pkt header;
2194 __le16 action;
2195 __le16 numaddr;
ce9e2e1b 2196 __u8 addr[0][ETH_ALEN];
a66098da
LB
2197};
2198
d5e30845
LB
2199#define MWL8K_ENABLE_RX_DIRECTED 0x0001
2200#define MWL8K_ENABLE_RX_MULTICAST 0x0002
2201#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004
2202#define MWL8K_ENABLE_RX_BROADCAST 0x0008
ce9e2e1b 2203
e81cd2d6 2204static struct mwl8k_cmd_pkt *
447ced07 2205__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
22bedad3 2206 struct netdev_hw_addr_list *mc_list)
a66098da 2207{
e81cd2d6 2208 struct mwl8k_priv *priv = hw->priv;
a66098da 2209 struct mwl8k_cmd_mac_multicast_adr *cmd;
e81cd2d6 2210 int size;
22bedad3
JP
2211 int mc_count = 0;
2212
2213 if (mc_list)
2214 mc_count = netdev_hw_addr_list_count(mc_list);
e81cd2d6 2215
447ced07 2216 if (allmulti || mc_count > priv->num_mcaddrs) {
d5e30845
LB
2217 allmulti = 1;
2218 mc_count = 0;
2219 }
e81cd2d6
LB
2220
2221 size = sizeof(*cmd) + mc_count * ETH_ALEN;
ce9e2e1b 2222
e81cd2d6 2223 cmd = kzalloc(size, GFP_ATOMIC);
a66098da 2224 if (cmd == NULL)
e81cd2d6 2225 return NULL;
a66098da
LB
2226
2227 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
2228 cmd->header.length = cpu_to_le16(size);
d5e30845
LB
2229 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED |
2230 MWL8K_ENABLE_RX_BROADCAST);
2231
2232 if (allmulti) {
2233 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST);
2234 } else if (mc_count) {
22bedad3
JP
2235 struct netdev_hw_addr *ha;
2236 int i = 0;
d5e30845
LB
2237
2238 cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
2239 cmd->numaddr = cpu_to_le16(mc_count);
22bedad3
JP
2240 netdev_hw_addr_list_for_each(ha, mc_list) {
2241 memcpy(cmd->addr[i], ha->addr, ETH_ALEN);
a66098da 2242 }
a66098da
LB
2243 }
2244
e81cd2d6 2245 return &cmd->header;
a66098da
LB
2246}
2247
2248/*
55489b6e 2249 * CMD_GET_STAT.
a66098da 2250 */
55489b6e 2251struct mwl8k_cmd_get_stat {
a66098da 2252 struct mwl8k_cmd_pkt header;
a66098da 2253 __le32 stats[64];
ba2d3587 2254} __packed;
a66098da
LB
2255
2256#define MWL8K_STAT_ACK_FAILURE 9
2257#define MWL8K_STAT_RTS_FAILURE 12
2258#define MWL8K_STAT_FCS_ERROR 24
2259#define MWL8K_STAT_RTS_SUCCESS 11
2260
55489b6e
LB
2261static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw,
2262 struct ieee80211_low_level_stats *stats)
a66098da 2263{
55489b6e 2264 struct mwl8k_cmd_get_stat *cmd;
a66098da
LB
2265 int rc;
2266
2267 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2268 if (cmd == NULL)
2269 return -ENOMEM;
2270
2271 cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT);
2272 cmd->header.length = cpu_to_le16(sizeof(*cmd));
a66098da
LB
2273
2274 rc = mwl8k_post_cmd(hw, &cmd->header);
2275 if (!rc) {
2276 stats->dot11ACKFailureCount =
2277 le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]);
2278 stats->dot11RTSFailureCount =
2279 le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]);
2280 stats->dot11FCSErrorCount =
2281 le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]);
2282 stats->dot11RTSSuccessCount =
2283 le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]);
2284 }
2285 kfree(cmd);
2286
2287 return rc;
2288}
2289
2290/*
55489b6e 2291 * CMD_RADIO_CONTROL.
a66098da 2292 */
55489b6e 2293struct mwl8k_cmd_radio_control {
a66098da
LB
2294 struct mwl8k_cmd_pkt header;
2295 __le16 action;
2296 __le16 control;
2297 __le16 radio_on;
ba2d3587 2298} __packed;
a66098da 2299
c46563b7 2300static int
55489b6e 2301mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force)
a66098da
LB
2302{
2303 struct mwl8k_priv *priv = hw->priv;
55489b6e 2304 struct mwl8k_cmd_radio_control *cmd;
a66098da
LB
2305 int rc;
2306
c46563b7 2307 if (enable == priv->radio_on && !force)
a66098da
LB
2308 return 0;
2309
a66098da
LB
2310 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2311 if (cmd == NULL)
2312 return -ENOMEM;
2313
2314 cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL);
2315 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2316 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
68ce3884 2317 cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1);
a66098da
LB
2318 cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000);
2319
2320 rc = mwl8k_post_cmd(hw, &cmd->header);
2321 kfree(cmd);
2322
2323 if (!rc)
c46563b7 2324 priv->radio_on = enable;
a66098da
LB
2325
2326 return rc;
2327}
2328
55489b6e 2329static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw)
c46563b7 2330{
55489b6e 2331 return mwl8k_cmd_radio_control(hw, 0, 0);
c46563b7
LB
2332}
2333
55489b6e 2334static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw)
c46563b7 2335{
55489b6e 2336 return mwl8k_cmd_radio_control(hw, 1, 0);
c46563b7
LB
2337}
2338
a66098da
LB
2339static int
2340mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
2341{
99200a99 2342 struct mwl8k_priv *priv = hw->priv;
a66098da 2343
68ce3884 2344 priv->radio_short_preamble = short_preamble;
a66098da 2345
55489b6e 2346 return mwl8k_cmd_radio_control(hw, 1, 1);
a66098da
LB
2347}
2348
2349/*
55489b6e 2350 * CMD_RF_TX_POWER.
a66098da 2351 */
41fdf097 2352#define MWL8K_RF_TX_POWER_LEVEL_TOTAL 8
a66098da 2353
55489b6e 2354struct mwl8k_cmd_rf_tx_power {
a66098da
LB
2355 struct mwl8k_cmd_pkt header;
2356 __le16 action;
2357 __le16 support_level;
2358 __le16 current_level;
2359 __le16 reserved;
41fdf097 2360 __le16 power_level_list[MWL8K_RF_TX_POWER_LEVEL_TOTAL];
ba2d3587 2361} __packed;
a66098da 2362
55489b6e 2363static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm)
a66098da 2364{
55489b6e 2365 struct mwl8k_cmd_rf_tx_power *cmd;
a66098da
LB
2366 int rc;
2367
2368 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2369 if (cmd == NULL)
2370 return -ENOMEM;
2371
2372 cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER);
2373 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2374 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
2375 cmd->support_level = cpu_to_le16(dBm);
2376
2377 rc = mwl8k_post_cmd(hw, &cmd->header);
2378 kfree(cmd);
2379
2380 return rc;
2381}
2382
41fdf097
NS
2383/*
2384 * CMD_TX_POWER.
2385 */
2386#define MWL8K_TX_POWER_LEVEL_TOTAL 12
2387
2388struct mwl8k_cmd_tx_power {
2389 struct mwl8k_cmd_pkt header;
2390 __le16 action;
2391 __le16 band;
2392 __le16 channel;
2393 __le16 bw;
2394 __le16 sub_ch;
2395 __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL];
2396} __attribute__((packed));
2397
2398static int mwl8k_cmd_tx_power(struct ieee80211_hw *hw,
2399 struct ieee80211_conf *conf,
2400 unsigned short pwr)
2401{
2402 struct ieee80211_channel *channel = conf->channel;
2403 struct mwl8k_cmd_tx_power *cmd;
2404 int rc;
2405 int i;
2406
2407 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2408 if (cmd == NULL)
2409 return -ENOMEM;
2410
2411 cmd->header.code = cpu_to_le16(MWL8K_CMD_TX_POWER);
2412 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2413 cmd->action = cpu_to_le16(MWL8K_CMD_SET_LIST);
2414
2415 if (channel->band == IEEE80211_BAND_2GHZ)
2416 cmd->band = cpu_to_le16(0x1);
2417 else if (channel->band == IEEE80211_BAND_5GHZ)
2418 cmd->band = cpu_to_le16(0x4);
2419
2420 cmd->channel = channel->hw_value;
2421
2422 if (conf->channel_type == NL80211_CHAN_NO_HT ||
2423 conf->channel_type == NL80211_CHAN_HT20) {
2424 cmd->bw = cpu_to_le16(0x2);
2425 } else {
2426 cmd->bw = cpu_to_le16(0x4);
2427 if (conf->channel_type == NL80211_CHAN_HT40MINUS)
2428 cmd->sub_ch = cpu_to_le16(0x3);
2429 else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
2430 cmd->sub_ch = cpu_to_le16(0x1);
2431 }
2432
2433 for (i = 0; i < MWL8K_TX_POWER_LEVEL_TOTAL; i++)
2434 cmd->power_level_list[i] = cpu_to_le16(pwr);
2435
2436 rc = mwl8k_post_cmd(hw, &cmd->header);
2437 kfree(cmd);
2438
2439 return rc;
2440}
2441
08b06347
LB
2442/*
2443 * CMD_RF_ANTENNA.
2444 */
2445struct mwl8k_cmd_rf_antenna {
2446 struct mwl8k_cmd_pkt header;
2447 __le16 antenna;
2448 __le16 mode;
ba2d3587 2449} __packed;
08b06347
LB
2450
2451#define MWL8K_RF_ANTENNA_RX 1
2452#define MWL8K_RF_ANTENNA_TX 2
2453
2454static int
2455mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
2456{
2457 struct mwl8k_cmd_rf_antenna *cmd;
2458 int rc;
2459
2460 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2461 if (cmd == NULL)
2462 return -ENOMEM;
2463
2464 cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_ANTENNA);
2465 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2466 cmd->antenna = cpu_to_le16(antenna);
2467 cmd->mode = cpu_to_le16(mask);
2468
2469 rc = mwl8k_post_cmd(hw, &cmd->header);
2470 kfree(cmd);
2471
2472 return rc;
2473}
2474
b64fe619
LB
2475/*
2476 * CMD_SET_BEACON.
2477 */
2478struct mwl8k_cmd_set_beacon {
2479 struct mwl8k_cmd_pkt header;
2480 __le16 beacon_len;
2481 __u8 beacon[0];
2482};
2483
aa21d0f6
LB
2484static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
2485 struct ieee80211_vif *vif, u8 *beacon, int len)
b64fe619
LB
2486{
2487 struct mwl8k_cmd_set_beacon *cmd;
2488 int rc;
2489
2490 cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
2491 if (cmd == NULL)
2492 return -ENOMEM;
2493
2494 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
2495 cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
2496 cmd->beacon_len = cpu_to_le16(len);
2497 memcpy(cmd->beacon, beacon, len);
2498
aa21d0f6 2499 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
b64fe619
LB
2500 kfree(cmd);
2501
2502 return rc;
2503}
2504
a66098da
LB
2505/*
2506 * CMD_SET_PRE_SCAN.
2507 */
2508struct mwl8k_cmd_set_pre_scan {
2509 struct mwl8k_cmd_pkt header;
ba2d3587 2510} __packed;
a66098da
LB
2511
2512static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw)
2513{
2514 struct mwl8k_cmd_set_pre_scan *cmd;
2515 int rc;
2516
2517 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2518 if (cmd == NULL)
2519 return -ENOMEM;
2520
2521 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN);
2522 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2523
2524 rc = mwl8k_post_cmd(hw, &cmd->header);
2525 kfree(cmd);
2526
2527 return rc;
2528}
2529
2530/*
2531 * CMD_SET_POST_SCAN.
2532 */
2533struct mwl8k_cmd_set_post_scan {
2534 struct mwl8k_cmd_pkt header;
2535 __le32 isibss;
d89173f2 2536 __u8 bssid[ETH_ALEN];
ba2d3587 2537} __packed;
a66098da
LB
2538
2539static int
0a11dfc3 2540mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, const __u8 *mac)
a66098da
LB
2541{
2542 struct mwl8k_cmd_set_post_scan *cmd;
2543 int rc;
2544
2545 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2546 if (cmd == NULL)
2547 return -ENOMEM;
2548
2549 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN);
2550 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2551 cmd->isibss = 0;
d89173f2 2552 memcpy(cmd->bssid, mac, ETH_ALEN);
a66098da
LB
2553
2554 rc = mwl8k_post_cmd(hw, &cmd->header);
2555 kfree(cmd);
2556
2557 return rc;
2558}
2559
2560/*
2561 * CMD_SET_RF_CHANNEL.
2562 */
2563struct mwl8k_cmd_set_rf_channel {
2564 struct mwl8k_cmd_pkt header;
2565 __le16 action;
2566 __u8 current_channel;
2567 __le32 channel_flags;
ba2d3587 2568} __packed;
a66098da
LB
2569
2570static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw,
610677d2 2571 struct ieee80211_conf *conf)
a66098da 2572{
610677d2 2573 struct ieee80211_channel *channel = conf->channel;
a66098da
LB
2574 struct mwl8k_cmd_set_rf_channel *cmd;
2575 int rc;
2576
2577 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2578 if (cmd == NULL)
2579 return -ENOMEM;
2580
2581 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL);
2582 cmd->header.length = cpu_to_le16(sizeof(*cmd));
2583 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
2584 cmd->current_channel = channel->hw_value;
610677d2 2585
a66098da 2586 if (channel->band == IEEE80211_BAND_2GHZ)
610677d2 2587 cmd->channel_flags |= cpu_to_le32(0x00000001);
42574ea2
LB
2588 else if (channel->band == IEEE80211_BAND_5GHZ)
2589 cmd->channel_flags |= cpu_to_le32(0x00000004);
610677d2
LB
2590
2591 if (conf->channel_type == NL80211_CHAN_NO_HT ||
2592 conf->channel_type == NL80211_CHAN_HT20)
2593 cmd->channel_flags |= cpu_to_le32(0x00000080);
2594 else if (conf->channel_type == NL80211_CHAN_HT40MINUS)
2595 cmd->channel_flags |= cpu_to_le32(0x000001900);
2596 else if (conf->channel_type == NL80211_CHAN_HT40PLUS)
2597 cmd->channel_flags |= cpu_to_le32(0x000000900);
a66098da
LB
2598
2599 rc = mwl8k_post_cmd(hw, &cmd->header);
2600 kfree(cmd);
2601
2602 return rc;
2603}
2604
2605/*
55489b6e 2606 * CMD_SET_AID.
a66098da 2607 */
55489b6e
LB
2608#define MWL8K_FRAME_PROT_DISABLED 0x00
2609#define MWL8K_FRAME_PROT_11G 0x07
2610#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02
2611#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06
a66098da 2612
55489b6e
LB
2613struct mwl8k_cmd_update_set_aid {
2614 struct mwl8k_cmd_pkt header;
2615 __le16 aid;
a66098da 2616
55489b6e
LB
2617 /* AP's MAC address (BSSID) */
2618 __u8 bssid[ETH_ALEN];
2619 __le16 protection_mode;
2620 __u8 supp_rates[14];
ba2d3587 2621} __packed;
a66098da 2622
c6e96010
LB
2623static void legacy_rate_mask_to_array(u8 *rates, u32 mask)
2624{
2625 int i;
2626 int j;
2627
2628 /*
2629 * Clear nonstandard rates 4 and 13.
2630 */
2631 mask &= 0x1fef;
2632
2633 for (i = 0, j = 0; i < 14; i++) {
2634 if (mask & (1 << i))
777ad375 2635 rates[j++] = mwl8k_rates_24[i].hw_value;
c6e96010
LB
2636 }
2637}
2638
55489b6e 2639static int
c6e96010
LB
2640mwl8k_cmd_set_aid(struct ieee80211_hw *hw,
2641 struct ieee80211_vif *vif, u32 legacy_rate_mask)
a66098da 2642{
55489b6e
LB
2643 struct mwl8k_cmd_update_set_aid *cmd;
2644 u16 prot_mode;
a66098da
LB
2645 int rc;
2646
2647 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2648 if (cmd == NULL)
2649 return -ENOMEM;
2650
55489b6e 2651 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID);
a66098da 2652 cmd->header.length = cpu_to_le16(sizeof(*cmd));
7dc6a7a7 2653 cmd->aid = cpu_to_le16(vif->bss_conf.aid);
0a11dfc3 2654 memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
a66098da 2655
7dc6a7a7 2656 if (vif->bss_conf.use_cts_prot) {
55489b6e
LB
2657 prot_mode = MWL8K_FRAME_PROT_11G;
2658 } else {
7dc6a7a7 2659 switch (vif->bss_conf.ht_operation_mode &
55489b6e
LB
2660 IEEE80211_HT_OP_MODE_PROTECTION) {
2661 case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
2662 prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY;
2663 break;
2664 case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
2665 prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL;
2666 break;
2667 default:
2668 prot_mode = MWL8K_FRAME_PROT_DISABLED;
2669 break;
2670 }
2671 }
2672 cmd->protection_mode = cpu_to_le16(prot_mode);
a66098da 2673
c6e96010 2674 legacy_rate_mask_to_array(cmd->supp_rates, legacy_rate_mask);
a66098da
LB
2675
2676 rc = mwl8k_post_cmd(hw, &cmd->header);
2677 kfree(cmd);
2678
2679 return rc;
2680}
2681
32060e1b 2682/*
55489b6e 2683 * CMD_SET_RATE.
32060e1b 2684 */
55489b6e
LB
2685struct mwl8k_cmd_set_rate {
2686 struct mwl8k_cmd_pkt header;
2687 __u8 legacy_rates[14];
2688
2689 /* Bitmap for supported MCS codes. */
2690 __u8 mcs_set[16];
2691 __u8 reserved[16];
ba2d3587 2692} __packed;
32060e1b 2693
55489b6e 2694static int
c6e96010 2695mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
13935e2c 2696 u32 legacy_rate_mask, u8 *mcs_rates)
32060e1b 2697{
55489b6e 2698 struct mwl8k_cmd_set_rate *cmd;
32060e1b
LB
2699 int rc;
2700
2701 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2702 if (cmd == NULL)
2703 return -ENOMEM;
2704
55489b6e 2705 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE);
32060e1b 2706 cmd->header.length = cpu_to_le16(sizeof(*cmd));
c6e96010 2707 legacy_rate_mask_to_array(cmd->legacy_rates, legacy_rate_mask);
13935e2c 2708 memcpy(cmd->mcs_set, mcs_rates, 16);
32060e1b
LB
2709
2710 rc = mwl8k_post_cmd(hw, &cmd->header);
2711 kfree(cmd);
2712
2713 return rc;
2714}
2715
a66098da 2716/*
55489b6e 2717 * CMD_FINALIZE_JOIN.
a66098da 2718 */
55489b6e
LB
2719#define MWL8K_FJ_BEACON_MAXLEN 128
2720
2721struct mwl8k_cmd_finalize_join {
a66098da 2722 struct mwl8k_cmd_pkt header;
55489b6e
LB
2723 __le32 sleep_interval; /* Number of beacon periods to sleep */
2724 __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN];
ba2d3587 2725} __packed;
a66098da 2726
55489b6e
LB
2727static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame,
2728 int framelen, int dtim)
a66098da 2729{
55489b6e
LB
2730 struct mwl8k_cmd_finalize_join *cmd;
2731 struct ieee80211_mgmt *payload = frame;
2732 int payload_len;
a66098da
LB
2733 int rc;
2734
2735 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2736 if (cmd == NULL)
2737 return -ENOMEM;
2738
55489b6e 2739 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN);
a66098da 2740 cmd->header.length = cpu_to_le16(sizeof(*cmd));
55489b6e
LB
2741 cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1);
2742
2743 payload_len = framelen - ieee80211_hdrlen(payload->frame_control);
2744 if (payload_len < 0)
2745 payload_len = 0;
2746 else if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
2747 payload_len = MWL8K_FJ_BEACON_MAXLEN;
2748
2749 memcpy(cmd->beacon_data, &payload->u.beacon, payload_len);
a66098da
LB
2750
2751 rc = mwl8k_post_cmd(hw, &cmd->header);
2752 kfree(cmd);
2753
2754 return rc;
2755}
2756
2757/*
55489b6e 2758 * CMD_SET_RTS_THRESHOLD.
a66098da 2759 */
55489b6e 2760struct mwl8k_cmd_set_rts_threshold {
a66098da
LB
2761 struct mwl8k_cmd_pkt header;
2762 __le16 action;
55489b6e 2763 __le16 threshold;
ba2d3587 2764} __packed;
a66098da 2765
c2c2b12a
LB
2766static int
2767mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, int rts_thresh)
a66098da 2768{
55489b6e 2769 struct mwl8k_cmd_set_rts_threshold *cmd;
a66098da
LB
2770 int rc;
2771
2772 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2773 if (cmd == NULL)
2774 return -ENOMEM;
2775
55489b6e 2776 cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD);
a66098da 2777 cmd->header.length = cpu_to_le16(sizeof(*cmd));
c2c2b12a
LB
2778 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
2779 cmd->threshold = cpu_to_le16(rts_thresh);
a66098da
LB
2780
2781 rc = mwl8k_post_cmd(hw, &cmd->header);
2782 kfree(cmd);
2783
a66098da
LB
2784 return rc;
2785}
2786
2787/*
55489b6e 2788 * CMD_SET_SLOT.
a66098da 2789 */
55489b6e 2790struct mwl8k_cmd_set_slot {
a66098da
LB
2791 struct mwl8k_cmd_pkt header;
2792 __le16 action;
55489b6e 2793 __u8 short_slot;
ba2d3587 2794} __packed;
a66098da 2795
55489b6e 2796static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time)
a66098da 2797{
55489b6e 2798 struct mwl8k_cmd_set_slot *cmd;
a66098da
LB
2799 int rc;
2800
2801 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2802 if (cmd == NULL)
2803 return -ENOMEM;
2804
55489b6e 2805 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT);
a66098da 2806 cmd->header.length = cpu_to_le16(sizeof(*cmd));
55489b6e
LB
2807 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
2808 cmd->short_slot = short_slot_time;
a66098da
LB
2809
2810 rc = mwl8k_post_cmd(hw, &cmd->header);
2811 kfree(cmd);
2812
2813 return rc;
2814}
2815
2816/*
2817 * CMD_SET_EDCA_PARAMS.
2818 */
2819struct mwl8k_cmd_set_edca_params {
2820 struct mwl8k_cmd_pkt header;
2821
2822 /* See MWL8K_SET_EDCA_XXX below */
2823 __le16 action;
2824
2825 /* TX opportunity in units of 32 us */
2826 __le16 txop;
2827
2e484c89
LB
2828 union {
2829 struct {
2830 /* Log exponent of max contention period: 0...15 */
2831 __le32 log_cw_max;
2832
2833 /* Log exponent of min contention period: 0...15 */
2834 __le32 log_cw_min;
2835
2836 /* Adaptive interframe spacing in units of 32us */
2837 __u8 aifs;
2838
2839 /* TX queue to configure */
2840 __u8 txq;
2841 } ap;
2842 struct {
2843 /* Log exponent of max contention period: 0...15 */
2844 __u8 log_cw_max;
a66098da 2845
2e484c89
LB
2846 /* Log exponent of min contention period: 0...15 */
2847 __u8 log_cw_min;
a66098da 2848
2e484c89
LB
2849 /* Adaptive interframe spacing in units of 32us */
2850 __u8 aifs;
a66098da 2851
2e484c89
LB
2852 /* TX queue to configure */
2853 __u8 txq;
2854 } sta;
2855 };
ba2d3587 2856} __packed;
a66098da 2857
a66098da
LB
2858#define MWL8K_SET_EDCA_CW 0x01
2859#define MWL8K_SET_EDCA_TXOP 0x02
2860#define MWL8K_SET_EDCA_AIFS 0x04
2861
2862#define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \
2863 MWL8K_SET_EDCA_TXOP | \
2864 MWL8K_SET_EDCA_AIFS)
2865
2866static int
55489b6e
LB
2867mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
2868 __u16 cw_min, __u16 cw_max,
2869 __u8 aifs, __u16 txop)
a66098da 2870{
2e484c89 2871 struct mwl8k_priv *priv = hw->priv;
a66098da 2872 struct mwl8k_cmd_set_edca_params *cmd;
a66098da
LB
2873 int rc;
2874
2875 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2876 if (cmd == NULL)
2877 return -ENOMEM;
2878
a66098da
LB
2879 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
2880 cmd->header.length = cpu_to_le16(sizeof(*cmd));
a66098da
LB
2881 cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
2882 cmd->txop = cpu_to_le16(txop);
2e484c89
LB
2883 if (priv->ap_fw) {
2884 cmd->ap.log_cw_max = cpu_to_le32(ilog2(cw_max + 1));
2885 cmd->ap.log_cw_min = cpu_to_le32(ilog2(cw_min + 1));
2886 cmd->ap.aifs = aifs;
2887 cmd->ap.txq = qnum;
2888 } else {
2889 cmd->sta.log_cw_max = (u8)ilog2(cw_max + 1);
2890 cmd->sta.log_cw_min = (u8)ilog2(cw_min + 1);
2891 cmd->sta.aifs = aifs;
2892 cmd->sta.txq = qnum;
2893 }
a66098da
LB
2894
2895 rc = mwl8k_post_cmd(hw, &cmd->header);
2896 kfree(cmd);
2897
2898 return rc;
2899}
2900
2901/*
55489b6e 2902 * CMD_SET_WMM_MODE.
a66098da 2903 */
55489b6e 2904struct mwl8k_cmd_set_wmm_mode {
a66098da 2905 struct mwl8k_cmd_pkt header;
55489b6e 2906 __le16 action;
ba2d3587 2907} __packed;
a66098da 2908
55489b6e 2909static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
a66098da 2910{
55489b6e
LB
2911 struct mwl8k_priv *priv = hw->priv;
2912 struct mwl8k_cmd_set_wmm_mode *cmd;
a66098da
LB
2913 int rc;
2914
a66098da
LB
2915 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2916 if (cmd == NULL)
2917 return -ENOMEM;
2918
55489b6e 2919 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE);
a66098da 2920 cmd->header.length = cpu_to_le16(sizeof(*cmd));
55489b6e 2921 cmd->action = cpu_to_le16(!!enable);
a66098da
LB
2922
2923 rc = mwl8k_post_cmd(hw, &cmd->header);
2924 kfree(cmd);
16cec43d 2925
55489b6e
LB
2926 if (!rc)
2927 priv->wmm_enabled = enable;
a66098da
LB
2928
2929 return rc;
2930}
2931
2932/*
55489b6e 2933 * CMD_MIMO_CONFIG.
a66098da 2934 */
55489b6e
LB
2935struct mwl8k_cmd_mimo_config {
2936 struct mwl8k_cmd_pkt header;
2937 __le32 action;
2938 __u8 rx_antenna_map;
2939 __u8 tx_antenna_map;
ba2d3587 2940} __packed;
a66098da 2941
55489b6e 2942static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx)
a66098da 2943{
55489b6e 2944 struct mwl8k_cmd_mimo_config *cmd;
a66098da
LB
2945 int rc;
2946
2947 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2948 if (cmd == NULL)
2949 return -ENOMEM;
2950
55489b6e 2951 cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG);
a66098da 2952 cmd->header.length = cpu_to_le16(sizeof(*cmd));
55489b6e
LB
2953 cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET);
2954 cmd->rx_antenna_map = rx;
2955 cmd->tx_antenna_map = tx;
a66098da
LB
2956
2957 rc = mwl8k_post_cmd(hw, &cmd->header);
2958 kfree(cmd);
2959
2960 return rc;
2961}
2962
2963/*
b71ed2c6 2964 * CMD_USE_FIXED_RATE (STA version).
a66098da 2965 */
b71ed2c6
LB
2966struct mwl8k_cmd_use_fixed_rate_sta {
2967 struct mwl8k_cmd_pkt header;
2968 __le32 action;
2969 __le32 allow_rate_drop;
2970 __le32 num_rates;
2971 struct {
2972 __le32 is_ht_rate;
2973 __le32 enable_retry;
2974 __le32 rate;
2975 __le32 retry_count;
2976 } rate_entry[8];
2977 __le32 rate_type;
2978 __le32 reserved1;
2979 __le32 reserved2;
ba2d3587 2980} __packed;
a66098da 2981
b71ed2c6
LB
2982#define MWL8K_USE_AUTO_RATE 0x0002
2983#define MWL8K_UCAST_RATE 0
a66098da 2984
b71ed2c6 2985static int mwl8k_cmd_use_fixed_rate_sta(struct ieee80211_hw *hw)
a66098da 2986{
b71ed2c6 2987 struct mwl8k_cmd_use_fixed_rate_sta *cmd;
a66098da
LB
2988 int rc;
2989
2990 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
2991 if (cmd == NULL)
2992 return -ENOMEM;
2993
2994 cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
2995 cmd->header.length = cpu_to_le16(sizeof(*cmd));
b71ed2c6
LB
2996 cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
2997 cmd->rate_type = cpu_to_le32(MWL8K_UCAST_RATE);
a66098da
LB
2998
2999 rc = mwl8k_post_cmd(hw, &cmd->header);
3000 kfree(cmd);
3001
3002 return rc;
3003}
3004
088aab8b
LB
3005/*
3006 * CMD_USE_FIXED_RATE (AP version).
3007 */
3008struct mwl8k_cmd_use_fixed_rate_ap {
3009 struct mwl8k_cmd_pkt header;
3010 __le32 action;
3011 __le32 allow_rate_drop;
3012 __le32 num_rates;
3013 struct mwl8k_rate_entry_ap {
3014 __le32 is_ht_rate;
3015 __le32 enable_retry;
3016 __le32 rate;
3017 __le32 retry_count;
3018 } rate_entry[4];
3019 u8 multicast_rate;
3020 u8 multicast_rate_type;
3021 u8 management_rate;
ba2d3587 3022} __packed;
088aab8b
LB
3023
3024static int
3025mwl8k_cmd_use_fixed_rate_ap(struct ieee80211_hw *hw, int mcast, int mgmt)
3026{
3027 struct mwl8k_cmd_use_fixed_rate_ap *cmd;
3028 int rc;
3029
3030 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3031 if (cmd == NULL)
3032 return -ENOMEM;
3033
3034 cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE);
3035 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3036 cmd->action = cpu_to_le32(MWL8K_USE_AUTO_RATE);
3037 cmd->multicast_rate = mcast;
3038 cmd->management_rate = mgmt;
3039
3040 rc = mwl8k_post_cmd(hw, &cmd->header);
3041 kfree(cmd);
3042
3043 return rc;
3044}
3045
55489b6e
LB
3046/*
3047 * CMD_ENABLE_SNIFFER.
3048 */
3049struct mwl8k_cmd_enable_sniffer {
3050 struct mwl8k_cmd_pkt header;
3051 __le32 action;
ba2d3587 3052} __packed;
55489b6e
LB
3053
3054static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable)
3055{
3056 struct mwl8k_cmd_enable_sniffer *cmd;
3057 int rc;
3058
3059 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3060 if (cmd == NULL)
3061 return -ENOMEM;
3062
3063 cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER);
3064 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3065 cmd->action = cpu_to_le32(!!enable);
3066
3067 rc = mwl8k_post_cmd(hw, &cmd->header);
3068 kfree(cmd);
3069
3070 return rc;
3071}
3072
3073/*
3074 * CMD_SET_MAC_ADDR.
3075 */
3076struct mwl8k_cmd_set_mac_addr {
3077 struct mwl8k_cmd_pkt header;
3078 union {
3079 struct {
3080 __le16 mac_type;
3081 __u8 mac_addr[ETH_ALEN];
3082 } mbss;
3083 __u8 mac_addr[ETH_ALEN];
3084 };
ba2d3587 3085} __packed;
55489b6e 3086
ee0ddf18
LB
3087#define MWL8K_MAC_TYPE_PRIMARY_CLIENT 0
3088#define MWL8K_MAC_TYPE_SECONDARY_CLIENT 1
3089#define MWL8K_MAC_TYPE_PRIMARY_AP 2
3090#define MWL8K_MAC_TYPE_SECONDARY_AP 3
a9e00b15 3091
aa21d0f6
LB
3092static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw,
3093 struct ieee80211_vif *vif, u8 *mac)
55489b6e
LB
3094{
3095 struct mwl8k_priv *priv = hw->priv;
ee0ddf18 3096 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
55489b6e 3097 struct mwl8k_cmd_set_mac_addr *cmd;
ee0ddf18 3098 int mac_type;
55489b6e
LB
3099 int rc;
3100
ee0ddf18
LB
3101 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
3102 if (vif != NULL && vif->type == NL80211_IFTYPE_STATION) {
3103 if (mwl8k_vif->macid + 1 == ffs(priv->sta_macids_supported))
3104 mac_type = MWL8K_MAC_TYPE_PRIMARY_CLIENT;
3105 else
3106 mac_type = MWL8K_MAC_TYPE_SECONDARY_CLIENT;
3107 } else if (vif != NULL && vif->type == NL80211_IFTYPE_AP) {
3108 if (mwl8k_vif->macid + 1 == ffs(priv->ap_macids_supported))
3109 mac_type = MWL8K_MAC_TYPE_PRIMARY_AP;
3110 else
3111 mac_type = MWL8K_MAC_TYPE_SECONDARY_AP;
3112 }
3113
55489b6e
LB
3114 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3115 if (cmd == NULL)
3116 return -ENOMEM;
3117
3118 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
3119 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3120 if (priv->ap_fw) {
ee0ddf18 3121 cmd->mbss.mac_type = cpu_to_le16(mac_type);
55489b6e
LB
3122 memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
3123 } else {
3124 memcpy(cmd->mac_addr, mac, ETH_ALEN);
3125 }
3126
aa21d0f6 3127 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
55489b6e
LB
3128 kfree(cmd);
3129
3130 return rc;
3131}
3132
3133/*
3134 * CMD_SET_RATEADAPT_MODE.
3135 */
3136struct mwl8k_cmd_set_rate_adapt_mode {
3137 struct mwl8k_cmd_pkt header;
3138 __le16 action;
3139 __le16 mode;
ba2d3587 3140} __packed;
55489b6e
LB
3141
3142static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode)
3143{
3144 struct mwl8k_cmd_set_rate_adapt_mode *cmd;
3145 int rc;
3146
3147 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3148 if (cmd == NULL)
3149 return -ENOMEM;
3150
3151 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE);
3152 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3153 cmd->action = cpu_to_le16(MWL8K_CMD_SET);
3154 cmd->mode = cpu_to_le16(mode);
3155
3156 rc = mwl8k_post_cmd(hw, &cmd->header);
3157 kfree(cmd);
3158
3159 return rc;
3160}
3161
b64fe619
LB
3162/*
3163 * CMD_BSS_START.
3164 */
3165struct mwl8k_cmd_bss_start {
3166 struct mwl8k_cmd_pkt header;
3167 __le32 enable;
ba2d3587 3168} __packed;
b64fe619 3169
aa21d0f6
LB
3170static int mwl8k_cmd_bss_start(struct ieee80211_hw *hw,
3171 struct ieee80211_vif *vif, int enable)
b64fe619
LB
3172{
3173 struct mwl8k_cmd_bss_start *cmd;
3174 int rc;
3175
3176 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3177 if (cmd == NULL)
3178 return -ENOMEM;
3179
3180 cmd->header.code = cpu_to_le16(MWL8K_CMD_BSS_START);
3181 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3182 cmd->enable = cpu_to_le32(enable);
3183
aa21d0f6 3184 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
b64fe619
LB
3185 kfree(cmd);
3186
3187 return rc;
3188}
3189
5faa1aff
NS
3190/*
3191 * CMD_BASTREAM.
3192 */
3193
3194/*
3195 * UPSTREAM is tx direction
3196 */
3197#define BASTREAM_FLAG_DIRECTION_UPSTREAM 0x00
3198#define BASTREAM_FLAG_IMMEDIATE_TYPE 0x01
3199
3200enum {
3201 MWL8K_BA_CREATE,
3202 MWL8K_BA_UPDATE,
3203 MWL8K_BA_DESTROY,
3204 MWL8K_BA_FLUSH,
3205 MWL8K_BA_CHECK,
3206} ba_stream_action_type;
3207
3208
3209struct mwl8k_create_ba_stream {
3210 __le32 flags;
3211 __le32 idle_thrs;
3212 __le32 bar_thrs;
3213 __le32 window_size;
3214 u8 peer_mac_addr[6];
3215 u8 dialog_token;
3216 u8 tid;
3217 u8 queue_id;
3218 u8 param_info;
3219 __le32 ba_context;
3220 u8 reset_seq_no_flag;
3221 __le16 curr_seq_no;
3222 u8 sta_src_mac_addr[6];
3223} __packed;
3224
3225struct mwl8k_destroy_ba_stream {
3226 __le32 flags;
3227 __le32 ba_context;
3228} __packed;
3229
3230struct mwl8k_cmd_bastream {
3231 struct mwl8k_cmd_pkt header;
3232 __le32 action;
3233 union {
3234 struct mwl8k_create_ba_stream create_params;
3235 struct mwl8k_destroy_ba_stream destroy_params;
3236 };
3237} __packed;
3238
3239static int
3240mwl8k_check_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream)
3241{
3242 struct mwl8k_cmd_bastream *cmd;
3243 int rc;
3244
3245 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3246 if (cmd == NULL)
3247 return -ENOMEM;
3248
3249 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3250 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3251
3252 cmd->action = cpu_to_le32(MWL8K_BA_CHECK);
3253
3254 cmd->create_params.queue_id = stream->idx;
3255 memcpy(&cmd->create_params.peer_mac_addr[0], stream->sta->addr,
3256 ETH_ALEN);
3257 cmd->create_params.tid = stream->tid;
3258
3259 cmd->create_params.flags =
3260 cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE) |
3261 cpu_to_le32(BASTREAM_FLAG_DIRECTION_UPSTREAM);
3262
3263 rc = mwl8k_post_cmd(hw, &cmd->header);
3264
3265 kfree(cmd);
3266
3267 return rc;
3268}
3269
3270static int
3271mwl8k_create_ba(struct ieee80211_hw *hw, struct mwl8k_ampdu_stream *stream,
3272 u8 buf_size)
3273{
3274 struct mwl8k_cmd_bastream *cmd;
3275 int rc;
3276
3277 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3278 if (cmd == NULL)
3279 return -ENOMEM;
3280
3281
3282 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3283 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3284
3285 cmd->action = cpu_to_le32(MWL8K_BA_CREATE);
3286
3287 cmd->create_params.bar_thrs = cpu_to_le32((u32)buf_size);
3288 cmd->create_params.window_size = cpu_to_le32((u32)buf_size);
3289 cmd->create_params.queue_id = stream->idx;
3290
3291 memcpy(cmd->create_params.peer_mac_addr, stream->sta->addr, ETH_ALEN);
3292 cmd->create_params.tid = stream->tid;
3293 cmd->create_params.curr_seq_no = cpu_to_le16(0);
3294 cmd->create_params.reset_seq_no_flag = 1;
3295
3296 cmd->create_params.param_info =
3297 (stream->sta->ht_cap.ampdu_factor &
3298 IEEE80211_HT_AMPDU_PARM_FACTOR) |
3299 ((stream->sta->ht_cap.ampdu_density << 2) &
3300 IEEE80211_HT_AMPDU_PARM_DENSITY);
3301
3302 cmd->create_params.flags =
3303 cpu_to_le32(BASTREAM_FLAG_IMMEDIATE_TYPE |
3304 BASTREAM_FLAG_DIRECTION_UPSTREAM);
3305
3306 rc = mwl8k_post_cmd(hw, &cmd->header);
3307
3308 wiphy_debug(hw->wiphy, "Created a BA stream for %pM : tid %d\n",
3309 stream->sta->addr, stream->tid);
3310 kfree(cmd);
3311
3312 return rc;
3313}
3314
3315static void mwl8k_destroy_ba(struct ieee80211_hw *hw,
3316 struct mwl8k_ampdu_stream *stream)
3317{
3318 struct mwl8k_cmd_bastream *cmd;
3319
3320 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3321 if (cmd == NULL)
3322 return;
3323
3324 cmd->header.code = cpu_to_le16(MWL8K_CMD_BASTREAM);
3325 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3326 cmd->action = cpu_to_le32(MWL8K_BA_DESTROY);
3327
3328 cmd->destroy_params.ba_context = cpu_to_le32(stream->idx);
3329 mwl8k_post_cmd(hw, &cmd->header);
3330
3331 wiphy_debug(hw->wiphy, "Deleted BA stream index %d\n", stream->idx);
3332
3333 kfree(cmd);
3334}
3335
3f5610ff
LB
3336/*
3337 * CMD_SET_NEW_STN.
3338 */
3339struct mwl8k_cmd_set_new_stn {
3340 struct mwl8k_cmd_pkt header;
3341 __le16 aid;
3342 __u8 mac_addr[6];
3343 __le16 stn_id;
3344 __le16 action;
3345 __le16 rsvd;
3346 __le32 legacy_rates;
3347 __u8 ht_rates[4];
3348 __le16 cap_info;
3349 __le16 ht_capabilities_info;
3350 __u8 mac_ht_param_info;
3351 __u8 rev;
3352 __u8 control_channel;
3353 __u8 add_channel;
3354 __le16 op_mode;
3355 __le16 stbc;
3356 __u8 add_qos_info;
3357 __u8 is_qos_sta;
3358 __le32 fw_sta_ptr;
ba2d3587 3359} __packed;
3f5610ff
LB
3360
3361#define MWL8K_STA_ACTION_ADD 0
3362#define MWL8K_STA_ACTION_REMOVE 2
3363
3364static int mwl8k_cmd_set_new_stn_add(struct ieee80211_hw *hw,
3365 struct ieee80211_vif *vif,
3366 struct ieee80211_sta *sta)
3367{
3368 struct mwl8k_cmd_set_new_stn *cmd;
8707d026 3369 u32 rates;
3f5610ff
LB
3370 int rc;
3371
3372 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3373 if (cmd == NULL)
3374 return -ENOMEM;
3375
3376 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
3377 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3378 cmd->aid = cpu_to_le16(sta->aid);
3379 memcpy(cmd->mac_addr, sta->addr, ETH_ALEN);
3380 cmd->stn_id = cpu_to_le16(sta->aid);
3381 cmd->action = cpu_to_le16(MWL8K_STA_ACTION_ADD);
8707d026
LB
3382 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
3383 rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
3384 else
3385 rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
3386 cmd->legacy_rates = cpu_to_le32(rates);
3f5610ff
LB
3387 if (sta->ht_cap.ht_supported) {
3388 cmd->ht_rates[0] = sta->ht_cap.mcs.rx_mask[0];
3389 cmd->ht_rates[1] = sta->ht_cap.mcs.rx_mask[1];
3390 cmd->ht_rates[2] = sta->ht_cap.mcs.rx_mask[2];
3391 cmd->ht_rates[3] = sta->ht_cap.mcs.rx_mask[3];
3392 cmd->ht_capabilities_info = cpu_to_le16(sta->ht_cap.cap);
3393 cmd->mac_ht_param_info = (sta->ht_cap.ampdu_factor & 3) |
3394 ((sta->ht_cap.ampdu_density & 7) << 2);
3395 cmd->is_qos_sta = 1;
3396 }
3397
aa21d0f6 3398 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
3f5610ff
LB
3399 kfree(cmd);
3400
3401 return rc;
3402}
3403
b64fe619
LB
3404static int mwl8k_cmd_set_new_stn_add_self(struct ieee80211_hw *hw,
3405 struct ieee80211_vif *vif)
3406{
3407 struct mwl8k_cmd_set_new_stn *cmd;
3408 int rc;
3409
3410 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3411 if (cmd == NULL)
3412 return -ENOMEM;
3413
3414 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
3415 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3416 memcpy(cmd->mac_addr, vif->addr, ETH_ALEN);
3417
aa21d0f6 3418 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
b64fe619
LB
3419 kfree(cmd);
3420
3421 return rc;
3422}
3423
3f5610ff
LB
3424static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
3425 struct ieee80211_vif *vif, u8 *addr)
3426{
3427 struct mwl8k_cmd_set_new_stn *cmd;
3428 int rc;
3429
3430 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3431 if (cmd == NULL)
3432 return -ENOMEM;
3433
3434 cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_NEW_STN);
3435 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3436 memcpy(cmd->mac_addr, addr, ETH_ALEN);
3437 cmd->action = cpu_to_le16(MWL8K_STA_ACTION_REMOVE);
3438
aa21d0f6 3439 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
3f5610ff
LB
3440 kfree(cmd);
3441
3442 return rc;
3443}
3444
fcdc403c
NS
3445/*
3446 * CMD_UPDATE_ENCRYPTION.
3447 */
3448
3449#define MAX_ENCR_KEY_LENGTH 16
3450#define MIC_KEY_LENGTH 8
3451
3452struct mwl8k_cmd_update_encryption {
3453 struct mwl8k_cmd_pkt header;
3454
3455 __le32 action;
3456 __le32 reserved;
3457 __u8 mac_addr[6];
3458 __u8 encr_type;
3459
3460} __attribute__((packed));
3461
3462struct mwl8k_cmd_set_key {
3463 struct mwl8k_cmd_pkt header;
3464
3465 __le32 action;
3466 __le32 reserved;
3467 __le16 length;
3468 __le16 key_type_id;
3469 __le32 key_info;
3470 __le32 key_id;
3471 __le16 key_len;
3472 __u8 key_material[MAX_ENCR_KEY_LENGTH];
3473 __u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
3474 __u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
3475 __le16 tkip_rsc_low;
3476 __le32 tkip_rsc_high;
3477 __le16 tkip_tsc_low;
3478 __le32 tkip_tsc_high;
3479 __u8 mac_addr[6];
3480} __attribute__((packed));
3481
3482enum {
3483 MWL8K_ENCR_ENABLE,
3484 MWL8K_ENCR_SET_KEY,
3485 MWL8K_ENCR_REMOVE_KEY,
3486 MWL8K_ENCR_SET_GROUP_KEY,
3487};
3488
3489#define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP 0
3490#define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE 1
3491#define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP 4
3492#define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED 7
3493#define MWL8K_UPDATE_ENCRYPTION_TYPE_AES 8
3494
3495enum {
3496 MWL8K_ALG_WEP,
3497 MWL8K_ALG_TKIP,
3498 MWL8K_ALG_CCMP,
3499};
3500
3501#define MWL8K_KEY_FLAG_TXGROUPKEY 0x00000004
3502#define MWL8K_KEY_FLAG_PAIRWISE 0x00000008
3503#define MWL8K_KEY_FLAG_TSC_VALID 0x00000040
3504#define MWL8K_KEY_FLAG_WEP_TXKEY 0x01000000
3505#define MWL8K_KEY_FLAG_MICKEY_VALID 0x02000000
3506
3507static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw,
3508 struct ieee80211_vif *vif,
3509 u8 *addr,
3510 u8 encr_type)
3511{
3512 struct mwl8k_cmd_update_encryption *cmd;
3513 int rc;
3514
3515 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3516 if (cmd == NULL)
3517 return -ENOMEM;
3518
3519 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
3520 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3521 cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE);
3522 memcpy(cmd->mac_addr, addr, ETH_ALEN);
3523 cmd->encr_type = encr_type;
3524
3525 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
3526 kfree(cmd);
3527
3528 return rc;
3529}
3530
3531static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd,
3532 u8 *addr,
3533 struct ieee80211_key_conf *key)
3534{
3535 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
3536 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3537 cmd->length = cpu_to_le16(sizeof(*cmd) -
3538 offsetof(struct mwl8k_cmd_set_key, length));
3539 cmd->key_id = cpu_to_le32(key->keyidx);
3540 cmd->key_len = cpu_to_le16(key->keylen);
3541 memcpy(cmd->mac_addr, addr, ETH_ALEN);
3542
3543 switch (key->cipher) {
3544 case WLAN_CIPHER_SUITE_WEP40:
3545 case WLAN_CIPHER_SUITE_WEP104:
3546 cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP);
3547 if (key->keyidx == 0)
3548 cmd->key_info = cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY);
3549
3550 break;
3551 case WLAN_CIPHER_SUITE_TKIP:
3552 cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP);
3553 cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3554 ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
3555 : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
3556 cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID
3557 | MWL8K_KEY_FLAG_TSC_VALID);
3558 break;
3559 case WLAN_CIPHER_SUITE_CCMP:
3560 cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP);
3561 cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3562 ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
3563 : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
3564 break;
3565 default:
3566 return -ENOTSUPP;
3567 }
3568
3569 return 0;
3570}
3571
3572static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw,
3573 struct ieee80211_vif *vif,
3574 u8 *addr,
3575 struct ieee80211_key_conf *key)
3576{
3577 struct mwl8k_cmd_set_key *cmd;
3578 int rc;
3579 int keymlen;
3580 u32 action;
3581 u8 idx;
3582 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
3583
3584 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3585 if (cmd == NULL)
3586 return -ENOMEM;
3587
3588 rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
3589 if (rc < 0)
3590 goto done;
3591
3592 idx = key->keyidx;
3593
3594 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
3595 action = MWL8K_ENCR_SET_KEY;
3596 else
3597 action = MWL8K_ENCR_SET_GROUP_KEY;
3598
3599 switch (key->cipher) {
3600 case WLAN_CIPHER_SUITE_WEP40:
3601 case WLAN_CIPHER_SUITE_WEP104:
3602 if (!mwl8k_vif->wep_key_conf[idx].enabled) {
3603 memcpy(mwl8k_vif->wep_key_conf[idx].key, key,
3604 sizeof(*key) + key->keylen);
3605 mwl8k_vif->wep_key_conf[idx].enabled = 1;
3606 }
3607
3608 keymlen = 0;
3609 action = MWL8K_ENCR_SET_KEY;
3610 break;
3611 case WLAN_CIPHER_SUITE_TKIP:
3612 keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
3613 break;
3614 case WLAN_CIPHER_SUITE_CCMP:
3615 keymlen = key->keylen;
3616 break;
3617 default:
3618 rc = -ENOTSUPP;
3619 goto done;
3620 }
3621
3622 memcpy(cmd->key_material, key->key, keymlen);
3623 cmd->action = cpu_to_le32(action);
3624
3625 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
3626done:
3627 kfree(cmd);
3628
3629 return rc;
3630}
3631
3632static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
3633 struct ieee80211_vif *vif,
3634 u8 *addr,
3635 struct ieee80211_key_conf *key)
3636{
3637 struct mwl8k_cmd_set_key *cmd;
3638 int rc;
3639 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
3640
3641 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3642 if (cmd == NULL)
3643 return -ENOMEM;
3644
3645 rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
3646 if (rc < 0)
3647 goto done;
3648
3649 if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
3650 WLAN_CIPHER_SUITE_WEP104)
3651 mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
3652
3653 cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
3654
3655 rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
3656done:
3657 kfree(cmd);
3658
3659 return rc;
3660}
3661
3662static int mwl8k_set_key(struct ieee80211_hw *hw,
3663 enum set_key_cmd cmd_param,
3664 struct ieee80211_vif *vif,
3665 struct ieee80211_sta *sta,
3666 struct ieee80211_key_conf *key)
3667{
3668 int rc = 0;
3669 u8 encr_type;
3670 u8 *addr;
3671 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
3672
3673 if (vif->type == NL80211_IFTYPE_STATION)
3674 return -EOPNOTSUPP;
3675
3676 if (sta == NULL)
3677 addr = hw->wiphy->perm_addr;
3678 else
3679 addr = sta->addr;
3680
3681 if (cmd_param == SET_KEY) {
3682 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3683 rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key);
3684 if (rc)
3685 goto out;
3686
3687 if ((key->cipher == WLAN_CIPHER_SUITE_WEP40)
3688 || (key->cipher == WLAN_CIPHER_SUITE_WEP104))
3689 encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP;
3690 else
3691 encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED;
3692
3693 rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr,
3694 encr_type);
3695 if (rc)
3696 goto out;
3697
3698 mwl8k_vif->is_hw_crypto_enabled = true;
3699
3700 } else {
3701 rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key);
3702
3703 if (rc)
3704 goto out;
3705
3706 mwl8k_vif->is_hw_crypto_enabled = false;
3707
3708 }
3709out:
3710 return rc;
3711}
3712
55489b6e
LB
3713/*
3714 * CMD_UPDATE_STADB.
3715 */
25d81b1e
LB
3716struct ewc_ht_info {
3717 __le16 control1;
3718 __le16 control2;
3719 __le16 control3;
ba2d3587 3720} __packed;
25d81b1e
LB
3721
3722struct peer_capability_info {
3723 /* Peer type - AP vs. STA. */
3724 __u8 peer_type;
3725
3726 /* Basic 802.11 capabilities from assoc resp. */
3727 __le16 basic_caps;
3728
3729 /* Set if peer supports 802.11n high throughput (HT). */
3730 __u8 ht_support;
3731
3732 /* Valid if HT is supported. */
3733 __le16 ht_caps;
3734 __u8 extended_ht_caps;
3735 struct ewc_ht_info ewc_info;
3736
3737 /* Legacy rate table. Intersection of our rates and peer rates. */
3738 __u8 legacy_rates[12];
3739
3740 /* HT rate table. Intersection of our rates and peer rates. */
3741 __u8 ht_rates[16];
3742 __u8 pad[16];
3743
3744 /* If set, interoperability mode, no proprietary extensions. */
3745 __u8 interop;
3746 __u8 pad2;
3747 __u8 station_id;
3748 __le16 amsdu_enabled;
ba2d3587 3749} __packed;
25d81b1e 3750
55489b6e
LB
3751struct mwl8k_cmd_update_stadb {
3752 struct mwl8k_cmd_pkt header;
3753
3754 /* See STADB_ACTION_TYPE */
3755 __le32 action;
3756
3757 /* Peer MAC address */
3758 __u8 peer_addr[ETH_ALEN];
3759
3760 __le32 reserved;
3761
3762 /* Peer info - valid during add/update. */
3763 struct peer_capability_info peer_info;
ba2d3587 3764} __packed;
55489b6e 3765
a680400e
LB
3766#define MWL8K_STA_DB_MODIFY_ENTRY 1
3767#define MWL8K_STA_DB_DEL_ENTRY 2
3768
3769/* Peer Entry flags - used to define the type of the peer node */
3770#define MWL8K_PEER_TYPE_ACCESSPOINT 2
3771
3772static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw,
c6e96010 3773 struct ieee80211_vif *vif,
13935e2c 3774 struct ieee80211_sta *sta)
55489b6e 3775{
55489b6e 3776 struct mwl8k_cmd_update_stadb *cmd;
a680400e 3777 struct peer_capability_info *p;
8707d026 3778 u32 rates;
55489b6e
LB
3779 int rc;
3780
3781 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3782 if (cmd == NULL)
3783 return -ENOMEM;
3784
3785 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
3786 cmd->header.length = cpu_to_le16(sizeof(*cmd));
a680400e 3787 cmd->action = cpu_to_le32(MWL8K_STA_DB_MODIFY_ENTRY);
13935e2c 3788 memcpy(cmd->peer_addr, sta->addr, ETH_ALEN);
55489b6e 3789
a680400e
LB
3790 p = &cmd->peer_info;
3791 p->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT;
3792 p->basic_caps = cpu_to_le16(vif->bss_conf.assoc_capability);
13935e2c 3793 p->ht_support = sta->ht_cap.ht_supported;
b603742f 3794 p->ht_caps = cpu_to_le16(sta->ht_cap.cap);
13935e2c
LB
3795 p->extended_ht_caps = (sta->ht_cap.ampdu_factor & 3) |
3796 ((sta->ht_cap.ampdu_density & 7) << 2);
8707d026
LB
3797 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
3798 rates = sta->supp_rates[IEEE80211_BAND_2GHZ];
3799 else
3800 rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5;
3801 legacy_rate_mask_to_array(p->legacy_rates, rates);
13935e2c 3802 memcpy(p->ht_rates, sta->ht_cap.mcs.rx_mask, 16);
a680400e
LB
3803 p->interop = 1;
3804 p->amsdu_enabled = 0;
3805
3806 rc = mwl8k_post_cmd(hw, &cmd->header);
3807 kfree(cmd);
3808
3809 return rc ? rc : p->station_id;
3810}
3811
3812static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
3813 struct ieee80211_vif *vif, u8 *addr)
3814{
3815 struct mwl8k_cmd_update_stadb *cmd;
3816 int rc;
3817
3818 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
3819 if (cmd == NULL)
3820 return -ENOMEM;
3821
3822 cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB);
3823 cmd->header.length = cpu_to_le16(sizeof(*cmd));
3824 cmd->action = cpu_to_le32(MWL8K_STA_DB_DEL_ENTRY);
bbfd9128 3825 memcpy(cmd->peer_addr, addr, ETH_ALEN);
55489b6e 3826
a680400e 3827 rc = mwl8k_post_cmd(hw, &cmd->header);
55489b6e
LB
3828 kfree(cmd);
3829
3830 return rc;
3831}
3832
a66098da
LB
3833
3834/*
3835 * Interrupt handling.
3836 */
3837static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
3838{
3839 struct ieee80211_hw *hw = dev_id;
3840 struct mwl8k_priv *priv = hw->priv;
3841 u32 status;
3842
3843 status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
a66098da
LB
3844 if (!status)
3845 return IRQ_NONE;
3846
1e9f9de3
LB
3847 if (status & MWL8K_A2H_INT_TX_DONE) {
3848 status &= ~MWL8K_A2H_INT_TX_DONE;
3849 tasklet_schedule(&priv->poll_tx_task);
3850 }
3851
a66098da 3852 if (status & MWL8K_A2H_INT_RX_READY) {
67e2eb27
LB
3853 status &= ~MWL8K_A2H_INT_RX_READY;
3854 tasklet_schedule(&priv->poll_rx_task);
a66098da
LB
3855 }
3856
67e2eb27
LB
3857 if (status)
3858 iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3859
a66098da 3860 if (status & MWL8K_A2H_INT_OPC_DONE) {
618952a7 3861 if (priv->hostcmd_wait != NULL)
a66098da 3862 complete(priv->hostcmd_wait);
a66098da
LB
3863 }
3864
3865 if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
618952a7 3866 if (!mutex_is_locked(&priv->fw_mutex) &&
88de754a 3867 priv->radio_on && priv->pending_tx_pkts)
618952a7 3868 mwl8k_tx_start(priv);
a66098da
LB
3869 }
3870
3871 return IRQ_HANDLED;
3872}
3873
1e9f9de3
LB
3874static void mwl8k_tx_poll(unsigned long data)
3875{
3876 struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
3877 struct mwl8k_priv *priv = hw->priv;
3878 int limit;
3879 int i;
3880
3881 limit = 32;
3882
3883 spin_lock_bh(&priv->tx_lock);
3884
e600707b 3885 for (i = 0; i < mwl8k_tx_queues(priv); i++)
1e9f9de3
LB
3886 limit -= mwl8k_txq_reclaim(hw, i, limit, 0);
3887
3888 if (!priv->pending_tx_pkts && priv->tx_wait != NULL) {
3889 complete(priv->tx_wait);
3890 priv->tx_wait = NULL;
3891 }
3892
3893 spin_unlock_bh(&priv->tx_lock);
3894
3895 if (limit) {
3896 writel(~MWL8K_A2H_INT_TX_DONE,
3897 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3898 } else {
3899 tasklet_schedule(&priv->poll_tx_task);
3900 }
3901}
3902
67e2eb27
LB
3903static void mwl8k_rx_poll(unsigned long data)
3904{
3905 struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
3906 struct mwl8k_priv *priv = hw->priv;
3907 int limit;
3908
3909 limit = 32;
3910 limit -= rxq_process(hw, 0, limit);
3911 limit -= rxq_refill(hw, 0, limit);
3912
3913 if (limit) {
3914 writel(~MWL8K_A2H_INT_RX_READY,
3915 priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
3916 } else {
3917 tasklet_schedule(&priv->poll_rx_task);
3918 }
3919}
3920
a66098da
LB
3921
3922/*
3923 * Core driver operations.
3924 */
7bb45683 3925static void mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
a66098da
LB
3926{
3927 struct mwl8k_priv *priv = hw->priv;
3928 int index = skb_get_queue_mapping(skb);
a66098da 3929
9189c100 3930 if (!priv->radio_on) {
c96c31e4
JP
3931 wiphy_debug(hw->wiphy,
3932 "dropped TX frame since radio disabled\n");
a66098da 3933 dev_kfree_skb(skb);
7bb45683 3934 return;
a66098da
LB
3935 }
3936
7bb45683 3937 mwl8k_txq_xmit(hw, index, skb);
a66098da
LB
3938}
3939
a66098da
LB
3940static int mwl8k_start(struct ieee80211_hw *hw)
3941{
a66098da
LB
3942 struct mwl8k_priv *priv = hw->priv;
3943 int rc;
3944
a0607fd3 3945 rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
a66098da
LB
3946 IRQF_SHARED, MWL8K_NAME, hw);
3947 if (rc) {
5db55844 3948 wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
2ec610cb 3949 return -EIO;
a66098da
LB
3950 }
3951
67e2eb27 3952 /* Enable TX reclaim and RX tasklets. */
1e9f9de3 3953 tasklet_enable(&priv->poll_tx_task);
67e2eb27 3954 tasklet_enable(&priv->poll_rx_task);
2ec610cb 3955
a66098da 3956 /* Enable interrupts */
c23b5a69 3957 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
a66098da 3958
2ec610cb
LB
3959 rc = mwl8k_fw_lock(hw);
3960 if (!rc) {
55489b6e 3961 rc = mwl8k_cmd_radio_enable(hw);
a66098da 3962
5e4cf166
LB
3963 if (!priv->ap_fw) {
3964 if (!rc)
55489b6e 3965 rc = mwl8k_cmd_enable_sniffer(hw, 0);
a66098da 3966
5e4cf166
LB
3967 if (!rc)
3968 rc = mwl8k_cmd_set_pre_scan(hw);
3969
3970 if (!rc)
3971 rc = mwl8k_cmd_set_post_scan(hw,
3972 "\x00\x00\x00\x00\x00\x00");
3973 }
2ec610cb
LB
3974
3975 if (!rc)
55489b6e 3976 rc = mwl8k_cmd_set_rateadapt_mode(hw, 0);
a66098da 3977
2ec610cb 3978 if (!rc)
55489b6e 3979 rc = mwl8k_cmd_set_wmm_mode(hw, 0);
a66098da 3980
2ec610cb
LB
3981 mwl8k_fw_unlock(hw);
3982 }
3983
3984 if (rc) {
3985 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
3986 free_irq(priv->pdev->irq, hw);
1e9f9de3 3987 tasklet_disable(&priv->poll_tx_task);
67e2eb27 3988 tasklet_disable(&priv->poll_rx_task);
2ec610cb 3989 }
a66098da
LB
3990
3991 return rc;
3992}
3993
a66098da
LB
3994static void mwl8k_stop(struct ieee80211_hw *hw)
3995{
a66098da
LB
3996 struct mwl8k_priv *priv = hw->priv;
3997 int i;
3998
55489b6e 3999 mwl8k_cmd_radio_disable(hw);
a66098da
LB
4000
4001 ieee80211_stop_queues(hw);
4002
a66098da 4003 /* Disable interrupts */
a66098da 4004 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
a66098da
LB
4005 free_irq(priv->pdev->irq, hw);
4006
4007 /* Stop finalize join worker */
4008 cancel_work_sync(&priv->finalize_join_worker);
4009 if (priv->beacon_skb != NULL)
4010 dev_kfree_skb(priv->beacon_skb);
4011
67e2eb27 4012 /* Stop TX reclaim and RX tasklets. */
1e9f9de3 4013 tasklet_disable(&priv->poll_tx_task);
67e2eb27 4014 tasklet_disable(&priv->poll_rx_task);
a66098da 4015
a66098da 4016 /* Return all skbs to mac80211 */
e600707b 4017 for (i = 0; i < mwl8k_tx_queues(priv); i++)
efb7c49a 4018 mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
a66098da
LB
4019}
4020
0863ade8
BC
4021static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image);
4022
a66098da 4023static int mwl8k_add_interface(struct ieee80211_hw *hw,
f5bb87cf 4024 struct ieee80211_vif *vif)
a66098da
LB
4025{
4026 struct mwl8k_priv *priv = hw->priv;
4027 struct mwl8k_vif *mwl8k_vif;
ee0ddf18 4028 u32 macids_supported;
0863ade8
BC
4029 int macid, rc;
4030 struct mwl8k_device_info *di;
a66098da 4031
a43c49a8
LB
4032 /*
4033 * Reject interface creation if sniffer mode is active, as
4034 * STA operation is mutually exclusive with hardware sniffer
b64fe619 4035 * mode. (Sniffer mode is only used on STA firmware.)
a43c49a8
LB
4036 */
4037 if (priv->sniffer_enabled) {
c96c31e4
JP
4038 wiphy_info(hw->wiphy,
4039 "unable to create STA interface because sniffer mode is enabled\n");
a43c49a8
LB
4040 return -EINVAL;
4041 }
4042
0863ade8 4043 di = priv->device_info;
ee0ddf18
LB
4044 switch (vif->type) {
4045 case NL80211_IFTYPE_AP:
0863ade8
BC
4046 if (!priv->ap_fw && di->fw_image_ap) {
4047 /* we must load the ap fw to meet this request */
4048 if (!list_empty(&priv->vif_list))
4049 return -EBUSY;
4050 rc = mwl8k_reload_firmware(hw, di->fw_image_ap);
4051 if (rc)
4052 return rc;
4053 }
ee0ddf18
LB
4054 macids_supported = priv->ap_macids_supported;
4055 break;
4056 case NL80211_IFTYPE_STATION:
0863ade8
BC
4057 if (priv->ap_fw && di->fw_image_sta) {
4058 /* we must load the sta fw to meet this request */
4059 if (!list_empty(&priv->vif_list))
4060 return -EBUSY;
4061 rc = mwl8k_reload_firmware(hw, di->fw_image_sta);
4062 if (rc)
4063 return rc;
4064 }
ee0ddf18
LB
4065 macids_supported = priv->sta_macids_supported;
4066 break;
4067 default:
4068 return -EINVAL;
4069 }
4070
4071 macid = ffs(macids_supported & ~priv->macids_used);
4072 if (!macid--)
4073 return -EBUSY;
4074
f5bb87cf 4075 /* Setup driver private area. */
1ed32e4f 4076 mwl8k_vif = MWL8K_VIF(vif);
a66098da 4077 memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
f5bb87cf 4078 mwl8k_vif->vif = vif;
ee0ddf18 4079 mwl8k_vif->macid = macid;
a66098da 4080 mwl8k_vif->seqno = 0;
d9a07d49
NS
4081 memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
4082 mwl8k_vif->is_hw_crypto_enabled = false;
a66098da 4083
aa21d0f6
LB
4084 /* Set the mac address. */
4085 mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
4086
4087 if (priv->ap_fw)
4088 mwl8k_cmd_set_new_stn_add_self(hw, vif);
4089
ee0ddf18 4090 priv->macids_used |= 1 << mwl8k_vif->macid;
f5bb87cf 4091 list_add_tail(&mwl8k_vif->list, &priv->vif_list);
a66098da
LB
4092
4093 return 0;
4094}
4095
4096static void mwl8k_remove_interface(struct ieee80211_hw *hw,
1ed32e4f 4097 struct ieee80211_vif *vif)
a66098da
LB
4098{
4099 struct mwl8k_priv *priv = hw->priv;
f5bb87cf 4100 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
a66098da 4101
b64fe619
LB
4102 if (priv->ap_fw)
4103 mwl8k_cmd_set_new_stn_del(hw, vif, vif->addr);
4104
aa21d0f6 4105 mwl8k_cmd_set_mac_addr(hw, vif, "\x00\x00\x00\x00\x00\x00");
32060e1b 4106
ee0ddf18 4107 priv->macids_used &= ~(1 << mwl8k_vif->macid);
f5bb87cf 4108 list_del(&mwl8k_vif->list);
a66098da
LB
4109}
4110
ee03a932 4111static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
a66098da 4112{
a66098da
LB
4113 struct ieee80211_conf *conf = &hw->conf;
4114 struct mwl8k_priv *priv = hw->priv;
ee03a932 4115 int rc;
a66098da 4116
7595d67a 4117 if (conf->flags & IEEE80211_CONF_IDLE) {
55489b6e 4118 mwl8k_cmd_radio_disable(hw);
ee03a932 4119 return 0;
7595d67a
LB
4120 }
4121
ee03a932
LB
4122 rc = mwl8k_fw_lock(hw);
4123 if (rc)
4124 return rc;
a66098da 4125
55489b6e 4126 rc = mwl8k_cmd_radio_enable(hw);
ee03a932
LB
4127 if (rc)
4128 goto out;
a66098da 4129
610677d2 4130 rc = mwl8k_cmd_set_rf_channel(hw, conf);
ee03a932
LB
4131 if (rc)
4132 goto out;
4133
a66098da
LB
4134 if (conf->power_level > 18)
4135 conf->power_level = 18;
a66098da 4136
08b06347 4137 if (priv->ap_fw) {
41fdf097
NS
4138 rc = mwl8k_cmd_tx_power(hw, conf, conf->power_level);
4139 if (rc)
4140 goto out;
4141
da62b761
NS
4142 rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3);
4143 if (rc)
4144 wiphy_warn(hw->wiphy, "failed to set # of RX antennas");
4145 rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
4146 if (rc)
4147 wiphy_warn(hw->wiphy, "failed to set # of TX antennas");
4148
08b06347 4149 } else {
41fdf097
NS
4150 rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
4151 if (rc)
4152 goto out;
08b06347
LB
4153 rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7);
4154 }
a66098da 4155
ee03a932
LB
4156out:
4157 mwl8k_fw_unlock(hw);
a66098da 4158
ee03a932 4159 return rc;
a66098da
LB
4160}
4161
b64fe619
LB
4162static void
4163mwl8k_bss_info_changed_sta(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
4164 struct ieee80211_bss_conf *info, u32 changed)
a66098da 4165{
a66098da 4166 struct mwl8k_priv *priv = hw->priv;
c3cbbe8a 4167 u32 ap_legacy_rates;
13935e2c 4168 u8 ap_mcs_rates[16];
3a980d0a
LB
4169 int rc;
4170
c3cbbe8a 4171 if (mwl8k_fw_lock(hw))
3a980d0a 4172 return;
a66098da 4173
c3cbbe8a
LB
4174 /*
4175 * No need to capture a beacon if we're no longer associated.
4176 */
4177 if ((changed & BSS_CHANGED_ASSOC) && !vif->bss_conf.assoc)
4178 priv->capture_beacon = false;
3a980d0a 4179
c3cbbe8a 4180 /*
13935e2c 4181 * Get the AP's legacy and MCS rates.
c3cbbe8a 4182 */
7dc6a7a7 4183 if (vif->bss_conf.assoc) {
c6e96010 4184 struct ieee80211_sta *ap;
c97470dd 4185
c6e96010 4186 rcu_read_lock();
c6e96010 4187
c3cbbe8a
LB
4188 ap = ieee80211_find_sta(vif, vif->bss_conf.bssid);
4189 if (ap == NULL) {
4190 rcu_read_unlock();
c6e96010 4191 goto out;
c3cbbe8a
LB
4192 }
4193
8707d026
LB
4194 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
4195 ap_legacy_rates = ap->supp_rates[IEEE80211_BAND_2GHZ];
4196 } else {
4197 ap_legacy_rates =
4198 ap->supp_rates[IEEE80211_BAND_5GHZ] << 5;
4199 }
13935e2c 4200 memcpy(ap_mcs_rates, ap->ht_cap.mcs.rx_mask, 16);
c3cbbe8a
LB
4201
4202 rcu_read_unlock();
4203 }
c6e96010 4204
c3cbbe8a 4205 if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc) {
13935e2c 4206 rc = mwl8k_cmd_set_rate(hw, vif, ap_legacy_rates, ap_mcs_rates);
3a980d0a
LB
4207 if (rc)
4208 goto out;
a66098da 4209
b71ed2c6 4210 rc = mwl8k_cmd_use_fixed_rate_sta(hw);
3a980d0a
LB
4211 if (rc)
4212 goto out;
c3cbbe8a 4213 }
a66098da 4214
c3cbbe8a 4215 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
7dc6a7a7
LB
4216 rc = mwl8k_set_radio_preamble(hw,
4217 vif->bss_conf.use_short_preamble);
3a980d0a
LB
4218 if (rc)
4219 goto out;
c3cbbe8a 4220 }
a66098da 4221
c3cbbe8a 4222 if (changed & BSS_CHANGED_ERP_SLOT) {
7dc6a7a7 4223 rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot);
3a980d0a
LB
4224 if (rc)
4225 goto out;
c3cbbe8a 4226 }
a66098da 4227
c97470dd
LB
4228 if (vif->bss_conf.assoc &&
4229 (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_ERP_CTS_PROT |
4230 BSS_CHANGED_HT))) {
c3cbbe8a 4231 rc = mwl8k_cmd_set_aid(hw, vif, ap_legacy_rates);
3a980d0a
LB
4232 if (rc)
4233 goto out;
c3cbbe8a 4234 }
a66098da 4235
c3cbbe8a
LB
4236 if (vif->bss_conf.assoc &&
4237 (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INT))) {
a66098da
LB
4238 /*
4239 * Finalize the join. Tell rx handler to process
4240 * next beacon from our BSSID.
4241 */
0a11dfc3 4242 memcpy(priv->capture_bssid, vif->bss_conf.bssid, ETH_ALEN);
a66098da 4243 priv->capture_beacon = true;
a66098da
LB
4244 }
4245
3a980d0a
LB
4246out:
4247 mwl8k_fw_unlock(hw);
a66098da
LB
4248}
4249
b64fe619
LB
4250static void
4251mwl8k_bss_info_changed_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
4252 struct ieee80211_bss_conf *info, u32 changed)
4253{
4254 int rc;
4255
4256 if (mwl8k_fw_lock(hw))
4257 return;
4258
4259 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
4260 rc = mwl8k_set_radio_preamble(hw,
4261 vif->bss_conf.use_short_preamble);
4262 if (rc)
4263 goto out;
4264 }
4265
4266 if (changed & BSS_CHANGED_BASIC_RATES) {
4267 int idx;
4268 int rate;
4269
4270 /*
4271 * Use lowest supported basic rate for multicasts
4272 * and management frames (such as probe responses --
4273 * beacons will always go out at 1 Mb/s).
4274 */
4275 idx = ffs(vif->bss_conf.basic_rates);
8707d026
LB
4276 if (idx)
4277 idx--;
4278
4279 if (hw->conf.channel->band == IEEE80211_BAND_2GHZ)
4280 rate = mwl8k_rates_24[idx].hw_value;
4281 else
4282 rate = mwl8k_rates_50[idx].hw_value;
b64fe619
LB
4283
4284 mwl8k_cmd_use_fixed_rate_ap(hw, rate, rate);
4285 }
4286
4287 if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) {
4288 struct sk_buff *skb;
4289
4290 skb = ieee80211_beacon_get(hw, vif);
4291 if (skb != NULL) {
aa21d0f6 4292 mwl8k_cmd_set_beacon(hw, vif, skb->data, skb->len);
b64fe619
LB
4293 kfree_skb(skb);
4294 }
4295 }
4296
4297 if (changed & BSS_CHANGED_BEACON_ENABLED)
aa21d0f6 4298 mwl8k_cmd_bss_start(hw, vif, info->enable_beacon);
b64fe619
LB
4299
4300out:
4301 mwl8k_fw_unlock(hw);
4302}
4303
4304static void
4305mwl8k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
4306 struct ieee80211_bss_conf *info, u32 changed)
4307{
4308 struct mwl8k_priv *priv = hw->priv;
4309
4310 if (!priv->ap_fw)
4311 mwl8k_bss_info_changed_sta(hw, vif, info, changed);
4312 else
4313 mwl8k_bss_info_changed_ap(hw, vif, info, changed);
4314}
4315
e81cd2d6 4316static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
22bedad3 4317 struct netdev_hw_addr_list *mc_list)
e81cd2d6
LB
4318{
4319 struct mwl8k_cmd_pkt *cmd;
4320
447ced07
LB
4321 /*
4322 * Synthesize and return a command packet that programs the
4323 * hardware multicast address filter. At this point we don't
4324 * know whether FIF_ALLMULTI is being requested, but if it is,
4325 * we'll end up throwing this packet away and creating a new
4326 * one in mwl8k_configure_filter().
4327 */
22bedad3 4328 cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_list);
e81cd2d6
LB
4329
4330 return (unsigned long)cmd;
4331}
4332
a43c49a8
LB
4333static int
4334mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
4335 unsigned int changed_flags,
4336 unsigned int *total_flags)
4337{
4338 struct mwl8k_priv *priv = hw->priv;
4339
4340 /*
4341 * Hardware sniffer mode is mutually exclusive with STA
4342 * operation, so refuse to enable sniffer mode if a STA
4343 * interface is active.
4344 */
f5bb87cf 4345 if (!list_empty(&priv->vif_list)) {
a43c49a8 4346 if (net_ratelimit())
c96c31e4
JP
4347 wiphy_info(hw->wiphy,
4348 "not enabling sniffer mode because STA interface is active\n");
a43c49a8
LB
4349 return 0;
4350 }
4351
4352 if (!priv->sniffer_enabled) {
55489b6e 4353 if (mwl8k_cmd_enable_sniffer(hw, 1))
a43c49a8
LB
4354 return 0;
4355 priv->sniffer_enabled = true;
4356 }
4357
4358 *total_flags &= FIF_PROMISC_IN_BSS | FIF_ALLMULTI |
4359 FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL |
4360 FIF_OTHER_BSS;
4361
4362 return 1;
4363}
4364
f5bb87cf
LB
4365static struct mwl8k_vif *mwl8k_first_vif(struct mwl8k_priv *priv)
4366{
4367 if (!list_empty(&priv->vif_list))
4368 return list_entry(priv->vif_list.next, struct mwl8k_vif, list);
4369
4370 return NULL;
4371}
4372
e6935ea1
LB
4373static void mwl8k_configure_filter(struct ieee80211_hw *hw,
4374 unsigned int changed_flags,
4375 unsigned int *total_flags,
4376 u64 multicast)
4377{
4378 struct mwl8k_priv *priv = hw->priv;
a43c49a8
LB
4379 struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast;
4380
c0adae2c
LB
4381 /*
4382 * AP firmware doesn't allow fine-grained control over
4383 * the receive filter.
4384 */
4385 if (priv->ap_fw) {
4386 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
4387 kfree(cmd);
4388 return;
4389 }
4390
a43c49a8
LB
4391 /*
4392 * Enable hardware sniffer mode if FIF_CONTROL or
4393 * FIF_OTHER_BSS is requested.
4394 */
4395 if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) &&
4396 mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) {
4397 kfree(cmd);
4398 return;
4399 }
a66098da 4400
e6935ea1 4401 /* Clear unsupported feature flags */
447ced07 4402 *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
a66098da 4403
90852f7a
LB
4404 if (mwl8k_fw_lock(hw)) {
4405 kfree(cmd);
e6935ea1 4406 return;
90852f7a 4407 }
a66098da 4408
a43c49a8 4409 if (priv->sniffer_enabled) {
55489b6e 4410 mwl8k_cmd_enable_sniffer(hw, 0);
a43c49a8
LB
4411 priv->sniffer_enabled = false;
4412 }
4413
e6935ea1 4414 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
77165d88
LB
4415 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
4416 /*
4417 * Disable the BSS filter.
4418 */
e6935ea1 4419 mwl8k_cmd_set_pre_scan(hw);
77165d88 4420 } else {
f5bb87cf 4421 struct mwl8k_vif *mwl8k_vif;
0a11dfc3 4422 const u8 *bssid;
a94cc97e 4423
77165d88
LB
4424 /*
4425 * Enable the BSS filter.
4426 *
4427 * If there is an active STA interface, use that
4428 * interface's BSSID, otherwise use a dummy one
4429 * (where the OUI part needs to be nonzero for
4430 * the BSSID to be accepted by POST_SCAN).
4431 */
f5bb87cf
LB
4432 mwl8k_vif = mwl8k_first_vif(priv);
4433 if (mwl8k_vif != NULL)
4434 bssid = mwl8k_vif->vif->bss_conf.bssid;
4435 else
4436 bssid = "\x01\x00\x00\x00\x00\x00";
a94cc97e 4437
e6935ea1 4438 mwl8k_cmd_set_post_scan(hw, bssid);
a66098da
LB
4439 }
4440 }
4441
447ced07
LB
4442 /*
4443 * If FIF_ALLMULTI is being requested, throw away the command
4444 * packet that ->prepare_multicast() built and replace it with
4445 * a command packet that enables reception of all multicast
4446 * packets.
4447 */
4448 if (*total_flags & FIF_ALLMULTI) {
4449 kfree(cmd);
22bedad3 4450 cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, NULL);
447ced07
LB
4451 }
4452
4453 if (cmd != NULL) {
4454 mwl8k_post_cmd(hw, cmd);
4455 kfree(cmd);
e6935ea1 4456 }
a66098da 4457
e6935ea1 4458 mwl8k_fw_unlock(hw);
a66098da
LB
4459}
4460
a66098da
LB
4461static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
4462{
c2c2b12a 4463 return mwl8k_cmd_set_rts_threshold(hw, value);
a66098da
LB
4464}
4465
4a6967b8
JB
4466static int mwl8k_sta_remove(struct ieee80211_hw *hw,
4467 struct ieee80211_vif *vif,
4468 struct ieee80211_sta *sta)
3f5610ff
LB
4469{
4470 struct mwl8k_priv *priv = hw->priv;
4471
4a6967b8
JB
4472 if (priv->ap_fw)
4473 return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr);
4474 else
4475 return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr);
bbfd9128
LB
4476}
4477
4a6967b8
JB
4478static int mwl8k_sta_add(struct ieee80211_hw *hw,
4479 struct ieee80211_vif *vif,
4480 struct ieee80211_sta *sta)
bbfd9128
LB
4481{
4482 struct mwl8k_priv *priv = hw->priv;
4a6967b8 4483 int ret;
fcdc403c
NS
4484 int i;
4485 struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
4486 struct ieee80211_key_conf *key;
bbfd9128 4487
4a6967b8
JB
4488 if (!priv->ap_fw) {
4489 ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
4490 if (ret >= 0) {
4491 MWL8K_STA(sta)->peer_id = ret;
fcdc403c 4492 ret = 0;
4a6967b8 4493 }
bbfd9128 4494
d9a07d49
NS
4495 } else {
4496 ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
bbfd9128 4497 }
4a6967b8 4498
d9a07d49
NS
4499 for (i = 0; i < NUM_WEP_KEYS; i++) {
4500 key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
4501 if (mwl8k_vif->wep_key_conf[i].enabled)
4502 mwl8k_set_key(hw, SET_KEY, vif, sta, key);
4503 }
fcdc403c 4504 return ret;
bbfd9128
LB
4505}
4506
a66098da
LB
4507static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
4508 const struct ieee80211_tx_queue_params *params)
4509{
3e4f542c 4510 struct mwl8k_priv *priv = hw->priv;
a66098da 4511 int rc;
a66098da 4512
3e4f542c
LB
4513 rc = mwl8k_fw_lock(hw);
4514 if (!rc) {
e600707b 4515 BUG_ON(queue > MWL8K_TX_WMM_QUEUES - 1);
0863ade8
BC
4516 memcpy(&priv->wmm_params[queue], params, sizeof(*params));
4517
3e4f542c 4518 if (!priv->wmm_enabled)
55489b6e 4519 rc = mwl8k_cmd_set_wmm_mode(hw, 1);
a66098da 4520
85c9205c 4521 if (!rc) {
e600707b 4522 int q = MWL8K_TX_WMM_QUEUES - 1 - queue;
85c9205c 4523 rc = mwl8k_cmd_set_edca_params(hw, q,
55489b6e
LB
4524 params->cw_min,
4525 params->cw_max,
4526 params->aifs,
4527 params->txop);
85c9205c 4528 }
3e4f542c
LB
4529
4530 mwl8k_fw_unlock(hw);
a66098da 4531 }
3e4f542c 4532
a66098da
LB
4533 return rc;
4534}
4535
a66098da
LB
4536static int mwl8k_get_stats(struct ieee80211_hw *hw,
4537 struct ieee80211_low_level_stats *stats)
4538{
55489b6e 4539 return mwl8k_cmd_get_stat(hw, stats);
a66098da
LB
4540}
4541
0d462bbb
JL
4542static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
4543 struct survey_info *survey)
4544{
4545 struct mwl8k_priv *priv = hw->priv;
4546 struct ieee80211_conf *conf = &hw->conf;
4547
4548 if (idx != 0)
4549 return -ENOENT;
4550
4551 survey->channel = conf->channel;
4552 survey->filled = SURVEY_INFO_NOISE_DBM;
4553 survey->noise = priv->noise;
4554
4555 return 0;
4556}
4557
a2292d83
LB
4558static int
4559mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
4560 enum ieee80211_ampdu_mlme_action action,
0b01f030
JB
4561 struct ieee80211_sta *sta, u16 tid, u16 *ssn,
4562 u8 buf_size)
a2292d83
LB
4563{
4564 switch (action) {
4565 case IEEE80211_AMPDU_RX_START:
4566 case IEEE80211_AMPDU_RX_STOP:
4567 if (!(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
4568 return -ENOTSUPP;
4569 return 0;
4570 default:
4571 return -ENOTSUPP;
4572 }
4573}
4574
a66098da
LB
4575static const struct ieee80211_ops mwl8k_ops = {
4576 .tx = mwl8k_tx,
4577 .start = mwl8k_start,
4578 .stop = mwl8k_stop,
4579 .add_interface = mwl8k_add_interface,
4580 .remove_interface = mwl8k_remove_interface,
4581 .config = mwl8k_config,
a66098da 4582 .bss_info_changed = mwl8k_bss_info_changed,
3ac64bee 4583 .prepare_multicast = mwl8k_prepare_multicast,
a66098da 4584 .configure_filter = mwl8k_configure_filter,
fcdc403c 4585 .set_key = mwl8k_set_key,
a66098da 4586 .set_rts_threshold = mwl8k_set_rts_threshold,
4a6967b8
JB
4587 .sta_add = mwl8k_sta_add,
4588 .sta_remove = mwl8k_sta_remove,
a66098da 4589 .conf_tx = mwl8k_conf_tx,
a66098da 4590 .get_stats = mwl8k_get_stats,
0d462bbb 4591 .get_survey = mwl8k_get_survey,
a2292d83 4592 .ampdu_action = mwl8k_ampdu_action,
a66098da
LB
4593};
4594
a66098da
LB
4595static void mwl8k_finalize_join_worker(struct work_struct *work)
4596{
4597 struct mwl8k_priv *priv =
4598 container_of(work, struct mwl8k_priv, finalize_join_worker);
4599 struct sk_buff *skb = priv->beacon_skb;
56007a02
JB
4600 struct ieee80211_mgmt *mgmt = (void *)skb->data;
4601 int len = skb->len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
4602 const u8 *tim = cfg80211_find_ie(WLAN_EID_TIM,
4603 mgmt->u.beacon.variable, len);
4604 int dtim_period = 1;
4605
4606 if (tim && tim[1] >= 2)
4607 dtim_period = tim[3];
a66098da 4608
56007a02 4609 mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, dtim_period);
a66098da 4610
f5bb87cf 4611 dev_kfree_skb(skb);
a66098da
LB
4612 priv->beacon_skb = NULL;
4613}
4614
bcb628d5 4615enum {
9e1b17ea
LB
4616 MWL8363 = 0,
4617 MWL8687,
bcb628d5 4618 MWL8366,
6f6d1e9a
LB
4619};
4620
8a7a578c 4621#define MWL8K_8366_AP_FW_API 2
952a0e96
BC
4622#define _MWL8K_8366_AP_FW(api) "mwl8k/fmimage_8366_ap-" #api ".fw"
4623#define MWL8K_8366_AP_FW(api) _MWL8K_8366_AP_FW(api)
4624
bcb628d5 4625static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
9e1b17ea
LB
4626 [MWL8363] = {
4627 .part_name = "88w8363",
4628 .helper_image = "mwl8k/helper_8363.fw",
0863ade8 4629 .fw_image_sta = "mwl8k/fmimage_8363.fw",
9e1b17ea 4630 },
49eb691c 4631 [MWL8687] = {
bcb628d5
JL
4632 .part_name = "88w8687",
4633 .helper_image = "mwl8k/helper_8687.fw",
0863ade8 4634 .fw_image_sta = "mwl8k/fmimage_8687.fw",
bcb628d5 4635 },
49eb691c 4636 [MWL8366] = {
bcb628d5
JL
4637 .part_name = "88w8366",
4638 .helper_image = "mwl8k/helper_8366.fw",
0863ade8 4639 .fw_image_sta = "mwl8k/fmimage_8366.fw",
952a0e96
BC
4640 .fw_image_ap = MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API),
4641 .fw_api_ap = MWL8K_8366_AP_FW_API,
89a91f4f 4642 .ap_rxd_ops = &rxd_8366_ap_ops,
bcb628d5 4643 },
45a390dd
LB
4644};
4645
c92d4ede
LB
4646MODULE_FIRMWARE("mwl8k/helper_8363.fw");
4647MODULE_FIRMWARE("mwl8k/fmimage_8363.fw");
4648MODULE_FIRMWARE("mwl8k/helper_8687.fw");
4649MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
4650MODULE_FIRMWARE("mwl8k/helper_8366.fw");
4651MODULE_FIRMWARE("mwl8k/fmimage_8366.fw");
952a0e96 4652MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
c92d4ede 4653
45a390dd 4654static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
e5868ba1 4655 { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
9e1b17ea
LB
4656 { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
4657 { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
bcb628d5
JL
4658 { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
4659 { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
4660 { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
ca66527c 4661 { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, },
bcb628d5 4662 { },
45a390dd
LB
4663};
4664MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
4665
99020471
BC
4666static int mwl8k_request_alt_fw(struct mwl8k_priv *priv)
4667{
4668 int rc;
4669 printk(KERN_ERR "%s: Error requesting preferred fw %s.\n"
4670 "Trying alternative firmware %s\n", pci_name(priv->pdev),
4671 priv->fw_pref, priv->fw_alt);
4672 rc = mwl8k_request_fw(priv, priv->fw_alt, &priv->fw_ucode, true);
4673 if (rc) {
4674 printk(KERN_ERR "%s: Error requesting alt fw %s\n",
4675 pci_name(priv->pdev), priv->fw_alt);
4676 return rc;
4677 }
4678 return 0;
4679}
4680
4681static int mwl8k_firmware_load_success(struct mwl8k_priv *priv);
4682static void mwl8k_fw_state_machine(const struct firmware *fw, void *context)
4683{
4684 struct mwl8k_priv *priv = context;
4685 struct mwl8k_device_info *di = priv->device_info;
4686 int rc;
4687
4688 switch (priv->fw_state) {
4689 case FW_STATE_INIT:
4690 if (!fw) {
4691 printk(KERN_ERR "%s: Error requesting helper fw %s\n",
4692 pci_name(priv->pdev), di->helper_image);
4693 goto fail;
4694 }
4695 priv->fw_helper = fw;
4696 rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode,
4697 true);
4698 if (rc && priv->fw_alt) {
4699 rc = mwl8k_request_alt_fw(priv);
4700 if (rc)
4701 goto fail;
4702 priv->fw_state = FW_STATE_LOADING_ALT;
4703 } else if (rc)
4704 goto fail;
4705 else
4706 priv->fw_state = FW_STATE_LOADING_PREF;
4707 break;
4708
4709 case FW_STATE_LOADING_PREF:
4710 if (!fw) {
4711 if (priv->fw_alt) {
4712 rc = mwl8k_request_alt_fw(priv);
4713 if (rc)
4714 goto fail;
4715 priv->fw_state = FW_STATE_LOADING_ALT;
4716 } else
4717 goto fail;
4718 } else {
4719 priv->fw_ucode = fw;
4720 rc = mwl8k_firmware_load_success(priv);
4721 if (rc)
4722 goto fail;
4723 else
4724 complete(&priv->firmware_loading_complete);
4725 }
4726 break;
4727
4728 case FW_STATE_LOADING_ALT:
4729 if (!fw) {
4730 printk(KERN_ERR "%s: Error requesting alt fw %s\n",
4731 pci_name(priv->pdev), di->helper_image);
4732 goto fail;
4733 }
4734 priv->fw_ucode = fw;
4735 rc = mwl8k_firmware_load_success(priv);
4736 if (rc)
4737 goto fail;
4738 else
4739 complete(&priv->firmware_loading_complete);
4740 break;
4741
4742 default:
4743 printk(KERN_ERR "%s: Unexpected firmware loading state: %d\n",
4744 MWL8K_NAME, priv->fw_state);
4745 BUG_ON(1);
4746 }
4747
4748 return;
4749
4750fail:
4751 priv->fw_state = FW_STATE_ERROR;
4752 complete(&priv->firmware_loading_complete);
4753 device_release_driver(&priv->pdev->dev);
4754 mwl8k_release_firmware(priv);
4755}
4756
4757static int mwl8k_init_firmware(struct ieee80211_hw *hw, char *fw_image,
4758 bool nowait)
a66098da 4759{
3cc7772c 4760 struct mwl8k_priv *priv = hw->priv;
a66098da 4761 int rc;
be695fc4
LB
4762
4763 /* Reset firmware and hardware */
4764 mwl8k_hw_reset(priv);
4765
4766 /* Ask userland hotplug daemon for the device firmware */
99020471 4767 rc = mwl8k_request_firmware(priv, fw_image, nowait);
be695fc4 4768 if (rc) {
5db55844 4769 wiphy_err(hw->wiphy, "Firmware files not found\n");
3cc7772c 4770 return rc;
be695fc4
LB
4771 }
4772
99020471
BC
4773 if (nowait)
4774 return rc;
4775
be695fc4
LB
4776 /* Load firmware into hardware */
4777 rc = mwl8k_load_firmware(hw);
3cc7772c 4778 if (rc)
5db55844 4779 wiphy_err(hw->wiphy, "Cannot start firmware\n");
be695fc4
LB
4780
4781 /* Reclaim memory once firmware is successfully loaded */
4782 mwl8k_release_firmware(priv);
4783
3cc7772c
BC
4784 return rc;
4785}
4786
73b46320
BC
4787static int mwl8k_init_txqs(struct ieee80211_hw *hw)
4788{
4789 struct mwl8k_priv *priv = hw->priv;
4790 int rc = 0;
4791 int i;
4792
e600707b 4793 for (i = 0; i < mwl8k_tx_queues(priv); i++) {
73b46320
BC
4794 rc = mwl8k_txq_init(hw, i);
4795 if (rc)
4796 break;
4797 if (priv->ap_fw)
4798 iowrite32(priv->txq[i].txd_dma,
4799 priv->sram + priv->txq_offset[i]);
4800 }
4801 return rc;
4802}
4803
3cc7772c
BC
4804/* initialize hw after successfully loading a firmware image */
4805static int mwl8k_probe_hw(struct ieee80211_hw *hw)
4806{
4807 struct mwl8k_priv *priv = hw->priv;
4808 int rc = 0;
4809 int i;
be695fc4 4810
91942230 4811 if (priv->ap_fw) {
89a91f4f 4812 priv->rxd_ops = priv->device_info->ap_rxd_ops;
91942230 4813 if (priv->rxd_ops == NULL) {
c96c31e4
JP
4814 wiphy_err(hw->wiphy,
4815 "Driver does not have AP firmware image support for this hardware\n");
91942230
LB
4816 goto err_stop_firmware;
4817 }
4818 } else {
89a91f4f 4819 priv->rxd_ops = &rxd_sta_ops;
91942230 4820 }
be695fc4
LB
4821
4822 priv->sniffer_enabled = false;
4823 priv->wmm_enabled = false;
4824 priv->pending_tx_pkts = 0;
4825
a66098da
LB
4826 rc = mwl8k_rxq_init(hw, 0);
4827 if (rc)
3cc7772c 4828 goto err_stop_firmware;
a66098da
LB
4829 rxq_refill(hw, 0, INT_MAX);
4830
73b46320
BC
4831 /* For the sta firmware, we need to know the dma addresses of tx queues
4832 * before sending MWL8K_CMD_GET_HW_SPEC. So we must initialize them
4833 * prior to issuing this command. But for the AP case, we learn the
4834 * total number of queues from the result CMD_GET_HW_SPEC, so for this
4835 * case we must initialize the tx queues after.
4836 */
8a7a578c 4837 priv->num_ampdu_queues = 0;
73b46320
BC
4838 if (!priv->ap_fw) {
4839 rc = mwl8k_init_txqs(hw);
a66098da
LB
4840 if (rc)
4841 goto err_free_queues;
4842 }
4843
4844 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS);
c23b5a69 4845 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
67e2eb27 4846 iowrite32(MWL8K_A2H_INT_TX_DONE | MWL8K_A2H_INT_RX_READY,
1e9f9de3 4847 priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL);
a66098da
LB
4848 iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK);
4849
a0607fd3 4850 rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
a66098da
LB
4851 IRQF_SHARED, MWL8K_NAME, hw);
4852 if (rc) {
5db55844 4853 wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
a66098da
LB
4854 goto err_free_queues;
4855 }
4856
a66098da
LB
4857 /*
4858 * Temporarily enable interrupts. Initial firmware host
c2c2b12a 4859 * commands use interrupts and avoid polling. Disable
a66098da
LB
4860 * interrupts when done.
4861 */
c23b5a69 4862 iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
a66098da
LB
4863
4864 /* Get config data, mac addrs etc */
42fba21d
LB
4865 if (priv->ap_fw) {
4866 rc = mwl8k_cmd_get_hw_spec_ap(hw);
73b46320
BC
4867 if (!rc)
4868 rc = mwl8k_init_txqs(hw);
42fba21d
LB
4869 if (!rc)
4870 rc = mwl8k_cmd_set_hw_spec(hw);
4871 } else {
4872 rc = mwl8k_cmd_get_hw_spec_sta(hw);
4873 }
a66098da 4874 if (rc) {
5db55844 4875 wiphy_err(hw->wiphy, "Cannot initialise firmware\n");
be695fc4 4876 goto err_free_irq;
a66098da
LB
4877 }
4878
4879 /* Turn radio off */
55489b6e 4880 rc = mwl8k_cmd_radio_disable(hw);
a66098da 4881 if (rc) {
5db55844 4882 wiphy_err(hw->wiphy, "Cannot disable\n");
be695fc4 4883 goto err_free_irq;
a66098da
LB
4884 }
4885
32060e1b 4886 /* Clear MAC address */
aa21d0f6 4887 rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
32060e1b 4888 if (rc) {
5db55844 4889 wiphy_err(hw->wiphy, "Cannot clear MAC address\n");
be695fc4 4890 goto err_free_irq;
32060e1b
LB
4891 }
4892
a66098da 4893 /* Disable interrupts */
a66098da 4894 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
a66098da
LB
4895 free_irq(priv->pdev->irq, hw);
4896
c96c31e4
JP
4897 wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n",
4898 priv->device_info->part_name,
4899 priv->hw_rev, hw->wiphy->perm_addr,
4900 priv->ap_fw ? "AP" : "STA",
4901 (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
4902 (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
a66098da
LB
4903
4904 return 0;
4905
a66098da 4906err_free_irq:
a66098da 4907 iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
a66098da
LB
4908 free_irq(priv->pdev->irq, hw);
4909
4910err_free_queues:
e600707b 4911 for (i = 0; i < mwl8k_tx_queues(priv); i++)
a66098da
LB
4912 mwl8k_txq_deinit(hw, i);
4913 mwl8k_rxq_deinit(hw, 0);
4914
3cc7772c
BC
4915err_stop_firmware:
4916 mwl8k_hw_reset(priv);
4917
4918 return rc;
4919}
4920
4921/*
4922 * invoke mwl8k_reload_firmware to change the firmware image after the device
4923 * has already been registered
4924 */
4925static int mwl8k_reload_firmware(struct ieee80211_hw *hw, char *fw_image)
4926{
4927 int i, rc = 0;
4928 struct mwl8k_priv *priv = hw->priv;
4929
4930 mwl8k_stop(hw);
4931 mwl8k_rxq_deinit(hw, 0);
4932
e600707b 4933 for (i = 0; i < mwl8k_tx_queues(priv); i++)
3cc7772c
BC
4934 mwl8k_txq_deinit(hw, i);
4935
99020471 4936 rc = mwl8k_init_firmware(hw, fw_image, false);
3cc7772c
BC
4937 if (rc)
4938 goto fail;
4939
4940 rc = mwl8k_probe_hw(hw);
4941 if (rc)
4942 goto fail;
4943
4944 rc = mwl8k_start(hw);
4945 if (rc)
4946 goto fail;
4947
4948 rc = mwl8k_config(hw, ~0);
4949 if (rc)
4950 goto fail;
4951
e600707b 4952 for (i = 0; i < MWL8K_TX_WMM_QUEUES; i++) {
3cc7772c
BC
4953 rc = mwl8k_conf_tx(hw, i, &priv->wmm_params[i]);
4954 if (rc)
4955 goto fail;
4956 }
4957
4958 return rc;
4959
4960fail:
4961 printk(KERN_WARNING "mwl8k: Failed to reload firmware image.\n");
4962 return rc;
4963}
4964
4965static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
4966{
4967 struct ieee80211_hw *hw = priv->hw;
4968 int i, rc;
4969
99020471
BC
4970 rc = mwl8k_load_firmware(hw);
4971 mwl8k_release_firmware(priv);
4972 if (rc) {
4973 wiphy_err(hw->wiphy, "Cannot start firmware\n");
4974 return rc;
4975 }
4976
3cc7772c
BC
4977 /*
4978 * Extra headroom is the size of the required DMA header
4979 * minus the size of the smallest 802.11 frame (CTS frame).
4980 */
4981 hw->extra_tx_headroom =
4982 sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts);
4983
4984 hw->channel_change_time = 10;
4985
e600707b 4986 hw->queues = MWL8K_TX_WMM_QUEUES;
3cc7772c
BC
4987
4988 /* Set rssi values to dBm */
0bf22c37 4989 hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
3cc7772c
BC
4990 hw->vif_data_size = sizeof(struct mwl8k_vif);
4991 hw->sta_data_size = sizeof(struct mwl8k_sta);
4992
4993 priv->macids_used = 0;
4994 INIT_LIST_HEAD(&priv->vif_list);
4995
4996 /* Set default radio state and preamble */
4997 priv->radio_on = 0;
4998 priv->radio_short_preamble = 0;
4999
5000 /* Finalize join worker */
5001 INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
5002
5003 /* TX reclaim and RX tasklets. */
5004 tasklet_init(&priv->poll_tx_task, mwl8k_tx_poll, (unsigned long)hw);
5005 tasklet_disable(&priv->poll_tx_task);
5006 tasklet_init(&priv->poll_rx_task, mwl8k_rx_poll, (unsigned long)hw);
5007 tasklet_disable(&priv->poll_rx_task);
5008
5009 /* Power management cookie */
5010 priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
5011 if (priv->cookie == NULL)
5012 return -ENOMEM;
5013
5014 mutex_init(&priv->fw_mutex);
5015 priv->fw_mutex_owner = NULL;
5016 priv->fw_mutex_depth = 0;
5017 priv->hostcmd_wait = NULL;
5018
5019 spin_lock_init(&priv->tx_lock);
5020
5021 priv->tx_wait = NULL;
5022
5023 rc = mwl8k_probe_hw(hw);
5024 if (rc)
5025 goto err_free_cookie;
5026
5027 hw->wiphy->interface_modes = 0;
5028 if (priv->ap_macids_supported || priv->device_info->fw_image_ap)
5029 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
5030 if (priv->sta_macids_supported || priv->device_info->fw_image_sta)
5031 hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
5032
5033 rc = ieee80211_register_hw(hw);
5034 if (rc) {
5035 wiphy_err(hw->wiphy, "Cannot register device\n");
5036 goto err_unprobe_hw;
5037 }
5038
5039 return 0;
5040
5041err_unprobe_hw:
e600707b 5042 for (i = 0; i < mwl8k_tx_queues(priv); i++)
3cc7772c
BC
5043 mwl8k_txq_deinit(hw, i);
5044 mwl8k_rxq_deinit(hw, 0);
5045
be695fc4 5046err_free_cookie:
a66098da
LB
5047 if (priv->cookie != NULL)
5048 pci_free_consistent(priv->pdev, 4,
5049 priv->cookie, priv->cookie_dma);
5050
3cc7772c
BC
5051 return rc;
5052}
5053static int __devinit mwl8k_probe(struct pci_dev *pdev,
5054 const struct pci_device_id *id)
5055{
5056 static int printed_version;
5057 struct ieee80211_hw *hw;
5058 struct mwl8k_priv *priv;
0863ade8 5059 struct mwl8k_device_info *di;
3cc7772c
BC
5060 int rc;
5061
5062 if (!printed_version) {
5063 printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION);
5064 printed_version = 1;
5065 }
5066
5067
5068 rc = pci_enable_device(pdev);
5069 if (rc) {
5070 printk(KERN_ERR "%s: Cannot enable new PCI device\n",
5071 MWL8K_NAME);
5072 return rc;
5073 }
5074
5075 rc = pci_request_regions(pdev, MWL8K_NAME);
5076 if (rc) {
5077 printk(KERN_ERR "%s: Cannot obtain PCI resources\n",
5078 MWL8K_NAME);
5079 goto err_disable_device;
5080 }
5081
5082 pci_set_master(pdev);
5083
5084
5085 hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops);
5086 if (hw == NULL) {
5087 printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME);
5088 rc = -ENOMEM;
5089 goto err_free_reg;
5090 }
5091
5092 SET_IEEE80211_DEV(hw, &pdev->dev);
5093 pci_set_drvdata(pdev, hw);
5094
5095 priv = hw->priv;
5096 priv->hw = hw;
5097 priv->pdev = pdev;
5098 priv->device_info = &mwl8k_info_tbl[id->driver_data];
5099
5100
5101 priv->sram = pci_iomap(pdev, 0, 0x10000);
5102 if (priv->sram == NULL) {
5103 wiphy_err(hw->wiphy, "Cannot map device SRAM\n");
5104 goto err_iounmap;
5105 }
5106
5107 /*
5108 * If BAR0 is a 32 bit BAR, the register BAR will be BAR1.
5109 * If BAR0 is a 64 bit BAR, the register BAR will be BAR2.
5110 */
5111 priv->regs = pci_iomap(pdev, 1, 0x10000);
5112 if (priv->regs == NULL) {
5113 priv->regs = pci_iomap(pdev, 2, 0x10000);
5114 if (priv->regs == NULL) {
5115 wiphy_err(hw->wiphy, "Cannot map device registers\n");
5116 goto err_iounmap;
5117 }
5118 }
5119
0863ade8 5120 /*
99020471
BC
5121 * Choose the initial fw image depending on user input. If a second
5122 * image is available, make it the alternative image that will be
5123 * loaded if the first one fails.
0863ade8 5124 */
99020471 5125 init_completion(&priv->firmware_loading_complete);
0863ade8 5126 di = priv->device_info;
99020471
BC
5127 if (ap_mode_default && di->fw_image_ap) {
5128 priv->fw_pref = di->fw_image_ap;
5129 priv->fw_alt = di->fw_image_sta;
5130 } else if (!ap_mode_default && di->fw_image_sta) {
5131 priv->fw_pref = di->fw_image_sta;
5132 priv->fw_alt = di->fw_image_ap;
5133 } else if (ap_mode_default && !di->fw_image_ap && di->fw_image_sta) {
0863ade8 5134 printk(KERN_WARNING "AP fw is unavailable. Using STA fw.");
99020471 5135 priv->fw_pref = di->fw_image_sta;
0863ade8
BC
5136 } else if (!ap_mode_default && !di->fw_image_sta && di->fw_image_ap) {
5137 printk(KERN_WARNING "STA fw is unavailable. Using AP fw.");
99020471
BC
5138 priv->fw_pref = di->fw_image_ap;
5139 }
5140 rc = mwl8k_init_firmware(hw, priv->fw_pref, true);
3cc7772c
BC
5141 if (rc)
5142 goto err_stop_firmware;
99020471 5143 return rc;
3cc7772c 5144
be695fc4
LB
5145err_stop_firmware:
5146 mwl8k_hw_reset(priv);
be695fc4
LB
5147
5148err_iounmap:
a66098da
LB
5149 if (priv->regs != NULL)
5150 pci_iounmap(pdev, priv->regs);
5151
5b9482dd
LB
5152 if (priv->sram != NULL)
5153 pci_iounmap(pdev, priv->sram);
5154
a66098da
LB
5155 pci_set_drvdata(pdev, NULL);
5156 ieee80211_free_hw(hw);
5157
5158err_free_reg:
5159 pci_release_regions(pdev);
3db95e50
LB
5160
5161err_disable_device:
a66098da
LB
5162 pci_disable_device(pdev);
5163
5164 return rc;
5165}
5166
230f7af0 5167static void __devexit mwl8k_shutdown(struct pci_dev *pdev)
a66098da
LB
5168{
5169 printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__);
5170}
5171
230f7af0 5172static void __devexit mwl8k_remove(struct pci_dev *pdev)
a66098da
LB
5173{
5174 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
5175 struct mwl8k_priv *priv;
5176 int i;
5177
5178 if (hw == NULL)
5179 return;
5180 priv = hw->priv;
5181
99020471
BC
5182 wait_for_completion(&priv->firmware_loading_complete);
5183
5184 if (priv->fw_state == FW_STATE_ERROR) {
5185 mwl8k_hw_reset(priv);
5186 goto unmap;
5187 }
5188
a66098da
LB
5189 ieee80211_stop_queues(hw);
5190
60aa569f
LB
5191 ieee80211_unregister_hw(hw);
5192
67e2eb27 5193 /* Remove TX reclaim and RX tasklets. */
1e9f9de3 5194 tasklet_kill(&priv->poll_tx_task);
67e2eb27 5195 tasklet_kill(&priv->poll_rx_task);
a66098da 5196
a66098da
LB
5197 /* Stop hardware */
5198 mwl8k_hw_reset(priv);
5199
5200 /* Return all skbs to mac80211 */
e600707b 5201 for (i = 0; i < mwl8k_tx_queues(priv); i++)
efb7c49a 5202 mwl8k_txq_reclaim(hw, i, INT_MAX, 1);
a66098da 5203
e600707b 5204 for (i = 0; i < mwl8k_tx_queues(priv); i++)
a66098da
LB
5205 mwl8k_txq_deinit(hw, i);
5206
5207 mwl8k_rxq_deinit(hw, 0);
5208
c2c357ce 5209 pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma);
a66098da 5210
99020471 5211unmap:
a66098da 5212 pci_iounmap(pdev, priv->regs);
5b9482dd 5213 pci_iounmap(pdev, priv->sram);
a66098da
LB
5214 pci_set_drvdata(pdev, NULL);
5215 ieee80211_free_hw(hw);
5216 pci_release_regions(pdev);
5217 pci_disable_device(pdev);
5218}
5219
5220static struct pci_driver mwl8k_driver = {
5221 .name = MWL8K_NAME,
45a390dd 5222 .id_table = mwl8k_pci_id_table,
a66098da
LB
5223 .probe = mwl8k_probe,
5224 .remove = __devexit_p(mwl8k_remove),
5225 .shutdown = __devexit_p(mwl8k_shutdown),
5226};
5227
5228static int __init mwl8k_init(void)
5229{
5230 return pci_register_driver(&mwl8k_driver);
5231}
5232
5233static void __exit mwl8k_exit(void)
5234{
5235 pci_unregister_driver(&mwl8k_driver);
5236}
5237
5238module_init(mwl8k_init);
5239module_exit(mwl8k_exit);
c2c357ce
LB
5240
5241MODULE_DESCRIPTION(MWL8K_DESC);
5242MODULE_VERSION(MWL8K_VERSION);
5243MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>");
5244MODULE_LICENSE("GPL");