~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/wl_mac80211.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/types.h>
 
22
#include <linux/pci_ids.h>
 
23
#include <linux/module.h>
 
24
#include <linux/pci.h>
 
25
#include <linux/sched.h>
 
26
#include <linux/firmware.h>
 
27
#include <net/mac80211.h>
 
28
 
 
29
#include <proto/802.11.h>
 
30
#include <bcmdefs.h>
 
31
#include <bcmwifi.h>
 
32
#include <bcmutils.h>
 
33
#include <pcicfg.h>
 
34
#include <wlioctl.h>
 
35
#include <sbhnddma.h>
 
36
 
 
37
#include "phy/wlc_phy_int.h"
 
38
#include "d11.h"
 
39
#include "wlc_types.h"
 
40
#include "wlc_cfg.h"
 
41
#include "phy/phy_version.h"
 
42
#include "wlc_key.h"
 
43
#include "wlc_channel.h"
 
44
#include "wlc_scb.h"
 
45
#include "wlc_pub.h"
 
46
#include "wl_dbg.h"
 
47
#include "wl_export.h"
 
48
#include "wl_ucode.h"
 
49
#include "wl_mac80211.h"
 
50
 
 
51
static void wl_timer(unsigned long data);
 
52
static void _wl_timer(struct wl_timer *t);
 
53
 
 
54
 
 
55
static int ieee_hw_init(struct ieee80211_hw *hw);
 
56
static int ieee_hw_rate_init(struct ieee80211_hw *hw);
 
57
 
 
58
static int wl_linux_watchdog(void *ctx);
 
59
 
 
60
/* Flags we support */
 
61
#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
 
62
        FIF_ALLMULTI | \
 
63
        FIF_FCSFAIL | \
 
64
        FIF_PLCPFAIL | \
 
65
        FIF_CONTROL | \
 
66
        FIF_OTHER_BSS | \
 
67
        FIF_BCN_PRBRESP_PROMISC)
 
68
 
 
69
static int wl_found;
 
70
 
 
71
#define WL_DEV_IF(dev)          ((struct wl_if *)netdev_priv(dev))
 
72
#define WL_INFO(dev)            ((struct wl_info *)(WL_DEV_IF(dev)->wl))
 
73
static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev);
 
74
static void wl_release_fw(struct wl_info *wl);
 
75
 
 
76
/* local prototypes */
 
77
static void wl_dpc(unsigned long data);
 
78
static irqreturn_t wl_isr(int irq, void *dev_id);
 
79
 
 
80
static int __devinit wl_pci_probe(struct pci_dev *pdev,
 
81
                                  const struct pci_device_id *ent);
 
82
static void wl_remove(struct pci_dev *pdev);
 
83
static void wl_free(struct wl_info *wl);
 
84
 
 
85
MODULE_AUTHOR("Broadcom Corporation");
 
86
MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
 
87
MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
 
88
MODULE_LICENSE("Dual BSD/GPL");
 
89
 
 
90
/* recognized PCI IDs */
 
91
static struct pci_device_id wl_id_table[] = {
 
92
        {PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 43225 2G */
 
93
        {PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 43224 DUAL */
 
94
        {PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},      /* 4313 DUAL */
 
95
        {0}
 
96
};
 
97
 
 
98
MODULE_DEVICE_TABLE(pci, wl_id_table);
 
99
 
 
100
#ifdef BCMDBG
 
101
static int msglevel = 0xdeadbeef;
 
102
module_param(msglevel, int, 0);
 
103
static int phymsglevel = 0xdeadbeef;
 
104
module_param(phymsglevel, int, 0);
 
105
#endif                          /* BCMDBG */
 
106
 
 
107
#define HW_TO_WL(hw)     (hw->priv)
 
108
#define WL_TO_HW(wl)      (wl->pub->ieee_hw)
 
109
 
 
110
/* MAC80211 callback functions */
 
111
static int wl_ops_start(struct ieee80211_hw *hw);
 
112
static void wl_ops_stop(struct ieee80211_hw *hw);
 
113
static int wl_ops_add_interface(struct ieee80211_hw *hw,
 
114
                                struct ieee80211_vif *vif);
 
115
static void wl_ops_remove_interface(struct ieee80211_hw *hw,
 
116
                                    struct ieee80211_vif *vif);
 
117
static int wl_ops_config(struct ieee80211_hw *hw, u32 changed);
 
118
static void wl_ops_bss_info_changed(struct ieee80211_hw *hw,
 
119
                                    struct ieee80211_vif *vif,
 
120
                                    struct ieee80211_bss_conf *info,
 
121
                                    u32 changed);
 
122
static void wl_ops_configure_filter(struct ieee80211_hw *hw,
 
123
                                    unsigned int changed_flags,
 
124
                                    unsigned int *total_flags, u64 multicast);
 
125
static int wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
 
126
                          bool set);
 
127
static void wl_ops_sw_scan_start(struct ieee80211_hw *hw);
 
128
static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
 
129
static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
 
130
static int wl_ops_get_stats(struct ieee80211_hw *hw,
 
131
                            struct ieee80211_low_level_stats *stats);
 
132
static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
 
133
static void wl_ops_sta_notify(struct ieee80211_hw *hw,
 
134
                              struct ieee80211_vif *vif,
 
135
                              enum sta_notify_cmd cmd,
 
136
                              struct ieee80211_sta *sta);
 
137
static int wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
138
                          const struct ieee80211_tx_queue_params *params);
 
139
static u64 wl_ops_get_tsf(struct ieee80211_hw *hw);
 
140
static int wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
141
                      struct ieee80211_sta *sta);
 
142
static int wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
143
                         struct ieee80211_sta *sta);
 
144
static int wl_ops_ampdu_action(struct ieee80211_hw *hw,
 
145
                               struct ieee80211_vif *vif,
 
146
                               enum ieee80211_ampdu_mlme_action action,
 
147
                               struct ieee80211_sta *sta, u16 tid, u16 *ssn,
 
148
                               u8 buf_size);
 
149
static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
 
150
 
 
151
static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
152
{
 
153
        struct wl_info *wl = hw->priv;
 
154
 
 
155
        WL_LOCK(wl);
 
156
        if (!wl->pub->up) {
 
157
                WL_ERROR("ops->tx called while down\n");
 
158
                kfree_skb(skb);
 
159
                goto done;
 
160
        }
 
161
        wlc_sendpkt_mac80211(wl->wlc, skb, hw);
 
162
 done:
 
163
        WL_UNLOCK(wl);
 
164
}
 
165
 
 
166
static int wl_ops_start(struct ieee80211_hw *hw)
 
167
{
 
168
        struct wl_info *wl = hw->priv;
 
169
        bool blocked;
 
170
        /*
 
171
          struct ieee80211_channel *curchan = hw->conf.channel;
 
172
          WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
 
173
        */
 
174
 
 
175
        ieee80211_wake_queues(hw);
 
176
        WL_LOCK(wl);
 
177
        blocked = wl_rfkill_set_hw_state(wl);
 
178
        WL_UNLOCK(wl);
 
179
        if (!blocked)
 
180
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
181
 
 
182
        return 0;
 
183
}
 
184
 
 
185
static void wl_ops_stop(struct ieee80211_hw *hw)
 
186
{
 
187
#ifdef BRCMDBG
 
188
        struct wl_info *wl = hw->priv;
 
189
        ASSERT(wl);
 
190
#endif /*BRCMDBG*/
 
191
        ieee80211_stop_queues(hw);
 
192
}
 
193
 
 
194
static int
 
195
wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
196
{
 
197
        struct wl_info *wl;
 
198
        int err;
 
199
 
 
200
        /* Just STA for now */
 
201
        if (vif->type != NL80211_IFTYPE_AP &&
 
202
            vif->type != NL80211_IFTYPE_MESH_POINT &&
 
203
            vif->type != NL80211_IFTYPE_STATION &&
 
204
            vif->type != NL80211_IFTYPE_WDS &&
 
205
            vif->type != NL80211_IFTYPE_ADHOC) {
 
206
                WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
 
207
                         __func__, vif->type);
 
208
                return -EOPNOTSUPP;
 
209
        }
 
210
 
 
211
        wl = HW_TO_WL(hw);
 
212
        WL_LOCK(wl);
 
213
        err = wl_up(wl);
 
214
        WL_UNLOCK(wl);
 
215
 
 
216
        if (err != 0) {
 
217
                WL_ERROR("%s: wl_up() returned %d\n", __func__, err);
 
218
        }
 
219
        return err;
 
220
}
 
221
 
 
222
static void
 
223
wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
224
{
 
225
        struct wl_info *wl;
 
226
 
 
227
        wl = HW_TO_WL(hw);
 
228
 
 
229
        /* put driver in down state */
 
230
        WL_LOCK(wl);
 
231
        wl_down(wl);
 
232
        WL_UNLOCK(wl);
 
233
}
 
234
 
 
235
/*
 
236
 * precondition: perimeter lock has been acquired
 
237
 */
 
238
static int
 
239
ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
 
240
                 enum nl80211_channel_type type)
 
241
{
 
242
        struct wl_info *wl = HW_TO_WL(hw);
 
243
        int err = 0;
 
244
 
 
245
        switch (type) {
 
246
        case NL80211_CHAN_HT20:
 
247
        case NL80211_CHAN_NO_HT:
 
248
                err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
 
249
                break;
 
250
        case NL80211_CHAN_HT40MINUS:
 
251
        case NL80211_CHAN_HT40PLUS:
 
252
                WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__);
 
253
                err = 1;
 
254
                break;
 
255
        }
 
256
 
 
257
        if (err)
 
258
                return -EIO;
 
259
        return err;
 
260
}
 
261
 
 
262
static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
 
263
{
 
264
        struct ieee80211_conf *conf = &hw->conf;
 
265
        struct wl_info *wl = HW_TO_WL(hw);
 
266
        int err = 0;
 
267
        int new_int;
 
268
 
 
269
        WL_LOCK(wl);
 
270
        if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
 
271
                if (wlc_iovar_setint
 
272
                    (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
 
273
                        WL_ERROR("%s: Error setting listen_interval\n",
 
274
                                 __func__);
 
275
                        err = -EIO;
 
276
                        goto config_out;
 
277
                }
 
278
                wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
 
279
                ASSERT(new_int == conf->listen_interval);
 
280
        }
 
281
        if (changed & IEEE80211_CONF_CHANGE_MONITOR)
 
282
                WL_ERROR("%s: change monitor mode: %s (implement)\n", __func__,
 
283
                         conf->flags & IEEE80211_CONF_MONITOR ?
 
284
                                "true" : "false");
 
285
        if (changed & IEEE80211_CONF_CHANGE_PS)
 
286
                WL_ERROR("%s: change power-save mode: %s (implement)\n",
 
287
                         __func__, conf->flags & IEEE80211_CONF_PS ?
 
288
                                "true" : "false");
 
289
 
 
290
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
 
291
                if (wlc_iovar_setint
 
292
                    (wl->wlc, "qtxpower", conf->power_level * 4)) {
 
293
                        WL_ERROR("%s: Error setting power_level\n", __func__);
 
294
                        err = -EIO;
 
295
                        goto config_out;
 
296
                }
 
297
                wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
 
298
                if (new_int != (conf->power_level * 4))
 
299
                        WL_ERROR("%s: Power level req != actual, %d %d\n",
 
300
                                 __func__, conf->power_level * 4, new_int);
 
301
        }
 
302
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 
303
                err = ieee_set_channel(hw, conf->channel, conf->channel_type);
 
304
        }
 
305
        if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
 
306
                if (wlc_set
 
307
                    (wl->wlc, WLC_SET_SRL,
 
308
                     conf->short_frame_max_tx_count) < 0) {
 
309
                        WL_ERROR("%s: Error setting srl\n", __func__);
 
310
                        err = -EIO;
 
311
                        goto config_out;
 
312
                }
 
313
                if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
 
314
                    < 0) {
 
315
                        WL_ERROR("%s: Error setting lrl\n", __func__);
 
316
                        err = -EIO;
 
317
                        goto config_out;
 
318
                }
 
319
        }
 
320
 
 
321
 config_out:
 
322
        WL_UNLOCK(wl);
 
323
        return err;
 
324
}
 
325
 
 
326
static void
 
327
wl_ops_bss_info_changed(struct ieee80211_hw *hw,
 
328
                        struct ieee80211_vif *vif,
 
329
                        struct ieee80211_bss_conf *info, u32 changed)
 
330
{
 
331
        struct wl_info *wl = HW_TO_WL(hw);
 
332
        int val;
 
333
 
 
334
        if (changed & BSS_CHANGED_ASSOC) {
 
335
                /* association status changed (associated/disassociated)
 
336
                 * also implies a change in the AID.
 
337
                 */
 
338
                WL_ERROR("%s: %s: %sassociated\n", KBUILD_MODNAME, __func__,
 
339
                         info->assoc ? "" : "dis");
 
340
                wlc_associate_upd(wl->wlc, info->assoc);
 
341
        }
 
342
        if (changed & BSS_CHANGED_ERP_CTS_PROT) {
 
343
                /* CTS protection changed */
 
344
                WL_ERROR("%s: use_cts_prot: %s (implement)\n", __func__,
 
345
                        info->use_cts_prot ? "true" : "false");
 
346
        }
 
347
        if (changed & BSS_CHANGED_ERP_PREAMBLE) {
 
348
                /* preamble changed */
 
349
                WL_ERROR("%s: short preamble: %s (implement)\n", __func__,
 
350
                        info->use_short_preamble ? "true" : "false");
 
351
        }
 
352
        if (changed & BSS_CHANGED_ERP_SLOT) {
 
353
                /* slot timing changed */
 
354
                if (info->use_short_slot)
 
355
                        val = 1;
 
356
                else
 
357
                        val = 0;
 
358
                WL_LOCK(wl);
 
359
                wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
 
360
                WL_UNLOCK(wl);
 
361
        }
 
362
 
 
363
        if (changed & BSS_CHANGED_HT) {
 
364
                /* 802.11n parameters changed */
 
365
                u16 mode = info->ht_operation_mode;
 
366
                WL_NONE("%s: HT mode: 0x%04X\n", __func__, mode);
 
367
                wlc_protection_upd(wl->wlc, WLC_PROT_N_CFG,
 
368
                        mode & IEEE80211_HT_OP_MODE_PROTECTION);
 
369
                wlc_protection_upd(wl->wlc, WLC_PROT_N_NONGF,
 
370
                        mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 
371
                wlc_protection_upd(wl->wlc, WLC_PROT_N_OBSS,
 
372
                        mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
 
373
        }
 
374
        if (changed & BSS_CHANGED_BASIC_RATES) {
 
375
                /* Basic rateset changed */
 
376
                WL_ERROR("%s: Need to change Basic Rates: 0x%x (implement)\n",
 
377
                         __func__, (u32) info->basic_rates);
 
378
        }
 
379
        if (changed & BSS_CHANGED_BEACON_INT) {
 
380
                /* Beacon interval changed */
 
381
                WL_NONE("%s: Beacon Interval: %d\n",
 
382
                        __func__, info->beacon_int);
 
383
                wlc_set(wl->wlc, WLC_SET_BCNPRD, info->beacon_int);
 
384
        }
 
385
        if (changed & BSS_CHANGED_BSSID) {
 
386
                /* BSSID changed, for whatever reason (IBSS and managed mode) */
 
387
                WL_NONE("%s: new BSSID: aid %d  bss:%pM\n", __func__,
 
388
                        info->aid, info->bssid);
 
389
                WL_LOCK(wl);
 
390
                wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
 
391
                                  info->bssid);
 
392
                WL_UNLOCK(wl);
 
393
        }
 
394
        if (changed & BSS_CHANGED_BEACON) {
 
395
                /* Beacon data changed, retrieve new beacon (beaconing modes) */
 
396
                WL_ERROR("%s: beacon changed\n", __func__);
 
397
        }
 
398
        if (changed & BSS_CHANGED_BEACON_ENABLED) {
 
399
                /* Beaconing should be enabled/disabled (beaconing modes) */
 
400
                WL_ERROR("%s: Beacon enabled: %s\n", __func__,
 
401
                         info->enable_beacon ? "true" : "false");
 
402
        }
 
403
        if (changed & BSS_CHANGED_CQM) {
 
404
                /* Connection quality monitor config changed */
 
405
                WL_ERROR("%s: cqm change: threshold %d, hys %d (implement)\n",
 
406
                        __func__, info->cqm_rssi_thold, info->cqm_rssi_hyst);
 
407
        }
 
408
        if (changed & BSS_CHANGED_IBSS) {
 
409
                /* IBSS join status changed */
 
410
                WL_ERROR("%s: IBSS joined: %s (implement)\n", __func__,
 
411
                        info->ibss_joined ? "true" : "false");
 
412
        }
 
413
        if (changed & BSS_CHANGED_ARP_FILTER) {
 
414
                /* Hardware ARP filter address list or state changed */
 
415
                WL_ERROR("%s: arp filtering: enabled %s, count %d (implement)\n",
 
416
                        __func__, info->arp_filter_enabled ? "true" : "false",
 
417
                        info->arp_addr_cnt);
 
418
        }
 
419
        if (changed & BSS_CHANGED_QOS) {
 
420
                /*
 
421
                 * QoS for this association was enabled/disabled.
 
422
                 * Note that it is only ever disabled for station mode.
 
423
                 */
 
424
                WL_ERROR("%s: qos enabled: %s (implement)\n", __func__,
 
425
                        info->qos ? "true" : "false");
 
426
        }
 
427
        if (changed & BSS_CHANGED_IDLE) {
 
428
                /* Idle changed for this BSS/interface */
 
429
                WL_ERROR("%s: BSS idle: %s (implement)\n", __func__,
 
430
                        info->idle ? "true" : "false");
 
431
        }
 
432
        return;
 
433
}
 
434
 
 
435
static void
 
436
wl_ops_configure_filter(struct ieee80211_hw *hw,
 
437
                        unsigned int changed_flags,
 
438
                        unsigned int *total_flags, u64 multicast)
 
439
{
 
440
        struct wl_info *wl = hw->priv;
 
441
 
 
442
        changed_flags &= MAC_FILTERS;
 
443
        *total_flags &= MAC_FILTERS;
 
444
        if (changed_flags & FIF_PROMISC_IN_BSS)
 
445
                WL_ERROR("FIF_PROMISC_IN_BSS\n");
 
446
        if (changed_flags & FIF_ALLMULTI)
 
447
                WL_ERROR("FIF_ALLMULTI\n");
 
448
        if (changed_flags & FIF_FCSFAIL)
 
449
                WL_ERROR("FIF_FCSFAIL\n");
 
450
        if (changed_flags & FIF_PLCPFAIL)
 
451
                WL_ERROR("FIF_PLCPFAIL\n");
 
452
        if (changed_flags & FIF_CONTROL)
 
453
                WL_ERROR("FIF_CONTROL\n");
 
454
        if (changed_flags & FIF_OTHER_BSS)
 
455
                WL_ERROR("FIF_OTHER_BSS\n");
 
456
        if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
 
457
                WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
 
458
                WL_LOCK(wl);
 
459
                if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
 
460
                        wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
 
461
                        wlc_mac_bcn_promisc_change(wl->wlc, 1);
 
462
                } else {
 
463
                        wlc_mac_bcn_promisc_change(wl->wlc, 0);
 
464
                        wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
 
465
                }
 
466
                WL_UNLOCK(wl);
 
467
        }
 
468
        return;
 
469
}
 
470
 
 
471
static int
 
472
wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
 
473
{
 
474
        WL_NONE("%s: Enter\n", __func__);
 
475
        return 0;
 
476
}
 
477
 
 
478
static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
 
479
{
 
480
        struct wl_info *wl = hw->priv;
 
481
        WL_NONE("Scan Start\n");
 
482
        WL_LOCK(wl);
 
483
        wlc_scan_start(wl->wlc);
 
484
        WL_UNLOCK(wl);
 
485
        return;
 
486
}
 
487
 
 
488
static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
 
489
{
 
490
        struct wl_info *wl = hw->priv;
 
491
        WL_NONE("Scan Complete\n");
 
492
        WL_LOCK(wl);
 
493
        wlc_scan_stop(wl->wlc);
 
494
        WL_UNLOCK(wl);
 
495
        return;
 
496
}
 
497
 
 
498
static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 
499
{
 
500
        WL_ERROR("%s: Enter\n", __func__);
 
501
        return;
 
502
}
 
503
 
 
504
static int
 
505
wl_ops_get_stats(struct ieee80211_hw *hw,
 
506
                 struct ieee80211_low_level_stats *stats)
 
507
{
 
508
        struct wl_info *wl = hw->priv;
 
509
        struct wl_cnt *cnt;
 
510
 
 
511
        WL_LOCK(wl);
 
512
        cnt = wl->pub->_cnt;
 
513
        stats->dot11ACKFailureCount = cnt->txnoack;
 
514
        stats->dot11RTSFailureCount = cnt->txnocts;
 
515
        stats->dot11FCSErrorCount = cnt->rxcrc;
 
516
        stats->dot11RTSSuccessCount = cnt->txrts;
 
517
        WL_UNLOCK(wl);
 
518
        return 0;
 
519
}
 
520
 
 
521
static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 
522
{
 
523
        struct wl_info *wl = hw->priv;
 
524
 
 
525
        WL_LOCK(wl);
 
526
        wlc_iovar_setint(wl->wlc, "rtsthresh", value & 0xFFFF);
 
527
        WL_UNLOCK(wl);
 
528
        return 0;
 
529
}
 
530
 
 
531
static void
 
532
wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
533
                  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
 
534
{
 
535
        WL_NONE("%s: Enter\n", __func__);
 
536
        switch (cmd) {
 
537
        default:
 
538
                WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
 
539
                break;
 
540
        }
 
541
        return;
 
542
}
 
543
 
 
544
static int
 
545
wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
546
               const struct ieee80211_tx_queue_params *params)
 
547
{
 
548
        struct wl_info *wl = hw->priv;
 
549
 
 
550
        WL_NONE("%s: Enter (WME config)\n", __func__);
 
551
        WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
 
552
                 params->txop, params->cw_min, params->cw_max, params->aifs);
 
553
 
 
554
        WL_LOCK(wl);
 
555
        wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
 
556
        WL_UNLOCK(wl);
 
557
 
 
558
        return 0;
 
559
}
 
560
 
 
561
static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
 
562
{
 
563
        WL_ERROR("%s: Enter\n", __func__);
 
564
        return 0;
 
565
}
 
566
 
 
567
static int
 
568
wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
569
               struct ieee80211_sta *sta)
 
570
{
 
571
        struct scb *scb;
 
572
 
 
573
        int i;
 
574
        struct wl_info *wl = hw->priv;
 
575
 
 
576
        /* Init the scb */
 
577
        scb = (struct scb *)sta->drv_priv;
 
578
        memset(scb, 0, sizeof(struct scb));
 
579
        for (i = 0; i < NUMPRIO; i++)
 
580
                scb->seqctl[i] = 0xFFFF;
 
581
        scb->seqctl_nonqos = 0xFFFF;
 
582
        scb->magic = SCB_MAGIC;
 
583
 
 
584
        wl->pub->global_scb = scb;
 
585
        wl->pub->global_ampdu = &(scb->scb_ampdu);
 
586
        wl->pub->global_ampdu->scb = scb;
 
587
        wl->pub->global_ampdu->max_pdu = 16;
 
588
        pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
 
589
                  AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
 
590
 
 
591
        sta->ht_cap.ht_supported = true;
 
592
        sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 
593
        sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
 
594
        sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
 
595
            IEEE80211_HT_CAP_SGI_20 |
 
596
            IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
 
597
 
 
598
        /* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
 
599
        return 0;
 
600
}
 
601
 
 
602
static int
 
603
wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
604
                  struct ieee80211_sta *sta)
 
605
{
 
606
        WL_NONE("%s: Enter\n", __func__);
 
607
        return 0;
 
608
}
 
609
 
 
610
static int
 
611
wl_ops_ampdu_action(struct ieee80211_hw *hw,
 
612
                    struct ieee80211_vif *vif,
 
613
                    enum ieee80211_ampdu_mlme_action action,
 
614
                    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
 
615
                    u8 buf_size)
 
616
{
 
617
#if defined(BCMDBG)
 
618
        struct scb *scb = (struct scb *)sta->drv_priv;
 
619
#endif
 
620
        struct wl_info *wl = hw->priv;
 
621
        int status;
 
622
 
 
623
        ASSERT(scb->magic == SCB_MAGIC);
 
624
        switch (action) {
 
625
        case IEEE80211_AMPDU_RX_START:
 
626
                WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
 
627
                break;
 
628
        case IEEE80211_AMPDU_RX_STOP:
 
629
                WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
 
630
                break;
 
631
        case IEEE80211_AMPDU_TX_START:
 
632
                WL_LOCK(wl);
 
633
                status = wlc_aggregatable(wl->wlc, tid);
 
634
                WL_UNLOCK(wl);
 
635
                if (!status) {
 
636
                        /* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
 
637
                        return -1;
 
638
                }
 
639
                /* XXX: Use the starting sequence number provided ... */
 
640
                *ssn = 0;
 
641
                ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 
642
                break;
 
643
 
 
644
        case IEEE80211_AMPDU_TX_STOP:
 
645
                WL_LOCK(wl);
 
646
                wlc_ampdu_flush(wl->wlc, sta, tid);
 
647
                WL_UNLOCK(wl);
 
648
                ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 
649
                break;
 
650
        case IEEE80211_AMPDU_TX_OPERATIONAL:
 
651
                /* Not sure what to do here */
 
652
                /* Power save wakeup */
 
653
                WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
 
654
                        __func__);
 
655
                break;
 
656
        default:
 
657
                WL_ERROR("%s: Invalid command, ignoring\n", __func__);
 
658
        }
 
659
 
 
660
        return 0;
 
661
}
 
662
 
 
663
static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
 
664
{
 
665
        struct wl_info *wl = HW_TO_WL(hw);
 
666
        bool blocked;
 
667
 
 
668
        WL_LOCK(wl);
 
669
        blocked = wlc_check_radio_disabled(wl->wlc);
 
670
        WL_UNLOCK(wl);
 
671
 
 
672
        WL_NONE("wl: rfkill_poll: %d\n", blocked);
 
673
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 
674
}
 
675
 
 
676
static const struct ieee80211_ops wl_ops = {
 
677
        .tx = wl_ops_tx,
 
678
        .start = wl_ops_start,
 
679
        .stop = wl_ops_stop,
 
680
        .add_interface = wl_ops_add_interface,
 
681
        .remove_interface = wl_ops_remove_interface,
 
682
        .config = wl_ops_config,
 
683
        .bss_info_changed = wl_ops_bss_info_changed,
 
684
        .configure_filter = wl_ops_configure_filter,
 
685
        .set_tim = wl_ops_set_tim,
 
686
        .sw_scan_start = wl_ops_sw_scan_start,
 
687
        .sw_scan_complete = wl_ops_sw_scan_complete,
 
688
        .set_tsf = wl_ops_set_tsf,
 
689
        .get_stats = wl_ops_get_stats,
 
690
        .set_rts_threshold = wl_ops_set_rts_threshold,
 
691
        .sta_notify = wl_ops_sta_notify,
 
692
        .conf_tx = wl_ops_conf_tx,
 
693
        .get_tsf = wl_ops_get_tsf,
 
694
        .sta_add = wl_ops_sta_add,
 
695
        .sta_remove = wl_ops_sta_remove,
 
696
        .ampdu_action = wl_ops_ampdu_action,
 
697
        .rfkill_poll = wl_ops_rfkill_poll,
 
698
};
 
699
 
 
700
/*
 
701
 * is called in wl_pci_probe() context, therefore no locking required.
 
702
 */
 
703
static int wl_set_hint(struct wl_info *wl, char *abbrev)
 
704
{
 
705
        WL_NONE("%s: Sending country code %c%c to MAC80211\n",
 
706
                 __func__, abbrev[0], abbrev[1]);
 
707
        return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
 
708
}
 
709
 
 
710
/**
 
711
 * attach to the WL device.
 
712
 *
 
713
 * Attach to the WL device identified by vendor and device parameters.
 
714
 * regs is a host accessible memory address pointing to WL device registers.
 
715
 *
 
716
 * wl_attach is not defined as static because in the case where no bus
 
717
 * is defined, wl_attach will never be called, and thus, gcc will issue
 
718
 * a warning that this function is defined but not used if we declare
 
719
 * it as static.
 
720
 *
 
721
 *
 
722
 * is called in wl_pci_probe() context, therefore no locking required.
 
723
 */
 
724
static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
 
725
                            uint bustype, void *btparam, uint irq)
 
726
{
 
727
        struct wl_info *wl;
 
728
        int unit, err;
 
729
 
 
730
        unsigned long base_addr;
 
731
        struct ieee80211_hw *hw;
 
732
        u8 perm[ETH_ALEN];
 
733
 
 
734
        unit = wl_found;
 
735
        err = 0;
 
736
 
 
737
        if (unit < 0) {
 
738
                WL_ERROR("wl%d: unit number overflow, exiting\n", unit);
 
739
                return NULL;
 
740
        }
 
741
 
 
742
        /* allocate private info */
 
743
        hw = pci_get_drvdata(btparam);  /* btparam == pdev */
 
744
        wl = hw->priv;
 
745
        ASSERT(wl);
 
746
 
 
747
        atomic_set(&wl->callbacks, 0);
 
748
 
 
749
        /* setup the bottom half handler */
 
750
        tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
 
751
 
 
752
 
 
753
 
 
754
        base_addr = regs;
 
755
 
 
756
        if (bustype == PCI_BUS) {
 
757
                wl->piomode = false;
 
758
        } else if (bustype == RPC_BUS) {
 
759
                /* Do nothing */
 
760
        } else {
 
761
                bustype = PCI_BUS;
 
762
                WL_TRACE("force to PCI\n");
 
763
        }
 
764
        wl->bcm_bustype = bustype;
 
765
 
 
766
        wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
 
767
        if (wl->regsva == NULL) {
 
768
                WL_ERROR("wl%d: ioremap() failed\n", unit);
 
769
                goto fail;
 
770
        }
 
771
        spin_lock_init(&wl->lock);
 
772
        spin_lock_init(&wl->isr_lock);
 
773
 
 
774
        /* prepare ucode */
 
775
        if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) {
 
776
                WL_ERROR("%s: Failed to find firmware usually in %s\n",
 
777
                         KBUILD_MODNAME, "/lib/firmware/brcm");
 
778
                wl_release_fw(wl);
 
779
                wl_remove((struct pci_dev *)btparam);
 
780
                goto fail1;
 
781
        }
 
782
 
 
783
        /* common load-time initialization */
 
784
        wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode,
 
785
                             wl->regsva, wl->bcm_bustype, btparam, &err);
 
786
        wl_release_fw(wl);
 
787
        if (!wl->wlc) {
 
788
                WL_ERROR("%s: wlc_attach() failed with code %d\n",
 
789
                         KBUILD_MODNAME, err);
 
790
                goto fail;
 
791
        }
 
792
        wl->pub = wlc_pub(wl->wlc);
 
793
 
 
794
        wl->pub->ieee_hw = hw;
 
795
        ASSERT(wl->pub->ieee_hw);
 
796
        ASSERT(wl->pub->ieee_hw->priv == wl);
 
797
 
 
798
 
 
799
        if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
 
800
                WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit);
 
801
        }
 
802
 
 
803
        /* register our interrupt handler */
 
804
        if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
 
805
                WL_ERROR("wl%d: request_irq() failed\n", unit);
 
806
                goto fail;
 
807
        }
 
808
        wl->irq = irq;
 
809
 
 
810
        /* register module */
 
811
        wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
 
812
                            NULL);
 
813
 
 
814
        if (ieee_hw_init(hw)) {
 
815
                WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit, __func__);
 
816
                goto fail;
 
817
        }
 
818
 
 
819
        memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
 
820
        ASSERT(is_valid_ether_addr(perm));
 
821
        SET_IEEE80211_PERM_ADDR(hw, perm);
 
822
 
 
823
        err = ieee80211_register_hw(hw);
 
824
        if (err) {
 
825
                WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
 
826
                         __func__, err);
 
827
        }
 
828
 
 
829
        if (wl->pub->srom_ccode[0])
 
830
                err = wl_set_hint(wl, wl->pub->srom_ccode);
 
831
        else
 
832
                err = wl_set_hint(wl, "US");
 
833
        if (err) {
 
834
                WL_ERROR("%s: regulatory_hint failed, status %d\n",
 
835
                         __func__, err);
 
836
        }
 
837
 
 
838
        wl_found++;
 
839
        return wl;
 
840
 
 
841
fail:
 
842
        wl_free(wl);
 
843
fail1:
 
844
        return NULL;
 
845
}
 
846
 
 
847
 
 
848
 
 
849
#define CHAN2GHZ(channel, freqency, chflags)  { \
 
850
        .band = IEEE80211_BAND_2GHZ, \
 
851
        .center_freq = (freqency), \
 
852
        .hw_value = (channel), \
 
853
        .flags = chflags, \
 
854
        .max_antenna_gain = 0, \
 
855
        .max_power = 19, \
 
856
}
 
857
 
 
858
static struct ieee80211_channel wl_2ghz_chantable[] = {
 
859
        CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
 
860
        CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
 
861
        CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
 
862
        CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
 
863
        CHAN2GHZ(5, 2432, 0),
 
864
        CHAN2GHZ(6, 2437, 0),
 
865
        CHAN2GHZ(7, 2442, 0),
 
866
        CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
 
867
        CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
 
868
        CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
 
869
        CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
 
870
        CHAN2GHZ(12, 2467,
 
871
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
 
872
                 IEEE80211_CHAN_NO_HT40PLUS),
 
873
        CHAN2GHZ(13, 2472,
 
874
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
 
875
                 IEEE80211_CHAN_NO_HT40PLUS),
 
876
        CHAN2GHZ(14, 2484,
 
877
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
 
878
                 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
 
879
};
 
880
 
 
881
#define CHAN5GHZ(channel, chflags)  { \
 
882
        .band = IEEE80211_BAND_5GHZ, \
 
883
        .center_freq = 5000 + 5*(channel), \
 
884
        .hw_value = (channel), \
 
885
        .flags = chflags, \
 
886
        .max_antenna_gain = 0, \
 
887
        .max_power = 21, \
 
888
}
 
889
 
 
890
static struct ieee80211_channel wl_5ghz_nphy_chantable[] = {
 
891
        /* UNII-1 */
 
892
        CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
 
893
        CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
 
894
        CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
 
895
        CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
 
896
        /* UNII-2 */
 
897
        CHAN5GHZ(52,
 
898
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
899
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
900
        CHAN5GHZ(56,
 
901
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
902
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
903
        CHAN5GHZ(60,
 
904
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
905
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
906
        CHAN5GHZ(64,
 
907
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
908
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
909
        /* MID */
 
910
        CHAN5GHZ(100,
 
911
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
912
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
913
        CHAN5GHZ(104,
 
914
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
915
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
916
        CHAN5GHZ(108,
 
917
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
918
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
919
        CHAN5GHZ(112,
 
920
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
921
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
922
        CHAN5GHZ(116,
 
923
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
924
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
925
        CHAN5GHZ(120,
 
926
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
927
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
928
        CHAN5GHZ(124,
 
929
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
930
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
931
        CHAN5GHZ(128,
 
932
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
933
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
934
        CHAN5GHZ(132,
 
935
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
936
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
 
937
        CHAN5GHZ(136,
 
938
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
939
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
 
940
        CHAN5GHZ(140,
 
941
                 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
 
942
                 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
 
943
                 IEEE80211_CHAN_NO_HT40MINUS),
 
944
        /* UNII-3 */
 
945
        CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
 
946
        CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
 
947
        CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
 
948
        CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
 
949
        CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
 
950
};
 
951
 
 
952
#define RATE(rate100m, _flags) { \
 
953
        .bitrate = (rate100m), \
 
954
        .flags = (_flags), \
 
955
        .hw_value = (rate100m / 5), \
 
956
}
 
957
 
 
958
static struct ieee80211_rate wl_legacy_ratetable[] = {
 
959
        RATE(10, 0),
 
960
        RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
 
961
        RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
 
962
        RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
 
963
        RATE(60, 0),
 
964
        RATE(90, 0),
 
965
        RATE(120, 0),
 
966
        RATE(180, 0),
 
967
        RATE(240, 0),
 
968
        RATE(360, 0),
 
969
        RATE(480, 0),
 
970
        RATE(540, 0),
 
971
};
 
972
 
 
973
static struct ieee80211_supported_band wl_band_2GHz_nphy = {
 
974
        .band = IEEE80211_BAND_2GHZ,
 
975
        .channels = wl_2ghz_chantable,
 
976
        .n_channels = ARRAY_SIZE(wl_2ghz_chantable),
 
977
        .bitrates = wl_legacy_ratetable,
 
978
        .n_bitrates = ARRAY_SIZE(wl_legacy_ratetable),
 
979
        .ht_cap = {
 
980
                   /* from include/linux/ieee80211.h */
 
981
                   .cap = IEEE80211_HT_CAP_GRN_FLD |
 
982
                   IEEE80211_HT_CAP_SGI_20 |
 
983
                   IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
 
984
                   .ht_supported = true,
 
985
                   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
 
986
                   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
 
987
                   .mcs = {
 
988
                           /* placeholders for now */
 
989
                           .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
 
990
                           .rx_highest = 500,
 
991
                           .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
 
992
                   }
 
993
};
 
994
 
 
995
static struct ieee80211_supported_band wl_band_5GHz_nphy = {
 
996
        .band = IEEE80211_BAND_5GHZ,
 
997
        .channels = wl_5ghz_nphy_chantable,
 
998
        .n_channels = ARRAY_SIZE(wl_5ghz_nphy_chantable),
 
999
        .bitrates = wl_legacy_ratetable + 4,
 
1000
        .n_bitrates = ARRAY_SIZE(wl_legacy_ratetable) - 4,
 
1001
        .ht_cap = {
 
1002
                   /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
 
1003
                   .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 */
 
1004
                   .ht_supported = true,
 
1005
                   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
 
1006
                   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
 
1007
                   .mcs = {
 
1008
                           /* placeholders for now */
 
1009
                           .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
 
1010
                           .rx_highest = 500,
 
1011
                           .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
 
1012
                   }
 
1013
};
 
1014
 
 
1015
/*
 
1016
 * is called in wl_pci_probe() context, therefore no locking required.
 
1017
 */
 
1018
static int ieee_hw_rate_init(struct ieee80211_hw *hw)
 
1019
{
 
1020
        struct wl_info *wl = HW_TO_WL(hw);
 
1021
        int has_5g;
 
1022
        char phy_list[4];
 
1023
 
 
1024
        has_5g = 0;
 
1025
 
 
1026
        hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
 
1027
        hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 
1028
 
 
1029
        if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
 
1030
                WL_ERROR("Phy list failed\n");
 
1031
        }
 
1032
        WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);
 
1033
 
 
1034
        if (phy_list[0] == 'n' || phy_list[0] == 'c') {
 
1035
                if (phy_list[0] == 'c') {
 
1036
                        /* Single stream */
 
1037
                        wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
 
1038
                        wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
 
1039
                }
 
1040
                hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
 
1041
        } else {
 
1042
                BUG();
 
1043
                return -1;
 
1044
        }
 
1045
 
 
1046
        /* Assume all bands use the same phy.  True for 11n devices. */
 
1047
        if (NBANDS_PUB(wl->pub) > 1) {
 
1048
                has_5g++;
 
1049
                if (phy_list[0] == 'n' || phy_list[0] == 'c') {
 
1050
                        hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 
1051
                            &wl_band_5GHz_nphy;
 
1052
                } else {
 
1053
                        return -1;
 
1054
                }
 
1055
        }
 
1056
 
 
1057
        WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);
 
1058
 
 
1059
        return 0;
 
1060
}
 
1061
 
 
1062
/*
 
1063
 * is called in wl_pci_probe() context, therefore no locking required.
 
1064
 */
 
1065
static int ieee_hw_init(struct ieee80211_hw *hw)
 
1066
{
 
1067
        hw->flags = IEEE80211_HW_SIGNAL_DBM
 
1068
            /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
 
1069
            | IEEE80211_HW_REPORTS_TX_ACK_STATUS
 
1070
            | IEEE80211_HW_AMPDU_AGGREGATION;
 
1071
 
 
1072
        hw->extra_tx_headroom = wlc_get_header_len();
 
1073
        /* FIXME: should get this from wlc->machwcap */
 
1074
        hw->queues = 4;
 
1075
        /* FIXME: this doesn't seem to be used properly in minstrel_ht.
 
1076
         * mac80211/status.c:ieee80211_tx_status() checks this value,
 
1077
         * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
 
1078
         * appears to always set 3 rates
 
1079
         */
 
1080
        hw->max_rates = 2;      /* Primary rate and 1 fallback rate */
 
1081
 
 
1082
        hw->channel_change_time = 7 * 1000;     /* channel change time is dependent on chip and band  */
 
1083
        hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 
1084
 
 
1085
        hw->rate_control_algorithm = "minstrel_ht";
 
1086
 
 
1087
        hw->sta_data_size = sizeof(struct scb);
 
1088
        return ieee_hw_rate_init(hw);
 
1089
}
 
1090
 
 
1091
/**
 
1092
 * determines if a device is a WL device, and if so, attaches it.
 
1093
 *
 
1094
 * This function determines if a device pointed to by pdev is a WL device,
 
1095
 * and if so, performs a wl_attach() on it.
 
1096
 *
 
1097
 * Perimeter lock is initialized in the course of this function.
 
1098
 */
 
1099
static int __devinit
 
1100
wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
1101
{
 
1102
        int rc;
 
1103
        struct wl_info *wl;
 
1104
        struct ieee80211_hw *hw;
 
1105
        u32 val;
 
1106
 
 
1107
        ASSERT(pdev);
 
1108
 
 
1109
        WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
 
1110
                 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
 
1111
                 PCI_FUNC(pdev->devfn), pdev->irq);
 
1112
 
 
1113
        if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
 
1114
            (((pdev->device & 0xff00) != 0x4300) &&
 
1115
             ((pdev->device & 0xff00) != 0x4700) &&
 
1116
             ((pdev->device < 43000) || (pdev->device > 43999))))
 
1117
                return -ENODEV;
 
1118
 
 
1119
        rc = pci_enable_device(pdev);
 
1120
        if (rc) {
 
1121
                WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
 
1122
                         __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
 
1123
                         PCI_FUNC(pdev->devfn));
 
1124
                return -ENODEV;
 
1125
        }
 
1126
        pci_set_master(pdev);
 
1127
 
 
1128
        pci_read_config_dword(pdev, 0x40, &val);
 
1129
        if ((val & 0x0000ff00) != 0)
 
1130
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
1131
 
 
1132
        hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
 
1133
        if (!hw) {
 
1134
                WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__);
 
1135
                rc = -ENOMEM;
 
1136
                goto err_1;
 
1137
        }
 
1138
 
 
1139
        SET_IEEE80211_DEV(hw, &pdev->dev);
 
1140
 
 
1141
        pci_set_drvdata(pdev, hw);
 
1142
 
 
1143
        memset(hw->priv, 0, sizeof(*wl));
 
1144
 
 
1145
        wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
 
1146
                       PCI_BUS, pdev, pdev->irq);
 
1147
 
 
1148
        if (!wl) {
 
1149
                WL_ERROR("%s: %s: wl_attach failed!\n",
 
1150
                         KBUILD_MODNAME, __func__);
 
1151
                return -ENODEV;
 
1152
        }
 
1153
        return 0;
 
1154
 err_1:
 
1155
        WL_ERROR("%s: err_1: Major hoarkage\n", __func__);
 
1156
        return 0;
 
1157
}
 
1158
 
 
1159
static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
 
1160
{
 
1161
        struct wl_info *wl;
 
1162
        struct ieee80211_hw *hw;
 
1163
 
 
1164
        WL_TRACE("wl: wl_suspend\n");
 
1165
 
 
1166
        hw = pci_get_drvdata(pdev);
 
1167
        wl = HW_TO_WL(hw);
 
1168
        if (!wl) {
 
1169
                WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
 
1170
                return -ENODEV;
 
1171
        }
 
1172
 
 
1173
        /* only need to flag hw is down for proper resume */
 
1174
        WL_LOCK(wl);
 
1175
        wl->pub->hw_up = false;
 
1176
        WL_UNLOCK(wl);
 
1177
 
 
1178
        pci_save_state(pdev);
 
1179
        pci_disable_device(pdev);
 
1180
        return pci_set_power_state(pdev, PCI_D3hot);
 
1181
}
 
1182
 
 
1183
static int wl_resume(struct pci_dev *pdev)
 
1184
{
 
1185
        struct wl_info *wl;
 
1186
        struct ieee80211_hw *hw;
 
1187
        int err = 0;
 
1188
        u32 val;
 
1189
 
 
1190
        WL_TRACE("wl: wl_resume\n");
 
1191
        hw = pci_get_drvdata(pdev);
 
1192
        wl = HW_TO_WL(hw);
 
1193
        if (!wl) {
 
1194
                WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
 
1195
                return -ENODEV;
 
1196
        }
 
1197
 
 
1198
        err = pci_set_power_state(pdev, PCI_D0);
 
1199
        if (err)
 
1200
                return err;
 
1201
 
 
1202
        pci_restore_state(pdev);
 
1203
 
 
1204
        err = pci_enable_device(pdev);
 
1205
        if (err)
 
1206
                return err;
 
1207
 
 
1208
        pci_set_master(pdev);
 
1209
 
 
1210
        pci_read_config_dword(pdev, 0x40, &val);
 
1211
        if ((val & 0x0000ff00) != 0)
 
1212
                pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
 
1213
 
 
1214
        /*
 
1215
        *  done. driver will be put in up state
 
1216
        *  in wl_ops_add_interface() call.
 
1217
        */
 
1218
        return err;
 
1219
}
 
1220
 
 
1221
/*
 
1222
* called from both kernel as from wl_*()
 
1223
* precondition: perimeter lock is not acquired.
 
1224
*/
 
1225
static void wl_remove(struct pci_dev *pdev)
 
1226
{
 
1227
        struct wl_info *wl;
 
1228
        struct ieee80211_hw *hw;
 
1229
        int status;
 
1230
 
 
1231
        hw = pci_get_drvdata(pdev);
 
1232
        wl = HW_TO_WL(hw);
 
1233
        if (!wl) {
 
1234
                WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
 
1235
                return;
 
1236
        }
 
1237
 
 
1238
        WL_LOCK(wl);
 
1239
        status = wlc_chipmatch(pdev->vendor, pdev->device);
 
1240
        WL_UNLOCK(wl);
 
1241
        if (!status) {
 
1242
                WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
 
1243
                return;
 
1244
        }
 
1245
        if (wl->wlc) {
 
1246
                wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
 
1247
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
1248
                ieee80211_unregister_hw(hw);
 
1249
                WL_LOCK(wl);
 
1250
                wl_down(wl);
 
1251
                WL_UNLOCK(wl);
 
1252
                WL_NONE("%s: Down\n", __func__);
 
1253
        }
 
1254
        pci_disable_device(pdev);
 
1255
 
 
1256
        wl_free(wl);
 
1257
 
 
1258
        pci_set_drvdata(pdev, NULL);
 
1259
        ieee80211_free_hw(hw);
 
1260
}
 
1261
 
 
1262
static struct pci_driver wl_pci_driver = {
 
1263
        .name     = KBUILD_MODNAME,
 
1264
        .probe    = wl_pci_probe,
 
1265
        .suspend  = wl_suspend,
 
1266
        .resume   = wl_resume,
 
1267
        .remove   = __devexit_p(wl_remove),
 
1268
        .id_table = wl_id_table,
 
1269
};
 
1270
 
 
1271
/**
 
1272
 * This is the main entry point for the WL driver.
 
1273
 *
 
1274
 * This function determines if a device pointed to by pdev is a WL device,
 
1275
 * and if so, performs a wl_attach() on it.
 
1276
 *
 
1277
 */
 
1278
static int __init wl_module_init(void)
 
1279
{
 
1280
        int error = -ENODEV;
 
1281
 
 
1282
#ifdef BCMDBG
 
1283
        if (msglevel != 0xdeadbeef)
 
1284
                wl_msg_level = msglevel;
 
1285
        else {
 
1286
                char *var = getvar(NULL, "wl_msglevel");
 
1287
                if (var) {
 
1288
                        unsigned long value;
 
1289
 
 
1290
                        (void)strict_strtoul(var, 0, &value);
 
1291
                        wl_msg_level = value;
 
1292
                }
 
1293
        }
 
1294
        if (phymsglevel != 0xdeadbeef)
 
1295
                phyhal_msg_level = phymsglevel;
 
1296
        else {
 
1297
                char *var = getvar(NULL, "phy_msglevel");
 
1298
                if (var) {
 
1299
                        unsigned long value;
 
1300
 
 
1301
                        (void)strict_strtoul(var, 0, &value);
 
1302
                        phyhal_msg_level = value;
 
1303
                }
 
1304
        }
 
1305
#endif                          /* BCMDBG */
 
1306
 
 
1307
        error = pci_register_driver(&wl_pci_driver);
 
1308
        if (!error)
 
1309
                return 0;
 
1310
 
 
1311
 
 
1312
 
 
1313
        return error;
 
1314
}
 
1315
 
 
1316
/**
 
1317
 * This function unloads the WL driver from the system.
 
1318
 *
 
1319
 * This function unconditionally unloads the WL driver module from the
 
1320
 * system.
 
1321
 *
 
1322
 */
 
1323
static void __exit wl_module_exit(void)
 
1324
{
 
1325
        pci_unregister_driver(&wl_pci_driver);
 
1326
 
 
1327
}
 
1328
 
 
1329
module_init(wl_module_init);
 
1330
module_exit(wl_module_exit);
 
1331
 
 
1332
/**
 
1333
 * This function frees the WL per-device resources.
 
1334
 *
 
1335
 * This function frees resources owned by the WL device pointed to
 
1336
 * by the wl parameter.
 
1337
 *
 
1338
 * precondition: can both be called locked and unlocked
 
1339
 *
 
1340
 */
 
1341
static void wl_free(struct wl_info *wl)
 
1342
{
 
1343
        struct wl_timer *t, *next;
 
1344
 
 
1345
        ASSERT(wl);
 
1346
        /* free ucode data */
 
1347
        if (wl->fw.fw_cnt)
 
1348
                wl_ucode_data_free();
 
1349
        if (wl->irq)
 
1350
                free_irq(wl->irq, wl);
 
1351
 
 
1352
        /* kill dpc */
 
1353
        tasklet_kill(&wl->tasklet);
 
1354
 
 
1355
        if (wl->pub) {
 
1356
                wlc_module_unregister(wl->pub, "linux", wl);
 
1357
        }
 
1358
 
 
1359
        /* free common resources */
 
1360
        if (wl->wlc) {
 
1361
                wlc_detach(wl->wlc);
 
1362
                wl->wlc = NULL;
 
1363
                wl->pub = NULL;
 
1364
        }
 
1365
 
 
1366
        /* virtual interface deletion is deferred so we cannot spinwait */
 
1367
 
 
1368
        /* wait for all pending callbacks to complete */
 
1369
        while (atomic_read(&wl->callbacks) > 0)
 
1370
                schedule();
 
1371
 
 
1372
        /* free timers */
 
1373
        for (t = wl->timers; t; t = next) {
 
1374
                next = t->next;
 
1375
#ifdef BCMDBG
 
1376
                kfree(t->name);
 
1377
#endif
 
1378
                kfree(t);
 
1379
        }
 
1380
 
 
1381
        /*
 
1382
         * unregister_netdev() calls get_stats() which may read chip registers
 
1383
         * so we cannot unmap the chip registers until after calling unregister_netdev() .
 
1384
         */
 
1385
        if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
 
1386
            wl->bcm_bustype != JTAG_BUS) {
 
1387
                iounmap((void *)wl->regsva);
 
1388
        }
 
1389
        wl->regsva = NULL;
 
1390
}
 
1391
 
 
1392
/*
 
1393
 * precondition: perimeter lock has been acquired
 
1394
 */
 
1395
void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
 
1396
                      int prio)
 
1397
{
 
1398
        WL_ERROR("Shouldn't be here %s\n", __func__);
 
1399
}
 
1400
 
 
1401
/*
 
1402
 * precondition: perimeter lock has been acquired
 
1403
 */
 
1404
void wl_init(struct wl_info *wl)
 
1405
{
 
1406
        WL_TRACE("wl%d: wl_init\n", wl->pub->unit);
 
1407
 
 
1408
        wl_reset(wl);
 
1409
 
 
1410
        wlc_init(wl->wlc);
 
1411
}
 
1412
 
 
1413
/*
 
1414
 * precondition: perimeter lock has been acquired
 
1415
 */
 
1416
uint wl_reset(struct wl_info *wl)
 
1417
{
 
1418
        WL_TRACE("wl%d: wl_reset\n", wl->pub->unit);
 
1419
 
 
1420
        wlc_reset(wl->wlc);
 
1421
 
 
1422
        /* dpc will not be rescheduled */
 
1423
        wl->resched = 0;
 
1424
 
 
1425
        return 0;
 
1426
}
 
1427
 
 
1428
/*
 
1429
 * These are interrupt on/off entry points. Disable interrupts
 
1430
 * during interrupt state transition.
 
1431
 */
 
1432
void BCMFASTPATH wl_intrson(struct wl_info *wl)
 
1433
{
 
1434
        unsigned long flags;
 
1435
 
 
1436
        INT_LOCK(wl, flags);
 
1437
        wlc_intrson(wl->wlc);
 
1438
        INT_UNLOCK(wl, flags);
 
1439
}
 
1440
 
 
1441
/*
 
1442
 * precondition: perimeter lock has been acquired
 
1443
 */
 
1444
bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
 
1445
{
 
1446
        return true;
 
1447
}
 
1448
 
 
1449
u32 BCMFASTPATH wl_intrsoff(struct wl_info *wl)
 
1450
{
 
1451
        unsigned long flags;
 
1452
        u32 status;
 
1453
 
 
1454
        INT_LOCK(wl, flags);
 
1455
        status = wlc_intrsoff(wl->wlc);
 
1456
        INT_UNLOCK(wl, flags);
 
1457
        return status;
 
1458
}
 
1459
 
 
1460
void wl_intrsrestore(struct wl_info *wl, u32 macintmask)
 
1461
{
 
1462
        unsigned long flags;
 
1463
 
 
1464
        INT_LOCK(wl, flags);
 
1465
        wlc_intrsrestore(wl->wlc, macintmask);
 
1466
        INT_UNLOCK(wl, flags);
 
1467
}
 
1468
 
 
1469
/*
 
1470
 * precondition: perimeter lock has been acquired
 
1471
 */
 
1472
int wl_up(struct wl_info *wl)
 
1473
{
 
1474
        int error = 0;
 
1475
 
 
1476
        if (wl->pub->up)
 
1477
                return 0;
 
1478
 
 
1479
        error = wlc_up(wl->wlc);
 
1480
 
 
1481
        return error;
 
1482
}
 
1483
 
 
1484
/*
 
1485
 * precondition: perimeter lock has been acquired
 
1486
 */
 
1487
void wl_down(struct wl_info *wl)
 
1488
{
 
1489
        uint callbacks, ret_val = 0;
 
1490
 
 
1491
        /* call common down function */
 
1492
        ret_val = wlc_down(wl->wlc);
 
1493
        callbacks = atomic_read(&wl->callbacks) - ret_val;
 
1494
 
 
1495
        /* wait for down callbacks to complete */
 
1496
        WL_UNLOCK(wl);
 
1497
 
 
1498
        /* For HIGH_only driver, it's important to actually schedule other work,
 
1499
         * not just spin wait since everything runs at schedule level
 
1500
         */
 
1501
        SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
 
1502
 
 
1503
        WL_LOCK(wl);
 
1504
}
 
1505
 
 
1506
static irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
 
1507
{
 
1508
        struct wl_info *wl;
 
1509
        bool ours, wantdpc;
 
1510
        unsigned long flags;
 
1511
 
 
1512
        wl = (struct wl_info *) dev_id;
 
1513
 
 
1514
        WL_ISRLOCK(wl, flags);
 
1515
 
 
1516
        /* call common first level interrupt handler */
 
1517
        ours = wlc_isr(wl->wlc, &wantdpc);
 
1518
        if (ours) {
 
1519
                /* if more to do... */
 
1520
                if (wantdpc) {
 
1521
 
 
1522
                        /* ...and call the second level interrupt handler */
 
1523
                        /* schedule dpc */
 
1524
                        ASSERT(wl->resched == false);
 
1525
                        tasklet_schedule(&wl->tasklet);
 
1526
                }
 
1527
        }
 
1528
 
 
1529
        WL_ISRUNLOCK(wl, flags);
 
1530
 
 
1531
        return IRQ_RETVAL(ours);
 
1532
}
 
1533
 
 
1534
static void BCMFASTPATH wl_dpc(unsigned long data)
 
1535
{
 
1536
        struct wl_info *wl;
 
1537
 
 
1538
        wl = (struct wl_info *) data;
 
1539
 
 
1540
        WL_LOCK(wl);
 
1541
 
 
1542
        /* call the common second level interrupt handler */
 
1543
        if (wl->pub->up) {
 
1544
                if (wl->resched) {
 
1545
                        unsigned long flags;
 
1546
 
 
1547
                        INT_LOCK(wl, flags);
 
1548
                        wlc_intrsupd(wl->wlc);
 
1549
                        INT_UNLOCK(wl, flags);
 
1550
                }
 
1551
 
 
1552
                wl->resched = wlc_dpc(wl->wlc, true);
 
1553
        }
 
1554
 
 
1555
        /* wlc_dpc() may bring the driver down */
 
1556
        if (!wl->pub->up)
 
1557
                goto done;
 
1558
 
 
1559
        /* re-schedule dpc */
 
1560
        if (wl->resched)
 
1561
                tasklet_schedule(&wl->tasklet);
 
1562
        else {
 
1563
                /* re-enable interrupts */
 
1564
                wl_intrson(wl);
 
1565
        }
 
1566
 
 
1567
 done:
 
1568
        WL_UNLOCK(wl);
 
1569
}
 
1570
 
 
1571
/*
 
1572
 * is called by the kernel from software irq context
 
1573
 */
 
1574
static void wl_timer(unsigned long data)
 
1575
{
 
1576
        _wl_timer((struct wl_timer *) data);
 
1577
}
 
1578
 
 
1579
/*
 
1580
* precondition: perimeter lock is not acquired
 
1581
 */
 
1582
static void _wl_timer(struct wl_timer *t)
 
1583
{
 
1584
        WL_LOCK(t->wl);
 
1585
 
 
1586
        if (t->set) {
 
1587
                if (t->periodic) {
 
1588
                        t->timer.expires = jiffies + t->ms * HZ / 1000;
 
1589
                        atomic_inc(&t->wl->callbacks);
 
1590
                        add_timer(&t->timer);
 
1591
                        t->set = true;
 
1592
                } else
 
1593
                        t->set = false;
 
1594
 
 
1595
                t->fn(t->arg);
 
1596
        }
 
1597
 
 
1598
        atomic_dec(&t->wl->callbacks);
 
1599
 
 
1600
        WL_UNLOCK(t->wl);
 
1601
}
 
1602
 
 
1603
/*
 
1604
 * Adds a timer to the list. Caller supplies a timer function.
 
1605
 * Is called from wlc.
 
1606
 *
 
1607
 * precondition: perimeter lock has been acquired
 
1608
 */
 
1609
struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg),
 
1610
                               void *arg, const char *name)
 
1611
{
 
1612
        struct wl_timer *t;
 
1613
 
 
1614
        t = kzalloc(sizeof(struct wl_timer), GFP_ATOMIC);
 
1615
        if (!t) {
 
1616
                WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl->pub->unit);
 
1617
                return 0;
 
1618
        }
 
1619
 
 
1620
        init_timer(&t->timer);
 
1621
        t->timer.data = (unsigned long) t;
 
1622
        t->timer.function = wl_timer;
 
1623
        t->wl = wl;
 
1624
        t->fn = fn;
 
1625
        t->arg = arg;
 
1626
        t->next = wl->timers;
 
1627
        wl->timers = t;
 
1628
 
 
1629
#ifdef BCMDBG
 
1630
        t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
 
1631
        if (t->name)
 
1632
                strcpy(t->name, name);
 
1633
#endif
 
1634
 
 
1635
        return t;
 
1636
}
 
1637
 
 
1638
/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
 
1639
 * as well as it's easier to make it periodic
 
1640
 *
 
1641
 * precondition: perimeter lock has been acquired
 
1642
 */
 
1643
void wl_add_timer(struct wl_info *wl, struct wl_timer *t, uint ms, int periodic)
 
1644
{
 
1645
#ifdef BCMDBG
 
1646
        if (t->set) {
 
1647
                WL_ERROR("%s: Already set. Name: %s, per %d\n",
 
1648
                         __func__, t->name, periodic);
 
1649
        }
 
1650
#endif
 
1651
        ASSERT(!t->set);
 
1652
 
 
1653
        t->ms = ms;
 
1654
        t->periodic = (bool) periodic;
 
1655
        t->set = true;
 
1656
        t->timer.expires = jiffies + ms * HZ / 1000;
 
1657
 
 
1658
        atomic_inc(&wl->callbacks);
 
1659
        add_timer(&t->timer);
 
1660
}
 
1661
 
 
1662
/*
 
1663
 * return true if timer successfully deleted, false if still pending
 
1664
 *
 
1665
 * precondition: perimeter lock has been acquired
 
1666
 */
 
1667
bool wl_del_timer(struct wl_info *wl, struct wl_timer *t)
 
1668
{
 
1669
        if (t->set) {
 
1670
                t->set = false;
 
1671
                if (!del_timer(&t->timer)) {
 
1672
                        return false;
 
1673
                }
 
1674
                atomic_dec(&wl->callbacks);
 
1675
        }
 
1676
 
 
1677
        return true;
 
1678
}
 
1679
 
 
1680
/*
 
1681
 * precondition: perimeter lock has been acquired
 
1682
 */
 
1683
void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
 
1684
{
 
1685
        struct wl_timer *tmp;
 
1686
 
 
1687
        /* delete the timer in case it is active */
 
1688
        wl_del_timer(wl, t);
 
1689
 
 
1690
        if (wl->timers == t) {
 
1691
                wl->timers = wl->timers->next;
 
1692
#ifdef BCMDBG
 
1693
                kfree(t->name);
 
1694
#endif
 
1695
                kfree(t);
 
1696
                return;
 
1697
 
 
1698
        }
 
1699
 
 
1700
        tmp = wl->timers;
 
1701
        while (tmp) {
 
1702
                if (tmp->next == t) {
 
1703
                        tmp->next = t->next;
 
1704
#ifdef BCMDBG
 
1705
                        kfree(t->name);
 
1706
#endif
 
1707
                        kfree(t);
 
1708
                        return;
 
1709
                }
 
1710
                tmp = tmp->next;
 
1711
        }
 
1712
 
 
1713
}
 
1714
 
 
1715
/*
 
1716
 * runs in software irq context
 
1717
 *
 
1718
 * precondition: perimeter lock is not acquired
 
1719
 */
 
1720
static int wl_linux_watchdog(void *ctx)
 
1721
{
 
1722
        struct wl_info *wl = (struct wl_info *) ctx;
 
1723
        struct wl_cnt *cnt;
 
1724
        struct net_device_stats *stats = NULL;
 
1725
        uint id;
 
1726
        /* refresh stats */
 
1727
        if (wl->pub->up) {
 
1728
                ASSERT(wl->stats_id < 2);
 
1729
 
 
1730
                cnt = wl->pub->_cnt;
 
1731
                id = 1 - wl->stats_id;
 
1732
                stats = &wl->stats_watchdog[id];
 
1733
                stats->rx_packets = cnt->rxframe;
 
1734
                stats->tx_packets = cnt->txframe;
 
1735
                stats->rx_bytes = cnt->rxbyte;
 
1736
                stats->tx_bytes = cnt->txbyte;
 
1737
                stats->rx_errors = cnt->rxerror;
 
1738
                stats->tx_errors = cnt->txerror;
 
1739
                stats->collisions = 0;
 
1740
 
 
1741
                stats->rx_length_errors = 0;
 
1742
                stats->rx_over_errors = cnt->rxoflo;
 
1743
                stats->rx_crc_errors = cnt->rxcrc;
 
1744
                stats->rx_frame_errors = 0;
 
1745
                stats->rx_fifo_errors = cnt->rxoflo;
 
1746
                stats->rx_missed_errors = 0;
 
1747
 
 
1748
                stats->tx_fifo_errors = cnt->txuflo;
 
1749
 
 
1750
                wl->stats_id = id;
 
1751
        }
 
1752
 
 
1753
        return 0;
 
1754
}
 
1755
 
 
1756
struct wl_fw_hdr {
 
1757
        u32 offset;
 
1758
        u32 len;
 
1759
        u32 idx;
 
1760
};
 
1761
 
 
1762
char *wl_firmwares[WL_MAX_FW] = {
 
1763
        "brcm/bcm43xx",
 
1764
        NULL
 
1765
};
 
1766
 
 
1767
/*
 
1768
 * precondition: perimeter lock has been acquired
 
1769
 */
 
1770
int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
 
1771
{
 
1772
        int i, entry;
 
1773
        const u8 *pdata;
 
1774
        struct wl_fw_hdr *hdr;
 
1775
        for (i = 0; i < wl->fw.fw_cnt; i++) {
 
1776
                hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
 
1777
                for (entry = 0; entry < wl->fw.hdr_num_entries[i];
 
1778
                     entry++, hdr++) {
 
1779
                        if (hdr->idx == idx) {
 
1780
                                pdata = wl->fw.fw_bin[i]->data + hdr->offset;
 
1781
                                *pbuf = kmalloc(hdr->len, GFP_ATOMIC);
 
1782
                                if (*pbuf == NULL) {
 
1783
                                        WL_ERROR("fail to alloc %d bytes\n",
 
1784
                                                 hdr->len);
 
1785
                                        goto fail;
 
1786
                                }
 
1787
                                memcpy(*pbuf, pdata, hdr->len);
 
1788
                                return 0;
 
1789
                        }
 
1790
                }
 
1791
        }
 
1792
        WL_ERROR("ERROR: ucode buf tag:%d can not be found!\n", idx);
 
1793
        *pbuf = NULL;
 
1794
fail:
 
1795
        return BCME_NOTFOUND;
 
1796
}
 
1797
 
 
1798
/*
 
1799
 * Precondition: Since this function is called in wl_pci_probe() context,
 
1800
 * no locking is required.
 
1801
 */
 
1802
int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
 
1803
{
 
1804
        int i, entry;
 
1805
        const u8 *pdata;
 
1806
        struct wl_fw_hdr *hdr;
 
1807
        for (i = 0; i < wl->fw.fw_cnt; i++) {
 
1808
                hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
 
1809
                for (entry = 0; entry < wl->fw.hdr_num_entries[i];
 
1810
                     entry++, hdr++) {
 
1811
                        if (hdr->idx == idx) {
 
1812
                                pdata = wl->fw.fw_bin[i]->data + hdr->offset;
 
1813
                                ASSERT(hdr->len == 4);
 
1814
                                *data = *((u32 *) pdata);
 
1815
                                return 0;
 
1816
                        }
 
1817
                }
 
1818
        }
 
1819
        WL_ERROR("ERROR: ucode tag:%d can not be found!\n", idx);
 
1820
        return -1;
 
1821
}
 
1822
 
 
1823
/*
 
1824
 * Precondition: Since this function is called in wl_pci_probe() context,
 
1825
 * no locking is required.
 
1826
 */
 
1827
static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
 
1828
{
 
1829
        int status;
 
1830
        struct device *device = &pdev->dev;
 
1831
        char fw_name[100];
 
1832
        int i;
 
1833
 
 
1834
        memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
 
1835
        for (i = 0; i < WL_MAX_FW; i++) {
 
1836
                if (wl_firmwares[i] == NULL)
 
1837
                        break;
 
1838
                sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
 
1839
                        UCODE_LOADER_API_VER);
 
1840
                WL_NONE("request fw %s\n", fw_name);
 
1841
                status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
 
1842
                if (status) {
 
1843
                        WL_ERROR("%s: fail to load firmware %s\n",
 
1844
                                 KBUILD_MODNAME, fw_name);
 
1845
                        return status;
 
1846
                }
 
1847
                WL_NONE("request fw %s\n", fw_name);
 
1848
                sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
 
1849
                        UCODE_LOADER_API_VER);
 
1850
                status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
 
1851
                if (status) {
 
1852
                        WL_ERROR("%s: fail to load firmware %s\n",
 
1853
                                 KBUILD_MODNAME, fw_name);
 
1854
                        return status;
 
1855
                }
 
1856
                wl->fw.hdr_num_entries[i] =
 
1857
                    wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
 
1858
                WL_NONE("request fw %s find: %d entries\n",
 
1859
                        fw_name, wl->fw.hdr_num_entries[i]);
 
1860
        }
 
1861
        wl->fw.fw_cnt = i;
 
1862
        return wl_ucode_data_init(wl);
 
1863
}
 
1864
 
 
1865
/*
 
1866
 * precondition: can both be called locked and unlocked
 
1867
 */
 
1868
void wl_ucode_free_buf(void *p)
 
1869
{
 
1870
        kfree(p);
 
1871
}
 
1872
 
 
1873
/*
 
1874
 * Precondition: Since this function is called in wl_pci_probe() context,
 
1875
 * no locking is required.
 
1876
 */
 
1877
static void wl_release_fw(struct wl_info *wl)
 
1878
{
 
1879
        int i;
 
1880
        for (i = 0; i < WL_MAX_FW; i++) {
 
1881
                release_firmware(wl->fw.fw_bin[i]);
 
1882
                release_firmware(wl->fw.fw_hdr[i]);
 
1883
        }
 
1884
}
 
1885
 
 
1886
 
 
1887
/*
 
1888
 * checks validity of all firmware images loaded from user space
 
1889
 *
 
1890
 * Precondition: Since this function is called in wl_pci_probe() context,
 
1891
 * no locking is required.
 
1892
 */
 
1893
int wl_check_firmwares(struct wl_info *wl)
 
1894
{
 
1895
        int i;
 
1896
        int entry;
 
1897
        int rc = 0;
 
1898
        const struct firmware *fw;
 
1899
        const struct firmware *fw_hdr;
 
1900
        struct wl_fw_hdr *ucode_hdr;
 
1901
        for (i = 0; i < WL_MAX_FW && rc == 0; i++) {
 
1902
                fw =  wl->fw.fw_bin[i];
 
1903
                fw_hdr = wl->fw.fw_hdr[i];
 
1904
                if (fw == NULL && fw_hdr == NULL) {
 
1905
                        break;
 
1906
                } else if (fw == NULL || fw_hdr == NULL) {
 
1907
                        WL_ERROR("%s: invalid bin/hdr fw\n", __func__);
 
1908
                        rc = -EBADF;
 
1909
                } else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
 
1910
                        WL_ERROR("%s: non integral fw hdr file size %zu/%zu\n",
 
1911
                                 __func__, fw_hdr->size,
 
1912
                                 sizeof(struct wl_fw_hdr));
 
1913
                        rc = -EBADF;
 
1914
                } else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
 
1915
                        WL_ERROR("%s: out of bounds fw file size %zu\n",
 
1916
                                 __func__, fw->size);
 
1917
                        rc = -EBADF;
 
1918
                } else {
 
1919
                        /* check if ucode section overruns firmware image */
 
1920
                        ucode_hdr = (struct wl_fw_hdr *)fw_hdr->data;
 
1921
                        for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
 
1922
                             !rc; entry++, ucode_hdr++) {
 
1923
                                if (ucode_hdr->offset + ucode_hdr->len >
 
1924
                                    fw->size) {
 
1925
                                        WL_ERROR("%s: conflicting bin/hdr\n",
 
1926
                                                 __func__);
 
1927
                                        rc = -EBADF;
 
1928
                                }
 
1929
                        }
 
1930
                }
 
1931
        }
 
1932
        if (rc == 0 && wl->fw.fw_cnt != i) {
 
1933
                WL_ERROR("%s: invalid fw_cnt=%d\n", __func__, wl->fw.fw_cnt);
 
1934
                rc = -EBADF;
 
1935
        }
 
1936
        return rc;
 
1937
}
 
1938
 
 
1939
/*
 
1940
 * precondition: perimeter lock has been acquired
 
1941
 */
 
1942
bool wl_rfkill_set_hw_state(struct wl_info *wl)
 
1943
{
 
1944
        bool blocked = wlc_check_radio_disabled(wl->wlc);
 
1945
 
 
1946
        WL_NONE("%s: update hw state: blocked=%s\n", __func__,
 
1947
                blocked ? "true" : "false");
 
1948
        WL_UNLOCK(wl);
 
1949
        wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
 
1950
        if (blocked)
 
1951
                wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
 
1952
        WL_LOCK(wl);
 
1953
        return blocked;
 
1954
}