~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

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