]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/brcm80211/sys/wl_mac80211.c
Staging: brcm80211: remove unneeded pm macro
[net-next-2.6.git] / drivers / staging / brcm80211 / sys / wl_mac80211.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #define __UNDEF_NO_VERSION__
18
19 #include <typedefs.h>
20 #include <linuxver.h>
21 #include <osl.h>
22 #include <linux/kernel.h>
23 #include <linux/etherdevice.h>
24 #include <linux/string.h>
25 #include <linux/pci_ids.h>
26 #define WLC_MAXBSSCFG           1       /* single BSS configs */
27
28 #include <wlc_cfg.h>
29 #include <net/mac80211.h>
30 #include <epivers.h>
31 #ifndef WLC_HIGH_ONLY
32 #include <phy_version.h>
33 #endif
34 #include <bcmutils.h>
35 #include <pcicfg.h>
36 #include <wlioctl.h>
37 #include <wlc_key.h>
38 #include <wlc_channel.h>
39 #include <wlc_pub.h>
40 #include <wlc_scb.h>
41 #include <wl_dbg.h>
42 #ifdef BCMSDIO
43 #include <bcmsdh.h>
44 #endif
45 #include <wl_export.h>
46 #ifdef WLC_HIGH_ONLY
47 #include "dbus.h"
48 #include "bcm_rpc_tp.h"
49 #include "bcm_rpc.h"
50 #include "bcm_xdr.h"
51 #include "wlc_rpc.h"
52 #endif
53
54 #include <wl_mac80211.h>
55 #include <linux/firmware.h>
56 #ifndef WLC_HIGH_ONLY
57 #include <wl_ucode.h>
58 #include <d11ucode_ext.h>
59 #endif
60
61 #ifdef BCMSDIO
62 extern struct device *sdiommc_dev;
63 #endif
64
65 extern void wlc_wme_setparams(wlc_info_t *wlc, u16 aci, void *arg,
66                               bool suspend);
67 bool wlc_sendpkt_mac80211(wlc_info_t *wlc, void *sdu, struct ieee80211_hw *hw);
68 void wlc_mac_bcn_promisc_change(wlc_info_t *wlc, bool promisc);
69 void wlc_set_addrmatch(wlc_info_t *wlc, int match_reg_offset,
70                        const struct ether_addr *addr);
71
72 static void wl_timer(unsigned long data);
73 static void _wl_timer(wl_timer_t *t);
74
75 #ifdef WLC_HIGH_ONLY
76 #define RPCQ_LOCK(_wl, _flags) spin_lock_irqsave(&(_wl)->rpcq_lock, (_flags))
77 #define RPCQ_UNLOCK(_wl, _flags)  spin_unlock_irqrestore(&(_wl)->rpcq_lock, (_flags))
78 #define TXQ_LOCK(_wl, _flags) spin_lock_irqsave(&(_wl)->txq_lock, (_flags))
79 #define TXQ_UNLOCK(_wl, _flags)  spin_unlock_irqrestore(&(_wl)->txq_lock, (_flags))
80 static void wl_rpc_down(void *wlh);
81 static void wl_rpcq_free(wl_info_t *wl);
82 static void wl_rpcq_dispatch(struct wl_task *task);
83 static void wl_rpc_dispatch_schedule(void *ctx, struct rpc_buf *buf);
84 static void wl_start_txqwork(struct wl_task *task);
85 static void wl_txq_free(wl_info_t *wl);
86 static void wl_timer_task(wl_task_t *task);
87 static int wl_schedule_task(wl_info_t *wl, void (*fn) (struct wl_task *),
88                             void *context);
89 #endif                          /* WLC_HIGH_ONLY */
90
91 static int ieee_hw_init(struct ieee80211_hw *hw);
92 static int ieee_hw_rate_init(struct ieee80211_hw *hw);
93
94 static int wl_linux_watchdog(void *ctx);
95
96 /* Flags we support */
97 #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
98         FIF_ALLMULTI | \
99         FIF_FCSFAIL | \
100         FIF_PLCPFAIL | \
101         FIF_CONTROL | \
102         FIF_OTHER_BSS | \
103         FIF_BCN_PRBRESP_PROMISC)
104
105 static int wl_found;
106
107 struct ieee80211_tkip_data {
108 #define TKIP_KEY_LEN 32
109         u8 key[TKIP_KEY_LEN];
110         int key_set;
111
112         u32 tx_iv32;
113         u16 tx_iv16;
114         u16 tx_ttak[5];
115         int tx_phase1_done;
116
117         u32 rx_iv32;
118         u16 rx_iv16;
119         u16 rx_ttak[5];
120         int rx_phase1_done;
121         u32 rx_iv32_new;
122         u16 rx_iv16_new;
123
124         u32 dot11RSNAStatsTKIPReplays;
125         u32 dot11RSNAStatsTKIPICVErrors;
126         u32 dot11RSNAStatsTKIPLocalMICFailures;
127
128         int key_idx;
129
130         struct crypto_tfm *tfm_arc4;
131         struct crypto_tfm *tfm_michael;
132
133         /* scratch buffers for virt_to_page() (crypto API) */
134         u8 rx_hdr[16], tx_hdr[16];
135 };
136
137 #ifndef WLC_HIGH_ONLY
138 #define WL_INFO(dev)            ((wl_info_t *)(WL_DEV_IF(dev)->wl))     /* points to wl */
139 static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev);
140 static void wl_release_fw(wl_info_t *wl);
141 #endif
142
143 /* local prototypes */
144 static int wl_start(struct sk_buff *skb, wl_info_t *wl);
145 static int wl_start_int(wl_info_t *wl, struct ieee80211_hw *hw,
146                         struct sk_buff *skb);
147 static void wl_dpc(unsigned long data);
148
149 MODULE_AUTHOR("Broadcom Corporation");
150 MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
151 MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
152 MODULE_LICENSE("Dual BSD/GPL");
153
154 #ifndef BCMSDIO
155 /* recognized PCI IDs */
156 static struct pci_device_id wl_id_table[] = {
157         {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 43225 2G */
158         {PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 43224 DUAL */
159         {PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 4313 DUAL */
160         {0}
161 };
162
163 MODULE_DEVICE_TABLE(pci, wl_id_table);
164 static void wl_remove(struct pci_dev *pdev);
165 #endif                          /* !BCMSDIO */
166
167 #ifdef BCMSDIO
168 static uint sd_drivestrength = 6;
169 module_param(sd_drivestrength, uint, 0);
170 #endif
171
172 #ifdef BCMDBG
173 static int msglevel = 0xdeadbeef;
174 module_param(msglevel, int, 0);
175 #ifndef WLC_HIGH_ONLY
176 static int phymsglevel = 0xdeadbeef;
177 module_param(phymsglevel, int, 0);
178 #endif                          /* WLC_HIGH_ONLY */
179 #endif                          /* BCMDBG */
180
181 static int oneonly;
182 module_param(oneonly, int, 0);
183
184 static int piomode;
185 module_param(piomode, int, 0);
186
187 static int instance_base;       /* Starting instance number */
188 module_param(instance_base, int, 0);
189
190 #if defined(BCMDBG)
191 static char *macaddr;
192 module_param(macaddr, charp, S_IRUGO);
193 #endif
194
195 static int nompc = 1;
196 module_param(nompc, int, 0);
197
198 static char name[IFNAMSIZ] = "eth%d";
199 module_param_string(name, name, IFNAMSIZ, 0);
200
201 #ifndef SRCBASE
202 #define SRCBASE "."
203 #endif
204
205 #define WL_MAGIC        0xdeadbeef
206
207 #define HW_TO_WL(hw)     (hw->priv)
208 #define WL_TO_HW(wl)      (wl->pub->ieee_hw)
209 #ifdef WLC_HIGH_ONLY
210 static int wl_ops_tx_nl(struct ieee80211_hw *hw, struct sk_buff *skb);
211 #else
212 static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
213 #endif
214 static int wl_ops_start(struct ieee80211_hw *hw);
215 static void wl_ops_stop(struct ieee80211_hw *hw);
216 static int wl_ops_add_interface(struct ieee80211_hw *hw,
217                                 struct ieee80211_vif *vif);
218 static void wl_ops_remove_interface(struct ieee80211_hw *hw,
219                                     struct ieee80211_vif *vif);
220 static int wl_ops_config(struct ieee80211_hw *hw, u32 changed);
221 static void wl_ops_bss_info_changed(struct ieee80211_hw *hw,
222                                     struct ieee80211_vif *vif,
223                                     struct ieee80211_bss_conf *info,
224                                     u32 changed);
225 static void wl_ops_configure_filter(struct ieee80211_hw *hw,
226                                     unsigned int changed_flags,
227                                     unsigned int *total_flags, u64 multicast);
228 static int wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
229                           bool set);
230 static void wl_ops_sw_scan_start(struct ieee80211_hw *hw);
231 static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
232 static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
233 static int wl_ops_get_stats(struct ieee80211_hw *hw,
234                             struct ieee80211_low_level_stats *stats);
235 static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
236 static void wl_ops_sta_notify(struct ieee80211_hw *hw,
237                               struct ieee80211_vif *vif,
238                               enum sta_notify_cmd cmd,
239                               struct ieee80211_sta *sta);
240 static int wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
241                           const struct ieee80211_tx_queue_params *params);
242 static u64 wl_ops_get_tsf(struct ieee80211_hw *hw);
243 static int wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
244                       struct ieee80211_sta *sta);
245 static int wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
246                          struct ieee80211_sta *sta);
247 static int wl_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
248                            enum ieee80211_ampdu_mlme_action action,
249                            struct ieee80211_sta *sta, u16 tid, u16 *ssn);
250
251 #ifdef WLC_HIGH_ONLY
252 static int wl_ops_tx_nl(struct ieee80211_hw *hw, struct sk_buff *skb)
253 {
254         int status;
255         wl_info_t *wl = hw->priv;
256         if (!wl->pub->up) {
257                 WL_ERROR(("ops->tx called while down\n"));
258                 status = -ENETDOWN;
259                 goto done;
260         }
261         status = wl_start(skb, wl);
262  done:
263         return status;
264 }
265 #else
266 static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
267 {
268         int status;
269         wl_info_t *wl = hw->priv;
270         WL_LOCK(wl);
271         if (!wl->pub->up) {
272                 WL_ERROR(("ops->tx called while down\n"));
273                 status = -ENETDOWN;
274                 goto done;
275         }
276         status = wl_start(skb, wl);
277  done:
278         WL_UNLOCK(wl);
279         return status;
280 }
281 #endif                          /* WLC_HIGH_ONLY */
282
283 static int wl_ops_start(struct ieee80211_hw *hw)
284 {
285         wl_info_t *wl = hw->priv;
286         /* struct ieee80211_channel *curchan = hw->conf.channel; */
287         WL_NONE(("%s : Initial channel: %d\n", __func__, curchan->hw_value));
288
289         WL_LOCK(wl);
290         ieee80211_wake_queues(hw);
291         WL_UNLOCK(wl);
292
293         return 0;
294 }
295
296 static void wl_ops_stop(struct ieee80211_hw *hw)
297 {
298         wl_info_t *wl = hw->priv;
299         ASSERT(wl);
300         WL_LOCK(wl);
301         wl_down(wl);
302         ieee80211_stop_queues(hw);
303         WL_UNLOCK(wl);
304
305         return;
306 }
307
308 static int
309 wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
310 {
311         wl_info_t *wl;
312         int err;
313
314         /* Just STA for now */
315         if (vif->type != NL80211_IFTYPE_AP &&
316             vif->type != NL80211_IFTYPE_MESH_POINT &&
317             vif->type != NL80211_IFTYPE_STATION &&
318             vif->type != NL80211_IFTYPE_WDS &&
319             vif->type != NL80211_IFTYPE_ADHOC) {
320                 WL_ERROR(("%s: Attempt to add type %d, only STA for now\n",
321                           __func__, vif->type));
322                 return -EOPNOTSUPP;
323         }
324
325         wl = HW_TO_WL(hw);
326         WL_LOCK(wl);
327         err = wl_up(wl);
328         WL_UNLOCK(wl);
329
330         if (err != 0)
331                 WL_ERROR(("%s: wl_up() returned %d\n", __func__, err));
332         return err;
333 }
334
335 static void
336 wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
337 {
338         return;
339 }
340
341 static int
342 ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
343                  enum nl80211_channel_type type)
344 {
345         wl_info_t *wl = HW_TO_WL(hw);
346         int err = 0;
347
348         switch (type) {
349         case NL80211_CHAN_HT20:
350         case NL80211_CHAN_NO_HT:
351                 WL_LOCK(wl);
352                 err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
353                 WL_UNLOCK(wl);
354                 break;
355         case NL80211_CHAN_HT40MINUS:
356         case NL80211_CHAN_HT40PLUS:
357                 WL_ERROR(("%s: Need to implement 40 Mhz Channels!\n",
358                           __func__));
359                 break;
360         }
361
362         if (err)
363                 return -EIO;
364         return err;
365 }
366
367 static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
368 {
369         struct ieee80211_conf *conf = &hw->conf;
370         wl_info_t *wl = HW_TO_WL(hw);
371         int err = 0;
372         int new_int;
373
374         if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
375                 WL_NONE(("%s: Setting listen interval to %d\n",
376                          __func__, conf->listen_interval));
377                 if (wlc_iovar_setint
378                     (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
379                         WL_ERROR(("%s: Error setting listen_interval\n",
380                                   __func__));
381                         err = -EIO;
382                         goto config_out;
383                 }
384                 wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
385                 ASSERT(new_int == conf->listen_interval);
386         }
387         if (changed & IEEE80211_CONF_CHANGE_MONITOR)
388                 WL_NONE(("Need to set monitor mode\n"));
389         if (changed & IEEE80211_CONF_CHANGE_PS)
390                 WL_NONE(("Need to set Power-save mode\n"));
391
392         if (changed & IEEE80211_CONF_CHANGE_POWER) {
393                 WL_NONE(("%s: Setting tx power to %d dbm\n", __func__,
394                          conf->power_level));
395                 if (wlc_iovar_setint
396                     (wl->wlc, "qtxpower", conf->power_level * 4)) {
397                         WL_ERROR(("%s: Error setting power_level\n", __func__));
398                         err = -EIO;
399                         goto config_out;
400                 }
401                 wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
402                 if (new_int != (conf->power_level * 4))
403                         WL_ERROR(("%s: Power level req != actual, %d %d\n",
404                                   __func__, conf->power_level * 4, new_int));
405         }
406         if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
407                 err = ieee_set_channel(hw, conf->channel, conf->channel_type);
408         }
409         if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
410                 WL_NONE(("%s: srl %d, lrl %d\n", __func__,
411                          conf->short_frame_max_tx_count,
412                          conf->long_frame_max_tx_count));
413                 if (wlc_set
414                     (wl->wlc, WLC_SET_SRL,
415                      conf->short_frame_max_tx_count) < 0) {
416                         WL_ERROR(("%s: Error setting srl\n", __func__));
417                         err = -EIO;
418                         goto config_out;
419                 }
420                 if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
421                     < 0) {
422                         WL_ERROR(("%s: Error setting lrl\n", __func__));
423                         err = -EIO;
424                         goto config_out;
425                 }
426         }
427
428  config_out:
429         return err;
430 }
431
432 static void
433 wl_ops_bss_info_changed(struct ieee80211_hw *hw,
434                         struct ieee80211_vif *vif,
435                         struct ieee80211_bss_conf *info, u32 changed)
436 {
437         wl_info_t *wl = HW_TO_WL(hw);
438         int val;
439
440 #ifdef WLC_HIGH_ONLY
441         WL_LOCK(wl);
442 #endif
443
444         if (changed & BSS_CHANGED_ASSOC) {
445                 WL_ERROR(("Associated:\t%s\n", info->assoc ? "True" : "False"));
446                 /* association status changed (associated/disassociated)
447                  * also implies a change in the AID.
448                  */
449         }
450         if (changed & BSS_CHANGED_ERP_CTS_PROT) {
451                 WL_NONE(("Use_cts_prot:\t%s Implement me\n",
452                          info->use_cts_prot ? "True" : "False"));
453                 /* CTS protection changed */
454         }
455         if (changed & BSS_CHANGED_ERP_PREAMBLE) {
456                 WL_NONE(("Short preamble:\t%s Implement me\n",
457                          info->use_short_preamble ? "True" : "False"));
458                 /* preamble changed */
459         }
460         if (changed & BSS_CHANGED_ERP_SLOT) {
461                 WL_NONE(("Changing short slot:\t%s\n",
462                          info->use_short_slot ? "True" : "False"));
463                 if (info->use_short_slot)
464                         val = 1;
465                 else
466                         val = 0;
467                 wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
468                 /* slot timing changed */
469         }
470
471         if (changed & BSS_CHANGED_HT) {
472                 WL_NONE(("%s: HT mode - Implement me\n", __func__));
473                 /* 802.11n parameters changed */
474         }
475         if (changed & BSS_CHANGED_BASIC_RATES) {
476                 WL_NONE(("Need to change Basic Rates:\t0x%x! Implement me\n",
477                          (uint32) info->basic_rates));
478                 /* Basic rateset changed */
479         }
480         if (changed & BSS_CHANGED_BEACON_INT) {
481                 WL_NONE(("Beacon Interval:\t%d Implement me\n",
482                          info->beacon_int));
483                 /* Beacon interval changed */
484         }
485         if (changed & BSS_CHANGED_BSSID) {
486                 /* char eabuf[ETHER_ADDR_STR_LEN]; */
487                 WL_NONE(("new BSSID:\taid %d  bss:%s\n",
488                          info->aid,
489                          bcm_ether_ntoa((struct ether_addr *)info->bssid,
490                                         eabuf)));
491                 /* BSSID changed, for whatever reason (IBSS and managed mode) */
492                 /* FIXME: need to store bssid in bsscfg */
493                 wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
494                                   (struct ether_addr *)info->bssid);
495         }
496         if (changed & BSS_CHANGED_BEACON) {
497                 WL_ERROR(("BSS_CHANGED_BEACON\n"));
498                 /* Beacon data changed, retrieve new beacon (beaconing modes) */
499         }
500         if (changed & BSS_CHANGED_BEACON_ENABLED) {
501                 WL_ERROR(("Beacon enabled:\t%s\n",
502                           info->enable_beacon ? "True" : "False"));
503                 /* Beaconing should be enabled/disabled (beaconing modes) */
504         }
505 #ifdef WLC_HIGH_ONLY
506         WL_UNLOCK(wl);
507 #endif
508         return;
509 }
510
511 static void
512 wl_ops_configure_filter(struct ieee80211_hw *hw,
513                         unsigned int changed_flags,
514                         unsigned int *total_flags, u64 multicast)
515 {
516 #ifndef WLC_HIGH_ONLY
517         wl_info_t *wl = hw->priv;
518 #endif
519
520         changed_flags &= MAC_FILTERS;
521         *total_flags &= MAC_FILTERS;
522         if (changed_flags & FIF_PROMISC_IN_BSS)
523                 WL_ERROR(("FIF_PROMISC_IN_BSS\n"));
524         if (changed_flags & FIF_ALLMULTI)
525                 WL_ERROR(("FIF_ALLMULTI\n"));
526         if (changed_flags & FIF_FCSFAIL)
527                 WL_ERROR(("FIF_FCSFAIL\n"));
528         if (changed_flags & FIF_PLCPFAIL)
529                 WL_ERROR(("FIF_PLCPFAIL\n"));
530         if (changed_flags & FIF_CONTROL)
531                 WL_ERROR(("FIF_CONTROL\n"));
532         if (changed_flags & FIF_OTHER_BSS)
533                 WL_ERROR(("FIF_OTHER_BSS\n"));
534         if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
535                 WL_NONE(("FIF_BCN_PRBRESP_PROMISC\n"));
536 #ifndef WLC_HIGH_ONLY
537                 WL_LOCK(wl);
538                 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
539                         wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
540                         wlc_mac_bcn_promisc_change(wl->wlc, 1);
541                 } else {
542                         wlc_mac_bcn_promisc_change(wl->wlc, 0);
543                         wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
544                 }
545                 WL_UNLOCK(wl);
546 #endif
547         }
548         return;
549 }
550
551 static int
552 wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
553 {
554         WL_ERROR(("%s: Enter\n", __func__));
555         return 0;
556 }
557
558 static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
559 {
560         WL_NONE(("Scan Start\n"));
561         return;
562 }
563
564 static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
565 {
566         WL_NONE(("Scan Complete\n"));
567         return;
568 }
569
570 static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
571 {
572         WL_ERROR(("%s: Enter\n", __func__));
573         return;
574 }
575
576 static int
577 wl_ops_get_stats(struct ieee80211_hw *hw,
578                  struct ieee80211_low_level_stats *stats)
579 {
580         WL_ERROR(("%s: Enter\n", __func__));
581         return 0;
582 }
583
584 static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
585 {
586         WL_ERROR(("%s: Enter\n", __func__));
587         return 0;
588 }
589
590 static void
591 wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
592                   enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
593 {
594         WL_NONE(("%s: Enter\n", __func__));
595         switch (cmd) {
596         default:
597                 WL_ERROR(("%s: Uknown cmd = %d\n", __func__, cmd));
598                 break;
599         }
600         return;
601 }
602
603 static int
604 wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
605                const struct ieee80211_tx_queue_params *params)
606 {
607         wl_info_t *wl = hw->priv;
608
609         WL_NONE(("%s: Enter (WME config)\n", __func__));
610         WL_NONE(("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
611                  params->txop, params->cw_min, params->cw_max, params->aifs));
612
613         WL_LOCK(wl);
614         wlc_wme_setparams(wl->wlc, queue, (void *)params, TRUE);
615         WL_UNLOCK(wl);
616
617         return 0;
618 }
619
620 static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
621 {
622         WL_ERROR(("%s: Enter\n", __func__));
623         return 0;
624 }
625
626 static int
627 wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
628            struct ieee80211_sta *sta)
629 {
630         struct scb *scb;
631
632         int i;
633         wl_info_t *wl = hw->priv;
634
635         /* Init the scb */
636         scb = (struct scb *)sta->drv_priv;
637         bzero(scb, sizeof(struct scb));
638         for (i = 0; i < NUMPRIO; i++)
639                 scb->seqctl[i] = 0xFFFF;
640         scb->seqctl_nonqos = 0xFFFF;
641         scb->magic = SCB_MAGIC;
642
643         wl->pub->global_scb = scb;
644         wl->pub->global_ampdu = &(scb->scb_ampdu);
645         wl->pub->global_ampdu->scb = scb;
646 #ifdef WLC_HIGH_ONLY
647         wl->pub->global_ampdu->max_pdu = AMPDU_NUM_MPDU;
648 #else
649         wl->pub->global_ampdu->max_pdu = 16;
650 #endif
651         pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
652                   AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
653
654         sta->ht_cap.ht_supported = TRUE;
655 #ifdef WLC_HIGH_ONLY
656         sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_16K;
657 #else
658         sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_64K;
659 #endif
660         sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
661         sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
662             IEEE80211_HT_CAP_SGI_20 |
663             IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
664
665         /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
666         return 0;
667 }
668
669 static int
670 wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
671               struct ieee80211_sta *sta)
672 {
673         WL_NONE(("%s: Enter\n", __func__));
674         return 0;
675 }
676
677 static int
678 wl_ampdu_action(struct ieee80211_hw *hw,
679                 struct ieee80211_vif *vif,
680                 enum ieee80211_ampdu_mlme_action action,
681                 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
682 {
683 #if defined(BCMDBG)
684         struct scb *scb = (struct scb *)sta->drv_priv;
685 #endif
686         wl_info_t *wl = hw->priv;
687
688         ASSERT(scb->magic == SCB_MAGIC);
689         switch (action) {
690         case IEEE80211_AMPDU_RX_START:
691                 WL_NONE(("%s: action = IEEE80211_AMPDU_RX_START\n", __func__));
692                 break;
693         case IEEE80211_AMPDU_RX_STOP:
694                 WL_NONE(("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__));
695                 break;
696         case IEEE80211_AMPDU_TX_START:
697                 if (!wlc_aggregatable(wl->wlc, tid)) {
698                         /* WL_ERROR(("START: tid %d is not agg' able, return FAILURE to stack\n", tid)); */
699                         return -1;
700                 }
701                 /* XXX: Use the starting sequence number provided ... */
702                 *ssn = 0;
703                 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
704                 break;
705
706         case IEEE80211_AMPDU_TX_STOP:
707                 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
708                 break;
709         case IEEE80211_AMPDU_TX_OPERATIONAL:
710                 /* Not sure what to do here */
711                 /* Power save wakeup */
712                 WL_NONE(("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
713                          __func__));
714                 break;
715         default:
716                 WL_ERROR(("%s: Invalid command, ignoring\n", __func__));
717         }
718
719         return 0;
720 }
721
722 static const struct ieee80211_ops wl_ops = {
723 #ifdef WLC_HIGH_ONLY
724         .tx = wl_ops_tx_nl,
725 #else
726         .tx = wl_ops_tx,
727 #endif
728         .start = wl_ops_start,
729         .stop = wl_ops_stop,
730         .add_interface = wl_ops_add_interface,
731         .remove_interface = wl_ops_remove_interface,
732         .config = wl_ops_config,
733         .bss_info_changed = wl_ops_bss_info_changed,
734         .configure_filter = wl_ops_configure_filter,
735         .set_tim = wl_ops_set_tim,
736         .sw_scan_start = wl_ops_sw_scan_start,
737         .sw_scan_complete = wl_ops_sw_scan_complete,
738         .set_tsf = wl_ops_set_tsf,
739         .get_stats = wl_ops_get_stats,
740         .set_rts_threshold = wl_ops_set_rts_threshold,
741         .sta_notify = wl_ops_sta_notify,
742         .conf_tx = wl_ops_conf_tx,
743         .get_tsf = wl_ops_get_tsf,
744         .sta_add = wl_sta_add,
745         .sta_remove = wl_sta_remove,
746         .ampdu_action = wl_ampdu_action,
747 };
748
749 static int wl_set_hint(wl_info_t *wl, char *abbrev)
750 {
751         WL_ERROR(("%s: Sending country code %c%c to MAC80211\n", __func__,
752                   abbrev[0], abbrev[1]));
753         return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
754 }
755
756 /**
757  * attach to the WL device.
758  *
759  * Attach to the WL device identified by vendor and device parameters.
760  * regs is a host accessible memory address pointing to WL device registers.
761  *
762  * wl_attach is not defined as static because in the case where no bus
763  * is defined, wl_attach will never be called, and thus, gcc will issue
764  * a warning that this function is defined but not used if we declare
765  * it as static.
766  */
767 static wl_info_t *wl_attach(uint16 vendor, uint16 device, unsigned long regs,
768                             uint bustype, void *btparam, uint irq)
769 {
770         wl_info_t *wl;
771         osl_t *osh;
772         int unit, err;
773
774         unsigned long base_addr;
775         struct ieee80211_hw *hw;
776         u8 perm[ETH_ALEN];
777
778         unit = wl_found + instance_base;
779         err = 0;
780
781         if (unit < 0) {
782                 WL_ERROR(("wl%d: unit number overflow, exiting\n", unit));
783                 return NULL;
784         }
785
786         if (oneonly && (unit != instance_base)) {
787                 WL_ERROR(("wl%d: wl_attach: oneonly is set, exiting\n", unit));
788                 return NULL;
789         }
790
791         /* Requires pkttag feature */
792         osh = osl_attach(btparam, bustype, TRUE);
793         ASSERT(osh);
794
795 #ifdef WLC_HIGH_ONLY
796         hw = ieee80211_alloc_hw(sizeof(wl_info_t), &wl_ops);
797         if (!hw) {
798                 WL_ERROR(("%s: ieee80211_alloc_hw failed\n", __func__));
799                 ASSERT(0);
800         }
801
802         bzero(hw->priv, sizeof(*wl));
803         wl = hw->priv;
804 #else
805         /* allocate private info */
806         hw = pci_get_drvdata(btparam);  /* btparam == pdev */
807         wl = hw->priv;
808 #endif
809         ASSERT(wl);
810
811         wl->magic = WL_MAGIC;
812         wl->osh = osh;
813         atomic_set(&wl->callbacks, 0);
814
815         /* setup the bottom half handler */
816         tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
817
818 #ifdef WLC_HIGH_ONLY
819         wl->rpc_th = bcm_rpc_tp_attach(osh, NULL);
820         if (wl->rpc_th == NULL) {
821                 WL_ERROR(("wl%d: %s: bcm_rpc_tp_attach failed!\n", unit,
822                           __func__));
823                 goto fail;
824         }
825
826         wl->rpc = bcm_rpc_attach(NULL, osh, wl->rpc_th);
827         if (wl->rpc == NULL) {
828                 WL_ERROR(("wl%d: %s: bcm_rpc_attach failed!\n", unit,
829                           __func__));
830                 goto fail;
831         }
832
833         /* init tx work queue for wl_start/send pkt; no need to destroy workitem  */
834         INIT_WORK(&wl->txq_task.work, (work_func_t) wl_start_txqwork);
835         wl->txq_task.context = wl;
836 #endif                          /* WLC_HIGH_ONLY */
837
838 #ifdef BCMSDIO
839         SET_IEEE80211_DEV(hw, sdiommc_dev);
840 #endif
841
842         base_addr = regs;
843
844         if (bustype == PCI_BUS) {
845                 /* piomode can be overwritten by command argument */
846                 wl->piomode = piomode;
847                 WL_TRACE(("PCI/%s\n", wl->piomode ? "PIO" : "DMA"));
848         } else if (bustype == RPC_BUS) {
849                 /* Do nothing */
850         } else {
851                 bustype = PCI_BUS;
852                 WL_TRACE(("force to PCI\n"));
853         }
854         wl->bcm_bustype = bustype;
855
856 #ifdef WLC_HIGH_ONLY
857         if (wl->bcm_bustype == RPC_BUS) {
858                 wl->regsva = (void *)0;
859                 btparam = wl->rpc;
860         } else
861 #endif
862         wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
863         if (wl->regsva == NULL) {
864                 WL_ERROR(("wl%d: ioremap() failed\n", unit));
865                 goto fail;
866         }
867 #ifdef WLC_HIGH_ONLY
868         spin_lock_init(&wl->rpcq_lock);
869         spin_lock_init(&wl->txq_lock);
870
871         init_MUTEX(&wl->sem);
872 #else
873         spin_lock_init(&wl->lock);
874         spin_lock_init(&wl->isr_lock);
875 #endif
876
877 #ifndef WLC_HIGH_ONLY
878         /* prepare ucode */
879         if (wl_request_fw(wl, (struct pci_dev *)btparam)) {
880                 printf("%s: Failed to find firmware usually in %s\n",
881                         KBUILD_MODNAME, "/lib/firmware/brcm");
882                 wl_release_fw(wl);
883                 wl_remove((struct pci_dev *)btparam);
884                 goto fail1;
885         }
886 #endif
887
888         /* common load-time initialization */
889         wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh,
890                              wl->regsva, wl->bcm_bustype, btparam, &err);
891 #ifndef WLC_HIGH_ONLY
892         wl_release_fw(wl);
893 #endif
894         if (!wl->wlc) {
895                 printf("%s: %s wlc_attach() failed with code %d\n",
896                         KBUILD_MODNAME, EPI_VERSION_STR, err);
897                 goto fail;
898         }
899         wl->pub = wlc_pub(wl->wlc);
900
901         wl->pub->ieee_hw = hw;
902         ASSERT(wl->pub->ieee_hw);
903         ASSERT(wl->pub->ieee_hw->priv == wl);
904
905 #ifdef WLC_HIGH_ONLY
906         REGOPSSET(osh, (osl_rreg_fn_t) wlc_reg_read,
907                   (osl_wreg_fn_t) wlc_reg_write, wl->wlc);
908         wl->rpc_dispatch_ctx.rpc = wl->rpc;
909         wl->rpc_dispatch_ctx.wlc = wl->wlc;
910         bcm_rpc_rxcb_init(wl->rpc, wl, wl_rpc_dispatch_schedule, wl,
911                           wl_rpc_down, NULL, NULL);
912 #endif                          /* WLC_HIGH_ONLY */
913
914         if (nompc) {
915                 if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
916                         WL_ERROR(("wl%d: Error setting MPC variable to 0\n",
917                                   unit));
918                 }
919         }
920 #ifdef BCMSDIO
921         /* Set SDIO drive strength */
922         wlc_iovar_setint(wl->wlc, "sd_drivestrength", sd_drivestrength);
923 #endif
924
925 #ifdef WLC_LOW
926         /* register our interrupt handler */
927         if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
928                 WL_ERROR(("wl%d: request_irq() failed\n", unit));
929                 goto fail;
930         }
931         wl->irq = irq;
932 #endif                          /* WLC_LOW */
933
934         /* register module */
935         wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
936                             NULL);
937
938         if (ieee_hw_init(hw)) {
939                 WL_ERROR(("wl%d: %s: ieee_hw_init failed!\n", unit, __func__));
940                 goto fail;
941         }
942
943         bcopy(&wl->pub->cur_etheraddr, perm, ETHER_ADDR_LEN);
944         ASSERT(is_valid_ether_addr(perm));
945         SET_IEEE80211_PERM_ADDR(hw, perm);
946
947         err = ieee80211_register_hw(hw);
948         if (err) {
949                 WL_ERROR(("%s: ieee80211_register_hw failed, status %d\n",
950                           __func__, err));
951         }
952
953         if (wl->pub->srom_ccode[0])
954                 err = wl_set_hint(wl, wl->pub->srom_ccode);
955         else
956                 err = wl_set_hint(wl, "US");
957         if (err) {
958                 WL_ERROR(("%s: regulatory_hint failed, status %d\n", __func__,
959                           err));
960         }
961 #ifndef WLC_HIGH_ONLY
962         WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver "
963                   EPI_VERSION_STR " (" PHY_VERSION_STR ")", unit));
964 #else
965         WL_ERROR(("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver "
966                   EPI_VERSION_STR, unit));
967 #endif
968
969 #ifdef BCMDBG
970         printf(" (Compiled in " SRCBASE " at " __TIME__ " on " __DATE__ ")");
971 #endif                          /* BCMDBG */
972         printf("\n");
973
974         wl_found++;
975         return wl;
976
977  fail:
978         wl_free(wl);
979 fail1:
980         return NULL;
981 }
982
983 #ifdef WLC_HIGH_ONLY
984 static void *wl_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
985                               uint32 hdrlen)
986 {
987         wl_info_t *wl;
988         WL_ERROR(("%s:\n", __func__));
989
990         wl = wl_attach(BCM_DNGL_VID, BCM_DNGL_BDC_PID, (unsigned long) NULL, RPC_BUS,
991                 NULL, 0);
992         if (!wl) {
993                 WL_ERROR(("%s: wl_attach failed\n", __func__));
994         }
995
996         /* This is later passed to wl_dbus_disconnect_cb */
997         return wl;
998 }
999
1000 static void wl_dbus_disconnect_cb(void *arg)
1001 {
1002         wl_info_t *wl = arg;
1003
1004         WL_ERROR(("%s:\n", __func__));
1005
1006         if (wl) {
1007 #ifdef WLC_HIGH_ONLY
1008                 if (wl->pub->ieee_hw) {
1009                         ieee80211_unregister_hw(wl->pub->ieee_hw);
1010                         WL_ERROR(("%s: Back from down\n", __func__));
1011                 }
1012                 wlc_device_removed(wl->wlc);
1013                 wlc_bmac_dngl_reboot(wl->rpc);
1014                 bcm_rpc_down(wl->rpc);
1015 #endif
1016                 WL_LOCK(wl);
1017                 wl_down(wl);
1018                 WL_UNLOCK(wl);
1019 #ifdef WLC_HIGH_ONLY
1020                 if (wl->pub->ieee_hw) {
1021                         ieee80211_free_hw(wl->pub->ieee_hw);
1022                         WL_ERROR(("%s: Back from ieee80211_free_hw\n",
1023                                   __func__));
1024                         wl->pub->ieee_hw = NULL;
1025                 }
1026 #endif
1027                 wl_free(wl);
1028         }
1029 }
1030 #endif                          /* WLC_HIGH_ONLY */
1031
1032
1033 #define CHAN2GHZ(channel, freqency, chflags)  { \
1034         .band = IEEE80211_BAND_2GHZ, \
1035         .center_freq = (freqency), \
1036         .hw_value = (channel), \
1037         .flags = chflags, \
1038         .max_antenna_gain = 0, \
1039         .max_power = 19, \
1040 }
1041
1042 static struct ieee80211_channel wl_2ghz_chantable[] = {
1043         CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
1044         CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
1045         CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
1046         CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
1047         CHAN2GHZ(5, 2432, 0),
1048         CHAN2GHZ(6, 2437, 0),
1049         CHAN2GHZ(7, 2442, 0),
1050         CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
1051         CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
1052         CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
1053         CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
1054         CHAN2GHZ(12, 2467,
1055                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
1056                  IEEE80211_CHAN_NO_HT40PLUS),
1057         CHAN2GHZ(13, 2472,
1058                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
1059                  IEEE80211_CHAN_NO_HT40PLUS),
1060         CHAN2GHZ(14, 2484,
1061                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
1062                  IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
1063 };
1064
1065 #define CHAN5GHZ(channel, chflags)  { \
1066         .band = IEEE80211_BAND_5GHZ, \
1067         .center_freq = 5000 + 5*(channel), \
1068         .hw_value = (channel), \
1069         .flags = chflags, \
1070         .max_antenna_gain = 0, \
1071         .max_power = 21, \
1072 }
1073
1074 static struct ieee80211_channel wl_5ghz_nphy_chantable[] = {
1075         /* UNII-1 */
1076         CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
1077         CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
1078         CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
1079         CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
1080         /* UNII-2 */
1081         CHAN5GHZ(52,
1082                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1083                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1084         CHAN5GHZ(56,
1085                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1086                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1087         CHAN5GHZ(60,
1088                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1089                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1090         CHAN5GHZ(64,
1091                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1092                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1093         /* MID */
1094         CHAN5GHZ(100,
1095                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1096                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1097         CHAN5GHZ(104,
1098                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1099                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1100         CHAN5GHZ(108,
1101                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1102                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1103         CHAN5GHZ(112,
1104                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1105                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1106         CHAN5GHZ(116,
1107                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1108                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1109         CHAN5GHZ(120,
1110                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1111                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1112         CHAN5GHZ(124,
1113                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1114                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1115         CHAN5GHZ(128,
1116                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1117                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1118         CHAN5GHZ(132,
1119                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1120                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
1121         CHAN5GHZ(136,
1122                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1123                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
1124         CHAN5GHZ(140,
1125                  IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
1126                  IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
1127                  IEEE80211_CHAN_NO_HT40MINUS),
1128         /* UNII-3 */
1129         CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
1130         CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
1131         CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
1132         CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
1133         CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
1134 };
1135
1136 #define RATE(rate100m, _flags) { \
1137         .bitrate = (rate100m), \
1138         .flags = (_flags), \
1139         .hw_value = (rate100m / 5), \
1140 }
1141
1142 static struct ieee80211_rate wl_legacy_ratetable[] = {
1143         RATE(10, 0),
1144         RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
1145         RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
1146         RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
1147         RATE(60, 0),
1148         RATE(90, 0),
1149         RATE(120, 0),
1150         RATE(180, 0),
1151         RATE(240, 0),
1152         RATE(360, 0),
1153         RATE(480, 0),
1154         RATE(540, 0),
1155 };
1156
1157 static struct ieee80211_supported_band wl_band_2GHz_nphy = {
1158         .band = IEEE80211_BAND_2GHZ,
1159         .channels = wl_2ghz_chantable,
1160         .n_channels = ARRAY_SIZE(wl_2ghz_chantable),
1161         .bitrates = wl_legacy_ratetable,
1162         .n_bitrates = ARRAY_SIZE(wl_legacy_ratetable),
1163         .ht_cap = {
1164                    /* from include/linux/ieee80211.h */
1165                    .cap = IEEE80211_HT_CAP_GRN_FLD |
1166                    IEEE80211_HT_CAP_SGI_20 |
1167                    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
1168 #ifdef WLC_HIGH_ONLY
1169                    .ht_supported = true,
1170                    .ampdu_factor = AMPDU_RX_FACTOR_16K,
1171 #else
1172                    .ht_supported = true,
1173                    .ampdu_factor = AMPDU_RX_FACTOR_64K,
1174 #endif
1175                    .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
1176                    .mcs = {
1177                            /* placeholders for now */
1178 #ifdef WLC_HIGH_ONLY
1179                            /*
1180                             * rx_mask[0] = 0xff by default
1181                             * rx_mask[1] = 0xff if number of rx chain >=2
1182                             * rx_mask[2] = 0xff if number of rx chain >=3
1183                             * rx_mask[4] = 1 if 40Mhz is supported
1184                             */
1185                            .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},
1186                            .rx_highest = 72,    /* max rate of single stream */
1187 #else
1188                            .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
1189                            .rx_highest = 500,
1190 #endif
1191                            .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
1192                    }
1193 };
1194
1195 static struct ieee80211_supported_band wl_band_5GHz_nphy = {
1196         .band = IEEE80211_BAND_5GHZ,
1197         .channels = wl_5ghz_nphy_chantable,
1198         .n_channels = ARRAY_SIZE(wl_5ghz_nphy_chantable),
1199         .bitrates = wl_legacy_ratetable + 4,
1200         .n_bitrates = ARRAY_SIZE(wl_legacy_ratetable) - 4,
1201         .ht_cap = {
1202                    /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
1203                    .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,     /* No 40 mhz yet */
1204                    .ht_supported = true,
1205                    .ampdu_factor = AMPDU_RX_FACTOR_64K,
1206                    .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
1207                    .mcs = {
1208                            /* placeholders for now */
1209                            .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
1210                            .rx_highest = 500,
1211                            .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
1212                    }
1213 };
1214
1215 static int ieee_hw_rate_init(struct ieee80211_hw *hw)
1216 {
1217         wl_info_t *wl = HW_TO_WL(hw);
1218         int has_5g;
1219         char phy_list[4];
1220
1221         has_5g = 0;
1222
1223         hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
1224         hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
1225
1226         if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
1227                 WL_ERROR(("Phy list failed\n"));
1228         }
1229         WL_NONE(("%s: phylist = %c\n", __func__, phy_list[0]));
1230
1231 #ifndef WLC_HIGH_ONLY
1232         if (phy_list[0] == 'n' || phy_list[0] == 'c') {
1233                 if (phy_list[0] == 'c') {
1234                         /* Single stream */
1235                         wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
1236                         wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
1237                 }
1238 #else
1239         if (phy_list[0] == 's') {
1240 #endif
1241                 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
1242         } else {
1243                 BUG();
1244                 return -1;
1245         }
1246
1247         /* Assume all bands use the same phy.  True for 11n devices. */
1248         if (NBANDS_PUB(wl->pub) > 1) {
1249                 has_5g++;
1250 #ifndef WLC_HIGH_ONLY
1251                 if (phy_list[0] == 'n' || phy_list[0] == 'c') {
1252 #else
1253                 if (phy_list[0] == 's') {
1254 #endif
1255                         hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1256                             &wl_band_5GHz_nphy;
1257                 } else {
1258                         return -1;
1259                 }
1260         }
1261
1262         WL_NONE(("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g));
1263
1264         return 0;
1265 }
1266
1267 static int ieee_hw_init(struct ieee80211_hw *hw)
1268 {
1269         hw->flags = IEEE80211_HW_SIGNAL_DBM
1270             /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
1271             | IEEE80211_HW_REPORTS_TX_ACK_STATUS
1272             | IEEE80211_HW_AMPDU_AGGREGATION;
1273
1274         hw->extra_tx_headroom = wlc_get_header_len();
1275         /* FIXME: should get this from wlc->machwcap */
1276         hw->queues = 4;
1277         /* FIXME: this doesn't seem to be used properly in minstrel_ht.
1278          * mac80211/status.c:ieee80211_tx_status() checks this value,
1279          * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
1280          * appears to always set 3 rates
1281          */
1282         hw->max_rates = 2;      /* Primary rate and 1 fallback rate */
1283
1284         hw->channel_change_time = 7 * 1000;     /* channel change time is dependant on chip and band  */
1285         hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1286
1287         hw->rate_control_algorithm = "minstrel_ht";
1288
1289         hw->sta_data_size = sizeof(struct scb);
1290         return ieee_hw_rate_init(hw);
1291 }
1292
1293 #ifndef BCMSDIO
1294 /**
1295  * determines if a device is a WL device, and if so, attaches it.
1296  *
1297  * This function determines if a device pointed to by pdev is a WL device,
1298  * and if so, performs a wl_attach() on it.
1299  *
1300  */
1301 int __devinit
1302 wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1303 {
1304         int rc;
1305         wl_info_t *wl;
1306         struct ieee80211_hw *hw;
1307         uint32 val;
1308
1309         ASSERT(pdev);
1310
1311         WL_TRACE(("%s: bus %d slot %d func %d irq %d\n", __func__,
1312                   pdev->bus->number, PCI_SLOT(pdev->devfn),
1313                   PCI_FUNC(pdev->devfn), pdev->irq));
1314
1315         if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
1316             (((pdev->device & 0xff00) != 0x4300) &&
1317              ((pdev->device & 0xff00) != 0x4700) &&
1318              ((pdev->device < 43000) || (pdev->device > 43999))))
1319                 return -ENODEV;
1320
1321         rc = pci_enable_device(pdev);
1322         if (rc) {
1323                 WL_ERROR(("%s: Cannot enable device %d-%d_%d\n", __func__,
1324                           pdev->bus->number, PCI_SLOT(pdev->devfn),
1325                           PCI_FUNC(pdev->devfn)));
1326                 return -ENODEV;
1327         }
1328         pci_set_master(pdev);
1329
1330         pci_read_config_dword(pdev, 0x40, &val);
1331         if ((val & 0x0000ff00) != 0)
1332                 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
1333
1334         hw = ieee80211_alloc_hw(sizeof(wl_info_t), &wl_ops);
1335         if (!hw) {
1336                 WL_ERROR(("%s: ieee80211_alloc_hw failed\n", __func__));
1337                 rc = -ENOMEM;
1338                 goto err_1;
1339         }
1340
1341         SET_IEEE80211_DEV(hw, &pdev->dev);
1342
1343         pci_set_drvdata(pdev, hw);
1344
1345         bzero(hw->priv, sizeof(*wl));
1346
1347         wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
1348                        PCI_BUS, pdev, pdev->irq);
1349
1350         if (!wl) {
1351                 WL_ERROR(("%s: %s: wl_attach failed!\n",
1352                         KBUILD_MODNAME, __func__));
1353                 return -ENODEV;
1354         }
1355         return 0;
1356  err_1:
1357         WL_ERROR(("%s: err_1: Major hoarkage\n", __func__));
1358         return 0;
1359 }
1360
1361 #ifdef LINUXSTA_PS
1362 static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
1363 {
1364         wl_info_t *wl;
1365         struct ieee80211_hw *hw;
1366
1367         WL_TRACE(("wl: wl_suspend\n"));
1368
1369         hw = pci_get_drvdata(pdev);
1370         wl = HW_TO_WL(hw);
1371         if (!wl) {
1372                 WL_ERROR(("wl: wl_suspend: pci_get_drvdata failed\n"));
1373                 return -ENODEV;
1374         }
1375
1376         WL_LOCK(wl);
1377         wl_down(wl);
1378         wl->pub->hw_up = FALSE;
1379         WL_UNLOCK(wl);
1380         pci_save_state(pdev, wl->pci_psstate);
1381         pci_disable_device(pdev);
1382         return pci_set_power_state(pdev, PCI_D3hot);
1383 }
1384
1385 static int wl_resume(struct pci_dev *pdev)
1386 {
1387         wl_info_t *wl;
1388         struct ieee80211_hw *hw;
1389         int err = 0;
1390         uint32 val;
1391
1392         WL_TRACE(("wl: wl_resume\n"));
1393         hw = pci_get_drvdata(pdev);
1394         wl = HW_TO_WL(hw);
1395         if (!wl) {
1396                 WL_ERROR(("wl: wl_resume: pci_get_drvdata failed\n"));
1397                 return -ENODEV;
1398         }
1399
1400         err = pci_set_power_state(pdev, PCI_D0);
1401         if (err)
1402                 return err;
1403
1404         pci_restore_state(pdev, wl->pci_psstate);
1405
1406         err = pci_enable_device(pdev);
1407         if (err)
1408                 return err;
1409
1410         pci_set_master(pdev);
1411
1412         pci_read_config_dword(pdev, 0x40, &val);
1413         if ((val & 0x0000ff00) != 0)
1414                 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
1415
1416         WL_LOCK(wl);
1417         err = wl_up(wl);
1418         WL_UNLOCK(wl);
1419
1420         return err;
1421 }
1422 #endif                          /* LINUXSTA_PS */
1423
1424 static void wl_remove(struct pci_dev *pdev)
1425 {
1426         wl_info_t *wl;
1427         struct ieee80211_hw *hw;
1428
1429         hw = pci_get_drvdata(pdev);
1430         wl = HW_TO_WL(hw);
1431         if (!wl) {
1432                 WL_ERROR(("wl: wl_remove: pci_get_drvdata failed\n"));
1433                 return;
1434         }
1435         if (!wlc_chipmatch(pdev->vendor, pdev->device)) {
1436                 WL_ERROR(("wl: wl_remove: wlc_chipmatch failed\n"));
1437                 return;
1438         }
1439         if (wl->wlc) {
1440                 ieee80211_unregister_hw(hw);
1441                 WL_LOCK(wl);
1442                 wl_down(wl);
1443                 WL_UNLOCK(wl);
1444                 WL_NONE(("%s: Down\n", __func__));
1445         }
1446         pci_disable_device(pdev);
1447
1448         wl_free(wl);
1449
1450         pci_set_drvdata(pdev, NULL);
1451         ieee80211_free_hw(hw);
1452 }
1453
1454 static struct pci_driver wl_pci_driver = {
1455  .name  = "brcm80211",
1456  .probe = wl_pci_probe,
1457 #ifdef LINUXSTA_PS
1458  .suspend = wl_suspend,
1459  .resume  = wl_resume,
1460 #endif                          /* LINUXSTA_PS */
1461  .remove   = __devexit_p(wl_remove),
1462  .id_table = wl_id_table,
1463 };
1464 #endif                          /* !BCMSDIO */
1465
1466 /**
1467  * This is the main entry point for the WL driver.
1468  *
1469  * This function determines if a device pointed to by pdev is a WL device,
1470  * and if so, performs a wl_attach() on it.
1471  *
1472  */
1473 static int __init wl_module_init(void)
1474 {
1475         int error = -ENODEV;
1476
1477 #ifdef BCMDBG
1478         if (msglevel != 0xdeadbeef)
1479                 wl_msg_level = msglevel;
1480         else {
1481                 char *var = getvar(NULL, "wl_msglevel");
1482                 if (var)
1483                         wl_msg_level = simple_strtoul(var, NULL, 0);
1484         }
1485 #ifndef WLC_HIGH_ONLY
1486         {
1487                 extern uint32 phyhal_msg_level;
1488
1489                 if (phymsglevel != 0xdeadbeef)
1490                         phyhal_msg_level = phymsglevel;
1491                 else {
1492                         char *var = getvar(NULL, "phy_msglevel");
1493                         if (var)
1494                                 phyhal_msg_level = simple_strtoul(var, NULL, 0);
1495                 }
1496         }
1497 #endif                          /* WLC_HIGH_ONLY */
1498 #endif                          /* BCMDBG */
1499
1500 #ifndef BCMSDIO
1501         error = pci_register_driver(&wl_pci_driver);
1502         if (!error)
1503                 return 0;
1504
1505 #endif                          /* !BCMSDIO */
1506
1507 #ifdef WLC_HIGH_ONLY
1508         /* BMAC_NOTE: define hardcode number, why NODEVICE is ok ? */
1509         error =
1510             dbus_register(BCM_DNGL_VID, 0, wl_dbus_probe_cb,
1511                           wl_dbus_disconnect_cb, NULL, NULL, NULL);
1512         if (error == DBUS_ERR_NODEVICE) {
1513                 error = DBUS_OK;
1514         }
1515 #endif                          /* WLC_HIGH_ONLY */
1516
1517         return error;
1518 }
1519
1520 /**
1521  * This function unloads the WL driver from the system.
1522  *
1523  * This function unconditionally unloads the WL driver module from the
1524  * system.
1525  *
1526  */
1527 static void __exit wl_module_exit(void)
1528 {
1529 #ifndef BCMSDIO
1530         pci_unregister_driver(&wl_pci_driver);
1531 #endif                          /* !BCMSDIO */
1532
1533 #ifdef WLC_HIGH_ONLY
1534         dbus_deregister();
1535 #endif                          /* WLC_HIGH_ONLY */
1536 }
1537
1538 module_init(wl_module_init);
1539 module_exit(wl_module_exit);
1540
1541 /**
1542  * This function frees the WL per-device resources.
1543  *
1544  * This function frees resources owned by the WL device pointed to
1545  * by the wl parameter.
1546  *
1547  */
1548 void wl_free(wl_info_t *wl)
1549 {
1550         wl_timer_t *t, *next;
1551         osl_t *osh;
1552
1553         ASSERT(wl);
1554 #ifndef WLC_HIGH_ONLY
1555         /* free ucode data */
1556         if (wl->fw.fw_cnt)
1557                 wl_ucode_data_free();
1558         if (wl->irq)
1559                 free_irq(wl->irq, wl);
1560 #endif
1561
1562         /* kill dpc */
1563         tasklet_kill(&wl->tasklet);
1564
1565         if (wl->pub) {
1566                 wlc_module_unregister(wl->pub, "linux", wl);
1567         }
1568
1569         /* free common resources */
1570         if (wl->wlc) {
1571                 wlc_detach(wl->wlc);
1572                 wl->wlc = NULL;
1573                 wl->pub = NULL;
1574         }
1575
1576         /* virtual interface deletion is deferred so we cannot spinwait */
1577
1578         /* wait for all pending callbacks to complete */
1579         while (atomic_read(&wl->callbacks) > 0)
1580                 schedule();
1581
1582         /* free timers */
1583         for (t = wl->timers; t; t = next) {
1584                 next = t->next;
1585 #ifdef BCMDBG
1586                 if (t->name)
1587                         MFREE(wl->osh, t->name, strlen(t->name) + 1);
1588 #endif
1589                 MFREE(wl->osh, t, sizeof(wl_timer_t));
1590         }
1591
1592         osh = wl->osh;
1593
1594         /*
1595          * unregister_netdev() calls get_stats() which may read chip registers
1596          * so we cannot unmap the chip registers until after calling unregister_netdev() .
1597          */
1598         if (wl->regsva && BUSTYPE(wl->bcm_bustype) != SDIO_BUS &&
1599             BUSTYPE(wl->bcm_bustype) != JTAG_BUS) {
1600                 iounmap((void *)wl->regsva);
1601         }
1602         wl->regsva = NULL;
1603
1604 #ifdef WLC_HIGH_ONLY
1605         wl_rpcq_free(wl);
1606
1607         wl_txq_free(wl);
1608
1609         if (wl->rpc) {
1610                 bcm_rpc_detach(wl->rpc);
1611                 wl->rpc = NULL;
1612         }
1613
1614         if (wl->rpc_th) {
1615                 bcm_rpc_tp_detach(wl->rpc_th);
1616                 wl->rpc_th = NULL;
1617         }
1618 #endif                          /* WLC_HIGH_ONLY */
1619
1620         if (osl_malloced(osh)) {
1621                 printf("****   Memory leak of bytes %d\n", osl_malloced(osh));
1622                 ASSERT(0 && "Memory Leak");
1623         }
1624
1625         osl_detach(osh);
1626 }
1627
1628 #ifdef WLC_LOW
1629 /* transmit a packet */
1630 static int BCMFASTPATH wl_start(struct sk_buff *skb, wl_info_t *wl)
1631 {
1632         if (!wl)
1633                 return -ENETDOWN;
1634
1635         return wl_start_int(wl, WL_TO_HW(wl), skb);
1636 }
1637 #endif                          /* WLC_LOW */
1638
1639 static int BCMFASTPATH
1640 wl_start_int(wl_info_t *wl, struct ieee80211_hw *hw, struct sk_buff *skb)
1641 {
1642 #ifdef WLC_HIGH_ONLY
1643         WL_LOCK(wl);
1644 #endif
1645         wlc_sendpkt_mac80211(wl->wlc, skb, hw);
1646 #ifdef WLC_HIGH_ONLY
1647         WL_UNLOCK(wl);
1648 #endif
1649         return NETDEV_TX_OK;
1650 }
1651
1652 void wl_txflowcontrol(wl_info_t *wl, struct wl_if *wlif, bool state, int prio)
1653 {
1654         WL_ERROR(("Shouldn't be here %s\n", __func__));
1655 }
1656
1657 #if defined(WLC_HIGH_ONLY)
1658 /* Schedule a completion handler to run at safe time */
1659 static int
1660 wl_schedule_task(wl_info_t *wl, void (*fn) (struct wl_task *task),
1661                  void *context)
1662 {
1663         wl_task_t *task;
1664
1665         WL_TRACE(("wl%d: wl_schedule_task\n", wl->pub->unit));
1666
1667         task = osl_malloc(wl->osh, sizeof(wl_task_t));
1668         if (!task) {
1669                 WL_ERROR(("wl%d: wl_schedule_task: out of memory, malloced %d bytes\n", wl->pub->unit, osl_malloced(wl->osh)));
1670                 return -ENOMEM;
1671         }
1672
1673         INIT_WORK(&task->work, (work_func_t) fn);
1674         task->context = context;
1675
1676         if (!schedule_work(&task->work)) {
1677                 WL_ERROR(("wl%d: schedule_work() failed\n", wl->pub->unit));
1678                 MFREE(wl->osh, task, sizeof(wl_task_t));
1679                 return -ENOMEM;
1680         }
1681
1682         atomic_inc(&wl->callbacks);
1683
1684         return 0;
1685 }
1686 #endif                          /* defined(WLC_HIGH_ONLY) */
1687
1688 void wl_init(wl_info_t *wl)
1689 {
1690         WL_TRACE(("wl%d: wl_init\n", wl->pub->unit));
1691
1692         wl_reset(wl);
1693
1694         wlc_init(wl->wlc);
1695 }
1696
1697 uint wl_reset(wl_info_t *wl)
1698 {
1699         WL_TRACE(("wl%d: wl_reset\n", wl->pub->unit));
1700
1701         wlc_reset(wl->wlc);
1702
1703         /* dpc will not be rescheduled */
1704         wl->resched = 0;
1705
1706         return 0;
1707 }
1708
1709 /*
1710  * These are interrupt on/off entry points. Disable interrupts
1711  * during interrupt state transition.
1712  */
1713 void BCMFASTPATH wl_intrson(wl_info_t *wl)
1714 {
1715 #if defined(WLC_LOW)
1716         unsigned long flags;
1717
1718         INT_LOCK(wl, flags);
1719         wlc_intrson(wl->wlc);
1720         INT_UNLOCK(wl, flags);
1721 #endif                          /* WLC_LOW */
1722 }
1723
1724 bool wl_alloc_dma_resources(wl_info_t *wl, uint addrwidth)
1725 {
1726         return TRUE;
1727 }
1728
1729 uint32 BCMFASTPATH wl_intrsoff(wl_info_t *wl)
1730 {
1731 #if defined(WLC_LOW)
1732         unsigned long flags;
1733         uint32 status;
1734
1735         INT_LOCK(wl, flags);
1736         status = wlc_intrsoff(wl->wlc);
1737         INT_UNLOCK(wl, flags);
1738         return status;
1739 #else
1740         return 0;
1741 #endif                          /* WLC_LOW */
1742 }
1743
1744 void wl_intrsrestore(wl_info_t *wl, uint32 macintmask)
1745 {
1746 #if defined(WLC_LOW)
1747         unsigned long flags;
1748
1749         INT_LOCK(wl, flags);
1750         wlc_intrsrestore(wl->wlc, macintmask);
1751         INT_UNLOCK(wl, flags);
1752 #endif                          /* WLC_LOW */
1753 }
1754
1755 int wl_up(wl_info_t *wl)
1756 {
1757         int error = 0;
1758
1759         if (wl->pub->up)
1760                 return 0;
1761
1762         error = wlc_up(wl->wlc);
1763
1764         return error;
1765 }
1766
1767 void wl_down(wl_info_t *wl)
1768 {
1769         uint callbacks, ret_val = 0;
1770
1771         /* call common down function */
1772         ret_val = wlc_down(wl->wlc);
1773         callbacks = atomic_read(&wl->callbacks) - ret_val;
1774
1775         /* wait for down callbacks to complete */
1776         WL_UNLOCK(wl);
1777
1778 #ifndef WLC_HIGH_ONLY
1779         /* For HIGH_only driver, it's important to actually schedule other work,
1780          * not just spin wait since everything runs at schedule level
1781          */
1782         SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
1783 #endif                          /* WLC_HIGH_ONLY */
1784
1785         WL_LOCK(wl);
1786 }
1787
1788 irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
1789 {
1790 #if defined(WLC_LOW)
1791         wl_info_t *wl;
1792         bool ours, wantdpc;
1793         unsigned long flags;
1794
1795         wl = (wl_info_t *) dev_id;
1796
1797         WL_ISRLOCK(wl, flags);
1798
1799         /* call common first level interrupt handler */
1800         ours = wlc_isr(wl->wlc, &wantdpc);
1801         if (ours) {
1802                 /* if more to do... */
1803                 if (wantdpc) {
1804
1805                         /* ...and call the second level interrupt handler */
1806                         /* schedule dpc */
1807                         ASSERT(wl->resched == FALSE);
1808                         tasklet_schedule(&wl->tasklet);
1809                 }
1810         }
1811
1812         WL_ISRUNLOCK(wl, flags);
1813
1814         return IRQ_RETVAL(ours);
1815 #else
1816         return IRQ_RETVAL(0);
1817 #endif                          /* WLC_LOW */
1818 }
1819
1820 static void BCMFASTPATH wl_dpc(unsigned long data)
1821 {
1822 #ifdef WLC_LOW
1823         wl_info_t *wl;
1824
1825         wl = (wl_info_t *) data;
1826
1827         WL_LOCK(wl);
1828
1829         /* call the common second level interrupt handler */
1830         if (wl->pub->up) {
1831                 if (wl->resched) {
1832                         unsigned long flags;
1833
1834                         INT_LOCK(wl, flags);
1835                         wlc_intrsupd(wl->wlc);
1836                         INT_UNLOCK(wl, flags);
1837                 }
1838
1839                 wl->resched = wlc_dpc(wl->wlc, TRUE);
1840         }
1841
1842         /* wlc_dpc() may bring the driver down */
1843         if (!wl->pub->up)
1844                 goto done;
1845
1846         /* re-schedule dpc */
1847         if (wl->resched)
1848                 tasklet_schedule(&wl->tasklet);
1849         else {
1850                 /* re-enable interrupts */
1851                 wl_intrson(wl);
1852         }
1853
1854  done:
1855         WL_UNLOCK(wl);
1856 #endif                          /* WLC_LOW */
1857 }
1858
1859 static void wl_link_up(wl_info_t *wl, char *ifname)
1860 {
1861         WL_ERROR(("wl%d: link up (%s)\n", wl->pub->unit, ifname));
1862 }
1863
1864 static void wl_link_down(wl_info_t *wl, char *ifname)
1865 {
1866         WL_ERROR(("wl%d: link down (%s)\n", wl->pub->unit, ifname));
1867 }
1868
1869 void wl_event(wl_info_t *wl, char *ifname, wlc_event_t *e)
1870 {
1871
1872         switch (e->event.event_type) {
1873         case WLC_E_LINK:
1874         case WLC_E_NDIS_LINK:
1875                 if (e->event.flags & WLC_EVENT_MSG_LINK)
1876                         wl_link_up(wl, ifname);
1877                 else
1878                         wl_link_down(wl, ifname);
1879                 break;
1880         case WLC_E_RADIO:
1881                 break;
1882         }
1883 }
1884
1885 static void wl_timer(unsigned long data)
1886 {
1887 #ifndef WLC_HIGH_ONLY
1888         _wl_timer((wl_timer_t *) data);
1889 #else
1890         wl_timer_t *t = (wl_timer_t *) data;
1891         wl_schedule_task(t->wl, wl_timer_task, t);
1892 #endif                          /* WLC_HIGH_ONLY */
1893 }
1894
1895 static void _wl_timer(wl_timer_t *t)
1896 {
1897         WL_LOCK(t->wl);
1898
1899         if (t->set) {
1900                 if (t->periodic) {
1901                         t->timer.expires = jiffies + t->ms * HZ / 1000;
1902                         atomic_inc(&t->wl->callbacks);
1903                         add_timer(&t->timer);
1904                         t->set = TRUE;
1905                 } else
1906                         t->set = FALSE;
1907
1908                 t->fn(t->arg);
1909         }
1910
1911         atomic_dec(&t->wl->callbacks);
1912
1913         WL_UNLOCK(t->wl);
1914 }
1915
1916 wl_timer_t *wl_init_timer(wl_info_t *wl, void (*fn) (void *arg), void *arg,
1917                           const char *name)
1918 {
1919         wl_timer_t *t;
1920
1921         t = osl_malloc(wl->osh, sizeof(wl_timer_t));
1922         if (!t) {
1923                 WL_ERROR(("wl%d: wl_init_timer: out of memory, malloced %d bytes\n", wl->pub->unit, osl_malloced(wl->osh)));
1924                 return 0;
1925         }
1926
1927         bzero(t, sizeof(wl_timer_t));
1928
1929         init_timer(&t->timer);
1930         t->timer.data = (unsigned long) t;
1931         t->timer.function = wl_timer;
1932         t->wl = wl;
1933         t->fn = fn;
1934         t->arg = arg;
1935         t->next = wl->timers;
1936         wl->timers = t;
1937
1938 #ifdef BCMDBG
1939         t->name = osl_malloc(wl->osh, strlen(name) + 1);
1940         if (t->name)
1941                 strcpy(t->name, name);
1942 #endif
1943
1944         return t;
1945 }
1946
1947 /* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
1948  * as well as it's easier to make it periodic
1949  */
1950 void wl_add_timer(wl_info_t *wl, wl_timer_t *t, uint ms, int periodic)
1951 {
1952 #ifdef BCMDBG
1953         if (t->set) {
1954                 WL_ERROR(("%s: Already set. Name: %s, per %d\n",
1955                           __func__, t->name, periodic));
1956         }
1957 #endif
1958         ASSERT(!t->set);
1959
1960         t->ms = ms;
1961         t->periodic = (bool) periodic;
1962         t->set = TRUE;
1963         t->timer.expires = jiffies + ms * HZ / 1000;
1964
1965         atomic_inc(&wl->callbacks);
1966         add_timer(&t->timer);
1967 }
1968
1969 /* return TRUE if timer successfully deleted, FALSE if still pending */
1970 bool wl_del_timer(wl_info_t *wl, wl_timer_t *t)
1971 {
1972         if (t->set) {
1973                 t->set = FALSE;
1974                 if (!del_timer(&t->timer)) {
1975                         return FALSE;
1976                 }
1977                 atomic_dec(&wl->callbacks);
1978         }
1979
1980         return TRUE;
1981 }
1982
1983 void wl_free_timer(wl_info_t *wl, wl_timer_t *t)
1984 {
1985         wl_timer_t *tmp;
1986
1987         /* delete the timer in case it is active */
1988         wl_del_timer(wl, t);
1989
1990         if (wl->timers == t) {
1991                 wl->timers = wl->timers->next;
1992 #ifdef BCMDBG
1993                 if (t->name)
1994                         MFREE(wl->osh, t->name, strlen(t->name) + 1);
1995 #endif
1996                 MFREE(wl->osh, t, sizeof(wl_timer_t));
1997                 return;
1998
1999         }
2000
2001         tmp = wl->timers;
2002         while (tmp) {
2003                 if (tmp->next == t) {
2004                         tmp->next = t->next;
2005 #ifdef BCMDBG
2006                         if (t->name)
2007                                 MFREE(wl->osh, t->name, strlen(t->name) + 1);
2008 #endif
2009                         MFREE(wl->osh, t, sizeof(wl_timer_t));
2010                         return;
2011                 }
2012                 tmp = tmp->next;
2013         }
2014
2015 }
2016
2017 static int wl_linux_watchdog(void *ctx)
2018 {
2019         wl_info_t *wl = (wl_info_t *) ctx;
2020         struct net_device_stats *stats = NULL;
2021         uint id;
2022         /* refresh stats */
2023         if (wl->pub->up) {
2024                 ASSERT(wl->stats_id < 2);
2025
2026                 id = 1 - wl->stats_id;
2027
2028                 stats = &wl->stats_watchdog[id];
2029                 stats->rx_packets = WLCNTVAL(wl->pub->_cnt->rxframe);
2030                 stats->tx_packets = WLCNTVAL(wl->pub->_cnt->txframe);
2031                 stats->rx_bytes = WLCNTVAL(wl->pub->_cnt->rxbyte);
2032                 stats->tx_bytes = WLCNTVAL(wl->pub->_cnt->txbyte);
2033                 stats->rx_errors = WLCNTVAL(wl->pub->_cnt->rxerror);
2034                 stats->tx_errors = WLCNTVAL(wl->pub->_cnt->txerror);
2035                 stats->collisions = 0;
2036
2037                 stats->rx_length_errors = 0;
2038                 stats->rx_over_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
2039                 stats->rx_crc_errors = WLCNTVAL(wl->pub->_cnt->rxcrc);
2040                 stats->rx_frame_errors = 0;
2041                 stats->rx_fifo_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
2042                 stats->rx_missed_errors = 0;
2043
2044                 stats->tx_fifo_errors = WLCNTVAL(wl->pub->_cnt->txuflo);
2045
2046                 wl->stats_id = id;
2047
2048         }
2049
2050         return 0;
2051 }
2052
2053 struct wl_fw_hdr {
2054         uint32 offset;
2055         uint32 len;
2056         uint32 idx;
2057 };
2058
2059 #ifdef WLC_HIGH_ONLY
2060 static void wl_rpc_down(void *wlh)
2061 {
2062         wl_info_t *wl = (wl_info_t *) (wlh);
2063
2064         wlc_device_removed(wl->wlc);
2065
2066         wl_rpcq_free(wl);
2067 }
2068
2069 static int BCMFASTPATH wl_start(struct sk_buff *skb, wl_info_t *wl)
2070 {
2071
2072         unsigned long flags;
2073
2074         skb->prev = NULL;
2075
2076         /* Lock the queue as tasklet could be running at this time */
2077         TXQ_LOCK(wl, flags);
2078         if (wl->txq_head == NULL)
2079                 wl->txq_head = skb;
2080         else {
2081                 wl->txq_tail->prev = skb;
2082         }
2083         wl->txq_tail = skb;
2084
2085         if (wl->txq_dispatched == FALSE) {
2086                 wl->txq_dispatched = TRUE;
2087
2088                 if (schedule_work(&wl->txq_task.work)) {
2089                         atomic_inc(&wl->callbacks);
2090                 } else {
2091                         WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
2092                                   wl->pub->unit));
2093                 }
2094         }
2095
2096         TXQ_UNLOCK(wl, flags);
2097
2098         return 0;
2099
2100 }
2101
2102 static void wl_start_txqwork(struct wl_task *task)
2103 {
2104         wl_info_t *wl = (wl_info_t *) task->context;
2105         struct sk_buff *skb;
2106         unsigned long flags;
2107         uint count = 0;
2108
2109         WL_TRACE(("wl%d: wl_start_txqwork\n", wl->pub->unit));
2110
2111         /* First remove an entry then go for execution */
2112         TXQ_LOCK(wl, flags);
2113         while (wl->txq_head) {
2114                 skb = wl->txq_head;
2115                 wl->txq_head = skb->prev;
2116                 skb->prev = NULL;
2117                 if (wl->txq_head == NULL)
2118                         wl->txq_tail = NULL;
2119                 TXQ_UNLOCK(wl, flags);
2120
2121                 /* it has WL_LOCK/WL_UNLOCK inside */
2122                 wl_start_int(wl, WL_TO_HW(wl), skb);
2123
2124                 /* bounded our execution, reshedule ourself next */
2125                 if (++count >= 10)
2126                         break;
2127
2128                 TXQ_LOCK(wl, flags);
2129         }
2130
2131         if (count >= 10) {
2132                 if (!schedule_work(&wl->txq_task.work)) {
2133                         WL_ERROR(("wl%d: wl_start/schedule_work failed\n",
2134                                   wl->pub->unit));
2135                         atomic_dec(&wl->callbacks);
2136                 }
2137         } else {
2138                 wl->txq_dispatched = FALSE;
2139                 TXQ_UNLOCK(wl, flags);
2140                 atomic_dec(&wl->callbacks);
2141         }
2142
2143         return;
2144 }
2145
2146 static void wl_txq_free(wl_info_t *wl)
2147 {
2148         struct sk_buff *skb;
2149
2150         if (wl->txq_head == NULL) {
2151                 ASSERT(wl->txq_tail == NULL);
2152                 return;
2153         }
2154
2155         while (wl->txq_head) {
2156                 skb = wl->txq_head;
2157                 wl->txq_head = skb->prev;
2158                 PKTFREE(wl->osh, skb, TRUE);
2159         }
2160
2161         wl->txq_tail = NULL;
2162 }
2163
2164 static void wl_rpcq_free(wl_info_t *wl)
2165 {
2166         rpc_buf_t *buf;
2167
2168         if (wl->rpcq_head == NULL) {
2169                 ASSERT(wl->rpcq_tail == NULL);
2170                 return;
2171         }
2172
2173         while (wl->rpcq_head) {
2174                 buf = wl->rpcq_head;
2175                 wl->rpcq_head = bcm_rpc_buf_next_get(wl->rpc_th, buf);
2176                 bcm_rpc_buf_free(wl->rpc_dispatch_ctx.rpc, buf);
2177         }
2178
2179         wl->rpcq_tail = NULL;
2180 }
2181
2182 static void wl_rpcq_dispatch(struct wl_task *task)
2183 {
2184         wl_info_t *wl = (wl_info_t *) task->context;
2185         rpc_buf_t *buf;
2186         unsigned long flags;
2187
2188         /* First remove an entry then go for execution */
2189         RPCQ_LOCK(wl, flags);
2190         while (wl->rpcq_head) {
2191                 buf = wl->rpcq_head;
2192                 wl->rpcq_head = bcm_rpc_buf_next_get(wl->rpc_th, buf);
2193
2194                 if (wl->rpcq_head == NULL)
2195                         wl->rpcq_tail = NULL;
2196                 RPCQ_UNLOCK(wl, flags);
2197
2198                 WL_LOCK(wl);
2199                 wlc_rpc_high_dispatch(&wl->rpc_dispatch_ctx, buf);
2200                 WL_UNLOCK(wl);
2201
2202                 RPCQ_LOCK(wl, flags);
2203         }
2204
2205         wl->rpcq_dispatched = FALSE;
2206
2207         RPCQ_UNLOCK(wl, flags);
2208
2209         MFREE(wl->osh, task, sizeof(wl_task_t));
2210         atomic_dec(&wl->callbacks);
2211 }
2212
2213 static void wl_rpcq_add(wl_info_t *wl, rpc_buf_t *buf)
2214 {
2215         unsigned long flags;
2216
2217         bcm_rpc_buf_next_set(wl->rpc_th, buf, NULL);
2218
2219         /* Lock the queue as tasklet could be running at this time */
2220         RPCQ_LOCK(wl, flags);
2221         if (wl->rpcq_head == NULL)
2222                 wl->rpcq_head = buf;
2223         else
2224                 bcm_rpc_buf_next_set(wl->rpc_th, wl->rpcq_tail, buf);
2225
2226         wl->rpcq_tail = buf;
2227
2228         if (wl->rpcq_dispatched == FALSE) {
2229                 wl->rpcq_dispatched = TRUE;
2230                 wl_schedule_task(wl, wl_rpcq_dispatch, wl);
2231         }
2232
2233         RPCQ_UNLOCK(wl, flags);
2234 }
2235
2236 #if defined(BCMDBG)
2237 static const struct name_entry rpc_name_tbl[] = RPC_ID_TABLE;
2238 #endif                          /* BCMDBG */
2239
2240 /* dongle-side rpc dispatch routine */
2241 static void wl_rpc_dispatch_schedule(void *ctx, struct rpc_buf *buf)
2242 {
2243         bcm_xdr_buf_t b;
2244         wl_info_t *wl = (wl_info_t *) ctx;
2245         wlc_rpc_id_t rpc_id;
2246         int err;
2247
2248         bcm_xdr_buf_init(&b, bcm_rpc_buf_data(wl->rpc_th, buf),
2249                          bcm_rpc_buf_len_get(wl->rpc_th, buf));
2250
2251         err = bcm_xdr_unpack_uint32(&b, &rpc_id);
2252         ASSERT(!err);
2253         WL_TRACE(("%s: Dispatch id %s\n", __func__,
2254                   WLC_RPC_ID_LOOKUP(rpc_name_tbl, rpc_id)));
2255
2256         /* Handle few emergency ones */
2257         switch (rpc_id) {
2258         default:
2259                 wl_rpcq_add(wl, buf);
2260                 break;
2261         }
2262 }
2263
2264 static void wl_timer_task(wl_task_t *task)
2265 {
2266         wl_timer_t *t = (wl_timer_t *) task->context;
2267
2268         _wl_timer(t);
2269         MFREE(t->wl->osh, task, sizeof(wl_task_t));
2270
2271         /* This dec is for the task_schedule. The timer related
2272          * callback is decremented in _wl_timer
2273          */
2274         atomic_dec(&t->wl->callbacks);
2275 }
2276 #endif                          /* WLC_HIGH_ONLY */
2277
2278 #ifndef WLC_HIGH_ONLY
2279 char *wl_firmwares[WL_MAX_FW] = {
2280         "brcm/bcm43xx",
2281         NULL
2282 };
2283
2284 #ifdef WLC_LOW
2285 int wl_ucode_init_buf(wl_info_t *wl, void **pbuf, uint32 idx)
2286 {
2287         int i, entry;
2288         const u8 *pdata;
2289         struct wl_fw_hdr *hdr;
2290         for (i = 0; i < wl->fw.fw_cnt; i++) {
2291                 hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
2292                 for (entry = 0; entry < wl->fw.hdr_num_entries[i];
2293                      entry++, hdr++) {
2294                         if (hdr->idx == idx) {
2295                                 pdata = wl->fw.fw_bin[i]->data + hdr->offset;
2296                                 *pbuf = kmalloc(hdr->len, GFP_ATOMIC);
2297                                 if (*pbuf == NULL) {
2298                                         printf("fail to alloc %d bytes\n",
2299                                                hdr->len);
2300                                 }
2301                                 bcopy(pdata, *pbuf, hdr->len);
2302                                 return 0;
2303                         }
2304                 }
2305         }
2306         printf("ERROR: ucode buf tag:%d can not be found!\n", idx);
2307         *pbuf = NULL;
2308         return -1;
2309 }
2310
2311 int wl_ucode_init_uint(wl_info_t *wl, uint32 *data, uint32 idx)
2312 {
2313         int i, entry;
2314         const u8 *pdata;
2315         struct wl_fw_hdr *hdr;
2316         for (i = 0; i < wl->fw.fw_cnt; i++) {
2317                 hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
2318                 for (entry = 0; entry < wl->fw.hdr_num_entries[i];
2319                      entry++, hdr++) {
2320                         if (hdr->idx == idx) {
2321                                 pdata = wl->fw.fw_bin[i]->data + hdr->offset;
2322                                 ASSERT(hdr->len == 4);
2323                                 *data = *((uint32 *) pdata);
2324                                 return 0;
2325                         }
2326                 }
2327         }
2328         printf("ERROR: ucode tag:%d can not be found!\n", idx);
2329         return -1;
2330 }
2331 #endif                          /* WLC_LOW */
2332
2333 static int wl_request_fw(wl_info_t *wl, struct pci_dev *pdev)
2334 {
2335         int status;
2336         struct device *device = &pdev->dev;
2337         char fw_name[100];
2338         int i;
2339
2340         bzero((void *)&wl->fw, sizeof(struct wl_firmware));
2341         for (i = 0; i < WL_MAX_FW; i++) {
2342                 if (wl_firmwares[i] == NULL)
2343                         break;
2344                 sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
2345                         UCODE_LOADER_API_VER);
2346                 WL_NONE(("request fw %s\n", fw_name));
2347                 status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
2348                 if (status) {
2349                         printf("%s: fail to load firmware %s\n",
2350                                 KBUILD_MODNAME, fw_name);
2351                         wl_release_fw(wl);
2352                         return status;
2353                 }
2354                 WL_NONE(("request fw %s\n", fw_name));
2355                 sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
2356                         UCODE_LOADER_API_VER);
2357                 status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
2358                 if (status) {
2359                         printf("%s: fail to load firmware %s\n",
2360                                 KBUILD_MODNAME, fw_name);
2361                         wl_release_fw(wl);
2362                         return status;
2363                 }
2364                 wl->fw.hdr_num_entries[i] =
2365                     wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
2366                 WL_NONE(("request fw %s find: %d entries\n", fw_name,
2367                          wl->fw.hdr_num_entries[i]));
2368         }
2369         wl->fw.fw_cnt = i;
2370         wl_ucode_data_init(wl);
2371         return 0;
2372 }
2373
2374 #ifdef WLC_LOW
2375 void wl_ucode_free_buf(void *p)
2376 {
2377         kfree(p);
2378 }
2379 #endif                          /* WLC_LOW */
2380
2381 static void wl_release_fw(wl_info_t *wl)
2382 {
2383         int i;
2384         for (i = 0; i < WL_MAX_FW; i++) {
2385                 release_firmware(wl->fw.fw_bin[i]);
2386                 release_firmware(wl->fw.fw_hdr[i]);
2387         }
2388 }
2389 #endif                          /* WLC_HIGH_ONLY */