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