]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/staging/brcm80211/brcmsmac/main.c
staging: brcm80211: use static qualifier for local symbols in brcmsmac
[mirror_ubuntu-bionic-kernel.git] / drivers / staging / brcm80211 / brcmsmac / main.c
CommitLineData
a9533e7e
HP
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 */
3bec7bb9 16
be1c09f9 17#include <linux/pci_ids.h>
5973f660 18#include <linux/if_ether.h>
45575664 19#include <net/mac80211.h>
cc3cea5a 20#include <brcm_hw_ids.h>
27302e8f 21#include <aiutils.h>
8702fee6 22#include <chipcommon.h>
cc3cea5a
RV
23#include "rate.h"
24#include "scb.h"
cc3cea5a
RV
25#include "phy/phy_hal.h"
26#include "channel.h"
cc3cea5a
RV
27#include "antsel.h"
28#include "stf.h"
29#include "ampdu.h"
30#include "alloc.h"
31#include "mac80211_if.h"
8702fee6 32#include "ucode_loader.h"
3bec7bb9 33#include "main.h"
8c2c8216 34
8702fee6 35
35af8764
AS
36/*
37 * WPA(2) definitions
38 */
39#define RSN_CAP_4_REPLAY_CNTRS 2
40#define RSN_CAP_16_REPLAY_CNTRS 3
41
42#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS
43#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS
44
70dfb584
AS
45/*
46 * Indication for txflowcontrol that all priority bits in
47 * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
48 */
49#define ALLPRIO -1
50
a9533e7e 51/*
a9533e7e
HP
52 * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
53 */
3726ed4d 54#define SSID_FMT_BUF_LEN ((4 * IEEE80211_MAX_SSID_LEN) + 1)
a9533e7e 55
419ad34e
AS
56/* watchdog timer, in unit of ms */
57#define TIMER_INTERVAL_WATCHDOG 1000
58/* radio monitor timer, in unit of ms */
59#define TIMER_INTERVAL_RADIOCHK 800
a9533e7e 60
7c783cef
RV
61/* Max MPC timeout, in unit of watchdog */
62#ifndef BRCMS_MPC_MAX_DELAYCNT
63#define BRCMS_MPC_MAX_DELAYCNT 10
a9533e7e 64#endif
7c783cef
RV
65
66/* Min MPC timeout, in unit of watchdog */
67#define BRCMS_MPC_MIN_DELAYCNT 1
68#define BRCMS_MPC_THRESHOLD 3 /* MPC count threshold level */
a9533e7e 69
419ad34e
AS
70/* beacon interval, in unit of 1024TU */
71#define BEACON_INTERVAL_DEFAULT 100
72/* DTIM interval, in unit of beacon interval */
73#define DTIM_INTERVAL_DEFAULT 3
a9533e7e
HP
74
75/* Scale down delays to accommodate QT slow speed */
419ad34e
AS
76/* beacon interval, in unit of 1024TU */
77#define BEACON_INTERVAL_DEF_QT 20
78/* DTIM interval, in unit of beacon interval */
79#define DTIM_INTERVAL_DEF_QT 1
a9533e7e
HP
80
81#define TBTT_ALIGN_LEEWAY_US 100 /* min leeway before first TBTT in us */
82
434c14ef
RV
83/* Software feature flag defines used by wlfeatureflag */
84#define WL_SWFL_NOHWRADIO 0x0004
85#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */
86#define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */
87
88/* n-mode support capability */
89/* 2x2 includes both 1x1 & 2x2 devices
90 * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
91 * control it independently
92 */
93#define WL_11N_2x2 1
94#define WL_11N_3x3 3
95#define WL_11N_4x4 4
96
97/* define 11n feature disable flags */
98#define WLFEATURE_DISABLE_11N 0x00000001
99#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002
100#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004
101#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008
102#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010
103#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
104#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
105#define WLFEATURE_DISABLE_11N_GF 0x00000080
106
9152bf26
RV
107#define EDCF_ACI_MASK 0x60
108#define EDCF_ACI_SHIFT 5
109#define EDCF_ECWMIN_MASK 0x0f
110#define EDCF_ECWMAX_SHIFT 4
111#define EDCF_AIFSN_MASK 0x0f
112#define EDCF_AIFSN_MAX 15
113#define EDCF_ECWMAX_MASK 0xf0
114
115#define EDCF_AC_BE_TXOP_STA 0x0000
116#define EDCF_AC_BK_TXOP_STA 0x0000
117#define EDCF_AC_VO_ACI_STA 0x62
118#define EDCF_AC_VO_ECW_STA 0x32
119#define EDCF_AC_VI_ACI_STA 0x42
120#define EDCF_AC_VI_ECW_STA 0x43
121#define EDCF_AC_BK_ECW_STA 0xA4
122#define EDCF_AC_VI_TXOP_STA 0x005e
123#define EDCF_AC_VO_TXOP_STA 0x002f
124#define EDCF_AC_BE_ACI_STA 0x03
125#define EDCF_AC_BE_ECW_STA 0xA4
126#define EDCF_AC_BK_ACI_STA 0x27
127#define EDCF_AC_VO_TXOP_AP 0x002f
128
129#define EDCF_TXOP2USEC(txop) ((txop) << 5)
130#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1)
131
132#define APHY_SYMBOL_TIME 4
133#define APHY_PREAMBLE_TIME 16
134#define APHY_SIGNAL_TIME 4
135#define APHY_SIFS_TIME 16
136#define APHY_SERVICE_NBITS 16
137#define APHY_TAIL_NBITS 6
138#define BPHY_SIFS_TIME 10
139#define BPHY_PLCP_SHORT_TIME 96
140
141#define PREN_PREAMBLE 24
142#define PREN_MM_EXT 12
143#define PREN_PREAMBLE_EXT 4
144
145#define DOT11_MAC_HDR_LEN 24
146#define DOT11_ACK_LEN 10
147#define DOT11_BA_LEN 4
148#define DOT11_OFDM_SIGNAL_EXTENSION 6
149#define DOT11_MIN_FRAG_LEN 256
150#define DOT11_RTS_LEN 16
151#define DOT11_CTS_LEN 10
152#define DOT11_BA_BITMAP_LEN 128
153#define DOT11_MIN_BEACON_PERIOD 1
154#define DOT11_MAX_BEACON_PERIOD 0xFFFF
155#define DOT11_MAXNUMFRAGS 16
156#define DOT11_MAX_FRAG_LEN 2346
157
158#define BPHY_PLCP_TIME 192
159#define RIFS_11N_TIME 2
160
161#define WME_VER 1
162#define WME_SUBTYPE_PARAM_IE 1
163#define WME_TYPE 2
164#define WME_OUI "\x00\x50\xf2"
165
166#define AC_BE 0
167#define AC_BK 1
168#define AC_VI 2
169#define AC_VO 3
170
a9533e7e 171/*
419ad34e
AS
172 * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s
173 * OS timer(soft watchdog) it is not a wall clock and won't increment when
174 * driver is in "down" state this low resolution driver tick can be used
175 * for maintenance tasks such as phy calibration and scb update
a9533e7e
HP
176 */
177
419ad34e
AS
178/*
179 * To inform the ucode of the last mcast frame posted
180 * so that it can clear moredata bit
181 */
c654fce6 182#define BCMCFID(wlc, fid) brcms_b_write_shm((wlc)->hw, M_BCMC_FID, (fid))
a9533e7e 183
821e4e93 184#define BRCMS_WAR16165(wlc) ((!AP_ENAB(wlc->pub)) && (wlc->war16165))
a9533e7e 185
a9533e7e 186/* Find basic rate for a given rate */
419ad34e
AS
187#define BRCMS_BASIC_RATE(wlc, rspec) \
188 (IS_MCS(rspec) \
189 ? (wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] \
190 : (wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
a9533e7e 191
419ad34e
AS
192#define FRAMETYPE(r, mimoframe) \
193 (IS_MCS(r) ? mimoframe : (IS_CCK(r) ? FT_CCK : FT_OFDM))
a9533e7e 194
419ad34e
AS
195/* rfdisable delay timer 500 ms, runs of ALP clock */
196#define RFDISABLE_DEFAULT 10000000
a9533e7e 197
7c783cef 198#define BRCMS_TEMPSENSE_PERIOD 10 /* 10 second timeout */
a9533e7e
HP
199
200#define SCAN_IN_PROGRESS(x) 0
201
4766ae6c
BR
202#define EPI_VERSION_NUM 0x054b0b00
203
a9533e7e
HP
204/* precedences numbers for wlc queues. These are twice as may levels as
205 * 802.1D priorities.
206 * Odd numbers are used for HI priority traffic at same precedence levels
419ad34e
AS
207 * These constants are used ONLY by wlc_prio2prec_map. Do not use them
208 * elsewhere.
a9533e7e 209 */
7c783cef
RV
210#define _BRCMS_PREC_NONE 0 /* None = - */
211#define _BRCMS_PREC_BK 2 /* BK - Background */
212#define _BRCMS_PREC_BE 4 /* BE - Best-effort */
213#define _BRCMS_PREC_EE 6 /* EE - Excellent-effort */
214#define _BRCMS_PREC_CL 8 /* CL - Controlled Load */
215#define _BRCMS_PREC_VI 10 /* Vi - Video */
216#define _BRCMS_PREC_VO 12 /* Vo - Voice */
217#define _BRCMS_PREC_NC 14 /* NC - Network Control */
a9533e7e 218
b745b6bb 219#define MAXMACLIST 64 /* max # source MAC matches */
8a76f1ee 220#define BCN_TEMPLATE_COUNT 2
b745b6bb 221
7c783cef
RV
222/* The BSS is generating beacons in HW */
223#define BRCMS_BSSCFG_HW_BCN 0x20
b745b6bb 224
7c783cef 225#define HWBCN_ENAB(cfg) (((cfg)->flags & BRCMS_BSSCFG_HW_BCN) != 0)
b745b6bb
RV
226
227#define MBSS_BCN_ENAB(cfg) 0
228#define MBSS_PRB_ENAB(cfg) 0
229#define SOFTBCN_ENAB(pub) (0)
230
8702fee6 231#define SYNTHPU_DLY_APHY_US 3700 /* a phy synthpu_dly time in us */
419ad34e
AS
232#define SYNTHPU_DLY_BPHY_US 1050 /* b/g phy synthpu_dly time in us */
233#define SYNTHPU_DLY_NPHY_US 2048 /* n phy REV3 synthpu_dly time in us */
8702fee6
RV
234#define SYNTHPU_DLY_LPPHY_US 300 /* lpphy synthpu_dly time in us */
235
236#define SYNTHPU_DLY_PHY_US_QT 100 /* QT synthpu_dly time in us */
237
238#define ANTCNT 10 /* vanilla M_MAX_ANTCNT value */
239
240#define DMAREG(wlc_hw, direction, fifonum) \
241 ((direction == DMA_TX) ? \
7b1cbc1d
RV
242 &(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
243 &(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
8702fee6
RV
244
245#define APHY_SLOT_TIME 9
246#define BPHY_SLOT_TIME 20
247
248/*
249 * The following table lists the buffer memory allocated to xmt fifos in HW.
250 * the size is in units of 256bytes(one block), total size is HW dependent
251 * ucode has default fifo partition, sw can overwrite if necessary
252 *
253 * This is documented in twiki under the topic UcodeTxFifo. Please ensure
254 * the twiki is updated before making changes.
255 */
256
419ad34e
AS
257/* Starting corerev for the fifo size table */
258#define XMTFIFOTBL_STARTREV 20
a9533e7e 259
b745b6bb
RV
260/* Check if a particular BSS config is AP or STA */
261#define BSSCFG_AP(cfg) (0)
262#define BSSCFG_STA(cfg) (1)
263#define BSSCFG_IBSS(cfg) (!(cfg)->BSS)
264
49552d33 265/* iterate through all valid bsscfg entries */
b745b6bb 266#define FOREACH_BSS(wlc, idx, cfg) \
49552d33
AS
267 for (idx = 0; (int) idx < BRCMS_MAXBSSCFG; idx++) { \
268 cfg = (wlc)->bsscfg[idx]; \
269 if (!cfg) \
270 continue;
271/* close marker for iterator code block */
272#define END_FOREACH_BSS() }
b745b6bb 273
a9533e7e
HP
274/* Shared memory location index for various AC params */
275#define wme_shmemacindex(ac) wme_ac2fifo[ac]
276
a9533e7e 277/* currently the best mechanism for determining SIFS is the band in use */
7c783cef
RV
278#define SIFS(band) ((band)->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME : \
279 BPHY_SIFS_TIME);
a9533e7e 280
8702fee6
RV
281/* dup state between BMAC(struct brcms_hardware) and HIGH(struct brcms_c_info)
282 driver */
283struct brcms_b_state {
284 u32 machwcap; /* mac hw capibility */
285 u32 preamble_ovr; /* preamble override */
286};
287
8702fee6
RV
288const u8 prio2fifo[NUMPRIO] = {
289 TX_AC_BE_FIFO, /* 0 BE AC_BE Best Effort */
290 TX_AC_BK_FIFO, /* 1 BK AC_BK Background */
291 TX_AC_BK_FIFO, /* 2 -- AC_BK Background */
292 TX_AC_BE_FIFO, /* 3 EE AC_BE Best Effort */
293 TX_AC_VI_FIFO, /* 4 CL AC_VI Video */
294 TX_AC_VI_FIFO, /* 5 VI AC_VI Video */
295 TX_AC_VO_FIFO, /* 6 VO AC_VO Voice */
296 TX_AC_VO_FIFO /* 7 NC AC_VO Voice */
297};
298
299/* debug/trace */
300uint brcm_msg_level =
301#if defined(BCMDBG)
302 LOG_ERROR_VAL;
303#else
304 0;
305#endif /* BCMDBG */
306
307/* TX FIFO number to WME/802.1E Access Category */
308const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
309
310/* WME/802.1E Access Category to TX FIFO number */
311static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
312
313static bool in_send_q;
314
315/* 802.1D Priority to precedence queue mapping */
316const u8 wlc_prio2prec_map[] = {
317 _BRCMS_PREC_BE, /* 0 BE - Best-effort */
318 _BRCMS_PREC_BK, /* 1 BK - Background */
319 _BRCMS_PREC_NONE, /* 2 None = - */
320 _BRCMS_PREC_EE, /* 3 EE - Excellent-effort */
321 _BRCMS_PREC_CL, /* 4 CL - Controlled Load */
322 _BRCMS_PREC_VI, /* 5 Vi - Video */
323 _BRCMS_PREC_VO, /* 6 Vo - Voice */
324 _BRCMS_PREC_NC, /* 7 NC - Network Control */
325};
326
327static u16 xmtfifo_sz[][NFIFO] = {
419ad34e
AS
328 /* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
329 {20, 192, 192, 21, 17, 5},
330 /* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
331 {9, 58, 22, 14, 14, 5},
332 /* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
333 {20, 192, 192, 21, 17, 5},
334 /* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
335 {20, 192, 192, 21, 17, 5},
336 /* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
337 {9, 58, 22, 14, 14, 5},
8702fee6
RV
338};
339
340static const u8 acbitmap2maxprio[] = {
341 PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
342 PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
343 PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
344 PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
345};
346
347#ifdef BCMDBG
348static const char * const fifo_names[] = {
349 "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
350#else
351static const char fifo_names[6][0];
352#endif
353
354#ifdef BCMDBG
355/* pointer to most recently allocated wl/wlc */
356static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
357#endif
358
8702fee6
RV
359/*
360 * Update the slot timing for standard 11b/g (20us slots)
361 * or shortslot 11g (9us slots)
362 * The PSM needs to be suspended for this call.
363 */
364static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
365 bool shortslot)
366{
0da64910 367 struct d11regs *regs;
8702fee6
RV
368
369 regs = wlc_hw->regs;
370
371 if (shortslot) {
372 /* 11g short slot: 11a timing */
373 W_REG(&regs->ifs_slot, 0x0207); /* APHY_SLOT_TIME */
374 brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
375 } else {
376 /* 11g long slot: 11b timing */
377 W_REG(&regs->ifs_slot, 0x0212); /* BPHY_SLOT_TIME */
378 brcms_b_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
379 }
380}
381
2682e2a3
AS
382static void brcms_c_write_inits(struct brcms_hardware *wlc_hw,
383 const struct d11init *inits)
384{
385 int i;
386 u8 *base;
387 u8 *addr;
388 u16 size;
389 u32 value;
390
391 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
392
393 base = (u8 *)wlc_hw->regs;
394
395 for (i = 0; inits[i].addr != 0xffff; i++) {
396 size = le16_to_cpu(inits[i].size);
397 addr = base + le16_to_cpu(inits[i].addr);
398 value = le32_to_cpu(inits[i].value);
399 if (size == 2)
400 W_REG((u16 *)addr, value);
401 else if (size == 4)
402 W_REG((u32 *)addr, value);
403 else
404 break;
405 }
406}
407
408static void brcms_c_write_mhf(struct brcms_hardware *wlc_hw, u16 *mhfs)
409{
410 u8 idx;
411 u16 addr[] = {
412 M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
413 M_HOST_FLAGS5
414 };
415
416 for (idx = 0; idx < MHFMAX; idx++)
417 brcms_b_write_shm(wlc_hw, addr[idx], mhfs[idx]);
418}
419
8702fee6
RV
420static void brcms_c_ucode_bsinit(struct brcms_hardware *wlc_hw)
421{
422 struct wiphy *wiphy = wlc_hw->wlc->wiphy;
423
424 /* init microcode host flags */
425 brcms_c_write_mhf(wlc_hw, wlc_hw->band->mhfs);
426
427 /* do band-specific ucode IHR, SHM, and SCR inits */
428 if (D11REV_IS(wlc_hw->corerev, 23)) {
8ea54c9f 429 if (BRCMS_ISNPHY(wlc_hw->band))
8702fee6 430 brcms_c_write_inits(wlc_hw, d11n0bsinitvals16);
8ea54c9f 431 else
8702fee6
RV
432 wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
433 " %d\n", __func__, wlc_hw->unit,
434 wlc_hw->corerev);
8702fee6
RV
435 } else {
436 if (D11REV_IS(wlc_hw->corerev, 24)) {
8ea54c9f 437 if (BRCMS_ISLCNPHY(wlc_hw->band))
8702fee6
RV
438 brcms_c_write_inits(wlc_hw,
439 d11lcn0bsinitvals24);
8ea54c9f 440 else
8702fee6
RV
441 wiphy_err(wiphy, "%s: wl%d: unsupported phy in"
442 " core rev %d\n", __func__,
443 wlc_hw->unit, wlc_hw->corerev);
444 } else {
445 wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
446 __func__, wlc_hw->unit, wlc_hw->corerev);
447 }
448 }
449}
450
2682e2a3
AS
451static void brcms_b_core_phy_clk(struct brcms_hardware *wlc_hw, bool clk)
452{
453 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: clk %d\n", wlc_hw->unit, clk);
454
455 wlc_hw->phyclk = clk;
456
457 if (OFF == clk) { /* clear gmode bit, put phy into reset */
458
459 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
460 (SICF_PRST | SICF_FGC));
461 udelay(1);
462 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
463 udelay(1);
464
465 } else { /* take phy out of reset */
466
467 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
468 udelay(1);
469 ai_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
470 udelay(1);
471
472 }
473}
474
8702fee6
RV
475/* switch to new band but leave it inactive */
476static u32 brcms_c_setband_inact(struct brcms_c_info *wlc, uint bandunit)
477{
478 struct brcms_hardware *wlc_hw = wlc->hw;
479 u32 macintmask;
480
481 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
482
483 WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
484
485 /* disable interrupts */
486 macintmask = brcms_intrsoff(wlc->wl);
487
488 /* radio off */
489 wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
490
491 brcms_b_core_phy_clk(wlc_hw, OFF);
492
493 brcms_c_setxband(wlc_hw, bandunit);
494
495 return macintmask;
496}
497
498/* Process received frames */
499/*
500 * Return true if more frames need to be processed. false otherwise.
501 * Param 'bound' indicates max. # frames to process before break out.
502 */
503static bool
504brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
505{
506 struct sk_buff *p;
507 struct sk_buff *head = NULL;
508 struct sk_buff *tail = NULL;
509 uint n = 0;
510 uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
511 struct brcms_d11rxhdr *wlc_rxhdr = NULL;
512
513 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
514 /* gather received frames */
515 while ((p = dma_rx(wlc_hw->di[fifo]))) {
516
517 if (!tail)
518 head = tail = p;
519 else {
520 tail->prev = p;
521 tail = p;
522 }
523
524 /* !give others some time to run! */
525 if (++n >= bound_limit)
526 break;
527 }
528
529 /* post more rbufs */
530 dma_rxfill(wlc_hw->di[fifo]);
531
532 /* process each frame */
533 while ((p = head) != NULL) {
534 head = head->prev;
535 p->prev = NULL;
536
537 wlc_rxhdr = (struct brcms_d11rxhdr *) p->data;
538
419ad34e
AS
539 /*
540 * compute the RSSI from d11rxhdr and record it in wlc_rxd11hr
541 */
8702fee6
RV
542 wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
543
544 brcms_c_recv(wlc_hw->wlc, p);
545 }
546
547 return n >= bound_limit;
548}
549
839f9f62
RV
550static bool
551brcms_b_dotxstatus(struct brcms_hardware *wlc_hw, struct tx_status *txs,
552 u32 s2)
553{
554 /* discard intermediate indications for ucode with one legitimate case:
419ad34e
AS
555 * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
556 * but the subsequent tx of DATA failed. so it will start rts/cts from
557 * the beginning (resetting the rts transmission count)
839f9f62
RV
558 */
559 if (!(txs->status & TX_STATUS_AMPDU)
8ea54c9f 560 && (txs->status & TX_STATUS_INTERMEDIATE))
839f9f62 561 return false;
839f9f62
RV
562
563 return brcms_c_dotxstatus(wlc_hw->wlc, txs, s2);
564}
565
566/* process tx completion events in BMAC
567 * Return true if more tx status need to be processed. false otherwise.
568 */
569static bool
570brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal)
571{
572 bool morepending = false;
573 struct brcms_c_info *wlc = wlc_hw->wlc;
0da64910 574 struct d11regs *regs;
839f9f62
RV
575 struct tx_status txstatus, *txs;
576 u32 s1, s2;
577 uint n = 0;
578 /*
579 * Param 'max_tx_num' indicates max. # tx status to process before
580 * break out.
581 */
582 uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
583
584 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
585
586 txs = &txstatus;
587 regs = wlc_hw->regs;
588 while (!(*fatal)
589 && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
590
591 if (s1 == 0xffffffff) {
592 wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n",
593 wlc_hw->unit, __func__);
594 return morepending;
595 }
596
597 s2 = R_REG(&regs->frmtxstatus2);
598
599 txs->status = s1 & TXS_STATUS_MASK;
600 txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
601 txs->sequence = s2 & TXS_SEQ_MASK;
602 txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
603 txs->lasttxtime = 0;
604
605 *fatal = brcms_b_dotxstatus(wlc_hw, txs, s2);
606
607 /* !give others some time to run! */
608 if (++n >= max_tx_num)
609 break;
610 }
611
612 if (*fatal)
613 return 0;
614
615 if (n >= max_tx_num)
616 morepending = true;
617
618 if (!pktq_empty(&wlc->pkt_queue->q))
619 brcms_c_send_q(wlc);
620
621 return morepending;
622}
623
2682e2a3
AS
624/* brcms_b_tx_fifo_suspended:
625 * Check the MAC's tx suspend status for a tx fifo.
626 *
627 * When the MAC acknowledges a tx suspend, it indicates that no more
628 * packets will be transmitted out the radio. This is independent of
629 * DMA channel suspension---the DMA may have finished suspending, or may still
630 * be pulling data into a tx fifo, by the time the MAC acks the suspend
631 * request.
632 */
633static bool brcms_b_tx_fifo_suspended(struct brcms_hardware *wlc_hw,
634 uint tx_fifo)
635{
636 /* check that a suspend has been requested and is no longer pending */
637
638 /*
639 * for DMA mode, the suspend request is set in xmtcontrol of the DMA
640 * engine, and the tx fifo suspend at the lower end of the MAC is
641 * acknowledged in the chnstatus register.
642 *
643 * The tx fifo suspend completion is independent of the DMA suspend
644 * completion and may be acked before or after the DMA is suspended.
645 */
646 if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
647 (R_REG(&wlc_hw->regs->chnstatus) &
648 (1 << tx_fifo)) == 0)
649 return true;
650
651 return false;
652}
653
8702fee6
RV
654/* second-level interrupt processing
655 * Return true if another dpc needs to be re-scheduled. false otherwise.
656 * Param 'bounded' indicates if applicable loops should be bounded.
657 */
658bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
659{
660 u32 macintstatus;
661 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 662 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
663 bool fatal = false;
664 struct wiphy *wiphy = wlc->wiphy;
665
666 if (DEVICEREMOVED(wlc)) {
667 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
668 __func__);
669 brcms_down(wlc->wl);
670 return false;
671 }
672
673 /* grab and clear the saved software intstatus bits */
674 macintstatus = wlc->macintstatus;
675 wlc->macintstatus = 0;
676
677 BCMMSG(wlc->wiphy, "wl%d: macintstatus 0x%x\n",
678 wlc_hw->unit, macintstatus);
679
680 WARN_ON(macintstatus & MI_PRQ); /* PRQ Interrupt in non-MBSS */
681
682 /* BCN template is available */
683 /* ZZZ: Use AP_ACTIVE ? */
684 if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub))
8ea54c9f 685 && (macintstatus & MI_BCNTPL))
8702fee6 686 brcms_c_update_beacon(wlc);
8702fee6
RV
687
688 /* tx status */
689 if (macintstatus & MI_TFS) {
690 if (brcms_b_txstatus(wlc->hw, bounded, &fatal))
691 wlc->macintstatus |= MI_TFS;
692 if (fatal) {
693 wiphy_err(wiphy, "MI_TFS: fatal\n");
694 goto fatal;
695 }
696 }
697
698 if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
699 brcms_c_tbtt(wlc);
700
701 /* ATIM window end */
702 if (macintstatus & MI_ATIMWINEND) {
703 BCMMSG(wlc->wiphy, "end of ATIM window\n");
704 OR_REG(&regs->maccommand, wlc->qvalid);
705 wlc->qvalid = 0;
706 }
707
419ad34e
AS
708 /*
709 * received data or control frame, MI_DMAINT is
710 * indication of RX_FIFO interrupt
711 */
8702fee6
RV
712 if (macintstatus & MI_DMAINT)
713 if (brcms_b_recv(wlc_hw, RX_FIFO, bounded))
714 wlc->macintstatus |= MI_DMAINT;
715
716 /* TX FIFO suspend/flush completion */
717 if (macintstatus & MI_TXSTOP)
718 brcms_b_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO);
719
720 /* noise sample collected */
8ea54c9f 721 if (macintstatus & MI_BG_NOISE)
8702fee6 722 wlc_phy_noise_sample_intr(wlc_hw->band->pi);
8702fee6
RV
723
724 if (macintstatus & MI_GP0) {
725 wiphy_err(wiphy, "wl%d: PSM microcode watchdog fired at %d "
726 "(seconds). Resetting.\n", wlc_hw->unit, wlc_hw->now);
727
728 printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
729 __func__, wlc_hw->sih->chip,
730 wlc_hw->sih->chiprev);
731 /* big hammer */
732 brcms_init(wlc->wl);
733 }
734
735 /* gptimer timeout */
8ea54c9f 736 if (macintstatus & MI_TO)
8702fee6 737 W_REG(&regs->gptimer, 0);
8702fee6
RV
738
739 if (macintstatus & MI_RFDISABLE) {
740 BCMMSG(wlc->wiphy, "wl%d: BMAC Detected a change on the"
741 " RF Disable Input\n", wlc_hw->unit);
742 brcms_rfkill_set_hw_state(wlc->wl);
743 }
744
745 /* send any enq'd tx packets. Just makes sure to jump start tx */
746 if (!pktq_empty(&wlc->pkt_queue->q))
747 brcms_c_send_q(wlc);
748
749 /* it isn't done and needs to be resched if macintstatus is non-zero */
750 return wlc->macintstatus != 0;
751
752 fatal:
753 brcms_init(wlc->wl);
754 return wlc->macintstatus != 0;
755}
756
11431424 757static int brcms_b_state_get(struct brcms_hardware *wlc_hw,
8702fee6
RV
758 struct brcms_b_state *state)
759{
760 state->machwcap = wlc_hw->machwcap;
761
762 return 0;
763}
764
2682e2a3
AS
765/* set initial host flags value */
766static void
767brcms_c_mhfdef(struct brcms_c_info *wlc, u16 *mhfs, u16 mhf2_init)
768{
769 struct brcms_hardware *wlc_hw = wlc->hw;
770
771 memset(mhfs, 0, MHFMAX * sizeof(u16));
772
773 mhfs[MHF2] |= mhf2_init;
774
775 /* prohibit use of slowclock on multifunction boards */
776 if (wlc_hw->boardflags & BFL_NOPLLDOWN)
777 mhfs[MHF1] |= MHF1_FORCEFASTCLK;
778
779 if (BRCMS_ISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
780 mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
781 mhfs[MHF1] |= MHF1_IQSWAP_WAR;
782 }
783}
784
8702fee6
RV
785static bool brcms_b_attach_dmapio(struct brcms_c_info *wlc, uint j, bool wme)
786{
787 uint i;
788 char name[8];
419ad34e
AS
789 /*
790 * ucode host flag 2 needed for pio mode, independent of band and fifo
791 */
8702fee6
RV
792 u16 pio_mhf2 = 0;
793 struct brcms_hardware *wlc_hw = wlc->hw;
794 uint unit = wlc_hw->unit;
795 struct brcms_tunables *tune = wlc->pub->tunables;
796 struct wiphy *wiphy = wlc->wiphy;
797
798 /* name and offsets for dma_attach */
799 snprintf(name, sizeof(name), "wl%d", unit);
800
801 if (wlc_hw->di[0] == 0) { /* Init FIFOs */
8702fee6 802 int dma_attach_err = 0;
8702fee6 803
8702fee6
RV
804 /*
805 * FIFO 0
806 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
807 * RX: RX_FIFO (RX data packets)
808 */
809 wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
810 (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
811 NULL), DMAREG(wlc_hw, DMA_RX, 0),
812 (wme ? tune->ntxd : 0), tune->nrxd,
813 tune->rxbufsz, -1, tune->nrxbufpost,
814 BRCMS_HWRXOFF, &brcm_msg_level);
815 dma_attach_err |= (NULL == wlc_hw->di[0]);
816
817 /*
818 * FIFO 1
819 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
820 * (legacy) TX_DATA_FIFO (TX data packets)
821 * RX: UNUSED
822 */
823 wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
824 DMAREG(wlc_hw, DMA_TX, 1), NULL,
825 tune->ntxd, 0, 0, -1, 0, 0,
826 &brcm_msg_level);
827 dma_attach_err |= (NULL == wlc_hw->di[1]);
828
829 /*
830 * FIFO 2
831 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
832 * RX: UNUSED
833 */
834 wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
835 DMAREG(wlc_hw, DMA_TX, 2), NULL,
836 tune->ntxd, 0, 0, -1, 0, 0,
837 &brcm_msg_level);
838 dma_attach_err |= (NULL == wlc_hw->di[2]);
839 /*
840 * FIFO 3
841 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
842 * (legacy) TX_CTL_FIFO (TX control & mgmt packets)
843 */
844 wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
845 DMAREG(wlc_hw, DMA_TX, 3),
846 NULL, tune->ntxd, 0, 0, -1,
847 0, 0, &brcm_msg_level);
848 dma_attach_err |= (NULL == wlc_hw->di[3]);
849/* Cleaner to leave this as if with AP defined */
850
851 if (dma_attach_err) {
852 wiphy_err(wiphy, "wl%d: wlc_attach: dma_attach failed"
853 "\n", unit);
854 return false;
855 }
856
857 /* get pointer to dma engine tx flow control variable */
858 for (i = 0; i < NFIFO; i++)
859 if (wlc_hw->di[i])
860 wlc_hw->txavail[i] =
861 (uint *) dma_getvar(wlc_hw->di[i],
862 "&txavail");
863 }
864
865 /* initial ucode host flags */
866 brcms_c_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
867
868 return true;
869}
870
871static void brcms_b_detach_dmapio(struct brcms_hardware *wlc_hw)
872{
873 uint j;
874
875 for (j = 0; j < NFIFO; j++) {
876 if (wlc_hw->di[j]) {
877 dma_detach(wlc_hw->di[j]);
878 wlc_hw->di[j] = NULL;
879 }
880 }
881}
882
839f9f62
RV
883/*
884 * Initialize brcms_c_info default values ...
885 * may get overrides later in this function
886 * BMAC_NOTES, move low out and resolve the dangling ones
8702fee6 887 */
839f9f62 888static void brcms_b_info_init(struct brcms_hardware *wlc_hw)
8702fee6 889{
839f9f62 890 struct brcms_c_info *wlc = wlc_hw->wlc;
8702fee6 891
839f9f62
RV
892 /* set default sw macintmask value */
893 wlc->defmacintmask = DEF_MACINTMASK;
8702fee6 894
839f9f62
RV
895 /* various 802.11g modes */
896 wlc_hw->shortslot = false;
8702fee6 897
839f9f62
RV
898 wlc_hw->SFBL = RETRY_SHORT_FB;
899 wlc_hw->LFBL = RETRY_LONG_FB;
8702fee6 900
839f9f62
RV
901 /* default mac retry limits */
902 wlc_hw->SRL = RETRY_SHORT_DEF;
903 wlc_hw->LRL = RETRY_LONG_DEF;
904 wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
905}
8702fee6 906
11431424 907static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
839f9f62
RV
908{
909 /* delay before first read of ucode state */
910 udelay(40);
8702fee6 911
839f9f62
RV
912 /* wait until ucode is no longer asleep */
913 SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
914 DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
915}
8702fee6 916
11431424 917static void brcms_b_hw_etheraddr(struct brcms_hardware *wlc_hw, u8 *ea)
8702fee6
RV
918{
919 memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
920}
921
922static int brcms_b_bandtype(struct brcms_hardware *wlc_hw)
923{
924 return wlc_hw->band->bandtype;
925}
926
927/* control chip clock to save power, enable dynamic clock or force fast clock */
928static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode)
929{
930 if (PMUCTL_ENAB(wlc_hw->sih)) {
419ad34e
AS
931 /* new chips with PMU, CCS_FORCEHT will distribute the HT clock
932 * on backplane, but mac core will still run on ALP(not HT) when
933 * it enters powersave mode, which means the FCA bit may not be
934 * set. Should wakeup mac if driver wants it to run on HT.
8702fee6
RV
935 */
936
937 if (wlc_hw->clk) {
938 if (mode == CLK_FAST) {
939 OR_REG(&wlc_hw->regs->clk_ctl_st,
940 CCS_FORCEHT);
941
942 udelay(64);
943
944 SPINWAIT(((R_REG
945 (&wlc_hw->regs->
946 clk_ctl_st) & CCS_HTAVAIL) == 0),
947 PMU_MAX_TRANSITION_DLY);
948 WARN_ON(!(R_REG
949 (&wlc_hw->regs->
950 clk_ctl_st) & CCS_HTAVAIL));
951 } else {
952 if ((wlc_hw->sih->pmurev == 0) &&
953 (R_REG
954 (&wlc_hw->regs->
955 clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
956 SPINWAIT(((R_REG
957 (&wlc_hw->regs->
958 clk_ctl_st) & CCS_HTAVAIL)
959 == 0),
960 PMU_MAX_TRANSITION_DLY);
961 AND_REG(&wlc_hw->regs->clk_ctl_st,
962 ~CCS_FORCEHT);
963 }
964 }
965 wlc_hw->forcefastclk = (mode == CLK_FAST);
966 } else {
967
968 /* old chips w/o PMU, force HT through cc,
969 * then use FCA to verify mac is running fast clock
970 */
971
972 wlc_hw->forcefastclk = ai_clkctl_cc(wlc_hw->sih, mode);
973
974 /* check fast clock is available (if core is not in reset) */
975 if (wlc_hw->forcefastclk && wlc_hw->clk)
976 WARN_ON(!(ai_core_sflags(wlc_hw->sih, 0, 0) &
977 SISF_FCLKA));
978
419ad34e
AS
979 /*
980 * keep the ucode wake bit on if forcefastclk is on since we
981 * do not want ucode to put us back to slow clock when it dozes
982 * for PM mode. Code below matches the wake override bit with
983 * current forcefastclk state. Only setting bit in wake_override
984 * instead of waking ucode immediately since old code had this
985 * behavior. Older code set wlc->forcefastclk but only had the
986 * wake happen if the wakup_ucode work (protected by an up
987 * check) was executed just below.
8702fee6
RV
988 */
989 if (wlc_hw->forcefastclk)
990 mboolset(wlc_hw->wake_override,
991 BRCMS_WAKE_OVERRIDE_FORCEFAST);
992 else
993 mboolclr(wlc_hw->wake_override,
994 BRCMS_WAKE_OVERRIDE_FORCEFAST);
995 }
996}
997
8702fee6
RV
998/* set or clear ucode host flag bits
999 * it has an optimization for no-change write
1000 * it only writes through shared memory when the core has clock;
1001 * pre-CLK changes should use wlc_write_mhf to get around the optimization
1002 *
1003 *
1004 * bands values are: BRCM_BAND_AUTO <--- Current band only
1005 * BRCM_BAND_5G <--- 5G band only
1006 * BRCM_BAND_2G <--- 2G band only
1007 * BRCM_BAND_ALL <--- All bands
1008 */
1009void
1010brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val,
1011 int bands)
1012{
1013 u16 save;
1014 u16 addr[MHFMAX] = {
1015 M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
1016 M_HOST_FLAGS5
1017 };
1018 struct brcms_hw_band *band;
1019
1020 if ((val & ~mask) || idx >= MHFMAX)
1021 return; /* error condition */
1022
1023 switch (bands) {
1024 /* Current band only or all bands,
1025 * then set the band to current band
1026 */
1027 case BRCM_BAND_AUTO:
1028 case BRCM_BAND_ALL:
1029 band = wlc_hw->band;
1030 break;
1031 case BRCM_BAND_5G:
1032 band = wlc_hw->bandstate[BAND_5G_INDEX];
1033 break;
1034 case BRCM_BAND_2G:
1035 band = wlc_hw->bandstate[BAND_2G_INDEX];
1036 break;
1037 default:
1038 band = NULL; /* error condition */
1039 }
1040
1041 if (band) {
1042 save = band->mhfs[idx];
1043 band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
1044
1045 /* optimization: only write through if changed, and
1046 * changed band is the current band
1047 */
1048 if (wlc_hw->clk && (band->mhfs[idx] != save)
1049 && (band == wlc_hw->band))
1050 brcms_b_write_shm(wlc_hw, addr[idx],
1051 (u16) band->mhfs[idx]);
1052 }
1053
1054 if (bands == BRCM_BAND_ALL) {
1055 wlc_hw->bandstate[0]->mhfs[idx] =
1056 (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
1057 wlc_hw->bandstate[1]->mhfs[idx] =
1058 (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
1059 }
1060}
1061
8702fee6
RV
1062/* set the maccontrol register to desired reset state and
1063 * initialize the sw cache of the register
1064 */
1065static void brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
1066{
1067 /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
1068 wlc_hw->maccontrol = 0;
1069 wlc_hw->suspended_fifos = 0;
1070 wlc_hw->wake_override = 0;
1071 wlc_hw->mute_override = 0;
1072 brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
1073}
1074
2682e2a3
AS
1075/*
1076 * write the software state of maccontrol and
1077 * overrides to the maccontrol register
1078 */
1079static void brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
1080{
1081 u32 maccontrol = wlc_hw->maccontrol;
1082
1083 /* OR in the wake bit if overridden */
1084 if (wlc_hw->wake_override)
1085 maccontrol |= MCTL_WAKE;
1086
1087 /* set AP and INFRA bits for mute if needed */
1088 if (wlc_hw->mute_override) {
1089 maccontrol &= ~(MCTL_AP);
1090 maccontrol |= MCTL_INFRA;
1091 }
1092
1093 W_REG(&wlc_hw->regs->maccontrol, maccontrol);
1094}
1095
8702fee6
RV
1096/* set or clear maccontrol bits */
1097void brcms_b_mctrl(struct brcms_hardware *wlc_hw, u32 mask, u32 val)
1098{
1099 u32 maccontrol;
1100 u32 new_maccontrol;
1101
1102 if (val & ~mask)
1103 return; /* error condition */
1104 maccontrol = wlc_hw->maccontrol;
1105 new_maccontrol = (maccontrol & ~mask) | val;
1106
1107 /* if the new maccontrol value is the same as the old, nothing to do */
1108 if (new_maccontrol == maccontrol)
1109 return;
1110
1111 /* something changed, cache the new value */
1112 wlc_hw->maccontrol = new_maccontrol;
1113
1114 /* write the new values with overrides applied */
1115 brcms_c_mctrl_write(wlc_hw);
1116}
1117
8702fee6
RV
1118void brcms_c_ucode_wake_override_set(struct brcms_hardware *wlc_hw,
1119 u32 override_bit)
1120{
1121 if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
1122 mboolset(wlc_hw->wake_override, override_bit);
1123 return;
1124 }
1125
1126 mboolset(wlc_hw->wake_override, override_bit);
1127
1128 brcms_c_mctrl_write(wlc_hw);
1129 brcms_b_wait_for_wake(wlc_hw);
1130
1131 return;
1132}
1133
1134void brcms_c_ucode_wake_override_clear(struct brcms_hardware *wlc_hw,
1135 u32 override_bit)
1136{
1137 mboolclr(wlc_hw->wake_override, override_bit);
1138
1139 if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
1140 return;
1141
1142 brcms_c_mctrl_write(wlc_hw);
1143
1144 return;
1145}
1146
1147/* When driver needs ucode to stop beaconing, it has to make sure that
1148 * MCTL_AP is clear and MCTL_INFRA is set
1149 * Mode MCTL_AP MCTL_INFRA
1150 * AP 1 1
1151 * STA 0 1 <--- This will ensure no beacons
1152 * IBSS 0 0
1153 */
1154static void brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
1155{
1156 wlc_hw->mute_override = 1;
1157
1158 /* if maccontrol already has AP == 0 and INFRA == 1 without this
1159 * override, then there is no change to write
1160 */
1161 if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
1162 return;
1163
1164 brcms_c_mctrl_write(wlc_hw);
1165
1166 return;
1167}
1168
1169/* Clear the override on AP and INFRA bits */
1170static void brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
1171{
1172 if (wlc_hw->mute_override == 0)
1173 return;
1174
1175 wlc_hw->mute_override = 0;
1176
1177 /* if maccontrol already has AP == 0 and INFRA == 1 without this
1178 * override, then there is no change to write
1179 */
1180 if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
1181 return;
1182
1183 brcms_c_mctrl_write(wlc_hw);
1184}
1185
1186/*
1187 * Write a MAC address to the given match reg offset in the RXE match engine.
1188 */
11431424 1189static void
8702fee6
RV
1190brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset,
1191 const u8 *addr)
1192{
0da64910 1193 struct d11regs *regs;
8702fee6
RV
1194 u16 mac_l;
1195 u16 mac_m;
1196 u16 mac_h;
1197
1198 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: brcms_b_set_addrmatch\n",
1199 wlc_hw->unit);
1200
1201 regs = wlc_hw->regs;
1202 mac_l = addr[0] | (addr[1] << 8);
1203 mac_m = addr[2] | (addr[3] << 8);
1204 mac_h = addr[4] | (addr[5] << 8);
1205
1206 /* enter the MAC addr into the RXE match registers */
1207 W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
1208 W_REG(&regs->rcm_mat_data, mac_l);
1209 W_REG(&regs->rcm_mat_data, mac_m);
1210 W_REG(&regs->rcm_mat_data, mac_h);
1211
1212}
1213
1214void
1215brcms_b_write_template_ram(struct brcms_hardware *wlc_hw, int offset, int len,
1216 void *buf)
1217{
0da64910 1218 struct d11regs *regs;
8702fee6
RV
1219 u32 word;
1220 bool be_bit;
1221 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1222
1223 regs = wlc_hw->regs;
1224 W_REG(&regs->tplatewrptr, offset);
1225
1226 /* if MCTL_BIGEND bit set in mac control register,
1227 * the chip swaps data in fifo, as well as data in
1228 * template ram
1229 */
1230 be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
1231
1232 while (len > 0) {
1233 memcpy(&word, buf, sizeof(u32));
1234
1235 if (be_bit)
1236 word = cpu_to_be32(word);
1237 else
1238 word = cpu_to_le32(word);
1239
1240 W_REG(&regs->tplatewrdata, word);
1241
1242 buf = (u8 *) buf + sizeof(u32);
1243 len -= sizeof(u32);
1244 }
1245}
1246
11431424 1247static void brcms_b_set_cwmin(struct brcms_hardware *wlc_hw, u16 newmin)
8702fee6
RV
1248{
1249 wlc_hw->band->CWmin = newmin;
1250
1251 W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
1252 (void)R_REG(&wlc_hw->regs->objaddr);
1253 W_REG(&wlc_hw->regs->objdata, newmin);
1254}
1255
11431424 1256static void brcms_b_set_cwmax(struct brcms_hardware *wlc_hw, u16 newmax)
8702fee6
RV
1257{
1258 wlc_hw->band->CWmax = newmax;
1259
1260 W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
1261 (void)R_REG(&wlc_hw->regs->objaddr);
1262 W_REG(&wlc_hw->regs->objdata, newmax);
1263}
1264
1265void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw)
1266{
1267 bool fastclk;
1268
1269 /* request FAST clock if not on */
1270 fastclk = wlc_hw->forcefastclk;
1271 if (!fastclk)
1272 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
1273
1274 wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
1275
1276 brcms_b_phy_reset(wlc_hw);
1277 wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
1278
1279 /* restore the clk */
1280 if (!fastclk)
1281 brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
1282}
1283
1284static void
2f6b1dde 1285brcms_c_write_hw_bcntemplate0(struct brcms_hardware *wlc_hw, u16 bcn[],
8702fee6
RV
1286 int len)
1287{
0da64910 1288 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
1289
1290 brcms_b_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
1291 bcn);
1292 /* write beacon length to SCR */
1293 brcms_b_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
1294 /* mark beacon0 valid */
1295 OR_REG(&regs->maccommand, MCMD_BCN0VLD);
1296}
1297
1298static void
2f6b1dde 1299brcms_c_write_hw_bcntemplate1(struct brcms_hardware *wlc_hw, u16 bcn[],
8702fee6
RV
1300 int len)
1301{
0da64910 1302 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
1303
1304 brcms_b_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
1305 bcn);
1306 /* write beacon length to SCR */
1307 brcms_b_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
1308 /* mark beacon1 valid */
1309 OR_REG(&regs->maccommand, MCMD_BCN1VLD);
1310}
1311
8702fee6
RV
1312static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw)
1313{
1314 u16 v;
1315 struct brcms_c_info *wlc = wlc_hw->wlc;
1316 /* update SYNTHPU_DLY */
1317
8ea54c9f 1318 if (BRCMS_ISLCNPHY(wlc->band))
8702fee6 1319 v = SYNTHPU_DLY_LPPHY_US;
8ea54c9f 1320 else if (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3)))
8702fee6 1321 v = SYNTHPU_DLY_NPHY_US;
8ea54c9f 1322 else
8702fee6 1323 v = SYNTHPU_DLY_BPHY_US;
8702fee6
RV
1324
1325 brcms_b_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
1326}
1327
2682e2a3 1328static void brcms_c_ucode_txant_set(struct brcms_hardware *wlc_hw)
8702fee6 1329{
2682e2a3
AS
1330 u16 phyctl;
1331 u16 phytxant = wlc_hw->bmac_phytxant;
1332 u16 mask = PHY_TXC_ANT_MASK;
8702fee6 1333
2682e2a3
AS
1334 /* set the Probe Response frame phy control word */
1335 phyctl = brcms_b_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
1336 phyctl = (phyctl & ~mask) | phytxant;
1337 brcms_b_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
8702fee6 1338
2682e2a3
AS
1339 /* set the Response (ACK/CTS) frame phy control word */
1340 phyctl = brcms_b_read_shm(wlc_hw, M_RSP_PCTLWD);
1341 phyctl = (phyctl & ~mask) | phytxant;
1342 brcms_b_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
1343}
8702fee6 1344
2682e2a3
AS
1345static u16 brcms_b_ofdm_ratetable_offset(struct brcms_hardware *wlc_hw,
1346 u8 rate)
1347{
1348 uint i;
1349 u8 plcp_rate = 0;
1350 struct plcp_signal_rate_lookup {
1351 u8 rate;
1352 u8 signal_rate;
1353 };
1354 /* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
1355 const struct plcp_signal_rate_lookup rate_lookup[] = {
1356 {BRCM_RATE_6M, 0xB},
1357 {BRCM_RATE_9M, 0xF},
1358 {BRCM_RATE_12M, 0xA},
1359 {BRCM_RATE_18M, 0xE},
1360 {BRCM_RATE_24M, 0x9},
1361 {BRCM_RATE_36M, 0xD},
1362 {BRCM_RATE_48M, 0x8},
1363 {BRCM_RATE_54M, 0xC}
1364 };
8702fee6 1365
2682e2a3
AS
1366 for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
1367 if (rate == rate_lookup[i].rate) {
1368 plcp_rate = rate_lookup[i].signal_rate;
1369 break;
1370 }
1371 }
8702fee6 1372
2682e2a3
AS
1373 /* Find the SHM pointer to the rate table entry by looking in the
1374 * Direct-map Table
419ad34e 1375 */
2682e2a3
AS
1376 return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
1377}
8702fee6 1378
2682e2a3
AS
1379static void brcms_upd_ofdm_pctl1_table(struct brcms_hardware *wlc_hw)
1380{
1381 u8 rate;
1382 u8 rates[8] = {
1383 BRCM_RATE_6M, BRCM_RATE_9M, BRCM_RATE_12M, BRCM_RATE_18M,
1384 BRCM_RATE_24M, BRCM_RATE_36M, BRCM_RATE_48M, BRCM_RATE_54M
1385 };
1386 u16 entry_ptr;
1387 u16 pctl1;
1388 uint i;
1389
1390 if (!BRCMS_PHY_11N_CAP(wlc_hw->band))
1391 return;
1392
1393 /* walk the phy rate table and update the entries */
1394 for (i = 0; i < ARRAY_SIZE(rates); i++) {
1395 rate = rates[i];
1396
1397 entry_ptr = brcms_b_ofdm_ratetable_offset(wlc_hw, rate);
1398
1399 /* read the SHM Rate Table entry OFDM PCTL1 values */
1400 pctl1 =
1401 brcms_b_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
1402
1403 /* modify the value */
1404 pctl1 &= ~PHY_TXC1_MODE_MASK;
1405 pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
1406
1407 /* Update the SHM Rate Table entry OFDM PCTL1 values */
1408 brcms_b_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
1409 pctl1);
1410 }
1411}
1412
1413/* band-specific init */
1414static void brcms_b_bsinit(struct brcms_c_info *wlc, u16 chanspec)
1415{
1416 struct brcms_hardware *wlc_hw = wlc->hw;
1417
1418 BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
1419 wlc_hw->band->bandunit);
1420
1421 brcms_c_ucode_bsinit(wlc_hw);
1422
1423 wlc_phy_init(wlc_hw->band->pi, chanspec);
1424
1425 brcms_c_ucode_txant_set(wlc_hw);
1426
1427 /*
1428 * cwmin is band-specific, update hardware
1429 * with value for current band
1430 */
1431 brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
1432 brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
1433
1434 brcms_b_update_slot_timing(wlc_hw,
8702fee6
RV
1435 BAND_5G(wlc_hw->band->
1436 bandtype) ? true : wlc_hw->
1437 shortslot);
1438
1439 /* write phytype and phyvers */
1440 brcms_b_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
1441 brcms_b_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
1442
419ad34e
AS
1443 /*
1444 * initialize the txphyctl1 rate table since
1445 * shmem is shared between bands
1446 */
8702fee6
RV
1447 brcms_upd_ofdm_pctl1_table(wlc_hw);
1448
1449 brcms_b_upd_synthpu(wlc_hw);
1450}
1451
8702fee6
RV
1452/* Perform a soft reset of the PHY PLL */
1453void brcms_b_core_phypll_reset(struct brcms_hardware *wlc_hw)
1454{
1455 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1456
1457 ai_corereg(wlc_hw->sih, SI_CC_IDX,
0da64910 1458 offsetof(struct chipcregs, chipcontrol_addr), ~0, 0);
8702fee6
RV
1459 udelay(1);
1460 ai_corereg(wlc_hw->sih, SI_CC_IDX,
0da64910 1461 offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
8702fee6
RV
1462 udelay(1);
1463 ai_corereg(wlc_hw->sih, SI_CC_IDX,
0da64910 1464 offsetof(struct chipcregs, chipcontrol_data), 0x4, 4);
8702fee6
RV
1465 udelay(1);
1466 ai_corereg(wlc_hw->sih, SI_CC_IDX,
0da64910 1467 offsetof(struct chipcregs, chipcontrol_data), 0x4, 0);
8702fee6
RV
1468 udelay(1);
1469}
1470
1471/* light way to turn on phy clock without reset for NPHY only
1472 * refer to brcms_b_core_phy_clk for full version
1473 */
1474void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
1475{
1476 /* support(necessary for NPHY and HYPHY) only */
1477 if (!BRCMS_ISNPHY(wlc_hw->band))
1478 return;
1479
1480 if (ON == clk)
1481 ai_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
1482 else
1483 ai_core_cflags(wlc_hw->sih, SICF_FGC, 0);
1484
1485}
1486
1487void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
1488{
1489 if (ON == clk)
1490 ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
1491 else
1492 ai_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
1493}
1494
1495void brcms_b_phy_reset(struct brcms_hardware *wlc_hw)
1496{
1497 struct brcms_phy_pub *pih = wlc_hw->band->pi;
1498 u32 phy_bw_clkbits;
1499 bool phy_in_reset = false;
1500
1501 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1502
1503 if (pih == NULL)
1504 return;
1505
1506 phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
1507
1508 /* Specific reset sequence required for NPHY rev 3 and 4 */
1509 if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
1510 NREV_LE(wlc_hw->band->phyrev, 4)) {
1511 /* Set the PHY bandwidth */
1512 ai_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
1513
1514 udelay(1);
1515
1516 /* Perform a soft reset of the PHY PLL */
1517 brcms_b_core_phypll_reset(wlc_hw);
1518
1519 /* reset the PHY */
1520 ai_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
1521 (SICF_PRST | SICF_PCLKE));
1522 phy_in_reset = true;
1523 } else {
8702fee6
RV
1524 ai_core_cflags(wlc_hw->sih,
1525 (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
1526 (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
1527 }
1528
1529 udelay(2);
1530 brcms_b_core_phy_clk(wlc_hw, ON);
1531
1532 if (pih)
1533 wlc_phy_anacore(pih, ON);
1534}
1535
1536/* switch to and initialize new band */
1537static void brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
6bd20a1b 1538 u16 chanspec) {
8702fee6
RV
1539 struct brcms_c_info *wlc = wlc_hw->wlc;
1540 u32 macintmask;
1541
1542 /* Enable the d11 core before accessing it */
1543 if (!ai_iscoreup(wlc_hw->sih)) {
1544 ai_core_reset(wlc_hw->sih, 0, 0);
1545 brcms_c_mctrl_reset(wlc_hw);
1546 }
1547
1548 macintmask = brcms_c_setband_inact(wlc, bandunit);
1549
1550 if (!wlc_hw->up)
1551 return;
1552
1553 brcms_b_core_phy_clk(wlc_hw, ON);
1554
1555 /* band-specific initializations */
1556 brcms_b_bsinit(wlc, chanspec);
1557
1558 /*
1559 * If there are any pending software interrupt bits,
1560 * then replace these with a harmless nonzero value
1561 * so brcms_c_dpc() will re-enable interrupts when done.
1562 */
1563 if (wlc->macintstatus)
1564 wlc->macintstatus = MI_DMAINT;
1565
1566 /* restore macintmask */
1567 brcms_intrsrestore(wlc->wl, macintmask);
1568
1569 /* ucode should still be suspended.. */
1570 WARN_ON((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) != 0);
1571}
1572
1573/* low-level band switch utility routine */
1574void brcms_c_setxband(struct brcms_hardware *wlc_hw, uint bandunit)
1575{
1576 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
1577 bandunit);
1578
1579 wlc_hw->band = wlc_hw->bandstate[bandunit];
1580
419ad34e
AS
1581 /*
1582 * BMAC_NOTE:
1583 * until we eliminate need for wlc->band refs in low level code
1584 */
8702fee6
RV
1585 wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
1586
1587 /* set gmode core flag */
8ea54c9f 1588 if (wlc_hw->sbclk && !wlc_hw->noreset)
8702fee6
RV
1589 ai_core_cflags(wlc_hw->sih, SICF_GMODE,
1590 ((bandunit == 0) ? SICF_GMODE : 0));
8702fee6
RV
1591}
1592
1593static bool brcms_c_isgoodchip(struct brcms_hardware *wlc_hw)
1594{
1595
1596 /* reject unsupported corerev */
1597 if (!VALID_COREREV(wlc_hw->corerev)) {
1598 wiphy_err(wlc_hw->wlc->wiphy, "unsupported core rev %d\n",
1599 wlc_hw->corerev);
1600 return false;
1601 }
1602
1603 return true;
1604}
1605
1606/* Validate some board info parameters */
1607static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw)
1608{
1609 uint boardrev = wlc_hw->boardrev;
1610
1611 /* 4 bits each for board type, major, minor, and tiny version */
1612 uint brt = (boardrev & 0xf000) >> 12;
1613 uint b0 = (boardrev & 0xf00) >> 8;
1614 uint b1 = (boardrev & 0xf0) >> 4;
1615 uint b2 = boardrev & 0xf;
1616
1617 /* voards from other vendors are always considered valid */
1618 if (wlc_hw->sih->boardvendor != PCI_VENDOR_ID_BROADCOM)
1619 return true;
1620
1621 /* do some boardrev sanity checks when boardvendor is Broadcom */
1622 if (boardrev == 0)
1623 return false;
1624
1625 if (boardrev <= 0xff)
1626 return true;
1627
1628 if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
1629 || (b2 > 9))
1630 return false;
1631
1632 return true;
1633}
1634
1635static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw)
1636{
1637 const char *varname = "macaddr";
1638 char *macaddr;
1639
1640 /* If macaddr exists, use it (Sromrev4, CIS, ...). */
1641 macaddr = getvar(wlc_hw->vars, varname);
1642 if (macaddr != NULL)
1643 return macaddr;
1644
1645 if (NBANDS_HW(wlc_hw) > 1)
1646 varname = "et1macaddr";
1647 else
1648 varname = "il0macaddr";
1649
1650 macaddr = getvar(wlc_hw->vars, varname);
8ea54c9f 1651 if (macaddr == NULL)
8702fee6
RV
1652 wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr "
1653 "getvar(%s) not found\n", wlc_hw->unit, varname);
8702fee6
RV
1654
1655 return macaddr;
1656}
1657
2682e2a3
AS
1658/* power both the pll and external oscillator on/off */
1659static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
1660{
1661 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: want %d\n", wlc_hw->unit, want);
1662
1663 /*
1664 * dont power down if plldown is false or
1665 * we must poll hw radio disable
1666 */
1667 if (!want && wlc_hw->pllreq)
1668 return;
1669
1670 if (wlc_hw->sih)
1671 ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
1672
1673 wlc_hw->sbclk = want;
1674 if (!wlc_hw->sbclk) {
1675 wlc_hw->clk = false;
1676 if (wlc_hw->band && wlc_hw->band->pi)
1677 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
1678 }
1679}
1680
8702fee6
RV
1681/*
1682 * Return true if radio is disabled, otherwise false.
1683 * hw radio disable signal is an external pin, users activate it asynchronously
1684 * this function could be called when driver is down and w/o clock
1685 * it operates on different registers depending on corerev and boardflag.
1686 */
11431424 1687static bool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
8702fee6
RV
1688{
1689 bool v, clk, xtal;
1690 u32 resetbits = 0, flags = 0;
1691
1692 xtal = wlc_hw->sbclk;
1693 if (!xtal)
1694 brcms_b_xtal(wlc_hw, ON);
1695
1696 /* may need to take core out of reset first */
1697 clk = wlc_hw->clk;
1698 if (!clk) {
1699 /*
1700 * mac no longer enables phyclk automatically when driver
1701 * accesses phyreg throughput mac. This can be skipped since
1702 * only mac reg is accessed below
1703 */
1704 flags |= SICF_PCLKE;
1705
419ad34e
AS
1706 /*
1707 * AI chip doesn't restore bar0win2 on
1708 * hibernation/resume, need sw fixup
1709 */
8702fee6
RV
1710 if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
1711 (wlc_hw->sih->chip == BCM43225_CHIP_ID))
0da64910
RV
1712 wlc_hw->regs = (struct d11regs *)
1713 ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
8702fee6
RV
1714 ai_core_reset(wlc_hw->sih, flags, resetbits);
1715 brcms_c_mctrl_reset(wlc_hw);
1716 }
1717
1718 v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
1719
1720 /* put core back into reset */
1721 if (!clk)
1722 ai_core_disable(wlc_hw->sih, 0);
1723
1724 if (!xtal)
1725 brcms_b_xtal(wlc_hw, OFF);
1726
1727 return v;
1728}
1729
8702fee6
RV
1730static bool wlc_dma_rxreset(struct brcms_hardware *wlc_hw, uint fifo)
1731{
1732 struct dma_pub *di = wlc_hw->di[fifo];
1733 return dma_rxreset(di);
1734}
1735
1736/* d11 core reset
1737 * ensure fask clock during reset
1738 * reset dma
1739 * reset d11(out of reset)
1740 * reset phy(out of reset)
1741 * clear software macintstatus for fresh new start
1742 * one testing hack wlc_hw->noreset will bypass the d11/phy reset
1743 */
1744void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags)
1745{
0da64910 1746 struct d11regs *regs;
8702fee6
RV
1747 uint i;
1748 bool fastclk;
1749 u32 resetbits = 0;
1750
1751 if (flags == BRCMS_USE_COREFLAGS)
1752 flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
1753
1754 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1755
1756 regs = wlc_hw->regs;
1757
1758 /* request FAST clock if not on */
1759 fastclk = wlc_hw->forcefastclk;
1760 if (!fastclk)
1761 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
1762
1763 /* reset the dma engines except first time thru */
1764 if (ai_iscoreup(wlc_hw->sih)) {
1765 for (i = 0; i < NFIFO; i++)
8ea54c9f 1766 if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
8702fee6
RV
1767 wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: "
1768 "dma_txreset[%d]: cannot stop dma\n",
1769 wlc_hw->unit, __func__, i);
8702fee6
RV
1770
1771 if ((wlc_hw->di[RX_FIFO])
8ea54c9f 1772 && (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
8702fee6
RV
1773 wiphy_err(wlc_hw->wlc->wiphy, "wl%d: %s: dma_rxreset"
1774 "[%d]: cannot stop dma\n",
1775 wlc_hw->unit, __func__, RX_FIFO);
8702fee6
RV
1776 }
1777 /* if noreset, just stop the psm and return */
1778 if (wlc_hw->noreset) {
1779 wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
1780 brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
1781 return;
1782 }
1783
1784 /*
1785 * mac no longer enables phyclk automatically when driver accesses
1786 * phyreg throughput mac, AND phy_reset is skipped at early stage when
1787 * band->pi is invalid. need to enable PHY CLK
1788 */
1789 flags |= SICF_PCLKE;
1790
419ad34e
AS
1791 /*
1792 * reset the core
1793 * In chips with PMU, the fastclk request goes through d11 core
1794 * reg 0x1e0, which is cleared by the core_reset. have to re-request it.
1795 *
1796 * This adds some delay and we can optimize it by also requesting
1797 * fastclk through chipcommon during this period if necessary. But
1798 * that has to work coordinate with other driver like mips/arm since
1799 * they may touch chipcommon as well.
8702fee6
RV
1800 */
1801 wlc_hw->clk = false;
1802 ai_core_reset(wlc_hw->sih, flags, resetbits);
1803 wlc_hw->clk = true;
1804 if (wlc_hw->band && wlc_hw->band->pi)
1805 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
1806
1807 brcms_c_mctrl_reset(wlc_hw);
1808
1809 if (PMUCTL_ENAB(wlc_hw->sih))
1810 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
1811
1812 brcms_b_phy_reset(wlc_hw);
1813
1814 /* turn on PHY_PLL */
1815 brcms_b_core_phypll_ctl(wlc_hw, true);
1816
1817 /* clear sw intstatus */
1818 wlc_hw->wlc->macintstatus = 0;
1819
1820 /* restore the clk setting */
1821 if (!fastclk)
1822 brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
1823}
1824
1825/* txfifo sizes needs to be modified(increased) since the newer cores
1826 * have more memory.
1827 */
1828static void brcms_b_corerev_fifofixup(struct brcms_hardware *wlc_hw)
1829{
0da64910 1830 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
1831 u16 fifo_nu;
1832 u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
1833 u16 txfifo_def, txfifo_def1;
1834 u16 txfifo_cmd;
1835
1836 /* tx fifos start at TXFIFO_START_BLK from the Base address */
839f9f62 1837 txfifo_startblk = TXFIFO_START_BLK;
8702fee6 1838
839f9f62
RV
1839 /* sequence of operations: reset fifo, set fifo size, reset fifo */
1840 for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
8702fee6 1841
839f9f62
RV
1842 txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
1843 txfifo_def = (txfifo_startblk & 0xff) |
1844 (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
1845 txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
1846 ((((txfifo_endblk -
1847 1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
1848 txfifo_cmd =
1849 TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
8702fee6 1850
839f9f62
RV
1851 W_REG(&regs->xmtfifocmd, txfifo_cmd);
1852 W_REG(&regs->xmtfifodef, txfifo_def);
1853 W_REG(&regs->xmtfifodef1, txfifo_def1);
8702fee6 1854
839f9f62 1855 W_REG(&regs->xmtfifocmd, txfifo_cmd);
8702fee6 1856
839f9f62 1857 txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
8702fee6 1858 }
839f9f62
RV
1859 /*
1860 * need to propagate to shm location to be in sync since ucode/hw won't
1861 * do this
1862 */
1863 brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
1864 wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
1865 brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
1866 wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
1867 brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
1868 ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
1869 xmtfifo_sz[TX_AC_BK_FIFO]));
1870 brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
1871 ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
1872 xmtfifo_sz[TX_BCMC_FIFO]));
8702fee6
RV
1873}
1874
1875/* This function is used for changing the tsf frac register
1876 * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
1877 * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
1878 * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
1879 * HTPHY Formula is 2^26/freq(MHz) e.g.
1880 * For spuron2 - 126MHz -> 2^26/126 = 532610.0
1881 * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
1882 * For spuron: 123MHz -> 2^26/123 = 545600.5
1883 * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
1884 * For spur off: 120MHz -> 2^26/120 = 559240.5
1885 * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
1886 */
1887
1888void brcms_b_switch_macfreq(struct brcms_hardware *wlc_hw, u8 spurmode)
1889{
0da64910 1890 struct d11regs *regs;
8702fee6
RV
1891 regs = wlc_hw->regs;
1892
1893 if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
1894 (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
1895 if (spurmode == WL_SPURAVOID_ON2) { /* 126Mhz */
1896 W_REG(&regs->tsf_clk_frac_l, 0x2082);
1897 W_REG(&regs->tsf_clk_frac_h, 0x8);
1898 } else if (spurmode == WL_SPURAVOID_ON1) { /* 123Mhz */
1899 W_REG(&regs->tsf_clk_frac_l, 0x5341);
1900 W_REG(&regs->tsf_clk_frac_h, 0x8);
1901 } else { /* 120Mhz */
1902 W_REG(&regs->tsf_clk_frac_l, 0x8889);
1903 W_REG(&regs->tsf_clk_frac_h, 0x8);
1904 }
1905 } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
1906 if (spurmode == WL_SPURAVOID_ON1) { /* 82Mhz */
1907 W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
1908 W_REG(&regs->tsf_clk_frac_h, 0xC);
1909 } else { /* 80Mhz */
1910 W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
1911 W_REG(&regs->tsf_clk_frac_h, 0xC);
1912 }
1913 }
1914}
1915
1916/* Initialize GPIOs that are controlled by D11 core */
1917static void brcms_c_gpio_init(struct brcms_c_info *wlc)
1918{
1919 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 1920 struct d11regs *regs;
8702fee6
RV
1921 u32 gc, gm;
1922
1923 regs = wlc_hw->regs;
1924
1925 /* use GPIO select 0 to get all gpio signals from the gpio out reg */
1926 brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
1927
1928 /*
1929 * Common GPIO setup:
1930 * G0 = LED 0 = WLAN Activity
1931 * G1 = LED 1 = WLAN 2.4 GHz Radio State
1932 * G2 = LED 2 = WLAN 5 GHz Radio State
1933 * G4 = radio disable input (HI enabled, LO disabled)
1934 */
1935
1936 gc = gm = 0;
1937
1938 /* Allocate GPIOs for mimo antenna diversity feature */
1939 if (wlc_hw->antsel_type == ANTSEL_2x3) {
1940 /* Enable antenna diversity, use 2x3 mode */
1941 brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
1942 MHF3_ANTSEL_EN, BRCM_BAND_ALL);
1943 brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
1944 MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
1945
1946 /* init superswitch control */
1947 wlc_phy_antsel_init(wlc_hw->band->pi, false);
1948
1949 } else if (wlc_hw->antsel_type == ANTSEL_2x4) {
1950 gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
1951 /*
1952 * The board itself is powered by these GPIOs
1953 * (when not sending pattern) so set them high
1954 */
1955 OR_REG(&regs->psm_gpio_oe,
1956 (BOARD_GPIO_12 | BOARD_GPIO_13));
1957 OR_REG(&regs->psm_gpio_out,
1958 (BOARD_GPIO_12 | BOARD_GPIO_13));
1959
1960 /* Enable antenna diversity, use 2x4 mode */
1961 brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
1962 MHF3_ANTSEL_EN, BRCM_BAND_ALL);
1963 brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
1964 BRCM_BAND_ALL);
1965
1966 /* Configure the desired clock to be 4Mhz */
1967 brcms_b_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
1968 ANTSEL_CLKDIV_4MHZ);
1969 }
1970
419ad34e
AS
1971 /*
1972 * gpio 9 controls the PA. ucode is responsible
1973 * for wiggling out and oe
1974 */
8702fee6
RV
1975 if (wlc_hw->boardflags & BFL_PACTRL)
1976 gm |= gc |= BOARD_GPIO_PACTRL;
1977
1978 /* apply to gpiocontrol register */
1979 ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
1980}
1981
2682e2a3
AS
1982static void brcms_ucode_write(struct brcms_hardware *wlc_hw, const u32 ucode[],
1983 const uint nbytes) {
1984 struct d11regs *regs = wlc_hw->regs;
1985 uint i;
1986 uint count;
1987
1988 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
1989
1990 count = (nbytes / sizeof(u32));
1991
1992 W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
1993 (void)R_REG(&regs->objaddr);
1994 for (i = 0; i < count; i++)
1995 W_REG(&regs->objdata, le32_to_cpu(ucode[i]));
1996
1997}
1998
8702fee6
RV
1999static void brcms_ucode_download(struct brcms_hardware *wlc_hw)
2000{
2001 struct brcms_c_info *wlc;
2002 wlc = wlc_hw->wlc;
2003
2004 if (wlc_hw->ucode_loaded)
2005 return;
2006
2007 if (D11REV_IS(wlc_hw->corerev, 23)) {
2008 if (BRCMS_ISNPHY(wlc_hw->band)) {
2009 brcms_ucode_write(wlc_hw, bcm43xx_16_mimo,
2010 bcm43xx_16_mimosz);
2011 wlc_hw->ucode_loaded = true;
2012 } else
2013 wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
2014 "corerev %d\n",
2015 __func__, wlc_hw->unit, wlc_hw->corerev);
2016 } else if (D11REV_IS(wlc_hw->corerev, 24)) {
2017 if (BRCMS_ISLCNPHY(wlc_hw->band)) {
2018 brcms_ucode_write(wlc_hw, bcm43xx_24_lcn,
2019 bcm43xx_24_lcnsz);
2020 wlc_hw->ucode_loaded = true;
2021 } else {
2022 wiphy_err(wlc->wiphy, "%s: wl%d: unsupported phy in "
2023 "corerev %d\n",
2024 __func__, wlc_hw->unit, wlc_hw->corerev);
2025 }
2026 }
2027}
2028
8702fee6
RV
2029void brcms_b_txant_set(struct brcms_hardware *wlc_hw, u16 phytxant)
2030{
2031 /* update sw state */
2032 wlc_hw->bmac_phytxant = phytxant;
2033
2034 /* push to ucode if up */
2035 if (!wlc_hw->up)
2036 return;
2037 brcms_c_ucode_txant_set(wlc_hw);
2038
2039}
2040
2041u16 brcms_b_get_txant(struct brcms_hardware *wlc_hw)
2042{
2043 return (u16) wlc_hw->wlc->stf->txant;
2044}
2045
2046void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
2047{
2048 wlc_hw->antsel_type = antsel_type;
2049
2050 /* Update the antsel type for phy module to use */
2051 wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
2052}
2053
11431424 2054static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
8702fee6
RV
2055{
2056 bool fatal = false;
2057 uint unit;
2058 uint intstatus, idx;
0da64910 2059 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
2060 struct wiphy *wiphy = wlc_hw->wlc->wiphy;
2061
2062 unit = wlc_hw->unit;
2063
2064 for (idx = 0; idx < NFIFO; idx++) {
2065 /* read intstatus register and ignore any non-error bits */
2066 intstatus =
2067 R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
2068 if (!intstatus)
2069 continue;
2070
2071 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: intstatus%d 0x%x\n",
2072 unit, idx, intstatus);
2073
2074 if (intstatus & I_RO) {
2075 wiphy_err(wiphy, "wl%d: fifo %d: receive fifo "
2076 "overflow\n", unit, idx);
2077 fatal = true;
2078 }
2079
2080 if (intstatus & I_PC) {
2081 wiphy_err(wiphy, "wl%d: fifo %d: descriptor error\n",
2082 unit, idx);
2083 fatal = true;
2084 }
2085
2086 if (intstatus & I_PD) {
2087 wiphy_err(wiphy, "wl%d: fifo %d: data error\n", unit,
2088 idx);
2089 fatal = true;
2090 }
2091
2092 if (intstatus & I_DE) {
2093 wiphy_err(wiphy, "wl%d: fifo %d: descriptor protocol "
2094 "error\n", unit, idx);
2095 fatal = true;
2096 }
2097
8ea54c9f 2098 if (intstatus & I_RU)
8702fee6
RV
2099 wiphy_err(wiphy, "wl%d: fifo %d: receive descriptor "
2100 "underflow\n", idx, unit);
8702fee6
RV
2101
2102 if (intstatus & I_XU) {
2103 wiphy_err(wiphy, "wl%d: fifo %d: transmit fifo "
2104 "underflow\n", idx, unit);
2105 fatal = true;
2106 }
2107
2108 if (fatal) {
2109 brcms_c_fatal_error(wlc_hw->wlc); /* big hammer */
2110 break;
2111 } else
2112 W_REG(&regs->intctrlregs[idx].intstatus,
2113 intstatus);
2114 }
2115}
2116
2117void brcms_c_intrson(struct brcms_c_info *wlc)
2118{
2119 struct brcms_hardware *wlc_hw = wlc->hw;
2120 wlc->macintmask = wlc->defmacintmask;
2121 W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
2122}
2123
419ad34e
AS
2124/*
2125 * callback for siutils.c, which has only wlc handler, no wl they both check
2126 * up, not only because there is no need to off/restore d11 interrupt but also
2127 * because per-port code may require sync with valid interrupt.
8702fee6 2128 */
8702fee6
RV
2129static u32 brcms_c_wlintrsoff(struct brcms_c_info *wlc)
2130{
2131 if (!wlc->hw->up)
2132 return 0;
2133
2134 return brcms_intrsoff(wlc->wl);
2135}
2136
2137static void brcms_c_wlintrsrestore(struct brcms_c_info *wlc, u32 macintmask)
2138{
2139 if (!wlc->hw->up)
2140 return;
2141
2142 brcms_intrsrestore(wlc->wl, macintmask);
2143}
2144
2145u32 brcms_c_intrsoff(struct brcms_c_info *wlc)
2146{
2147 struct brcms_hardware *wlc_hw = wlc->hw;
2148 u32 macintmask;
2149
2150 if (!wlc_hw->clk)
2151 return 0;
2152
2153 macintmask = wlc->macintmask; /* isr can still happen */
2154
2155 W_REG(&wlc_hw->regs->macintmask, 0);
2156 (void)R_REG(&wlc_hw->regs->macintmask); /* sync readback */
2157 udelay(1); /* ensure int line is no longer driven */
2158 wlc->macintmask = 0;
2159
2160 /* return previous macintmask; resolve race between us and our isr */
2161 return wlc->macintstatus ? 0 : macintmask;
2162}
2163
2164void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
2165{
2166 struct brcms_hardware *wlc_hw = wlc->hw;
2167 if (!wlc_hw->clk)
2168 return;
2169
2170 wlc->macintmask = macintmask;
2171 W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
2172}
2173
839f9f62
RV
2174static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
2175 uint tx_fifo)
2176{
2177 u8 fifo = 1 << tx_fifo;
2178
2179 /* Two clients of this code, 11h Quiet period and scanning. */
2180
2181 /* only suspend if not already suspended */
2182 if ((wlc_hw->suspended_fifos & fifo) == fifo)
2183 return;
2184
2185 /* force the core awake only if not already */
2186 if (wlc_hw->suspended_fifos == 0)
2187 brcms_c_ucode_wake_override_set(wlc_hw,
2188 BRCMS_WAKE_OVERRIDE_TXFIFO);
2189
2190 wlc_hw->suspended_fifos |= fifo;
2191
2192 if (wlc_hw->di[tx_fifo]) {
419ad34e
AS
2193 /*
2194 * Suspending AMPDU transmissions in the middle can cause
2195 * underflow which may result in mismatch between ucode and
2196 * driver so suspend the mac before suspending the FIFO
839f9f62
RV
2197 */
2198 if (BRCMS_PHY_11N_CAP(wlc_hw->band))
2199 brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
2200
2201 dma_txsuspend(wlc_hw->di[tx_fifo]);
2202
2203 if (BRCMS_PHY_11N_CAP(wlc_hw->band))
2204 brcms_c_enable_mac(wlc_hw->wlc);
2205 }
2206}
2207
2682e2a3
AS
2208static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
2209 uint tx_fifo)
2210{
2211 /* BMAC_NOTE: BRCMS_TX_FIFO_ENAB is done in brcms_c_dpc() for DMA case
2212 * but need to be done here for PIO otherwise the watchdog will catch
2213 * the inconsistency and fire
2214 */
2215 /* Two clients of this code, 11h Quiet period and scanning. */
2216 if (wlc_hw->di[tx_fifo])
2217 dma_txresume(wlc_hw->di[tx_fifo]);
2218
2219 /* allow core to sleep again */
2220 if (wlc_hw->suspended_fifos == 0)
2221 return;
2222 else {
2223 wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
2224 if (wlc_hw->suspended_fifos == 0)
2225 brcms_c_ucode_wake_override_clear(wlc_hw,
2226 BRCMS_WAKE_OVERRIDE_TXFIFO);
2227 }
2228}
2229
6bd20a1b 2230static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags)
8702fee6
RV
2231{
2232 u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
2233
2234 if (on) {
2235 /* suspend tx fifos */
2236 brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
2237 brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
2238 brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
2239 brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
2240
2241 /* zero the address match register so we do not send ACKs */
2242 brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
2243 null_ether_addr);
2244 } else {
2245 /* resume tx fifos */
8ea54c9f 2246 if (!wlc_hw->wlc->tx_suspended)
8702fee6 2247 brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
8ea54c9f 2248
8702fee6
RV
2249 brcms_b_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
2250 brcms_b_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
2251 brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
2252
2253 /* Restore address */
2254 brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
2255 wlc_hw->etheraddr);
2256 }
2257
2258 wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
2259
2260 if (on)
2261 brcms_c_ucode_mute_override_set(wlc_hw);
2262 else
2263 brcms_c_ucode_mute_override_clear(wlc_hw);
2264}
2265
8702fee6
RV
2266/*
2267 * Read and clear macintmask and macintstatus and intstatus registers.
2268 * This routine should be called with interrupts off
2269 * Return:
2270 * -1 if DEVICEREMOVED(wlc) evaluates to true;
2271 * 0 if the interrupt is not for us, or we are in some special cases;
2272 * device interrupt status bits otherwise.
2273 */
2274static inline u32 wlc_intstatus(struct brcms_c_info *wlc, bool in_isr)
2275{
2276 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 2277 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
2278 u32 macintstatus;
2279
2280 /* macintstatus includes a DMA interrupt summary bit */
2281 macintstatus = R_REG(&regs->macintstatus);
2282
2283 BCMMSG(wlc->wiphy, "wl%d: macintstatus: 0x%x\n", wlc_hw->unit,
2284 macintstatus);
2285
2286 /* detect cardbus removed, in power down(suspend) and in reset */
2287 if (DEVICEREMOVED(wlc))
2288 return -1;
2289
2290 /* DEVICEREMOVED succeeds even when the core is still resetting,
2291 * handle that case here.
2292 */
2293 if (macintstatus == 0xffffffff)
2294 return 0;
2295
2296 /* defer unsolicited interrupts */
2297 macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
2298
2299 /* if not for us */
2300 if (macintstatus == 0)
2301 return 0;
2302
2303 /* interrupts are already turned off for CFE build
2304 * Caution: For CFE Turning off the interrupts again has some undesired
2305 * consequences
2306 */
2307 /* turn off the interrupts */
2308 W_REG(&regs->macintmask, 0);
2309 (void)R_REG(&regs->macintmask); /* sync readback */
2310 wlc->macintmask = 0;
2311
2312 /* clear device interrupts */
2313 W_REG(&regs->macintstatus, macintstatus);
2314
2315 /* MI_DMAINT is indication of non-zero intstatus */
8ea54c9f 2316 if (macintstatus & MI_DMAINT)
8702fee6
RV
2317 /*
2318 * only fifo interrupt enabled is I_RI in
2319 * RX_FIFO. If MI_DMAINT is set, assume it
2320 * is set and clear the interrupt.
2321 */
2322 W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
2323 DEF_RXINTMASK);
8702fee6
RV
2324
2325 return macintstatus;
2326}
2327
2328/* Update wlc->macintstatus and wlc->intstatus[]. */
2329/* Return true if they are updated successfully. false otherwise */
2330bool brcms_c_intrsupd(struct brcms_c_info *wlc)
2331{
2332 u32 macintstatus;
2333
2334 /* read and clear macintstatus and intstatus registers */
2335 macintstatus = wlc_intstatus(wlc, false);
2336
2337 /* device is removed */
2338 if (macintstatus == 0xffffffff)
2339 return false;
2340
2341 /* update interrupt status in software */
2342 wlc->macintstatus |= macintstatus;
2343
2344 return true;
2345}
2346
2347/*
2348 * First-level interrupt processing.
2349 * Return true if this was our interrupt, false otherwise.
2350 * *wantdpc will be set to true if further brcms_c_dpc() processing is required,
2351 * false otherwise.
2352 */
2353bool brcms_c_isr(struct brcms_c_info *wlc, bool *wantdpc)
2354{
2355 struct brcms_hardware *wlc_hw = wlc->hw;
2356 u32 macintstatus;
2357
2358 *wantdpc = false;
2359
2360 if (!wlc_hw->up || !wlc->macintmask)
2361 return false;
2362
2363 /* read and clear macintstatus and intstatus registers */
2364 macintstatus = wlc_intstatus(wlc, true);
2365
2366 if (macintstatus == 0xffffffff)
2367 wiphy_err(wlc->wiphy, "DEVICEREMOVED detected in the ISR code"
2368 " path\n");
2369
2370 /* it is not for us */
2371 if (macintstatus == 0)
2372 return false;
2373
2374 *wantdpc = true;
2375
2376 /* save interrupt status bits */
2377 wlc->macintstatus = macintstatus;
2378
2379 return true;
2380
2381}
2382
8702fee6
RV
2383void brcms_c_suspend_mac_and_wait(struct brcms_c_info *wlc)
2384{
2385 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 2386 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
2387 u32 mc, mi;
2388 struct wiphy *wiphy = wlc->wiphy;
2389
2390 BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
2391 wlc_hw->band->bandunit);
2392
2393 /*
2394 * Track overlapping suspend requests
2395 */
2396 wlc_hw->mac_suspend_depth++;
2397 if (wlc_hw->mac_suspend_depth > 1)
2398 return;
2399
2400 /* force the core awake */
2401 brcms_c_ucode_wake_override_set(wlc_hw, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
2402
2403 mc = R_REG(&regs->maccontrol);
2404
2405 if (mc == 0xffffffff) {
2406 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
2407 __func__);
2408 brcms_down(wlc->wl);
2409 return;
2410 }
2411 WARN_ON(mc & MCTL_PSM_JMP_0);
2412 WARN_ON(!(mc & MCTL_PSM_RUN));
2413 WARN_ON(!(mc & MCTL_EN_MAC));
2414
2415 mi = R_REG(&regs->macintstatus);
2416 if (mi == 0xffffffff) {
2417 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
2418 __func__);
2419 brcms_down(wlc->wl);
2420 return;
2421 }
2422 WARN_ON(mi & MI_MACSSPNDD);
2423
2424 brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, 0);
2425
2426 SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
2427 BRCMS_MAX_MAC_SUSPEND);
2428
2429 if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
2430 wiphy_err(wiphy, "wl%d: wlc_suspend_mac_and_wait: waited %d uS"
2431 " and MI_MACSSPNDD is still not on.\n",
2432 wlc_hw->unit, BRCMS_MAX_MAC_SUSPEND);
2433 wiphy_err(wiphy, "wl%d: psmdebug 0x%08x, phydebug 0x%08x, "
2434 "psm_brc 0x%04x\n", wlc_hw->unit,
2435 R_REG(&regs->psmdebug),
2436 R_REG(&regs->phydebug),
2437 R_REG(&regs->psm_brc));
2438 }
2439
2440 mc = R_REG(&regs->maccontrol);
2441 if (mc == 0xffffffff) {
2442 wiphy_err(wiphy, "wl%d: %s: dead chip\n", wlc_hw->unit,
2443 __func__);
2444 brcms_down(wlc->wl);
2445 return;
2446 }
2447 WARN_ON(mc & MCTL_PSM_JMP_0);
2448 WARN_ON(!(mc & MCTL_PSM_RUN));
2449 WARN_ON(mc & MCTL_EN_MAC);
2450}
2451
2452void brcms_c_enable_mac(struct brcms_c_info *wlc)
2453{
2454 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 2455 struct d11regs *regs = wlc_hw->regs;
8702fee6
RV
2456 u32 mc, mi;
2457
2458 BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n", wlc_hw->unit,
2459 wlc->band->bandunit);
2460
2461 /*
2462 * Track overlapping suspend requests
2463 */
2464 wlc_hw->mac_suspend_depth--;
2465 if (wlc_hw->mac_suspend_depth > 0)
2466 return;
2467
2468 mc = R_REG(&regs->maccontrol);
2469 WARN_ON(mc & MCTL_PSM_JMP_0);
2470 WARN_ON(mc & MCTL_EN_MAC);
2471 WARN_ON(!(mc & MCTL_PSM_RUN));
2472
2473 brcms_b_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
2474 W_REG(&regs->macintstatus, MI_MACSSPNDD);
2475
2476 mc = R_REG(&regs->maccontrol);
2477 WARN_ON(mc & MCTL_PSM_JMP_0);
2478 WARN_ON(!(mc & MCTL_EN_MAC));
2479 WARN_ON(!(mc & MCTL_PSM_RUN));
2480
2481 mi = R_REG(&regs->macintstatus);
2482 WARN_ON(mi & MI_MACSSPNDD);
2483
2484 brcms_c_ucode_wake_override_clear(wlc_hw,
2485 BRCMS_WAKE_OVERRIDE_MACSUSPEND);
2486}
2487
2682e2a3 2488void brcms_b_band_stf_ss_set(struct brcms_hardware *wlc_hw, u8 stf_mode)
8702fee6
RV
2489{
2490 wlc_hw->hw_stf_ss_opmode = stf_mode;
2491
2492 if (wlc_hw->clk)
2493 brcms_upd_ofdm_pctl1_table(wlc_hw);
2494}
2495
8702fee6
RV
2496static bool brcms_b_validate_chip_access(struct brcms_hardware *wlc_hw)
2497{
0da64910 2498 struct d11regs *regs;
8702fee6
RV
2499 u32 w, val;
2500 struct wiphy *wiphy = wlc_hw->wlc->wiphy;
2501
2502 BCMMSG(wiphy, "wl%d\n", wlc_hw->unit);
2503
2504 regs = wlc_hw->regs;
2505
2506 /* Validate dchip register access */
2507
2508 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2509 (void)R_REG(&regs->objaddr);
2510 w = R_REG(&regs->objdata);
2511
2512 /* Can we write and read back a 32bit register? */
2513 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2514 (void)R_REG(&regs->objaddr);
2515 W_REG(&regs->objdata, (u32) 0xaa5555aa);
2516
2517 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2518 (void)R_REG(&regs->objaddr);
2519 val = R_REG(&regs->objdata);
2520 if (val != (u32) 0xaa5555aa) {
2521 wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
2522 "expected 0xaa5555aa\n", wlc_hw->unit, val);
2523 return false;
2524 }
2525
2526 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2527 (void)R_REG(&regs->objaddr);
2528 W_REG(&regs->objdata, (u32) 0x55aaaa55);
2529
2530 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2531 (void)R_REG(&regs->objaddr);
2532 val = R_REG(&regs->objdata);
2533 if (val != (u32) 0x55aaaa55) {
2534 wiphy_err(wiphy, "wl%d: validate_chip_access: SHM = 0x%x, "
2535 "expected 0x55aaaa55\n", wlc_hw->unit, val);
2536 return false;
2537 }
2538
2539 W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
2540 (void)R_REG(&regs->objaddr);
2541 W_REG(&regs->objdata, w);
2542
2543 /* clear CFPStart */
2544 W_REG(&regs->tsf_cfpstart, 0);
2545
2546 w = R_REG(&regs->maccontrol);
2547 if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
2548 (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
2549 wiphy_err(wiphy, "wl%d: validate_chip_access: maccontrol = "
2550 "0x%x, expected 0x%x or 0x%x\n", wlc_hw->unit, w,
2551 (MCTL_IHR_EN | MCTL_WAKE),
2552 (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
2553 return false;
2554 }
2555
2556 return true;
2557}
2558
2559#define PHYPLL_WAIT_US 100000
2560
2561void brcms_b_core_phypll_ctl(struct brcms_hardware *wlc_hw, bool on)
2562{
0da64910 2563 struct d11regs *regs;
8702fee6
RV
2564 u32 tmp;
2565
2566 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2567
2568 tmp = 0;
2569 regs = wlc_hw->regs;
2570
2571 if (on) {
2572 if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
2573 OR_REG(&regs->clk_ctl_st,
2574 (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
2575 CCS_ERSRC_REQ_PHYPLL));
2576 SPINWAIT((R_REG(&regs->clk_ctl_st) &
2577 (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
2578 PHYPLL_WAIT_US);
2579
2580 tmp = R_REG(&regs->clk_ctl_st);
2581 if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
8ea54c9f 2582 (CCS_ERSRC_AVAIL_HT))
8702fee6
RV
2583 wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on PHY"
2584 " PLL failed\n", __func__);
8702fee6
RV
2585 } else {
2586 OR_REG(&regs->clk_ctl_st,
2587 (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
2588 SPINWAIT((R_REG(&regs->clk_ctl_st) &
2589 (CCS_ERSRC_AVAIL_D11PLL |
2590 CCS_ERSRC_AVAIL_PHYPLL)) !=
2591 (CCS_ERSRC_AVAIL_D11PLL |
2592 CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
2593
2594 tmp = R_REG(&regs->clk_ctl_st);
2595 if ((tmp &
2596 (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
2597 !=
8ea54c9f 2598 (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
8702fee6
RV
2599 wiphy_err(wlc_hw->wlc->wiphy, "%s: turn on "
2600 "PHY PLL failed\n", __func__);
8702fee6
RV
2601 }
2602 } else {
419ad34e
AS
2603 /*
2604 * Since the PLL may be shared, other cores can still
2605 * be requesting it; so we'll deassert the request but
2606 * not wait for status to comply.
8702fee6
RV
2607 */
2608 AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
2609 tmp = R_REG(&regs->clk_ctl_st);
2610 }
2611}
2612
2613void brcms_c_coredisable(struct brcms_hardware *wlc_hw)
2614{
2615 bool dev_gone;
2616
2617 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2618
2619 dev_gone = DEVICEREMOVED(wlc_hw->wlc);
2620
2621 if (dev_gone)
2622 return;
2623
2624 if (wlc_hw->noreset)
2625 return;
2626
2627 /* radio off */
2628 wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
2629
2630 /* turn off analog core */
2631 wlc_phy_anacore(wlc_hw->band->pi, OFF);
2632
2633 /* turn off PHYPLL to save power */
2634 brcms_b_core_phypll_ctl(wlc_hw, false);
2635
2636 /* No need to set wlc->pub->radio_active = OFF
2637 * because this function needs down capability and
2638 * radio_active is designed for BCMNODOWN.
2639 */
2640
2641 /* remove gpio controls */
2642 if (wlc_hw->ucode_dbgsel)
2643 ai_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
2644
2645 wlc_hw->clk = false;
2646 ai_core_disable(wlc_hw->sih, 0);
2647 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
2648}
2649
8702fee6
RV
2650static void brcms_c_flushqueues(struct brcms_c_info *wlc)
2651{
2652 struct brcms_hardware *wlc_hw = wlc->hw;
2653 uint i;
2654
2655 wlc->txpend16165war = 0;
2656
2657 /* free any posted tx packets */
2658 for (i = 0; i < NFIFO; i++)
2659 if (wlc_hw->di[i]) {
2660 dma_txreclaim(wlc_hw->di[i], DMA_RANGE_ALL);
2661 TXPKTPENDCLR(wlc, i);
2662 BCMMSG(wlc->wiphy, "pktpend fifo %d clrd\n", i);
2663 }
2664
2665 /* free any posted rx packets */
2666 dma_rxreclaim(wlc_hw->di[RX_FIFO]);
2667}
2668
8702fee6
RV
2669static u16
2670brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
2671{
0da64910 2672 struct d11regs *regs = wlc_hw->regs;
a918137a
AS
2673 u16 *objdata_lo = (u16 *)&regs->objdata;
2674 u16 *objdata_hi = objdata_lo + 1;
8702fee6
RV
2675 u16 v;
2676
2677 W_REG(&regs->objaddr, sel | (offset >> 2));
2678 (void)R_REG(&regs->objaddr);
8ea54c9f 2679 if (offset & 2)
8702fee6 2680 v = R_REG(objdata_hi);
8ea54c9f 2681 else
8702fee6 2682 v = R_REG(objdata_lo);
8702fee6
RV
2683
2684 return v;
2685}
2686
2687static void
2688brcms_b_write_objmem(struct brcms_hardware *wlc_hw, uint offset, u16 v,
2689 u32 sel)
2690{
0da64910 2691 struct d11regs *regs = wlc_hw->regs;
a918137a
AS
2692 u16 *objdata_lo = (u16 *)&regs->objdata;
2693 u16 *objdata_hi = objdata_lo + 1;
8702fee6
RV
2694
2695 W_REG(&regs->objaddr, sel | (offset >> 2));
2696 (void)R_REG(&regs->objaddr);
8ea54c9f 2697 if (offset & 2)
8702fee6 2698 W_REG(objdata_hi, v);
8ea54c9f 2699 else
8702fee6 2700 W_REG(objdata_lo, v);
8702fee6
RV
2701}
2702
2682e2a3
AS
2703u16 brcms_b_read_shm(struct brcms_hardware *wlc_hw, uint offset)
2704{
2705 return brcms_b_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
2706}
2707
2708void brcms_b_write_shm(struct brcms_hardware *wlc_hw, uint offset, u16 v)
2709{
2710 brcms_b_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
2711}
2712
8702fee6
RV
2713/* Copy a buffer to shared memory of specified type .
2714 * SHM 'offset' needs to be an even address and
2715 * Buffer length 'len' must be an even number of bytes
2716 * 'sel' selects the type of memory
2717 */
2718void
2719brcms_b_copyto_objmem(struct brcms_hardware *wlc_hw, uint offset,
2720 const void *buf, int len, u32 sel)
2721{
2722 u16 v;
2723 const u8 *p = (const u8 *)buf;
2724 int i;
2725
2726 if (len <= 0 || (offset & 1) || (len & 1))
2727 return;
2728
2729 for (i = 0; i < len; i += 2) {
2730 v = p[i] | (p[i + 1] << 8);
2731 brcms_b_write_objmem(wlc_hw, offset + i, v, sel);
2732 }
2733}
2734
2735/* Copy a piece of shared memory of specified type to a buffer .
2736 * SHM 'offset' needs to be an even address and
2737 * Buffer length 'len' must be an even number of bytes
2738 * 'sel' selects the type of memory
2739 */
2740void
2741brcms_b_copyfrom_objmem(struct brcms_hardware *wlc_hw, uint offset, void *buf,
2742 int len, u32 sel)
2743{
2744 u16 v;
2745 u8 *p = (u8 *) buf;
2746 int i;
2747
2748 if (len <= 0 || (offset & 1) || (len & 1))
2749 return;
2750
2751 for (i = 0; i < len; i += 2) {
2752 v = brcms_b_read_objmem(wlc_hw, offset + i, sel);
2753 p[i] = v & 0xFF;
2754 p[i + 1] = (v >> 8) & 0xFF;
2755 }
2756}
2757
11431424 2758static void brcms_b_copyfrom_vars(struct brcms_hardware *wlc_hw, char **buf,
8702fee6
RV
2759 uint *len)
2760{
2761 BCMMSG(wlc_hw->wlc->wiphy, "nvram vars totlen=%d\n",
2762 wlc_hw->vars_size);
2763
2764 *buf = wlc_hw->vars;
2765 *len = wlc_hw->vars_size;
2766}
2767
11431424
AS
2768static void brcms_b_retrylimit_upd(struct brcms_hardware *wlc_hw,
2769 u16 SRL, u16 LRL)
8702fee6
RV
2770{
2771 wlc_hw->SRL = SRL;
2772 wlc_hw->LRL = LRL;
2773
2774 /* write retry limit to SCR, shouldn't need to suspend */
2775 if (wlc_hw->up) {
2776 W_REG(&wlc_hw->regs->objaddr,
2777 OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
2778 (void)R_REG(&wlc_hw->regs->objaddr);
2779 W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
2780 W_REG(&wlc_hw->regs->objaddr,
2781 OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
2782 (void)R_REG(&wlc_hw->regs->objaddr);
2783 W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
2784 }
2785}
2786
11431424 2787static void brcms_b_pllreq(struct brcms_hardware *wlc_hw, bool set, u32 req_bit)
8702fee6
RV
2788{
2789 if (set) {
2790 if (mboolisset(wlc_hw->pllreq, req_bit))
2791 return;
2792
2793 mboolset(wlc_hw->pllreq, req_bit);
2794
2795 if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
8ea54c9f 2796 if (!wlc_hw->sbclk)
8702fee6 2797 brcms_b_xtal(wlc_hw, ON);
8702fee6
RV
2798 }
2799 } else {
2800 if (!mboolisset(wlc_hw->pllreq, req_bit))
2801 return;
2802
2803 mboolclr(wlc_hw->pllreq, req_bit);
2804
2805 if (mboolisset(wlc_hw->pllreq, BRCMS_PLLREQ_FLIP)) {
8ea54c9f 2806 if (wlc_hw->sbclk)
8702fee6 2807 brcms_b_xtal(wlc_hw, OFF);
8702fee6
RV
2808 }
2809 }
2810
2811 return;
2812}
2813
11431424 2814static void brcms_b_antsel_set(struct brcms_hardware *wlc_hw, u32 antsel_avail)
8702fee6
RV
2815{
2816 wlc_hw->antsel_avail = antsel_avail;
2817}
2818
419ad34e
AS
2819/*
2820 * conditions under which the PM bit should be set in outgoing frames
2821 * and STAY_AWAKE is meaningful
a9533e7e 2822 */
fe741e5e 2823bool brcms_c_ps_allowed(struct brcms_c_info *wlc)
a9533e7e
HP
2824{
2825 int idx;
471f1b51 2826 struct brcms_bss_cfg *cfg;
a9533e7e
HP
2827
2828 /* disallow PS when one of the following global conditions meets */
5dc16874 2829 if (!wlc->pub->associated)
0965ae88 2830 return false;
a9533e7e
HP
2831
2832 /* disallow PS when one of these meets when not scanning */
5dc16874
AS
2833 if (AP_ACTIVE(wlc) || wlc->monitor)
2834 return false;
a9533e7e 2835
7c783cef 2836 for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
edb3f7cf
AS
2837 cfg = wlc->bsscfg[idx];
2838 if (cfg && BSSCFG_STA(cfg) && cfg->associated) {
2839 /*
2840 * disallow PS when one of the following
2841 * bsscfg specific conditions meets
2842 */
7c783cef 2843 if (!cfg->BSS || !BRCMS_PORTOPEN(cfg))
edb3f7cf 2844 return false;
a9533e7e 2845
839f9f62
RV
2846 if (!cfg->dtim_programmed)
2847 return false;
2848 }
2849 }
2850
2851 return true;
2852}
2853
11431424 2854static void brcms_b_reset(struct brcms_hardware *wlc_hw)
839f9f62
RV
2855{
2856 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
2857
2858 /* reset the core */
2859 if (!DEVICEREMOVED(wlc_hw->wlc))
2860 brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
2861
2862 /* purge the dma rings */
2863 brcms_c_flushqueues(wlc_hw->wlc);
a9533e7e 2864
839f9f62 2865 brcms_c_reset_bmac_done(wlc_hw->wlc);
a9533e7e
HP
2866}
2867
fe741e5e 2868void brcms_c_reset(struct brcms_c_info *wlc)
a2627bc0 2869{
792aa408 2870 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
a9533e7e 2871
a9533e7e 2872 /* slurp up hw mac counters before core reset */
fe741e5e 2873 brcms_c_statsupd(wlc);
a9533e7e 2874
e4cf544e
AS
2875 /* reset our snapshot of macstat counters */
2876 memset((char *)wlc->core->macstat_snapshot, 0,
cc87568a 2877 sizeof(struct macstat));
a9533e7e 2878
c654fce6 2879 brcms_b_reset(wlc->hw);
a9533e7e
HP
2880}
2881
fe741e5e 2882void brcms_c_fatal_error(struct brcms_c_info *wlc)
a9533e7e 2883{
b8f092c9
RV
2884 wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
2885 wlc->pub->unit);
8817f754 2886 brcms_init(wlc->wl);
a9533e7e
HP
2887}
2888
fe741e5e 2889/* Return the channel the driver should initialize during brcms_c_init.
a9533e7e
HP
2890 * the channel may have to be changed from the currently configured channel
2891 * if other configurations are in conflict (bandlocked, 11n mode disabled,
2892 * invalid channel for current country, etc.)
2893 */
6bd20a1b 2894static u16 brcms_c_init_chanspec(struct brcms_c_info *wlc)
a2627bc0 2895{
6bd20a1b 2896 u16 chanspec =
a9533e7e
HP
2897 1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
2898 WL_CHANSPEC_BAND_2G;
2899
a9533e7e
HP
2900 return chanspec;
2901}
2902
11431424 2903static struct scb global_scb;
a9533e7e 2904
1c4c54ba 2905static void brcms_c_init_scb(struct brcms_c_info *wlc, struct scb *scb)
a9533e7e
HP
2906{
2907 int i;
2908 scb->flags = SCB_WMECAP | SCB_HTCAP;
2909 for (i = 0; i < NUMPRIO; i++)
2910 scb->seqnum[i] = 0;
2911}
2912
839f9f62
RV
2913/* d11 core init
2914 * reset PSM
2915 * download ucode/PCM
2916 * let ucode run to suspended
2917 * download ucode inits
2918 * config other core registers
2919 * init dma
2920 */
2921static void brcms_b_coreinit(struct brcms_c_info *wlc)
2922{
2923 struct brcms_hardware *wlc_hw = wlc->hw;
0da64910 2924 struct d11regs *regs;
839f9f62
RV
2925 u32 sflags;
2926 uint bcnint_us;
2927 uint i = 0;
2928 bool fifosz_fixup = false;
2929 int err = 0;
2930 u16 buf[NFIFO];
2931 struct wiphy *wiphy = wlc->wiphy;
2932
2933 regs = wlc_hw->regs;
2934
2935 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
2936
2937 /* reset PSM */
2938 brcms_b_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
2939
2940 brcms_ucode_download(wlc_hw);
2941 /*
2942 * FIFOSZ fixup. driver wants to controls the fifo allocation.
2943 */
2944 fifosz_fixup = true;
2945
2946 /* let the PSM run to the suspended state, set mode to BSS STA */
2947 W_REG(&regs->macintstatus, -1);
2948 brcms_b_mctrl(wlc_hw, ~0,
2949 (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
2950
2951 /* wait for ucode to self-suspend after auto-init */
2952 SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
2953 1000 * 1000);
2954 if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
2955 wiphy_err(wiphy, "wl%d: wlc_coreinit: ucode did not self-"
2956 "suspend!\n", wlc_hw->unit);
2957
2958 brcms_c_gpio_init(wlc);
2959
2960 sflags = ai_core_sflags(wlc_hw->sih, 0, 0);
2961
2962 if (D11REV_IS(wlc_hw->corerev, 23)) {
2963 if (BRCMS_ISNPHY(wlc_hw->band))
2964 brcms_c_write_inits(wlc_hw, d11n0initvals16);
2965 else
2966 wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
2967 " %d\n", __func__, wlc_hw->unit,
2968 wlc_hw->corerev);
2969 } else if (D11REV_IS(wlc_hw->corerev, 24)) {
8ea54c9f 2970 if (BRCMS_ISLCNPHY(wlc_hw->band))
839f9f62 2971 brcms_c_write_inits(wlc_hw, d11lcn0initvals24);
8ea54c9f 2972 else
839f9f62
RV
2973 wiphy_err(wiphy, "%s: wl%d: unsupported phy in corerev"
2974 " %d\n", __func__, wlc_hw->unit,
2975 wlc_hw->corerev);
839f9f62
RV
2976 } else {
2977 wiphy_err(wiphy, "%s: wl%d: unsupported corerev %d\n",
2978 __func__, wlc_hw->unit, wlc_hw->corerev);
2979 }
2980
2981 /* For old ucode, txfifo sizes needs to be modified(increased) */
8ea54c9f 2982 if (fifosz_fixup == true)
839f9f62 2983 brcms_b_corerev_fifofixup(wlc_hw);
839f9f62
RV
2984
2985 /* check txfifo allocations match between ucode and driver */
2986 buf[TX_AC_BE_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE0);
2987 if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
2988 i = TX_AC_BE_FIFO;
2989 err = -1;
2990 }
2991 buf[TX_AC_VI_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE1);
2992 if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
2993 i = TX_AC_VI_FIFO;
2994 err = -1;
2995 }
2996 buf[TX_AC_BK_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE2);
2997 buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
2998 buf[TX_AC_BK_FIFO] &= 0xff;
2999 if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
3000 i = TX_AC_BK_FIFO;
3001 err = -1;
3002 }
3003 if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
3004 i = TX_AC_VO_FIFO;
3005 err = -1;
3006 }
3007 buf[TX_BCMC_FIFO] = brcms_b_read_shm(wlc_hw, M_FIFOSIZE3);
3008 buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
3009 buf[TX_BCMC_FIFO] &= 0xff;
3010 if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
3011 i = TX_BCMC_FIFO;
3012 err = -1;
3013 }
3014 if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
3015 i = TX_ATIM_FIFO;
3016 err = -1;
3017 }
8ea54c9f 3018 if (err != 0)
839f9f62
RV
3019 wiphy_err(wiphy, "wlc_coreinit: txfifo mismatch: ucode size %d"
3020 " driver size %d index %d\n", buf[i],
3021 wlc_hw->xmtfifo_sz[i], i);
839f9f62
RV
3022
3023 /* make sure we can still talk to the mac */
3024 WARN_ON(R_REG(&regs->maccontrol) == 0xffffffff);
3025
3026 /* band-specific inits done by wlc_bsinit() */
3027
3028 /* Set up frame burst size and antenna swap threshold init values */
3029 brcms_b_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
3030 brcms_b_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
3031
3032 /* enable one rx interrupt per received frame */
3033 W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
3034
3035 /* set the station mode (BSS STA) */
3036 brcms_b_mctrl(wlc_hw,
3037 (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
3038 (MCTL_INFRA | MCTL_DISCARD_PMQ));
3039
3040 /* set up Beacon interval */
3041 bcnint_us = 0x8000 << 10;
3042 W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
3043 W_REG(&regs->tsf_cfpstart, bcnint_us);
3044 W_REG(&regs->macintstatus, MI_GP1);
3045
3046 /* write interrupt mask */
3047 W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
3048
3049 /* allow the MAC to control the PHY clock (dynamic on/off) */
3050 brcms_b_macphyclk_set(wlc_hw, ON);
3051
3052 /* program dynamic clock control fast powerup delay register */
3053 wlc->fastpwrup_dly = ai_clkctl_fast_pwrup_delay(wlc_hw->sih);
3054 W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
3055
3056 /* tell the ucode the corerev */
3057 brcms_b_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
3058
3059 /* tell the ucode MAC capabilities */
3060 brcms_b_write_shm(wlc_hw, M_MACHW_CAP_L,
3061 (u16) (wlc_hw->machwcap & 0xffff));
3062 brcms_b_write_shm(wlc_hw, M_MACHW_CAP_H,
3063 (u16) ((wlc_hw->
3064 machwcap >> 16) & 0xffff));
3065
3066 /* write retry limits to SCR, this done after PSM init */
3067 W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
3068 (void)R_REG(&regs->objaddr);
3069 W_REG(&regs->objdata, wlc_hw->SRL);
3070 W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
3071 (void)R_REG(&regs->objaddr);
3072 W_REG(&regs->objdata, wlc_hw->LRL);
3073
3074 /* write rate fallback retry limits */
3075 brcms_b_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
3076 brcms_b_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
3077
3078 AND_REG(&regs->ifs_ctl, 0x0FFF);
3079 W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
3080
3081 /* dma initializations */
3082 wlc->txpend16165war = 0;
3083
3084 /* init the tx dma engines */
3085 for (i = 0; i < NFIFO; i++) {
3086 if (wlc_hw->di[i])
3087 dma_txinit(wlc_hw->di[i]);
3088 }
3089
3090 /* init the rx dma engine(s) and post receive buffers */
3091 dma_rxinit(wlc_hw->di[RX_FIFO]);
3092 dma_rxfill(wlc_hw->di[RX_FIFO]);
3093}
3094
3095void
11431424 3096static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec,
839f9f62
RV
3097 bool mute) {
3098 u32 macintmask;
3099 bool fastclk;
3100 struct brcms_c_info *wlc = wlc_hw->wlc;
3101
3102 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
3103
3104 /* request FAST clock if not on */
3105 fastclk = wlc_hw->forcefastclk;
3106 if (!fastclk)
3107 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
3108
3109 /* disable interrupts */
3110 macintmask = brcms_intrsoff(wlc->wl);
3111
3112 /* set up the specified band and chanspec */
3113 brcms_c_setxband(wlc_hw, CHSPEC_BANDUNIT(chanspec));
3114 wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
3115
3116 /* do one-time phy inits and calibration */
3117 wlc_phy_cal_init(wlc_hw->band->pi);
3118
3119 /* core-specific initialization */
3120 brcms_b_coreinit(wlc);
3121
3122 /* suspend the tx fifos and mute the phy for preism cac time */
3123 if (mute)
3124 brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
3125
3126 /* band-specific inits */
3127 brcms_b_bsinit(wlc, chanspec);
3128
3129 /* restore macintmask */
3130 brcms_intrsrestore(wlc->wl, macintmask);
3131
3132 /* seed wake_override with BRCMS_WAKE_OVERRIDE_MACSUSPEND since the mac
3133 * is suspended and brcms_c_enable_mac() will clear this override bit.
3134 */
3135 mboolset(wlc_hw->wake_override, BRCMS_WAKE_OVERRIDE_MACSUSPEND);
3136
3137 /*
419ad34e
AS
3138 * initialize mac_suspend_depth to 1 to match ucode
3139 * initial suspended state
839f9f62
RV
3140 */
3141 wlc_hw->mac_suspend_depth = 1;
3142
3143 /* restore the clk */
3144 if (!fastclk)
3145 brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
3146}
3147
2682e2a3 3148static u8 brcms_c_local_constraint_qdbm(struct brcms_c_info *wlc)
a2627bc0 3149{
2682e2a3
AS
3150 u8 local;
3151 s16 local_max;
a9533e7e 3152
2682e2a3
AS
3153 local = BRCMS_TXPWR_MAX;
3154 if (wlc->pub->associated &&
3155 (brcmu_chspec_ctlchan(wlc->chanspec) ==
3156 brcmu_chspec_ctlchan(wlc->home_chanspec))) {
a9533e7e 3157
2682e2a3
AS
3158 /* get the local power constraint if we are on the AP's
3159 * channel [802.11h, 7.3.2.13]
3160 */
3161 /* Clamp the value between 0 and BRCMS_TXPWR_MAX w/o
3162 * overflowing the target */
3163 local_max =
3164 (wlc->txpwr_local_max -
3165 wlc->txpwr_local_constraint) * BRCMS_TXPWR_DB_FACTOR;
3166 if (local_max > 0 && local_max < BRCMS_TXPWR_MAX)
3167 return (u8) local_max;
3168 if (local_max < 0)
3169 return 0;
3170 }
a9533e7e 3171
2682e2a3
AS
3172 return local;
3173}
a9533e7e 3174
2682e2a3
AS
3175static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc,
3176 u16 chanspec)
3177{
3178 /* Save our copy of the chanspec */
3179 wlc->chanspec = chanspec;
a9533e7e 3180
2682e2a3
AS
3181 /* Set the chanspec and power limits for this locale after computing
3182 * any 11h local tx power constraints.
3183 */
3184 brcms_c_channel_set_chanspec(wlc->cmi, chanspec,
3185 brcms_c_local_constraint_qdbm(wlc));
a9533e7e 3186
2682e2a3
AS
3187 if (wlc->stf->ss_algosel_auto)
3188 brcms_c_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
3189 chanspec);
a9533e7e 3190
2682e2a3 3191 brcms_c_stf_ss_update(wlc, wlc->band);
a9533e7e 3192
2682e2a3 3193}
a9533e7e 3194
2682e2a3
AS
3195static void brcms_c_bandinit_ordered(struct brcms_c_info *wlc,
3196 u16 chanspec)
3197{
3198 struct brcms_c_rateset default_rateset;
3199 uint parkband;
3200 uint i, band_order[2];
a9533e7e 3201
2682e2a3
AS
3202 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
3203 /*
3204 * We might have been bandlocked during down and the chip
3205 * power-cycled (hibernate). Figure out the right band to park on
3206 */
3207 if (wlc->bandlocked || NBANDS(wlc) == 1) {
3208 /* updated in brcms_c_bandlock() */
3209 parkband = wlc->band->bandunit;
3210 band_order[0] = band_order[1] = parkband;
3211 } else {
3212 /* park on the band of the specified chanspec */
3213 parkband = CHSPEC_BANDUNIT(chanspec);
a9533e7e 3214
2682e2a3
AS
3215 /* order so that parkband initialize last */
3216 band_order[0] = parkband ^ 1;
3217 band_order[1] = parkband;
a9533e7e
HP
3218 }
3219
2682e2a3
AS
3220 /* make each band operational, software state init */
3221 for (i = 0; i < NBANDS(wlc); i++) {
3222 uint j = band_order[i];
a9533e7e 3223
2682e2a3 3224 wlc->band = wlc->bandstate[j];
a9533e7e 3225
2682e2a3 3226 brcms_default_rateset(wlc, &default_rateset);
a9533e7e 3227
2682e2a3
AS
3228 /* fill in hw_rate */
3229 brcms_c_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
3230 false, BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
3231 (bool) N_ENAB(wlc->pub));
a9533e7e 3232
2682e2a3
AS
3233 /* init basic rate lookup */
3234 brcms_c_rate_lookup_init(wlc, &default_rateset);
a9533e7e
HP
3235 }
3236
2682e2a3
AS
3237 /* sync up phy/radio chanspec */
3238 brcms_c_set_phy_chanspec(wlc, chanspec);
3239}
a9533e7e 3240
2682e2a3
AS
3241/*
3242 * ucode, hwmac update
3243 * Channel dependent updates for ucode and hw
3244 */
3245static void brcms_c_ucode_mac_upd(struct brcms_c_info *wlc)
3246{
3247 /* enable or disable any active IBSSs depending on whether or not
3248 * we are on the home channel
3249 */
3250 if (wlc->home_chanspec == BRCMS_BAND_PI_RADIO_CHANSPEC) {
3251 if (wlc->pub->associated) {
3252 /*
3253 * BMAC_NOTE: This is something that should be fixed
3254 * in ucode inits. I think that the ucode inits set
3255 * up the bcn templates and shm values with a bogus
3256 * beacon. This should not be done in the inits. If
3257 * ucode needs to set up a beacon for testing, the
3258 * test routines should write it down, not expect the
3259 * inits to populate a bogus beacon.
3260 */
3261 if (BRCMS_PHY_11N_CAP(wlc->band))
3262 brcms_c_write_shm(wlc, M_BCN_TXTSF_OFFSET,
3263 wlc->band->bcntsfoff);
3264 }
3265 } else {
3266 /* disable an active IBSS if we are not on the home channel */
3267 }
3268
3269 /* update the various promisc bits */
3270 brcms_c_mac_bcn_promisc(wlc);
3271 brcms_c_mac_promisc(wlc);
3272}
3273
3274/* band-specific init */
3275static void brcms_c_bsinit(struct brcms_c_info *wlc)
3276{
3277 BCMMSG(wlc->wiphy, "wl%d: bandunit %d\n",
3278 wlc->pub->unit, wlc->band->bandunit);
3279
3280 /* write ucode ACK/CTS rate table */
3281 brcms_c_set_ratetable(wlc);
3282
3283 /* update some band specific mac configuration */
3284 brcms_c_ucode_mac_upd(wlc);
3285
3286 /* init antenna selection */
3287 brcms_c_antsel_init(wlc->asi);
3288
3289}
3290
3291/* formula: IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
3292static int
3293brcms_c_duty_cycle_set(struct brcms_c_info *wlc, int duty_cycle, bool isOFDM,
3294 bool writeToShm)
3295{
3296 int idle_busy_ratio_x_16 = 0;
3297 uint offset =
3298 isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
3299 M_TX_IDLE_BUSY_RATIO_X_16_CCK;
3300 if (duty_cycle > 100 || duty_cycle < 0) {
3301 wiphy_err(wlc->wiphy, "wl%d: duty cycle value off limit\n",
3302 wlc->pub->unit);
3303 return -EINVAL;
3304 }
3305 if (duty_cycle)
3306 idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
3307 /* Only write to shared memory when wl is up */
3308 if (writeToShm)
3309 brcms_c_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
3310
3311 if (isOFDM)
3312 wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
3313 else
3314 wlc->tx_duty_cycle_cck = (u16) duty_cycle;
3315
3316 return 0;
3317}
3318
3319/*
3320 * Initialize the base precedence map for dequeueing
3321 * from txq based on WME settings
3322 */
3323static void brcms_c_tx_prec_map_init(struct brcms_c_info *wlc)
3324{
3325 wlc->tx_prec_map = BRCMS_PREC_BMP_ALL;
3326 memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
3327
3328 /*
3329 * For non-WME, both fifos have overlapping MAXPRIO. So just
3330 * disable all precedences if either is full.
3331 */
3332 if (!EDCF_ENAB(wlc->pub)) {
3333 wlc->fifo2prec_map[TX_DATA_FIFO] = BRCMS_PREC_BMP_ALL;
3334 wlc->fifo2prec_map[TX_CTL_FIFO] = BRCMS_PREC_BMP_ALL;
3335 } else {
3336 wlc->fifo2prec_map[TX_AC_BK_FIFO] = BRCMS_PREC_BMP_AC_BK;
3337 wlc->fifo2prec_map[TX_AC_BE_FIFO] = BRCMS_PREC_BMP_AC_BE;
3338 wlc->fifo2prec_map[TX_AC_VI_FIFO] = BRCMS_PREC_BMP_AC_VI;
3339 wlc->fifo2prec_map[TX_AC_VO_FIFO] = BRCMS_PREC_BMP_AC_VO;
3340 }
3341}
3342
3343static void
3344brcms_c_txflowcontrol_signal(struct brcms_c_info *wlc,
3345 struct brcms_txq_info *qi, bool on, int prio)
3346{
3347 /* transmit flowcontrol is not yet implemented */
3348}
3349
3350static void brcms_c_txflowcontrol_reset(struct brcms_c_info *wlc)
3351{
3352 struct brcms_txq_info *qi;
3353
3354 for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
3355 if (qi->stopped) {
3356 brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
3357 qi->stopped = 0;
3358 }
3359 }
3360}
3361
3362void brcms_c_init(struct brcms_c_info *wlc)
3363{
3364 struct d11regs *regs;
3365 u16 chanspec;
3366 int i;
3367 struct brcms_bss_cfg *bsscfg;
3368 bool mute = false;
3369
3370 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
3371
3372 regs = wlc->regs;
3373
3374 /*
3375 * This will happen if a big-hammer was executed. In
3376 * that case, we want to go back to the channel that
3377 * we were on and not new channel
3378 */
3379 if (wlc->pub->associated)
3380 chanspec = wlc->home_chanspec;
3381 else
3382 chanspec = brcms_c_init_chanspec(wlc);
3383
3384 brcms_b_init(wlc->hw, chanspec, mute);
3385
3386 /* update beacon listen interval */
3387 brcms_c_bcn_li_upd(wlc);
3388
3389 /* the world is new again, so is our reported rate */
3390 brcms_c_reprate_init(wlc);
3391
3392 /* write ethernet address to core */
3393 FOREACH_BSS(wlc, i, bsscfg)
3394 brcms_c_set_mac(bsscfg);
3395 brcms_c_set_bssid(bsscfg);
3396 END_FOREACH_BSS()
3397
3398 /* Update tsf_cfprep if associated and up */
3399 if (wlc->pub->associated) {
3400 FOREACH_BSS(wlc, i, bsscfg)
3401 if (bsscfg->up) {
3402 u32 bi;
3403
3404 /* get beacon period and convert to uS */
3405 bi = bsscfg->current_bss->beacon_period << 10;
3406 /*
3407 * update since init path would reset
3408 * to default value
3409 */
3410 W_REG(&regs->tsf_cfprep,
3411 (bi << CFPREP_CBI_SHIFT));
3412
3413 /* Update maccontrol PM related bits */
3414 brcms_c_set_ps_ctrl(wlc);
3415
3416 break;
3417 }
3418 END_FOREACH_BSS()
3419 }
3420
3421 brcms_c_bandinit_ordered(wlc, chanspec);
3422
3423 brcms_c_init_scb(wlc, &global_scb);
3424
3425 /* init probe response timeout */
3426 brcms_c_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
3427
3428 /* init max burst txop (framebursting) */
3429 brcms_c_write_shm(wlc, M_MBURST_TXOP,
3430 (wlc->
3431 _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
3432
3433 /* initialize maximum allowed duty cycle */
3434 brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
3435 brcms_c_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
3436
3437 /*
3438 * Update some shared memory locations related to
3439 * max AMPDU size allowed to received
3440 */
3441 brcms_c_ampdu_shm_upd(wlc->ampdu);
3442
3443 /* band-specific inits */
3444 brcms_c_bsinit(wlc);
3445
3446 /* Enable EDCF mode (while the MAC is suspended) */
3447 if (EDCF_ENAB(wlc->pub)) {
3448 OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
3449 brcms_c_edcf_setparams(wlc, false);
3450 }
3451
3452 /* Init precedence maps for empty FIFOs */
3453 brcms_c_tx_prec_map_init(wlc);
3454
3455 /* read the ucode version if we have not yet done so */
3456 if (wlc->ucode_rev == 0) {
a9533e7e 3457 wlc->ucode_rev =
fe741e5e
RV
3458 brcms_c_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
3459 wlc->ucode_rev |= brcms_c_read_shm(wlc, M_BOM_REV_MINOR);
a9533e7e
HP
3460 }
3461
3462 /* ..now really unleash hell (allow the MAC out of suspend) */
fe741e5e 3463 brcms_c_enable_mac(wlc);
a9533e7e
HP
3464
3465 /* clear tx flow control */
1c4c54ba 3466 brcms_c_txflowcontrol_reset(wlc);
a9533e7e
HP
3467
3468 /* clear tx data fifo suspends */
0965ae88 3469 wlc->tx_suspended = false;
a9533e7e
HP
3470
3471 /* enable the RF Disable Delay timer */
ff31c54c 3472 W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
a9533e7e
HP
3473
3474 /* initialize mpc delay */
7c783cef 3475 wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
a9533e7e
HP
3476
3477 /*
3478 * Initialize WME parameters; if they haven't been set by some other
3479 * mechanism (IOVar, etc) then read them from the hardware.
3480 */
7c783cef
RV
3481 if (BRCMS_WME_RETRY_SHORT_GET(wlc, 0) == 0) {
3482 /* Uninitialized; read from HW */
a9533e7e
HP
3483 int ac;
3484
8ea54c9f 3485 for (ac = 0; ac < AC_COUNT; ac++)
a9533e7e 3486 wlc->wme_retries[ac] =
fe741e5e 3487 brcms_c_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
a9533e7e
HP
3488 }
3489}
3490
fe741e5e 3491void brcms_c_mac_bcn_promisc_change(struct brcms_c_info *wlc, bool promisc)
a9533e7e
HP
3492{
3493 wlc->bcnmisc_monitor = promisc;
fe741e5e 3494 brcms_c_mac_bcn_promisc(wlc);
a9533e7e
HP
3495}
3496
fe741e5e 3497void brcms_c_mac_bcn_promisc(struct brcms_c_info *wlc)
a9533e7e
HP
3498{
3499 if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
3500 wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
fe741e5e 3501 brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
a9533e7e 3502 else
fe741e5e 3503 brcms_c_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
a9533e7e
HP
3504}
3505
3506/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
fe741e5e 3507void brcms_c_mac_promisc(struct brcms_c_info *wlc)
a9533e7e 3508{
66cbd3ab 3509 u32 promisc_bits = 0;
a9533e7e 3510
419ad34e
AS
3511 /*
3512 * promiscuous mode just sets MCTL_PROMISC
3513 * Note: APs get all BSS traffic without the need to set
3514 * the MCTL_PROMISC bit since all BSS data traffic is
3515 * directed at the AP
a9533e7e 3516 */
5dc16874 3517 if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub))
a9533e7e
HP
3518 promisc_bits |= MCTL_PROMISC;
3519
3520 /* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
3521 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
fe741e5e 3522 * handled in brcms_c_mac_bcn_promisc()
a9533e7e
HP
3523 */
3524 if (MONITOR_ENAB(wlc))
3525 promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
3526
fe741e5e 3527 brcms_c_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
a9533e7e
HP
3528}
3529
a9533e7e 3530/* push sw hps and wake state through hardware */
fe741e5e 3531void brcms_c_set_ps_ctrl(struct brcms_c_info *wlc)
a9533e7e 3532{
66cbd3ab 3533 u32 v1, v2;
c3ecec39 3534 bool hps;
a9533e7e
HP
3535 bool awake_before;
3536
3537 hps = PS_ALLOWED(wlc);
a9533e7e 3538
c3ecec39 3539 BCMMSG(wlc->wiphy, "wl%d: hps %d\n", wlc->pub->unit, hps);
a9533e7e 3540
ff31c54c 3541 v1 = R_REG(&wlc->regs->maccontrol);
c3ecec39 3542 v2 = MCTL_WAKE;
a9533e7e
HP
3543 if (hps)
3544 v2 |= MCTL_HPS;
a9533e7e 3545
fe741e5e 3546 brcms_c_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
a9533e7e
HP
3547
3548 awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
3549
c3ecec39 3550 if (!awake_before)
c654fce6 3551 brcms_b_wait_for_wake(wlc->hw);
a9533e7e
HP
3552
3553}
3554
3555/*
3556 * Write this BSS config's MAC address to core.
3557 * Updates RXE match engine.
3558 */
471f1b51 3559int brcms_c_set_mac(struct brcms_bss_cfg *cfg)
a9533e7e
HP
3560{
3561 int err = 0;
fe741e5e 3562 struct brcms_c_info *wlc = cfg->wlc;
a9533e7e 3563
8ea54c9f 3564 if (cfg == wlc->cfg)
a9533e7e 3565 /* enter the MAC addr into the RXE match registers */
fe741e5e 3566 brcms_c_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
a9533e7e 3567
f52a0ad0 3568 brcms_c_ampdu_macaddr_upd(wlc);
a9533e7e
HP
3569
3570 return err;
3571}
3572
3573/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
3574 * Updates RXE match engine.
3575 */
471f1b51 3576void brcms_c_set_bssid(struct brcms_bss_cfg *cfg)
a9533e7e 3577{
fe741e5e 3578 struct brcms_c_info *wlc = cfg->wlc;
a9533e7e
HP
3579
3580 /* if primary config, we need to update BSSID in RXE match registers */
8ea54c9f 3581 if (cfg == wlc->cfg)
fe741e5e 3582 brcms_c_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
839f9f62
RV
3583}
3584
11431424 3585static void brcms_b_set_shortslot(struct brcms_hardware *wlc_hw, bool shortslot)
839f9f62
RV
3586{
3587 wlc_hw->shortslot = shortslot;
3588
3589 if (BAND_2G(brcms_b_bandtype(wlc_hw)) && wlc_hw->up) {
3590 brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
3591 brcms_b_update_slot_timing(wlc_hw, shortslot);
3592 brcms_c_enable_mac(wlc_hw->wlc);
3593 }
a9533e7e
HP
3594}
3595
3596/*
3597 * Suspend the the MAC and update the slot timing
3598 * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
3599 */
fe741e5e 3600void brcms_c_switch_shortslot(struct brcms_c_info *wlc, bool shortslot)
a9533e7e
HP
3601{
3602 int idx;
471f1b51 3603 struct brcms_bss_cfg *cfg;
a9533e7e 3604
a9533e7e 3605 /* use the override if it is set */
7c783cef
RV
3606 if (wlc->shortslot_override != BRCMS_SHORTSLOT_AUTO)
3607 shortslot = (wlc->shortslot_override == BRCMS_SHORTSLOT_ON);
a9533e7e
HP
3608
3609 if (wlc->shortslot == shortslot)
3610 return;
3611
3612 wlc->shortslot = shortslot;
3613
3614 /* update the capability based on current shortslot mode */
49552d33 3615 FOREACH_BSS(wlc, idx, cfg)
a9533e7e
HP
3616 if (!cfg->associated)
3617 continue;
04795017
RV
3618 cfg->current_bss->capability &=
3619 ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
a9533e7e 3620 if (wlc->shortslot)
04795017
RV
3621 cfg->current_bss->capability |=
3622 WLAN_CAPABILITY_SHORT_SLOT_TIME;
49552d33 3623 END_FOREACH_BSS()
a9533e7e 3624
c654fce6 3625 brcms_b_set_shortslot(wlc->hw, shortslot);
a9533e7e
HP
3626}
3627
419ad34e
AS
3628/*
3629 * propagate home chanspec to all bsscfgs in
3630 * case bsscfg->current_bss->chanspec is referenced
3631 */
6bd20a1b 3632void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
a9533e7e
HP
3633{
3634 if (wlc->home_chanspec != chanspec) {
3635 int idx;
471f1b51 3636 struct brcms_bss_cfg *cfg;
a9533e7e
HP
3637
3638 wlc->home_chanspec = chanspec;
3639
49552d33 3640 FOREACH_BSS(wlc, idx, cfg)
a9533e7e
HP
3641 if (!cfg->associated)
3642 continue;
eff1b99a 3643
a9533e7e 3644 cfg->current_bss->chanspec = chanspec;
49552d33
AS
3645 END_FOREACH_BSS()
3646
a9533e7e
HP
3647
3648 }
3649}
3650
2682e2a3
AS
3651void
3652brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
3653 bool mute, struct txpwr_limits *txpwr)
a9533e7e 3654{
2682e2a3 3655 uint bandunit;
a9533e7e 3656
2682e2a3 3657 BCMMSG(wlc_hw->wlc->wiphy, "wl%d: 0x%x\n", wlc_hw->unit, chanspec);
839f9f62
RV
3658
3659 wlc_hw->chanspec = chanspec;
3660
3661 /* Switch bands if necessary */
3662 if (NBANDS_HW(wlc_hw) > 1) {
3663 bandunit = CHSPEC_BANDUNIT(chanspec);
3664 if (wlc_hw->band->bandunit != bandunit) {
3665 /* brcms_b_setband disables other bandunit,
3666 * use light band switch if not up yet
3667 */
3668 if (wlc_hw->up) {
3669 wlc_phy_chanspec_radio_set(wlc_hw->
3670 bandstate[bandunit]->
3671 pi, chanspec);
3672 brcms_b_setband(wlc_hw, bandunit, chanspec);
3673 } else {
3674 brcms_c_setxband(wlc_hw, bandunit);
3675 }
3676 }
3677 }
3678
3679 wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
3680
3681 if (!wlc_hw->up) {
3682 if (wlc_hw->clk)
3683 wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
3684 chanspec);
3685 wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
3686 } else {
3687 wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
3688 wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
3689
3690 /* Update muting of the channel */
3691 brcms_b_mute(wlc_hw, mute, 0);
3692 }
3693}
3694
2682e2a3
AS
3695/* switch to and initialize new band */
3696static void brcms_c_setband(struct brcms_c_info *wlc,
3697 uint bandunit)
3698{
3699 int idx;
3700 struct brcms_bss_cfg *cfg;
3701
3702 wlc->band = wlc->bandstate[bandunit];
3703
3704 if (!wlc->pub->up)
3705 return;
3706
3707 /* wait for at least one beacon before entering sleeping state */
3708 for (idx = 0; idx < BRCMS_MAXBSSCFG; idx++) {
3709 cfg = wlc->bsscfg[idx];
3710 if (cfg && BSSCFG_STA(cfg) && cfg->associated)
3711 cfg->PMawakebcn = true;
3712 }
3713 brcms_c_set_ps_ctrl(wlc);
3714
3715 /* band-specific initializations */
3716 brcms_c_bsinit(wlc);
3717}
3718
6bd20a1b 3719void brcms_c_set_chanspec(struct brcms_c_info *wlc, u16 chanspec)
a9533e7e
HP
3720{
3721 uint bandunit;
0965ae88 3722 bool switchband = false;
6bd20a1b 3723 u16 old_chanspec = wlc->chanspec;
a9533e7e 3724
f52a0ad0 3725 if (!brcms_c_valid_chanspec_db(wlc->cmi, chanspec)) {
b8f092c9
RV
3726 wiphy_err(wlc->wiphy, "wl%d: %s: Bad channel %d\n",
3727 wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
a9533e7e
HP
3728 return;
3729 }
3730
3731 /* Switch bands if necessary */
3732 if (NBANDS(wlc) > 1) {
7c783cef 3733 bandunit = CHSPEC_BANDUNIT(chanspec);
a9533e7e 3734 if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
0f0881b0 3735 switchband = true;
a9533e7e 3736 if (wlc->bandlocked) {
b8f092c9
RV
3737 wiphy_err(wlc->wiphy, "wl%d: %s: chspec %d "
3738 "band is locked!\n",
3739 wlc->pub->unit, __func__,
3740 CHSPEC_CHANNEL(chanspec));
a9533e7e
HP
3741 return;
3742 }
c654fce6
RV
3743 /*
3744 * should the setband call come after the
3745 * brcms_b_chanspec() ? if the setband updates
1c4c54ba 3746 * (brcms_c_bsinit) use low level calls to inspect and
c654fce6
RV
3747 * set state, the state inspected may be from the wrong
3748 * band, or the following brcms_b_set_chanspec() may
3749 * undo the work.
a9533e7e 3750 */
1c4c54ba 3751 brcms_c_setband(wlc, bandunit);
a9533e7e
HP
3752 }
3753 }
3754
a9533e7e 3755 /* sync up phy/radio chanspec */
1c4c54ba 3756 brcms_c_set_phy_chanspec(wlc, chanspec);
a9533e7e
HP
3757
3758 /* init antenna selection */
3759 if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
f52a0ad0 3760 brcms_c_antsel_init(wlc->asi);
a9533e7e
HP
3761
3762 /* Fix the hardware rateset based on bw.
3763 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
3764 */
f52a0ad0 3765 brcms_c_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
a9533e7e
HP
3766 wlc->band->
3767 mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
3768 : 0);
3769 }
3770
3771 /* update some mac configuration since chanspec changed */
1c4c54ba 3772 brcms_c_ucode_mac_upd(wlc);
a9533e7e
HP
3773}
3774
6bd20a1b 3775u32 brcms_c_lowest_basic_rspec(struct brcms_c_info *wlc,
fa67ebba 3776 struct brcms_c_rateset *rs)
a9533e7e 3777{
6bd20a1b 3778 u32 lowest_basic_rspec;
a9533e7e
HP
3779 uint i;
3780
3781 /* Use the lowest basic rate */
7c783cef 3782 lowest_basic_rspec = rs->rates[0] & BRCMS_RATE_MASK;
a9533e7e 3783 for (i = 0; i < rs->count; i++) {
7c783cef
RV
3784 if (rs->rates[i] & BRCMS_RATE_FLAG) {
3785 lowest_basic_rspec = rs->rates[i] & BRCMS_RATE_MASK;
a9533e7e
HP
3786 break;
3787 }
3788 }
b61c23c8 3789
419ad34e
AS
3790 /*
3791 * pick siso/cdd as default for OFDM (note no basic
3792 * rate MCSs are supported yet)
3793 */
8ea54c9f 3794 if (IS_OFDM(lowest_basic_rspec))
a9533e7e 3795 lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
8ea54c9f 3796
90ea2296 3797 return lowest_basic_rspec;
a9533e7e
HP
3798}
3799
419ad34e
AS
3800/*
3801 * This function changes the phytxctl for beacon based on current
3802 * beacon ratespec AND txant setting as per this table:
a9533e7e 3803 * ratespec CCK ant = wlc->stf->txant
8a76f1ee 3804 * OFDM ant = 3
a9533e7e 3805 */
fe741e5e 3806void brcms_c_beacon_phytxctl_txant_upd(struct brcms_c_info *wlc,
6bd20a1b 3807 u32 bcn_rspec)
a9533e7e 3808{
7d4df48e
GKH
3809 u16 phyctl;
3810 u16 phytxant = wlc->stf->phytxant;
3811 u16 mask = PHY_TXC_ANT_MASK;
a9533e7e
HP
3812
3813 /* for non-siso rates or default setting, use the available chains */
7c783cef 3814 if (BRCMS_PHY_11N_CAP(wlc->band))
f52a0ad0 3815 phytxant = brcms_c_stf_phytxchain_sel(wlc, bcn_rspec);
a9533e7e 3816
fe741e5e 3817 phyctl = brcms_c_read_shm(wlc, M_BCN_PCTLWD);
a9533e7e 3818 phyctl = (phyctl & ~mask) | phytxant;
fe741e5e 3819 brcms_c_write_shm(wlc, M_BCN_PCTLWD, phyctl);
a9533e7e
HP
3820}
3821
419ad34e
AS
3822/*
3823 * centralized protection config change function to simplify debugging, no
3824 * consistency checking this should be called only on changes to avoid overhead
3825 * in periodic function
3826 */
fe741e5e 3827void brcms_c_protection_upd(struct brcms_c_info *wlc, uint idx, int val)
a9533e7e 3828{
792aa408 3829 BCMMSG(wlc->wiphy, "idx %d, val %d\n", idx, val);
a9533e7e
HP
3830
3831 switch (idx) {
7c783cef 3832 case BRCMS_PROT_G_SPEC:
a9533e7e
HP
3833 wlc->protection->_g = (bool) val;
3834 break;
7c783cef 3835 case BRCMS_PROT_G_OVR:
562c8850 3836 wlc->protection->g_override = (s8) val;
a9533e7e 3837 break;
7c783cef 3838 case BRCMS_PROT_G_USER:
41feb5ed 3839 wlc->protection->gmode_user = (u8) val;
a9533e7e 3840 break;
7c783cef 3841 case BRCMS_PROT_OVERLAP:
562c8850 3842 wlc->protection->overlap = (s8) val;
a9533e7e 3843 break;
7c783cef 3844 case BRCMS_PROT_N_USER:
562c8850 3845 wlc->protection->nmode_user = (s8) val;
a9533e7e 3846 break;
7c783cef 3847 case BRCMS_PROT_N_CFG:
562c8850 3848 wlc->protection->n_cfg = (s8) val;
a9533e7e 3849 break;
7c783cef 3850 case BRCMS_PROT_N_CFG_OVR:
562c8850 3851 wlc->protection->n_cfg_override = (s8) val;
a9533e7e 3852 break;
7c783cef 3853 case BRCMS_PROT_N_NONGF:
a9533e7e
HP
3854 wlc->protection->nongf = (bool) val;
3855 break;
7c783cef 3856 case BRCMS_PROT_N_NONGF_OVR:
562c8850 3857 wlc->protection->nongf_override = (s8) val;
a9533e7e 3858 break;
7c783cef 3859 case BRCMS_PROT_N_PAM_OVR:
562c8850 3860 wlc->protection->n_pam_override = (s8) val;
a9533e7e 3861 break;
7c783cef 3862 case BRCMS_PROT_N_OBSS:
a9533e7e
HP
3863 wlc->protection->n_obss = (bool) val;
3864 break;
3865
3866 default:
a9533e7e
HP
3867 break;
3868 }
3869
3870}
3871
1c4c54ba 3872static void brcms_c_ht_update_sgi_rx(struct brcms_c_info *wlc, int val)
a9533e7e 3873{
651bd3a9
RV
3874 wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
3875 IEEE80211_HT_CAP_SGI_40);
7c783cef 3876 wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_20) ?
651bd3a9 3877 IEEE80211_HT_CAP_SGI_20 : 0;
7c783cef 3878 wlc->ht_cap.cap_info |= (val & BRCMS_N_SGI_40) ?
651bd3a9 3879 IEEE80211_HT_CAP_SGI_40 : 0;
a9533e7e
HP
3880
3881 if (wlc->pub->up) {
fe741e5e
RV
3882 brcms_c_update_beacon(wlc);
3883 brcms_c_update_probe_resp(wlc, true);
a9533e7e
HP
3884 }
3885}
3886
1c4c54ba 3887static void brcms_c_ht_update_ldpc(struct brcms_c_info *wlc, s8 val)
a9533e7e
HP
3888{
3889 wlc->stf->ldpc = val;
3890
651bd3a9 3891 wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
a9533e7e 3892 if (wlc->stf->ldpc != OFF)
651bd3a9 3893 wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
a9533e7e
HP
3894
3895 if (wlc->pub->up) {
fe741e5e
RV
3896 brcms_c_update_beacon(wlc);
3897 brcms_c_update_probe_resp(wlc, true);
0965ae88 3898 wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
a9533e7e
HP
3899 }
3900}
3901
419ad34e
AS
3902/*
3903 * Initialize a WME Parameter Info Element with default
3904 * STA parameters from WMM Spec, Table 12
3905 */
cc87568a
RV
3906void
3907brcms_c_wme_initparams_sta(struct brcms_c_info *wlc, struct wme_param_ie *pe)
a9533e7e 3908{
cc87568a 3909 static const struct wme_param_ie stadef = {
a9533e7e
HP
3910 WME_OUI,
3911 WME_TYPE,
3912 WME_SUBTYPE_PARAM_IE,
3913 WME_VER,
3914 0,
3915 0,
3916 {
3917 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
628f10ba 3918 cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
a9533e7e 3919 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
628f10ba 3920 cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
a9533e7e 3921 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
628f10ba 3922 cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
a9533e7e 3923 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
628f10ba 3924 cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
a9533e7e
HP
3925 }
3926 };
a9533e7e
HP
3927 memcpy(pe, &stadef, sizeof(*pe));
3928}
3929
fe741e5e 3930void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
a332bfc9
RV
3931 const struct ieee80211_tx_queue_params *params,
3932 bool suspend)
a9533e7e
HP
3933{
3934 int i;
cc87568a 3935 struct shm_acparams acp_shm;
7d4df48e 3936 u16 *shm_entry;
a9533e7e 3937
a9533e7e
HP
3938 /* Only apply params if the core is out of reset and has clocks */
3939 if (!wlc->clk) {
b8f092c9
RV
3940 wiphy_err(wlc->wiphy, "wl%d: %s : no-clock\n", wlc->pub->unit,
3941 __func__);
a9533e7e
HP
3942 return;
3943 }
3944
a9533e7e 3945 do {
cc87568a 3946 memset((char *)&acp_shm, 0, sizeof(struct shm_acparams));
a9533e7e 3947 /* fill in shm ac params struct */
628f10ba 3948 acp_shm.txop = le16_to_cpu(params->txop);
a9533e7e
HP
3949 /* convert from units of 32us to us for ucode */
3950 wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
3951 EDCF_TXOP2USEC(acp_shm.txop);
3952 acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
3953
3954 if (aci == AC_VI && acp_shm.txop == 0
3955 && acp_shm.aifs < EDCF_AIFSN_MAX)
3956 acp_shm.aifs++;
3957
3958 if (acp_shm.aifs < EDCF_AIFSN_MIN
3959 || acp_shm.aifs > EDCF_AIFSN_MAX) {
1c4c54ba 3960 wiphy_err(wlc->wiphy, "wl%d: edcf_setparams: bad "
b8f092c9 3961 "aifs %d\n", wlc->pub->unit, acp_shm.aifs);
a9533e7e
HP
3962 continue;
3963 }
3964
3965 acp_shm.cwmin = params->cw_min;
3966 acp_shm.cwmax = params->cw_max;
3967 acp_shm.cwcur = acp_shm.cwmin;
3968 acp_shm.bslots =
ff31c54c 3969 R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
a9533e7e
HP
3970 acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
3971 /* Indicate the new params to the ucode */
fe741e5e 3972 acp_shm.status = brcms_c_read_shm(wlc, (M_EDCF_QINFO +
a9533e7e
HP
3973 wme_shmemacindex(aci) *
3974 M_EDCF_QLEN +
3975 M_EDCF_STATUS_OFF));
3976 acp_shm.status |= WME_STATUS_NEWAC;
3977
3978 /* Fill in shm acparam table */
7d4df48e 3979 shm_entry = (u16 *) &acp_shm;
cc87568a 3980 for (i = 0; i < (int)sizeof(struct shm_acparams); i += 2)
fe741e5e 3981 brcms_c_write_shm(wlc,
a9533e7e
HP
3982 M_EDCF_QINFO +
3983 wme_shmemacindex(aci) * M_EDCF_QLEN + i,
3984 *shm_entry++);
3985
3986 } while (0);
3987
839f9f62
RV
3988 if (suspend)
3989 brcms_c_suspend_mac_and_wait(wlc);
3990
3991 if (suspend)
3992 brcms_c_enable_mac(wlc);
3993
3994}
3995
3996void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
3997{
3998 u16 aci;
3999 int i_ac;
4000 struct edcf_acparam *edcf_acp;
4001
4002 struct ieee80211_tx_queue_params txq_pars;
4003 struct ieee80211_tx_queue_params *params = &txq_pars;
4004
4005 /*
4006 * AP uses AC params from wme_param_ie_ap.
4007 * AP advertises AC params from wme_param_ie.
4008 * STA uses AC params from wme_param_ie.
4009 */
4010
4011 edcf_acp = (struct edcf_acparam *) &wlc->wme_param_ie.acparam[0];
4012
4013 for (i_ac = 0; i_ac < AC_COUNT; i_ac++, edcf_acp++) {
4014 /* find out which ac this set of params applies to */
4015 aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
4016
4017 /* fill in shm ac params struct */
4018 params->txop = edcf_acp->TXOP;
4019 params->aifs = edcf_acp->ACI;
4020
4021 /* CWmin = 2^(ECWmin) - 1 */
4022 params->cw_min = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
4023 /* CWmax = 2^(ECWmax) - 1 */
4024 params->cw_max = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
4025 >> EDCF_ECWMAX_SHIFT);
4026 brcms_c_wme_setparams(wlc, aci, params, suspend);
4027 }
4028
4029 if (suspend)
4030 brcms_c_suspend_mac_and_wait(wlc);
4031
4032 if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
4033 brcms_c_update_beacon(wlc);
4034 brcms_c_update_probe_resp(wlc, false);
4035 }
4036
4037 if (suspend)
4038 brcms_c_enable_mac(wlc);
4039
4040}
4041
2682e2a3
AS
4042/* maintain LED behavior in down state */
4043static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
839f9f62 4044{
2682e2a3
AS
4045 /*
4046 * maintain LEDs while in down state, turn on sbclk if
4047 * not available yet. Turn on sbclk if necessary
4048 */
4049 if (!AP_ENAB(wlc->pub)) {
4050 brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_FLIP);
839f9f62 4051
2682e2a3 4052 brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_FLIP);
839f9f62 4053 }
2682e2a3 4054}
839f9f62 4055
2682e2a3
AS
4056static bool brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
4057{
4058 /* Don't start the timer if HWRADIO feature is disabled */
4059 if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
4060 return true;
839f9f62 4061
2682e2a3
AS
4062 wlc->radio_monitor = true;
4063 brcms_c_pllreq(wlc, true, BRCMS_PLLREQ_RADIO_MON);
4064 brcms_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK,
4065 true);
4066 return true;
839f9f62
RV
4067}
4068
2682e2a3 4069void brcms_c_radio_disable(struct brcms_c_info *wlc)
839f9f62 4070{
2682e2a3
AS
4071 if (!wlc->pub->up) {
4072 brcms_c_down_led_upd(wlc);
4073 return;
4074 }
839f9f62 4075
2682e2a3
AS
4076 brcms_c_radio_monitor_start(wlc);
4077 brcms_down(wlc->wl);
4078}
839f9f62 4079
2682e2a3
AS
4080static void brcms_c_radio_enable(struct brcms_c_info *wlc)
4081{
4082 if (wlc->pub->up)
4083 return;
839f9f62 4084
2682e2a3
AS
4085 if (DEVICEREMOVED(wlc))
4086 return;
839f9f62 4087
2682e2a3
AS
4088 brcms_up(wlc->wl);
4089}
839f9f62 4090
2682e2a3
AS
4091bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
4092{
4093 if (!wlc->radio_monitor)
4094 return true;
839f9f62 4095
2682e2a3
AS
4096 wlc->radio_monitor = false;
4097 brcms_c_pllreq(wlc, false, BRCMS_PLLREQ_RADIO_MON);
4098 return brcms_del_timer(wlc->wl, wlc->radio_timer);
4099}
839f9f62 4100
2682e2a3
AS
4101/* read hwdisable state and propagate to wlc flag */
4102static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
4103{
4104 if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
4105 return;
4106
4107 if (brcms_b_radio_read_hwdisabled(wlc->hw))
4108 mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
4109 else
4110 mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
4111}
4112
4113/*
4114 * centralized radio disable/enable function,
4115 * invoke radio enable/disable after updating hwradio status
4116 */
4117static void brcms_c_radio_upd(struct brcms_c_info *wlc)
4118{
4119 if (wlc->pub->radio_disabled)
4120 brcms_c_radio_disable(wlc);
4121 else
4122 brcms_c_radio_enable(wlc);
4123}
4124
4125/* update hwradio status and return it */
4126bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
4127{
4128 brcms_c_radio_hwdisable_upd(wlc);
4129
4130 return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ?
4131 true : false;
4132}
4133
4134/* periodical query hw radio button while driver is "down" */
4135static void brcms_c_radio_timer(void *arg)
4136{
4137 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4138
4139 if (DEVICEREMOVED(wlc)) {
4140 wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
4141 __func__);
4142 brcms_down(wlc->wl);
4143 return;
4144 }
4145
4146 /* cap mpc off count */
4147 if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
4148 wlc->mpc_offcnt++;
4149
4150 brcms_c_radio_hwdisable_upd(wlc);
4151 brcms_c_radio_upd(wlc);
4152}
4153
4154/* common low-level watchdog code */
11431424 4155static void brcms_b_watchdog(void *arg)
2682e2a3
AS
4156{
4157 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4158 struct brcms_hardware *wlc_hw = wlc->hw;
4159
4160 BCMMSG(wlc->wiphy, "wl%d\n", wlc_hw->unit);
4161
4162 if (!wlc_hw->up)
4163 return;
4164
4165 /* increment second count */
4166 wlc_hw->now++;
4167
4168 /* Check for FIFO error interrupts */
4169 brcms_b_fifoerrors(wlc_hw);
4170
4171 /* make sure RX dma has buffers */
4172 dma_rxfill(wlc->hw->di[RX_FIFO]);
4173
4174 wlc_phy_watchdog(wlc_hw->band->pi);
4175}
4176
4177/* common watchdog code */
4178static void brcms_c_watchdog(void *arg)
4179{
4180 struct brcms_c_info *wlc = (struct brcms_c_info *) arg;
4181 int i;
4182 struct brcms_bss_cfg *cfg;
4183
4184 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
4185
4186 if (!wlc->pub->up)
4187 return;
4188
4189 if (DEVICEREMOVED(wlc)) {
4190 wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
4191 __func__);
4192 brcms_down(wlc->wl);
4193 return;
4194 }
4195
4196 /* increment second count */
4197 wlc->pub->now++;
4198
4199 /* delay radio disable */
4200 if (wlc->mpc_delay_off) {
4201 if (--wlc->mpc_delay_off == 0) {
4202 mboolset(wlc->pub->radio_disabled,
4203 WL_RADIO_MPC_DISABLE);
4204 if (wlc->mpc && brcms_c_ismpc(wlc))
4205 wlc->mpc_offcnt = 0;
4206 wlc->mpc_laston_ts = OSL_SYSUPTIME();
4207 }
4208 }
4209
4210 /* mpc sync */
4211 brcms_c_radio_mpc_upd(wlc);
4212 /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
4213 brcms_c_radio_hwdisable_upd(wlc);
4214 brcms_c_radio_upd(wlc);
4215 /* if radio is disable, driver may be down, quit here */
4216 if (wlc->pub->radio_disabled)
4217 return;
4218
4219 brcms_b_watchdog(wlc);
4220
4221 /*
4222 * occasionally sample mac stat counters to
4223 * detect 16-bit counter wrap
4224 */
4225 if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
4226 brcms_c_statsupd(wlc);
4227
4228 /* Manage TKIP countermeasures timers */
4229 FOREACH_BSS(wlc, i, cfg)
4230 if (cfg->tk_cm_dt)
4231 cfg->tk_cm_dt--;
4232 if (cfg->tk_cm_bt)
4233 cfg->tk_cm_bt--;
4234 END_FOREACH_BSS()
4235
4236 if (BRCMS_ISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
4237 ((wlc->pub->now - wlc->tempsense_lasttime) >=
4238 BRCMS_TEMPSENSE_PERIOD)) {
4239 wlc->tempsense_lasttime = wlc->pub->now;
4240 brcms_c_tempsense_upd(wlc);
4241 }
4242}
4243
4244static void brcms_c_watchdog_by_timer(void *arg)
4245{
4246 brcms_c_watchdog(arg);
4247}
4248
4249bool brcms_c_timers_init(struct brcms_c_info *wlc, int unit)
4250{
4251 wlc->wdtimer = brcms_init_timer(wlc->wl, brcms_c_watchdog_by_timer,
4252 wlc, "watchdog");
4253 if (!wlc->wdtimer) {
4254 wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for wdtimer "
4255 "failed\n", unit);
4256 goto fail;
4257 }
4258
4259 wlc->radio_timer = brcms_init_timer(wlc->wl, brcms_c_radio_timer,
4260 wlc, "radio");
4261 if (!wlc->radio_timer) {
4262 wiphy_err(wlc->wiphy, "wl%d: wl_init_timer for radio_timer "
4263 "failed\n", unit);
4264 goto fail;
4265 }
4266
4267 return true;
4268
4269 fail:
4270 return false;
4271}
4272
4273/*
4274 * Initialize brcms_c_info default values ...
4275 * may get overrides later in this function
4276 */
4277void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
4278{
4279 int i;
4280 /* Assume the device is there until proven otherwise */
4281 wlc->device_present = true;
4282
4283 /* Save our copy of the chanspec */
4284 wlc->chanspec = CH20MHZ_CHSPEC(1);
4285
4286 /* various 802.11g modes */
4287 wlc->shortslot = false;
4288 wlc->shortslot_override = BRCMS_SHORTSLOT_AUTO;
4289
4290 brcms_c_protection_upd(wlc, BRCMS_PROT_G_OVR, BRCMS_PROTECTION_AUTO);
4291 brcms_c_protection_upd(wlc, BRCMS_PROT_G_SPEC, false);
4292
4293 brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG_OVR,
4294 BRCMS_PROTECTION_AUTO);
4295 brcms_c_protection_upd(wlc, BRCMS_PROT_N_CFG, BRCMS_N_PROTECTION_OFF);
4296 brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF_OVR,
4297 BRCMS_PROTECTION_AUTO);
4298 brcms_c_protection_upd(wlc, BRCMS_PROT_N_NONGF, false);
4299 brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR, AUTO);
4300
4301 brcms_c_protection_upd(wlc, BRCMS_PROT_OVERLAP,
4302 BRCMS_PROTECTION_CTL_OVERLAP);
4303
4304 /* 802.11g draft 4.0 NonERP elt advertisement */
4305 wlc->include_legacy_erp = true;
4306
4307 wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
4308 wlc->stf->txant = ANT_TX_DEF;
4309
4310 wlc->prb_resp_timeout = BRCMS_PRB_RESP_TIMEOUT;
839f9f62
RV
4311
4312 wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
4313 for (i = 0; i < NFIFO; i++)
4314 wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
4315 wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
4316
4317 /* default rate fallback retry limits */
4318 wlc->SFBL = RETRY_SHORT_FB;
4319 wlc->LFBL = RETRY_LONG_FB;
4320
4321 /* default mac retry limits */
4322 wlc->SRL = RETRY_SHORT_DEF;
4323 wlc->LRL = RETRY_LONG_DEF;
4324
4325 /* Set flag to indicate that hw keys should be used when available. */
4326 wlc->wsec_swkeys = false;
4327
4328 /* init the 4 static WEP default keys */
4329 for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
4330 wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
4331 wlc->wsec_keys[i]->idx = (u8) i;
4332 }
4333
4334 /* WME QoS mode is Auto by default */
4335 wlc->pub->_wme = AUTO;
839f9f62
RV
4336 wlc->pub->_ampdu = AMPDU_AGG_HOST;
4337 wlc->pub->bcmerror = 0;
4338 wlc->pub->_coex = ON;
4339
4340 /* initialize mpc delay */
4341 wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
4342}
4343
4344static bool brcms_c_state_bmac_sync(struct brcms_c_info *wlc)
4345{
4346 struct brcms_b_state state_bmac = {0};
4347
4348 if (brcms_b_state_get(wlc->hw, &state_bmac) != 0)
4349 return false;
4350
4351 wlc->machwcap = state_bmac.machwcap;
4352 brcms_c_protection_upd(wlc, BRCMS_PROT_N_PAM_OVR,
4353 (s8) state_bmac.preamble_ovr);
4354
4355 return true;
4356}
4357
4358static uint brcms_c_attach_module(struct brcms_c_info *wlc)
4359{
4360 uint err = 0;
4361 uint unit;
4362 unit = wlc->pub->unit;
4363
4364 wlc->asi = brcms_c_antsel_attach(wlc);
4365 if (wlc->asi == NULL) {
4366 wiphy_err(wlc->wiphy, "wl%d: attach: antsel_attach "
4367 "failed\n", unit);
4368 err = 44;
4369 goto fail;
4370 }
4371
4372 wlc->ampdu = brcms_c_ampdu_attach(wlc);
4373 if (wlc->ampdu == NULL) {
4374 wiphy_err(wlc->wiphy, "wl%d: attach: ampdu_attach "
4375 "failed\n", unit);
4376 err = 50;
4377 goto fail;
4378 }
4379
4380 if ((brcms_c_stf_attach(wlc) != 0)) {
4381 wiphy_err(wlc->wiphy, "wl%d: attach: stf_attach "
4382 "failed\n", unit);
4383 err = 68;
4384 goto fail;
4385 }
4386 fail:
4387 return err;
4388}
4389
2f6b1dde 4390struct brcms_pub *brcms_c_pub(struct brcms_c_info *wlc)
839f9f62 4391{
2f6b1dde 4392 return wlc->pub;
839f9f62
RV
4393}
4394
4395#define CHIP_SUPPORTS_11N(wlc) 1
4396
4397/* low level attach
4398 * run backplane attach, init nvram
4399 * run phy attach
4400 * initialize software state for each core and band
4401 * put the whole chip in reset(driver down state), no clock
4402 */
11431424
AS
4403static int brcms_b_attach(struct brcms_c_info *wlc, u16 vendor, u16 device,
4404 uint unit, bool piomode, void *regsva,
4405 struct pci_dev *btparam)
839f9f62
RV
4406{
4407 struct brcms_hardware *wlc_hw;
0da64910 4408 struct d11regs *regs;
839f9f62
RV
4409 char *macaddr = NULL;
4410 char *vars;
4411 uint err = 0;
4412 uint j;
4413 bool wme = false;
4414 struct shared_phy_params sha_params;
4415 struct wiphy *wiphy = wlc->wiphy;
821e4e93
RV
4416 char *var;
4417 unsigned long res;
839f9f62
RV
4418
4419 BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, vendor,
4420 device);
a9533e7e 4421
839f9f62 4422 wme = true;
a9533e7e 4423
839f9f62
RV
4424 wlc_hw = wlc->hw;
4425 wlc_hw->wlc = wlc;
4426 wlc_hw->unit = unit;
4427 wlc_hw->band = wlc_hw->bandstate[0];
4428 wlc_hw->_piomode = piomode;
a9533e7e 4429
839f9f62
RV
4430 /* populate struct brcms_hardware with default values */
4431 brcms_b_info_init(wlc_hw);
3b6ee723 4432
839f9f62 4433 /*
419ad34e
AS
4434 * Do the hardware portion of the attach. Also initialize software
4435 * state that depends on the particular hardware we are running.
839f9f62 4436 */
821e4e93 4437 wlc_hw->sih = ai_attach(regsva, btparam,
839f9f62
RV
4438 &wlc_hw->vars, &wlc_hw->vars_size);
4439 if (wlc_hw->sih == NULL) {
4440 wiphy_err(wiphy, "wl%d: brcms_b_attach: si_attach failed\n",
4441 unit);
4442 err = 11;
4443 goto fail;
4444 }
4445 vars = wlc_hw->vars;
a9533e7e 4446
a9533e7e 4447 /*
839f9f62
RV
4448 * Get vendid/devid nvram overwrites, which could be different
4449 * than those the BIOS recognizes for devices on PCMCIA_BUS,
4450 * SDIO_BUS, and SROMless devices on PCI_BUS.
a9533e7e 4451 */
821e4e93
RV
4452 var = getvar(vars, "vendid");
4453 if (var && !kstrtoul(var, 0, &res)) {
4454 vendor = (u16)res;
4455 wiphy_err(wiphy, "Overriding vendor id = 0x%x\n",
4456 vendor);
4457 }
4458 var = getvar(vars, "devid");
4459 if (var && !kstrtoul(var, 0, &res)) {
4460 u16 devid = (u16)res;
4461 if (devid != 0xffff) {
4462 device = devid;
4463 wiphy_err(wiphy, "Overriding device id = 0x%x"
4464 "\n", device);
839f9f62 4465 }
821e4e93 4466 }
a9533e7e 4467
821e4e93
RV
4468 /* verify again the device is supported */
4469 if (!brcms_c_chipmatch(vendor, device)) {
4470 wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported "
4471 "vendor/device (0x%x/0x%x)\n",
4472 unit, vendor, device);
4473 err = 12;
4474 goto fail;
839f9f62 4475 }
a9533e7e 4476
839f9f62
RV
4477 wlc_hw->vendorid = vendor;
4478 wlc_hw->deviceid = device;
a9533e7e 4479
839f9f62 4480 /* set bar0 window to point at D11 core */
0da64910
RV
4481 wlc_hw->regs = (struct d11regs *) ai_setcore(wlc_hw->sih, D11_CORE_ID,
4482 0);
839f9f62 4483 wlc_hw->corerev = ai_corerev(wlc_hw->sih);
a9533e7e 4484
839f9f62 4485 regs = wlc_hw->regs;
a9533e7e 4486
839f9f62
RV
4487 wlc->regs = wlc_hw->regs;
4488
4489 /* validate chip, chiprev and corerev */
4490 if (!brcms_c_isgoodchip(wlc_hw)) {
4491 err = 13;
4492 goto fail;
a9533e7e
HP
4493 }
4494
839f9f62
RV
4495 /* initialize power control registers */
4496 ai_clkctl_init(wlc_hw->sih);
a9533e7e 4497
839f9f62
RV
4498 /* request fastclock and force fastclock for the rest of attach
4499 * bring the d11 core out of reset.
419ad34e
AS
4500 * For PMU chips, the first wlc_clkctl_clk is no-op since core-clk
4501 * is still false; But it will be called again inside wlc_corereset,
4502 * after d11 is out of reset.
839f9f62
RV
4503 */
4504 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
4505 brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
a9533e7e 4506
839f9f62
RV
4507 if (!brcms_b_validate_chip_access(wlc_hw)) {
4508 wiphy_err(wiphy, "wl%d: brcms_b_attach: validate_chip_access "
4509 "failed\n", unit);
4510 err = 14;
a9533e7e
HP
4511 goto fail;
4512 }
4513
839f9f62
RV
4514 /* get the board rev, used just below */
4515 j = getintvar(vars, "boardrev");
4516 /* promote srom boardrev of 0xFF to 1 */
4517 if (j == BOARDREV_PROMOTABLE)
4518 j = BOARDREV_PROMOTED;
4519 wlc_hw->boardrev = (u16) j;
4520 if (!brcms_c_validboardtype(wlc_hw)) {
4521 wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported Broadcom "
4522 "board type (0x%x)" " or revision level (0x%x)\n",
4523 unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
4524 err = 15;
a9533e7e
HP
4525 goto fail;
4526 }
839f9f62
RV
4527 wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
4528 wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
4529 wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
a9533e7e 4530
839f9f62
RV
4531 if (wlc_hw->boardflags & BFL_NOPLLDOWN)
4532 brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED);
a9533e7e 4533
821e4e93 4534 if (ai_pci_war16165(wlc_hw->sih))
839f9f62 4535 wlc->war16165 = true;
a9533e7e 4536
839f9f62
RV
4537 /* check device id(srom, nvram etc.) to set bands */
4538 if (wlc_hw->deviceid == BCM43224_D11N_ID ||
8ea54c9f 4539 wlc_hw->deviceid == BCM43224_D11N_ID_VEN1)
839f9f62
RV
4540 /* Dualband boards */
4541 wlc_hw->_nbands = 2;
8ea54c9f 4542 else
839f9f62 4543 wlc_hw->_nbands = 1;
a9533e7e 4544
839f9f62
RV
4545 if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
4546 wlc_hw->_nbands = 1;
a9533e7e 4547
839f9f62
RV
4548 /* BMAC_NOTE: remove init of pub values when brcms_c_attach()
4549 * unconditionally does the init of these values
4550 */
4551 wlc->vendorid = wlc_hw->vendorid;
4552 wlc->deviceid = wlc_hw->deviceid;
4553 wlc->pub->sih = wlc_hw->sih;
4554 wlc->pub->corerev = wlc_hw->corerev;
4555 wlc->pub->sromrev = wlc_hw->sromrev;
4556 wlc->pub->boardrev = wlc_hw->boardrev;
4557 wlc->pub->boardflags = wlc_hw->boardflags;
4558 wlc->pub->boardflags2 = wlc_hw->boardflags2;
4559 wlc->pub->_nbands = wlc_hw->_nbands;
a9533e7e 4560
839f9f62 4561 wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
a9533e7e 4562
839f9f62
RV
4563 if (wlc_hw->physhim == NULL) {
4564 wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_shim_attach "
4565 "failed\n", unit);
4566 err = 25;
4567 goto fail;
4568 }
a9533e7e 4569
839f9f62
RV
4570 /* pass all the parameters to wlc_phy_shared_attach in one struct */
4571 sha_params.sih = wlc_hw->sih;
4572 sha_params.physhim = wlc_hw->physhim;
4573 sha_params.unit = unit;
4574 sha_params.corerev = wlc_hw->corerev;
4575 sha_params.vars = vars;
4576 sha_params.vid = wlc_hw->vendorid;
4577 sha_params.did = wlc_hw->deviceid;
4578 sha_params.chip = wlc_hw->sih->chip;
4579 sha_params.chiprev = wlc_hw->sih->chiprev;
4580 sha_params.chippkg = wlc_hw->sih->chippkg;
4581 sha_params.sromrev = wlc_hw->sromrev;
4582 sha_params.boardtype = wlc_hw->sih->boardtype;
4583 sha_params.boardrev = wlc_hw->boardrev;
4584 sha_params.boardvendor = wlc_hw->sih->boardvendor;
4585 sha_params.boardflags = wlc_hw->boardflags;
4586 sha_params.boardflags2 = wlc_hw->boardflags2;
839f9f62 4587 sha_params.buscorerev = wlc_hw->sih->buscorerev;
a9533e7e 4588
839f9f62
RV
4589 /* alloc and save pointer to shared phy state area */
4590 wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
4591 if (!wlc_hw->phy_sh) {
4592 err = 16;
4593 goto fail;
4594 }
4595
4596 /* initialize software state for each core and band */
4597 for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
4598 /*
4599 * band0 is always 2.4Ghz
4600 * band1, if present, is 5Ghz
4601 */
a9533e7e 4602
839f9f62
RV
4603 /* So if this is a single band 11a card, use band 1 */
4604 if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
4605 j = BAND_5G_INDEX;
a9533e7e 4606
839f9f62 4607 brcms_c_setxband(wlc_hw, j);
a9533e7e 4608
839f9f62
RV
4609 wlc_hw->band->bandunit = j;
4610 wlc_hw->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
4611 wlc->band->bandunit = j;
4612 wlc->band->bandtype = j ? BRCM_BAND_5G : BRCM_BAND_2G;
4613 wlc->core->coreidx = ai_coreidx(wlc_hw->sih);
a9533e7e 4614
839f9f62
RV
4615 wlc_hw->machwcap = R_REG(&regs->machwcap);
4616 wlc_hw->machwcap_backup = wlc_hw->machwcap;
a9533e7e 4617
839f9f62
RV
4618 /* init tx fifo size */
4619 wlc_hw->xmtfifo_sz =
4620 xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
a9533e7e 4621
839f9f62 4622 /* Get a phy for this band */
d89a4c80
RV
4623 wlc_hw->band->pi =
4624 wlc_phy_attach(wlc_hw->phy_sh, regs,
4625 brcms_b_bandtype(wlc_hw), vars,
4626 wlc->wiphy);
839f9f62
RV
4627 if (wlc_hw->band->pi == NULL) {
4628 wiphy_err(wiphy, "wl%d: brcms_b_attach: wlc_phy_"
4629 "attach failed\n", unit);
4630 err = 17;
4631 goto fail;
4632 }
a9533e7e 4633
839f9f62 4634 wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
a9533e7e 4635
839f9f62
RV
4636 wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
4637 &wlc_hw->band->phyrev,
4638 &wlc_hw->band->radioid,
4639 &wlc_hw->band->radiorev);
4640 wlc_hw->band->abgphy_encore =
4641 wlc_phy_get_encore(wlc_hw->band->pi);
4642 wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
4643 wlc_hw->band->core_flags =
4644 wlc_phy_get_coreflags(wlc_hw->band->pi);
a9533e7e 4645
839f9f62
RV
4646 /* verify good phy_type & supported phy revision */
4647 if (BRCMS_ISNPHY(wlc_hw->band)) {
4648 if (NCONF_HAS(wlc_hw->band->phyrev))
4649 goto good_phy;
4650 else
4651 goto bad_phy;
4652 } else if (BRCMS_ISLCNPHY(wlc_hw->band)) {
4653 if (LCNCONF_HAS(wlc_hw->band->phyrev))
4654 goto good_phy;
4655 else
4656 goto bad_phy;
4657 } else {
4658 bad_phy:
4659 wiphy_err(wiphy, "wl%d: brcms_b_attach: unsupported "
4660 "phy type/rev (%d/%d)\n", unit,
4661 wlc_hw->band->phytype, wlc_hw->band->phyrev);
4662 err = 18;
4663 goto fail;
4664 }
a9533e7e 4665
839f9f62 4666 good_phy:
419ad34e
AS
4667 /*
4668 * BMAC_NOTE: wlc->band->pi should not be set below and should
4669 * be done in the high level attach. However we can not make
4670 * that change until all low level access is changed to
4671 * wlc_hw->band->pi. Instead do the wlc->band->pi init below,
4672 * keeping wlc_hw->band->pi as well for incremental update of
4673 * low level fns, and cut over low only init when all fns
4674 * updated.
839f9f62
RV
4675 */
4676 wlc->band->pi = wlc_hw->band->pi;
4677 wlc->band->phytype = wlc_hw->band->phytype;
4678 wlc->band->phyrev = wlc_hw->band->phyrev;
4679 wlc->band->radioid = wlc_hw->band->radioid;
4680 wlc->band->radiorev = wlc_hw->band->radiorev;
a9533e7e 4681
839f9f62
RV
4682 /* default contention windows size limits */
4683 wlc_hw->band->CWmin = APHY_CWMIN;
4684 wlc_hw->band->CWmax = PHY_CWMAX;
a9533e7e 4685
839f9f62
RV
4686 if (!brcms_b_attach_dmapio(wlc, j, wme)) {
4687 err = 19;
4688 goto fail;
4689 }
4690 }
a9533e7e 4691
839f9f62
RV
4692 /* disable core to match driver "down" state */
4693 brcms_c_coredisable(wlc_hw);
a9533e7e 4694
839f9f62 4695 /* Match driver "down" state */
821e4e93 4696 ai_pci_down(wlc_hw->sih);
a9533e7e 4697
839f9f62
RV
4698 /* register sb interrupt callback functions */
4699 ai_register_intr_callback(wlc_hw->sih, (void *)brcms_c_wlintrsoff,
4700 (void *)brcms_c_wlintrsrestore, NULL, wlc);
a9533e7e 4701
839f9f62
RV
4702 /* turn off pll and xtal to match driver "down" state */
4703 brcms_b_xtal(wlc_hw, OFF);
a9533e7e 4704
419ad34e 4705 /* *******************************************************************
839f9f62
RV
4706 * The hardware is in the DOWN state at this point. D11 core
4707 * or cores are in reset with clocks off, and the board PLLs
4708 * are off if possible.
4709 *
4710 * Beyond this point, wlc->sbclk == false and chip registers
4711 * should not be touched.
4712 *********************************************************************
4713 */
a9533e7e 4714
839f9f62
RV
4715 /* init etheraddr state variables */
4716 macaddr = brcms_c_get_macaddr(wlc_hw);
4717 if (macaddr == NULL) {
4718 wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n",
4719 unit);
4720 err = 21;
a9533e7e
HP
4721 goto fail;
4722 }
5973f660
AS
4723 if (!mac_pton(macaddr, wlc_hw->etheraddr) ||
4724 is_broadcast_ether_addr(wlc_hw->etheraddr) ||
839f9f62
RV
4725 is_zero_ether_addr(wlc_hw->etheraddr)) {
4726 wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n",
4727 unit, macaddr);
4728 err = 22;
a9533e7e
HP
4729 goto fail;
4730 }
839f9f62
RV
4731
4732 BCMMSG(wlc->wiphy,
4733 "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
4734 wlc_hw->deviceid, wlc_hw->_nbands,
4735 wlc_hw->sih->boardtype, macaddr);
4736
a9533e7e 4737 return err;
a9533e7e 4738
839f9f62
RV
4739 fail:
4740 wiphy_err(wiphy, "wl%d: brcms_b_attach: failed with err %d\n", unit,
4741 err);
4742 return err;
a9533e7e
HP
4743}
4744
2682e2a3 4745static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
0d2f0724 4746{
2682e2a3
AS
4747 uint unit;
4748 unit = wlc->pub->unit;
a9533e7e 4749
2682e2a3
AS
4750 if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
4751 /* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
4752 wlc->band->antgain = 8;
4753 } else if (wlc->band->antgain == -1) {
4754 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
4755 " srom, using 2dB\n", unit, __func__);
4756 wlc->band->antgain = 8;
4757 } else {
4758 s8 gain, fract;
4759 /* Older sroms specified gain in whole dbm only. In order
4760 * be able to specify qdbm granularity and remain backward
4761 * compatible the whole dbms are now encoded in only
4762 * low 6 bits and remaining qdbms are encoded in the hi 2 bits.
4763 * 6 bit signed number ranges from -32 - 31.
4764 *
4765 * Examples:
4766 * 0x1 = 1 db,
4767 * 0xc1 = 1.75 db (1 + 3 quarters),
4768 * 0x3f = -1 (-1 + 0 quarters),
4769 * 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
4770 * 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
4771 */
4772 gain = wlc->band->antgain & 0x3f;
4773 gain <<= 2; /* Sign extend */
4774 gain >>= 2;
4775 fract = (wlc->band->antgain & 0xc0) >> 6;
4776 wlc->band->antgain = 4 * gain + fract;
4777 }
4778}
a9533e7e 4779
2682e2a3
AS
4780static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
4781{
4782 int aa;
4783 uint unit;
4784 char *vars;
4785 int bandtype;
4786
4787 unit = wlc->pub->unit;
4788 vars = wlc->pub->vars;
4789 bandtype = wlc->band->bandtype;
4790
4791 /* get antennas available */
4792 aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
4793 if (aa == 0)
4794 aa = (s8) getintvar(vars,
4795 (BAND_5G(bandtype) ? "aa1" : "aa0"));
4796 if ((aa < 1) || (aa > 15)) {
4797 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
4798 " srom (0x%x), using 3\n", unit, __func__, aa);
4799 aa = 3;
4800 }
4801
4802 /* reset the defaults if we have a single antenna */
4803 if (aa == 1) {
4804 wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
4805 wlc->stf->txant = ANT_TX_FORCE_0;
4806 } else if (aa == 2) {
4807 wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
4808 wlc->stf->txant = ANT_TX_FORCE_1;
4809 } else {
4810 }
4811
4812 /* Compute Antenna Gain */
4813 wlc->band->antgain =
4814 (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
4815 brcms_c_attach_antgain_init(wlc);
4816
4817 return true;
4818}
4819
4820static void brcms_c_bss_default_init(struct brcms_c_info *wlc)
4821{
4822 u16 chanspec;
4823 struct brcms_band *band;
4824 struct brcms_bss_info *bi = wlc->default_bss;
4825
4826 /* init default and target BSS with some sane initial values */
4827 memset((char *)(bi), 0, sizeof(struct brcms_bss_info));
4828 bi->beacon_period = BEACON_INTERVAL_DEFAULT;
4829 bi->dtim_period = DTIM_INTERVAL_DEFAULT;
4830
4831 /* fill the default channel as the first valid channel
4832 * starting from the 2G channels
4833 */
4834 chanspec = CH20MHZ_CHSPEC(1);
4835 wlc->home_chanspec = bi->chanspec = chanspec;
4836
4837 /* find the band of our default channel */
4838 band = wlc->band;
4839 if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_BANDUNIT(chanspec))
4840 band = wlc->bandstate[OTHERBANDUNIT(wlc)];
4841
4842 /* init bss rates to the band specific default rate set */
4843 brcms_c_rateset_default(&bi->rateset, NULL, band->phytype,
4844 band->bandtype, false, BRCMS_RATE_MASK_FULL,
4845 (bool) N_ENAB(wlc->pub), CHSPEC_WLC_BW(chanspec),
4846 wlc->stf->txstreams);
4847
4848 if (N_ENAB(wlc->pub))
4849 bi->flags |= BRCMS_BSS_HT;
4850}
4851
4852static struct brcms_txq_info *brcms_c_txq_alloc(struct brcms_c_info *wlc)
4853{
4854 struct brcms_txq_info *qi, *p;
4855
4856 qi = kzalloc(sizeof(struct brcms_txq_info), GFP_ATOMIC);
4857 if (qi != NULL) {
4858 /*
4859 * Have enough room for control packets along with HI watermark
4860 * Also, add room to txq for total psq packets if all the SCBs
4861 * leave PS mode. The watermark for flowcontrol to OS packets
4862 * will remain the same
4863 */
4864 brcmu_pktq_init(&qi->q, BRCMS_PREC_COUNT,
4865 (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
4866 + wlc->pub->psq_pkts_total);
4867
4868 /* add this queue to the the global list */
4869 p = wlc->tx_queues;
4870 if (p == NULL) {
4871 wlc->tx_queues = qi;
4872 } else {
4873 while (p->next != NULL)
4874 p = p->next;
4875 p->next = qi;
4876 }
4877 }
4878 return qi;
4879}
4880
4881static void brcms_c_txq_free(struct brcms_c_info *wlc,
4882 struct brcms_txq_info *qi)
4883{
4884 struct brcms_txq_info *p;
4885
4886 if (qi == NULL)
4887 return;
4888
4889 /* remove the queue from the linked list */
4890 p = wlc->tx_queues;
4891 if (p == qi)
4892 wlc->tx_queues = p->next;
4893 else {
4894 while (p != NULL && p->next != qi)
4895 p = p->next;
4896 if (p != NULL)
4897 p->next = p->next->next;
4898 }
4899
4900 kfree(qi);
4901}
4902
4903static void brcms_c_update_mimo_band_bwcap(struct brcms_c_info *wlc, u8 bwcap)
4904{
4905 uint i;
4906 struct brcms_band *band;
4907
4908 for (i = 0; i < NBANDS(wlc); i++) {
4909 if (IS_SINGLEBAND_5G(wlc->deviceid))
4910 i = BAND_5G_INDEX;
4911 band = wlc->bandstate[i];
4912 if (band->bandtype == BRCM_BAND_5G) {
4913 if ((bwcap == BRCMS_N_BW_40ALL)
4914 || (bwcap == BRCMS_N_BW_20IN2G_40IN5G))
4915 band->mimo_cap_40 = true;
4916 else
4917 band->mimo_cap_40 = false;
4918 } else {
4919 if (bwcap == BRCMS_N_BW_40ALL)
4920 band->mimo_cap_40 = true;
4921 else
4922 band->mimo_cap_40 = false;
4923 }
4924 }
4925}
4926
4927/*
4928 * The common driver entry routine. Error codes should be unique
4929 */
4930struct brcms_c_info *
4931brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
4932 bool piomode, void *regsva, struct pci_dev *btparam, uint *perr)
4933{
4934 struct brcms_c_info *wlc;
4935 uint err = 0;
4936 uint j;
4937 struct brcms_pub *pub;
4938 uint n_disabled;
4939
4940 /* allocate struct brcms_c_info state and its substructures */
4941 wlc = (struct brcms_c_info *) brcms_c_attach_malloc(unit, &err, device);
4942 if (wlc == NULL)
4943 goto fail;
4944 wlc->wiphy = wl->wiphy;
4945 pub = wlc->pub;
4946
4947#if defined(BCMDBG)
4948 wlc_info_dbg = wlc;
a9533e7e
HP
4949#endif
4950
4951 wlc->band = wlc->bandstate[0];
4952 wlc->core = wlc->corestate;
4953 wlc->wl = wl;
4954 pub->unit = unit;
a9533e7e 4955 pub->_piomode = piomode;
0965ae88 4956 wlc->bandinit_pending = false;
a9533e7e 4957
fe741e5e
RV
4958 /* populate struct brcms_c_info with default values */
4959 brcms_c_info_init(wlc, unit);
a9533e7e
HP
4960
4961 /* update sta/ap related parameters */
fe741e5e 4962 brcms_c_ap_upd(wlc);
a9533e7e
HP
4963
4964 /* 11n_disable nvram */
4965 n_disabled = getintvar(pub->vars, "11n_disable");
4966
810acd19
AS
4967 /*
4968 * low level attach steps(all hw accesses go
4969 * inside, no more in rest of the attach)
4970 */
c654fce6 4971 err = brcms_b_attach(wlc, vendor, device, unit, piomode, regsva,
821e4e93 4972 btparam);
a9533e7e
HP
4973 if (err)
4974 goto fail;
4975
419ad34e
AS
4976 /*
4977 * for some states, due to different info pointer(e,g, wlc, wlc_hw) or
4978 * master/slave split, HIGH driver(both monolithic and HIGH_ONLY) needs
4979 * to sync states FROM BMAC portion driver
a9533e7e 4980 */
1c4c54ba 4981 if (!brcms_c_state_bmac_sync(wlc)) {
a9533e7e
HP
4982 err = 20;
4983 goto fail;
4984 }
4985
7c783cef 4986 pub->phy_11ncapable = BRCMS_PHY_11N_CAP(wlc->band);
a9533e7e
HP
4987
4988 /* propagate *vars* from BMAC driver to high driver */
c654fce6 4989 brcms_b_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
a9533e7e 4990
a9533e7e
HP
4991
4992 /* set maximum allowed duty cycle */
4993 wlc->tx_duty_cycle_ofdm =
7d4df48e 4994 (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
a9533e7e 4995 wlc->tx_duty_cycle_cck =
7d4df48e 4996 (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
a9533e7e 4997
f52a0ad0 4998 brcms_c_stf_phy_chain_calc(wlc);
a9533e7e
HP
4999
5000 /* txchain 1: txant 0, txchain 2: txant 1 */
7c783cef 5001 if (BRCMS_ISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
a9533e7e
HP
5002 wlc->stf->txant = wlc->stf->hw_txchain - 1;
5003
5004 /* push to BMAC driver */
5005 wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
5006 wlc->stf->hw_rxchain);
5007
a9533e7e
HP
5008 /* pull up some info resulting from the low attach */
5009 {
5010 int i;
5011 for (i = 0; i < NFIFO; i++)
5012 wlc->core->txavail[i] = wlc->hw->txavail[i];
5013 }
a9533e7e 5014
c654fce6 5015 brcms_b_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
a9533e7e 5016
02160695 5017 memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
a9533e7e
HP
5018
5019 for (j = 0; j < NBANDS(wlc); j++) {
5020 /* Use band 1 for single band 11a */
5021 if (IS_SINGLEBAND_5G(wlc->deviceid))
5022 j = BAND_5G_INDEX;
5023
5024 wlc->band = wlc->bandstate[j];
5025
1c4c54ba 5026 if (!brcms_c_attach_stf_ant_init(wlc)) {
a9533e7e
HP
5027 err = 24;
5028 goto fail;
5029 }
5030
5031 /* default contention windows size limits */
5032 wlc->band->CWmin = APHY_CWMIN;
5033 wlc->band->CWmax = PHY_CWMAX;
5034
5035 /* init gmode value */
5036 if (BAND_2G(wlc->band->bandtype)) {
5037 wlc->band->gmode = GMODE_AUTO;
7c783cef 5038 brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER,
a9533e7e
HP
5039 wlc->band->gmode);
5040 }
5041
5042 /* init _n_enab supported mode */
7c783cef 5043 if (BRCMS_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
a9533e7e
HP
5044 if (n_disabled & WLFEATURE_DISABLE_11N) {
5045 pub->_n_enab = OFF;
7c783cef 5046 brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
fe741e5e 5047 OFF);
a9533e7e
HP
5048 } else {
5049 pub->_n_enab = SUPPORT_11N;
7c783cef 5050 brcms_c_protection_upd(wlc, BRCMS_PROT_N_USER,
a9533e7e
HP
5051 ((pub->_n_enab ==
5052 SUPPORT_11N) ? WL_11N_2x2 :
5053 WL_11N_3x3));
5054 }
5055 }
5056
5057 /* init per-band default rateset, depend on band->gmode */
fe741e5e 5058 brcms_default_rateset(wlc, &wlc->band->defrateset);
a9533e7e 5059
7c783cef 5060 /* fill in hw_rateset (used early by BRCM_SET_RATESET) */
f52a0ad0 5061 brcms_c_rateset_filter(&wlc->band->defrateset,
0965ae88 5062 &wlc->band->hw_rateset, false,
7c783cef 5063 BRCMS_RATES_CCK_OFDM, BRCMS_RATE_MASK,
a9533e7e
HP
5064 (bool) N_ENAB(wlc->pub));
5065 }
5066
419ad34e
AS
5067 /*
5068 * update antenna config due to
5069 * wlc->stf->txant/txchain/ant_rx_ovr change
5070 */
f52a0ad0 5071 brcms_c_stf_phy_txant_upd(wlc);
a9533e7e
HP
5072
5073 /* attach each modules */
1c4c54ba 5074 err = brcms_c_attach_module(wlc);
a9533e7e
HP
5075 if (err != 0)
5076 goto fail;
5077
fe741e5e 5078 if (!brcms_c_timers_init(wlc, unit)) {
1c4c54ba 5079 wiphy_err(wl->wiphy, "wl%d: %s: init_timer failed\n", unit,
b8f092c9 5080 __func__);
a9533e7e
HP
5081 err = 32;
5082 goto fail;
5083 }
5084
5085 /* depend on rateset, gmode */
f52a0ad0 5086 wlc->cmi = brcms_c_channel_mgr_attach(wlc);
a9533e7e 5087 if (!wlc->cmi) {
f52a0ad0 5088 wiphy_err(wl->wiphy, "wl%d: %s: channel_mgr_attach failed"
b8f092c9 5089 "\n", unit, __func__);
a9533e7e
HP
5090 err = 33;
5091 goto fail;
5092 }
5093
5094 /* init default when all parameters are ready, i.e. ->rateset */
1c4c54ba 5095 brcms_c_bss_default_init(wlc);
a9533e7e
HP
5096
5097 /*
5098 * Complete the wlc default state initializations..
5099 */
5100
5101 /* allocate our initial queue */
1c4c54ba 5102 wlc->pkt_queue = brcms_c_txq_alloc(wlc);
3a730500 5103 if (wlc->pkt_queue == NULL) {
b8f092c9
RV
5104 wiphy_err(wl->wiphy, "wl%d: %s: failed to malloc tx queue\n",
5105 unit, __func__);
a9533e7e
HP
5106 err = 100;
5107 goto fail;
5108 }
a9533e7e
HP
5109
5110 wlc->bsscfg[0] = wlc->cfg;
5111 wlc->cfg->_idx = 0;
5112 wlc->cfg->wlc = wlc;
5113 pub->txmaxpkts = MAXTXPKTS;
5114
fe741e5e 5115 brcms_c_wme_initparams_sta(wlc, &wlc->wme_param_ie);
a9533e7e
HP
5116
5117 wlc->mimoft = FT_HT;
651bd3a9 5118 wlc->ht_cap.cap_info = HT_CAP;
a9533e7e
HP
5119 if (HT_ENAB(wlc->pub))
5120 wlc->stf->ldpc = AUTO;
5121
5122 wlc->mimo_40txbw = AUTO;
5123 wlc->ofdm_40txbw = AUTO;
5124 wlc->cck_40txbw = AUTO;
7c783cef 5125 brcms_c_update_mimo_band_bwcap(wlc, BRCMS_N_BW_20IN2G_40IN5G);
a9533e7e 5126
a9533e7e 5127 /* Set default values of SGI */
7c783cef
RV
5128 if (BRCMS_SGI_CAP_PHY(wlc)) {
5129 brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
5130 BRCMS_N_SGI_40));
a9533e7e 5131 wlc->sgi_tx = AUTO;
7c783cef
RV
5132 } else if (BRCMS_ISSSLPNPHY(wlc->band)) {
5133 brcms_c_ht_update_sgi_rx(wlc, (BRCMS_N_SGI_20 |
5134 BRCMS_N_SGI_40));
a9533e7e
HP
5135 wlc->sgi_tx = AUTO;
5136 } else {
1c4c54ba 5137 brcms_c_ht_update_sgi_rx(wlc, 0);
a9533e7e
HP
5138 wlc->sgi_tx = OFF;
5139 }
5140
5141 /* *******nvram 11n config overrides Start ********* */
5142
5143 /* apply the sgi override from nvram conf */
5144 if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
5145 wlc->sgi_tx = OFF;
5146
5147 if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
1c4c54ba 5148 brcms_c_ht_update_sgi_rx(wlc, 0);
a9533e7e
HP
5149
5150 /* apply the stbc override from nvram conf */
5151 if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
5152 wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
5153 wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
651bd3a9 5154 wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
a9533e7e
HP
5155 }
5156 if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
f52a0ad0 5157 brcms_c_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
a9533e7e
HP
5158
5159 /* apply the GF override from nvram conf */
5160 if (n_disabled & WLFEATURE_DISABLE_11N_GF)
651bd3a9 5161 wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
a9533e7e
HP
5162
5163 /* initialize radio_mpc_disable according to wlc->mpc */
fe741e5e 5164 brcms_c_radio_mpc_upd(wlc);
763456a6 5165 brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
a9533e7e
HP
5166
5167 if (perr)
5168 *perr = 0;
5169
2f6b1dde 5170 return wlc;
a9533e7e
HP
5171
5172 fail:
b8f092c9
RV
5173 wiphy_err(wl->wiphy, "wl%d: %s: failed with err %d\n",
5174 unit, __func__, err);
a9533e7e 5175 if (wlc)
fe741e5e 5176 brcms_c_detach(wlc);
a9533e7e
HP
5177
5178 if (perr)
5179 *perr = err;
90ea2296 5180 return NULL;
a9533e7e
HP
5181}
5182
1c4c54ba 5183static void brcms_c_timers_deinit(struct brcms_c_info *wlc)
a2627bc0 5184{
a9533e7e
HP
5185 /* free timer state */
5186 if (wlc->wdtimer) {
8817f754 5187 brcms_free_timer(wlc->wl, wlc->wdtimer);
a9533e7e
HP
5188 wlc->wdtimer = NULL;
5189 }
5190 if (wlc->radio_timer) {
8817f754 5191 brcms_free_timer(wlc->wl, wlc->radio_timer);
a9533e7e
HP
5192 wlc->radio_timer = NULL;
5193 }
5194}
5195
1c4c54ba 5196static void brcms_c_detach_module(struct brcms_c_info *wlc)
a2627bc0 5197{
a9533e7e 5198 if (wlc->asi) {
f52a0ad0 5199 brcms_c_antsel_detach(wlc->asi);
a9533e7e
HP
5200 wlc->asi = NULL;
5201 }
5202
5203 if (wlc->ampdu) {
f52a0ad0 5204 brcms_c_ampdu_detach(wlc->ampdu);
a9533e7e
HP
5205 wlc->ampdu = NULL;
5206 }
5207
f52a0ad0 5208 brcms_c_stf_detach(wlc);
a9533e7e
HP
5209}
5210
839f9f62
RV
5211/*
5212 * low level detach
5213 */
11431424 5214static int brcms_b_detach(struct brcms_c_info *wlc)
839f9f62
RV
5215{
5216 uint i;
5217 struct brcms_hw_band *band;
5218 struct brcms_hardware *wlc_hw = wlc->hw;
5219 int callbacks;
5220
5221 callbacks = 0;
5222
5223 if (wlc_hw->sih) {
419ad34e
AS
5224 /*
5225 * detach interrupt sync mechanism since interrupt is disabled
5226 * and per-port interrupt object may has been freed. this must
5227 * be done before sb core switch
839f9f62
RV
5228 */
5229 ai_deregister_intr_callback(wlc_hw->sih);
821e4e93 5230 ai_pci_sleep(wlc_hw->sih);
839f9f62
RV
5231 }
5232
5233 brcms_b_detach_dmapio(wlc_hw);
5234
5235 band = wlc_hw->band;
5236 for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
5237 if (band->pi) {
5238 /* Detach this band's phy */
5239 wlc_phy_detach(band->pi);
5240 band->pi = NULL;
5241 }
5242 band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
5243 }
5244
5245 /* Free shared phy state */
5246 kfree(wlc_hw->phy_sh);
5247
5248 wlc_phy_shim_detach(wlc_hw->physhim);
5249
5250 /* free vars */
5251 kfree(wlc_hw->vars);
5252 wlc_hw->vars = NULL;
5253
5254 if (wlc_hw->sih) {
5255 ai_detach(wlc_hw->sih);
5256 wlc_hw->sih = NULL;
5257 }
5258
5259 return callbacks;
5260
5261}
5262
a9533e7e
HP
5263/*
5264 * Return a count of the number of driver callbacks still pending.
5265 *
fe741e5e
RV
5266 * General policy is that brcms_c_detach can only dealloc/free software states.
5267 * It can NOT touch hardware registers since the d11core may be in reset and
5268 * clock may not be available.
5269 * One exception is sb register access, which is possible if crystal is turned
5270 * on after "down" state, driver should avoid software timer with the exception
5271 * of radio_monitor.
a9533e7e 5272 */
fe741e5e 5273uint brcms_c_detach(struct brcms_c_info *wlc)
a2627bc0 5274{
a9533e7e
HP
5275 uint callbacks = 0;
5276
5277 if (wlc == NULL)
5278 return 0;
5279
792aa408 5280 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
a9533e7e 5281
c654fce6 5282 callbacks += brcms_b_detach(wlc);
a9533e7e
HP
5283
5284 /* delete software timers */
1c4c54ba 5285 if (!brcms_c_radio_monitor_stop(wlc))
a9533e7e
HP
5286 callbacks++;
5287
f52a0ad0 5288 brcms_c_channel_mgr_detach(wlc->cmi);
a9533e7e 5289
1c4c54ba 5290 brcms_c_timers_deinit(wlc);
a9533e7e 5291
1c4c54ba 5292 brcms_c_detach_module(wlc);
a9533e7e 5293
a9533e7e 5294
228a00f8 5295 while (wlc->tx_queues != NULL)
1c4c54ba 5296 brcms_c_txq_free(wlc, wlc->tx_queues);
a9533e7e 5297
f52a0ad0 5298 brcms_c_detach_mfree(wlc);
90ea2296 5299 return callbacks;
a9533e7e
HP
5300}
5301
5302/* update state that depends on the current value of "ap" */
fe741e5e 5303void brcms_c_ap_upd(struct brcms_c_info *wlc)
a9533e7e
HP
5304{
5305 if (AP_ENAB(wlc->pub))
7c783cef
RV
5306 /* AP: short not allowed, but not enforced */
5307 wlc->PLCPHdr_override = BRCMS_PLCP_AUTO;
a9533e7e 5308 else
7c783cef
RV
5309 /* STA-BSS; short capable */
5310 wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
a9533e7e 5311
a9533e7e 5312 /* fixup mpc */
0f0881b0 5313 wlc->mpc = true;
a9533e7e
HP
5314}
5315
2682e2a3
AS
5316/*
5317 * return true if Minimum Power Consumption should
5318 * be entered, false otherwise
5319 */
5320bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
a9533e7e 5321{
2682e2a3
AS
5322 return false;
5323}
a9533e7e 5324
fe741e5e 5325bool brcms_c_ismpc(struct brcms_c_info *wlc)
a9533e7e 5326{
fe741e5e 5327 return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
a9533e7e
HP
5328}
5329
fe741e5e 5330void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
a9533e7e
HP
5331{
5332 bool mpc_radio, radio_state;
5333
5334 /*
5335 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
5336 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
5337 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
5338 * the radio is going down.
5339 */
5340 if (!wlc->mpc) {
5341 if (!wlc->pub->radio_disabled)
5342 return;
5343 mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
1c4c54ba 5344 brcms_c_radio_upd(wlc);
a9533e7e 5345 if (!wlc->pub->radio_disabled)
1c4c54ba 5346 brcms_c_radio_monitor_stop(wlc);
a9533e7e
HP
5347 return;
5348 }
5349
5350 /*
419ad34e
AS
5351 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
5352 * wlc->pub->radio_disabled to go ON, always call radio_upd
5353 * synchronously to go OFF, postpone radio_upd to later when
5354 * context is safe(e.g. watchdog)
a9533e7e
HP
5355 */
5356 radio_state =
5357 (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
5358 ON);
fe741e5e 5359 mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
a9533e7e
HP
5360
5361 if (radio_state == ON && mpc_radio == OFF)
5362 wlc->mpc_delay_off = wlc->mpc_dlycnt;
5363 else if (radio_state == OFF && mpc_radio == ON) {
5364 mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
1c4c54ba 5365 brcms_c_radio_upd(wlc);
7c783cef
RV
5366 if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
5367 wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
5368 else
5369 wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
a9533e7e
HP
5370 wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
5371 }
419ad34e
AS
5372 /*
5373 * Below logic is meant to capture the transition from mpc off
5374 * to mpc on for reasons other than wlc->mpc_delay_off keeping
5375 * the mpc off. In that case reset wlc->mpc_delay_off to
5376 * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
a9533e7e 5377 */
0965ae88 5378 if ((wlc->prev_non_delay_mpc == false) &&
8ea54c9f 5379 (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
a9533e7e 5380 wlc->mpc_delay_off = wlc->mpc_dlycnt;
8ea54c9f 5381
fe741e5e 5382 wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
a9533e7e 5383}
839f9f62 5384/* Initialize just the hardware when coming out of POR or S3/S5 system states */
11431424 5385static void brcms_b_hw_up(struct brcms_hardware *wlc_hw)
839f9f62
RV
5386{
5387 if (wlc_hw->wlc->pub->hw_up)
5388 return;
5389
5390 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
5391
5392 /*
5393 * Enable pll and xtal, initialize the power control registers,
5394 * and force fastclock for the remainder of brcms_c_up().
5395 */
5396 brcms_b_xtal(wlc_hw, ON);
5397 ai_clkctl_init(wlc_hw->sih);
5398 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
5399
821e4e93 5400 ai_pci_fixcfg(wlc_hw->sih);
839f9f62 5401
821e4e93
RV
5402 /*
5403 * AI chip doesn't restore bar0win2 on
5404 * hibernation/resume, need sw fixup
5405 */
5406 if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
5407 (wlc_hw->sih->chip == BCM43225_CHIP_ID))
5408 wlc_hw->regs = (struct d11regs *)
5409 ai_setcore(wlc_hw->sih, D11_CORE_ID, 0);
839f9f62 5410
419ad34e
AS
5411 /*
5412 * Inform phy that a POR reset has occurred so
5413 * it does a complete phy init
5414 */
839f9f62
RV
5415 wlc_phy_por_inform(wlc_hw->band->pi);
5416
5417 wlc_hw->ucode_loaded = false;
5418 wlc_hw->wlc->pub->hw_up = true;
5419
5420 if ((wlc_hw->boardflags & BFL_FEM)
5421 && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
5422 if (!
5423 (wlc_hw->boardrev >= 0x1250
5424 && (wlc_hw->boardflags & BFL_FEM_BT)))
5425 ai_epa_4313war(wlc_hw->sih);
5426 }
5427}
5428
11431424 5429static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
839f9f62
RV
5430{
5431 uint coremask;
5432
5433 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
5434
5435 /*
5436 * Enable pll and xtal, initialize the power control registers,
5437 * and force fastclock for the remainder of brcms_c_up().
5438 */
5439 brcms_b_xtal(wlc_hw, ON);
5440 ai_clkctl_init(wlc_hw->sih);
5441 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
5442
5443 /*
5444 * Configure pci/pcmcia here instead of in brcms_c_attach()
5445 * to allow mfg hotswap: down, hotswap (chip power cycle), up.
5446 */
5447 coremask = (1 << wlc_hw->wlc->core->coreidx);
5448
821e4e93 5449 ai_pci_setup(wlc_hw->sih, coremask);
839f9f62
RV
5450
5451 /*
419ad34e
AS
5452 * Need to read the hwradio status here to cover the case where the
5453 * system is loaded with the hw radio disabled. We do not want to
5454 * bring the driver up in this case.
839f9f62
RV
5455 */
5456 if (brcms_b_radio_read_hwdisabled(wlc_hw)) {
5457 /* put SB PCI in down state again */
821e4e93 5458 ai_pci_down(wlc_hw->sih);
839f9f62
RV
5459 brcms_b_xtal(wlc_hw, OFF);
5460 return -ENOMEDIUM;
5461 }
5462
821e4e93 5463 ai_pci_up(wlc_hw->sih);
839f9f62
RV
5464
5465 /* reset the d11 core */
5466 brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS);
5467
5468 return 0;
5469}
5470
11431424 5471static int brcms_b_up_finish(struct brcms_hardware *wlc_hw)
839f9f62
RV
5472{
5473 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
5474
5475 wlc_hw->up = true;
5476 wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
5477
5478 /* FULLY enable dynamic power control and d11 core interrupt */
5479 brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC);
5480 brcms_intrson(wlc_hw->wlc->wl);
5481 return 0;
5482}
5483
2682e2a3
AS
5484/*
5485 * Write WME tunable parameters for retransmit/max rate
5486 * from wlc struct to ucode
5487 */
5488static void brcms_c_wme_retries_write(struct brcms_c_info *wlc)
5489{
5490 int ac;
5491
5492 /* Need clock to do this */
5493 if (!wlc->clk)
5494 return;
5495
5496 for (ac = 0; ac < AC_COUNT; ac++)
5497 brcms_c_write_shm(wlc, M_AC_TXLMT_ADDR(ac),
5498 wlc->wme_retries[ac]);
5499}
5500
a9533e7e 5501/* make interface operational */
fe741e5e 5502int brcms_c_up(struct brcms_c_info *wlc)
a2627bc0 5503{
792aa408 5504 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
a9533e7e
HP
5505
5506 /* HW is turned off so don't try to access it */
5507 if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
b74ac12e 5508 return -ENOMEDIUM;
a9533e7e
HP
5509
5510 if (!wlc->pub->hw_up) {
c654fce6 5511 brcms_b_hw_up(wlc->hw);
0f0881b0 5512 wlc->pub->hw_up = true;
a9533e7e
HP
5513 }
5514
5515 if ((wlc->pub->boardflags & BFL_FEM)
dfa26436 5516 && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
a9533e7e 5517 if (wlc->pub->boardrev >= 0x1250
8ea54c9f 5518 && (wlc->pub->boardflags & BFL_FEM_BT))
fe741e5e 5519 brcms_c_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
7c783cef 5520 MHF5_4313_GPIOCTRL, BRCM_BAND_ALL);
8ea54c9f 5521 else
fe741e5e 5522 brcms_c_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE,
7c783cef 5523 MHF4_EXTPA_ENABLE, BRCM_BAND_ALL);
a9533e7e
HP
5524 }
5525
5526 /*
419ad34e
AS
5527 * Need to read the hwradio status here to cover the case where the
5528 * system is loaded with the hw radio disabled. We do not want to bring
5529 * the driver up in this case. If radio is disabled, abort up, lower
5530 * power, start radio timer and return 0(for NDIS) don't call
5531 * radio_update to avoid looping brcms_c_up.
a9533e7e 5532 *
c654fce6 5533 * brcms_b_up_prep() returns either 0 or -BCME_RADIOOFF only
a9533e7e
HP
5534 */
5535 if (!wlc->pub->radio_disabled) {
c654fce6 5536 int status = brcms_b_up_prep(wlc->hw);
b74ac12e 5537 if (status == -ENOMEDIUM) {
a9533e7e
HP
5538 if (!mboolisset
5539 (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
5540 int idx;
471f1b51 5541 struct brcms_bss_cfg *bsscfg;
a9533e7e
HP
5542 mboolset(wlc->pub->radio_disabled,
5543 WL_RADIO_HW_DISABLE);
5544
49552d33 5545 FOREACH_BSS(wlc, idx, bsscfg)
a9533e7e
HP
5546 if (!BSSCFG_STA(bsscfg)
5547 || !bsscfg->enable || !bsscfg->BSS)
5548 continue;
1c4c54ba 5549 wiphy_err(wlc->wiphy, "wl%d.%d: up"
b8f092c9 5550 ": rfdisable -> "
1c4c54ba 5551 "bsscfg_disable()\n",
b8f092c9 5552 wlc->pub->unit, idx);
49552d33 5553 END_FOREACH_BSS()
a9533e7e 5554 }
af4e9c09 5555 }
a9533e7e
HP
5556 }
5557
5558 if (wlc->pub->radio_disabled) {
1c4c54ba 5559 brcms_c_radio_monitor_start(wlc);
a9533e7e
HP
5560 return 0;
5561 }
5562
1c4c54ba 5563 /* brcms_b_up_prep has done brcms_c_corereset(). so clk is on, set it */
0f0881b0 5564 wlc->clk = true;
a9533e7e 5565
1c4c54ba 5566 brcms_c_radio_monitor_stop(wlc);
a9533e7e
HP
5567
5568 /* Set EDCF hostflags */
8ea54c9f 5569 if (EDCF_ENAB(wlc->pub))
7c783cef 5570 brcms_c_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, BRCM_BAND_ALL);
8ea54c9f 5571 else
7c783cef 5572 brcms_c_mhf(wlc, MHF1, MHF1_EDCF, 0, BRCM_BAND_ALL);
a9533e7e 5573
7c783cef 5574 if (BRCMS_WAR16165(wlc))
fe741e5e 5575 brcms_c_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
7c783cef 5576 BRCM_BAND_ALL);
a9533e7e 5577
8817f754 5578 brcms_init(wlc->wl);
0f0881b0 5579 wlc->pub->up = true;
a9533e7e
HP
5580
5581 if (wlc->bandinit_pending) {
fe741e5e
RV
5582 brcms_c_suspend_mac_and_wait(wlc);
5583 brcms_c_set_chanspec(wlc, wlc->default_bss->chanspec);
0965ae88 5584 wlc->bandinit_pending = false;
fe741e5e 5585 brcms_c_enable_mac(wlc);
a9533e7e
HP
5586 }
5587
c654fce6 5588 brcms_b_up_finish(wlc->hw);
a9533e7e
HP
5589
5590 /* other software states up after ISR is running */
5591 /* start APs that were to be brought up but are not up yet */
1c4c54ba 5592 /* if (AP_ENAB(wlc->pub)) brcms_c_restart_ap(wlc->ap); */
a9533e7e
HP
5593
5594 /* Program the TX wme params with the current settings */
1c4c54ba 5595 brcms_c_wme_retries_write(wlc);
a9533e7e
HP
5596
5597 /* start one second watchdog timer */
8817f754 5598 brcms_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
0f0881b0 5599 wlc->WDarmed = true;
a9533e7e
HP
5600
5601 /* ensure antenna config is up to date */
f52a0ad0 5602 brcms_c_stf_phy_txant_upd(wlc);
a9533e7e 5603 /* ensure LDPC config is in sync */
1c4c54ba 5604 brcms_c_ht_update_ldpc(wlc, wlc->stf->ldpc);
a9533e7e 5605
90ea2296 5606 return 0;
a9533e7e
HP
5607}
5608
1c4c54ba 5609static uint brcms_c_down_del_timer(struct brcms_c_info *wlc)
a2627bc0 5610{
a9533e7e
HP
5611 uint callbacks = 0;
5612
5613 return callbacks;
5614}
5615
11431424 5616static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw)
839f9f62
RV
5617{
5618 bool dev_gone;
5619 uint callbacks = 0;
5620
5621 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
5622
5623 if (!wlc_hw->up)
5624 return callbacks;
5625
5626 dev_gone = DEVICEREMOVED(wlc_hw->wlc);
5627
5628 /* disable interrupts */
5629 if (dev_gone)
5630 wlc_hw->wlc->macintmask = 0;
5631 else {
5632 /* now disable interrupts */
5633 brcms_intrsoff(wlc_hw->wlc->wl);
5634
5635 /* ensure we're running on the pll clock again */
5636 brcms_b_clkctl_clk(wlc_hw, CLK_FAST);
5637 }
5638 /* down phy at the last of this stage */
5639 callbacks += wlc_phy_down(wlc_hw->band->pi);
5640
5641 return callbacks;
5642}
5643
11431424 5644static int brcms_b_down_finish(struct brcms_hardware *wlc_hw)
839f9f62
RV
5645{
5646 uint callbacks = 0;
5647 bool dev_gone;
5648
5649 BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
5650
5651 if (!wlc_hw->up)
5652 return callbacks;
5653
5654 wlc_hw->up = false;
5655 wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
5656
5657 dev_gone = DEVICEREMOVED(wlc_hw->wlc);
5658
5659 if (dev_gone) {
5660 wlc_hw->sbclk = false;
5661 wlc_hw->clk = false;
5662 wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
5663
5664 /* reclaim any posted packets */
5665 brcms_c_flushqueues(wlc_hw->wlc);
5666 } else {
5667
5668 /* Reset and disable the core */
5669 if (ai_iscoreup(wlc_hw->sih)) {
5670 if (R_REG(&wlc_hw->regs->maccontrol) &
5671 MCTL_EN_MAC)
5672 brcms_c_suspend_mac_and_wait(wlc_hw->wlc);
5673 callbacks += brcms_reset(wlc_hw->wlc->wl);
5674 brcms_c_coredisable(wlc_hw);
5675 }
5676
5677 /* turn off primary xtal and pll */
5678 if (!wlc_hw->noreset) {
821e4e93 5679 ai_pci_down(wlc_hw->sih);
839f9f62
RV
5680 brcms_b_xtal(wlc_hw, OFF);
5681 }
5682 }
5683
5684 return callbacks;
5685}
5686
a9533e7e
HP
5687/*
5688 * Mark the interface nonoperational, stop the software mechanisms,
5689 * disable the hardware, free any transient buffer state.
5690 * Return a count of the number of driver callbacks still pending.
5691 */
fe741e5e 5692uint brcms_c_down(struct brcms_c_info *wlc)
a2627bc0 5693{
a9533e7e
HP
5694
5695 uint callbacks = 0;
5696 int i;
0965ae88 5697 bool dev_gone = false;
471f1b51 5698 struct brcms_txq_info *qi;
a9533e7e 5699
792aa408 5700 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
a9533e7e
HP
5701
5702 /* check if we are already in the going down path */
5703 if (wlc->going_down) {
b8f092c9
RV
5704 wiphy_err(wlc->wiphy, "wl%d: %s: Driver going down so return"
5705 "\n", wlc->pub->unit, __func__);
a9533e7e
HP
5706 return 0;
5707 }
5708 if (!wlc->pub->up)
90ea2296 5709 return callbacks;
a9533e7e
HP
5710
5711 /* in between, mpc could try to bring down again.. */
0f0881b0 5712 wlc->going_down = true;
a9533e7e 5713
c654fce6 5714 callbacks += brcms_b_bmac_down_prep(wlc->hw);
a9533e7e
HP
5715
5716 dev_gone = DEVICEREMOVED(wlc);
5717
5718 /* Call any registered down handlers */
7c783cef 5719 for (i = 0; i < BRCMS_MAXMODULES; i++) {
a9533e7e
HP
5720 if (wlc->modulecb[i].down_fn)
5721 callbacks +=
5722 wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
5723 }
5724
5725 /* cancel the watchdog timer */
5726 if (wlc->WDarmed) {
8817f754 5727 if (!brcms_del_timer(wlc->wl, wlc->wdtimer))
a9533e7e 5728 callbacks++;
0965ae88 5729 wlc->WDarmed = false;
a9533e7e
HP
5730 }
5731 /* cancel all other timers */
1c4c54ba 5732 callbacks += brcms_c_down_del_timer(wlc);
a9533e7e 5733
0965ae88 5734 wlc->pub->up = false;
a9533e7e 5735
0965ae88 5736 wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
a9533e7e
HP
5737
5738 /* clear txq flow control */
1c4c54ba 5739 brcms_c_txflowcontrol_reset(wlc);
a9533e7e
HP
5740
5741 /* flush tx queues */
8ea54c9f 5742 for (qi = wlc->tx_queues; qi != NULL; qi = qi->next)
67ad48bc 5743 brcmu_pktq_flush(&qi->q, true, NULL, NULL);
a9533e7e 5744
c654fce6 5745 callbacks += brcms_b_down_finish(wlc->hw);
a9533e7e 5746
fe741e5e 5747 /* brcms_b_down_finish has done brcms_c_coredisable(). so clk is off */
0965ae88 5748 wlc->clk = false;
a9533e7e 5749
0965ae88 5750 wlc->going_down = false;
90ea2296 5751 return callbacks;
a9533e7e
HP
5752}
5753
5754/* Set the current gmode configuration */
fe741e5e 5755int brcms_c_set_gmode(struct brcms_c_info *wlc, u8 gmode, bool config)
a9533e7e
HP
5756{
5757 int ret = 0;
5758 uint i;
fa67ebba 5759 struct brcms_c_rateset rs;
a9533e7e 5760 /* Default to 54g Auto */
7c783cef
RV
5761 /* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
5762 s8 shortslot = BRCMS_SHORTSLOT_AUTO;
419ad34e
AS
5763 bool shortslot_restrict = false; /* Restrict association to stations
5764 * that support shortslot
5765 */
0965ae88 5766 bool ofdm_basic = false; /* Make 6, 12, and 24 basic rates */
7c783cef
RV
5767 /* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
5768 int preamble = BRCMS_PLCP_LONG;
419ad34e
AS
5769 bool preamble_restrict = false; /* Restrict association to stations
5770 * that support short preambles
a9533e7e 5771 */
471f1b51 5772 struct brcms_band *band;
a9533e7e
HP
5773
5774 /* if N-support is enabled, allow Gmode set as long as requested
5775 * Gmode is not GMODE_LEGACY_B
5776 */
5777 if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
e10d82d4 5778 return -ENOTSUPP;
a9533e7e
HP
5779
5780 /* verify that we are dealing with 2G band and grab the band pointer */
7c783cef 5781 if (wlc->band->bandtype == BRCM_BAND_2G)
a9533e7e
HP
5782 band = wlc->band;
5783 else if ((NBANDS(wlc) > 1) &&
7c783cef 5784 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == BRCM_BAND_2G))
a9533e7e
HP
5785 band = wlc->bandstate[OTHERBANDUNIT(wlc)];
5786 else
e10d82d4 5787 return -EINVAL;
a9533e7e
HP
5788
5789 /* Legacy or bust when no OFDM is supported by regulatory */
f52a0ad0 5790 if ((brcms_c_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
7c783cef 5791 BRCMS_NO_OFDM) && (gmode != GMODE_LEGACY_B))
b74ac12e 5792 return -EINVAL;
a9533e7e
HP
5793
5794 /* update configuration value */
0f0881b0 5795 if (config == true)
7c783cef 5796 brcms_c_protection_upd(wlc, BRCMS_PROT_G_USER, gmode);
a9533e7e
HP
5797
5798 /* Clear supported rates filter */
fa67ebba 5799 memset(&wlc->sup_rates_override, 0, sizeof(struct brcms_c_rateset));
a9533e7e
HP
5800
5801 /* Clear rateset override */
fa67ebba 5802 memset(&rs, 0, sizeof(struct brcms_c_rateset));
a9533e7e
HP
5803
5804 switch (gmode) {
5805 case GMODE_LEGACY_B:
7c783cef 5806 shortslot = BRCMS_SHORTSLOT_OFF;
f52a0ad0 5807 brcms_c_rateset_copy(&gphy_legacy_rates, &rs);
a9533e7e
HP
5808
5809 break;
5810
5811 case GMODE_LRS:
5812 if (AP_ENAB(wlc->pub))
f52a0ad0
RV
5813 brcms_c_rateset_copy(&cck_rates,
5814 &wlc->sup_rates_override);
a9533e7e
HP
5815 break;
5816
5817 case GMODE_AUTO:
5818 /* Accept defaults */
5819 break;
5820
5821 case GMODE_ONLY:
0f0881b0 5822 ofdm_basic = true;
7c783cef 5823 preamble = BRCMS_PLCP_SHORT;
0f0881b0 5824 preamble_restrict = true;
a9533e7e
HP
5825 break;
5826
5827 case GMODE_PERFORMANCE:
419ad34e
AS
5828 if (AP_ENAB(wlc->pub))
5829 /* Put all rates into the Supported Rates element */
f52a0ad0 5830 brcms_c_rateset_copy(&cck_ofdm_rates,
a9533e7e
HP
5831 &wlc->sup_rates_override);
5832
7c783cef 5833 shortslot = BRCMS_SHORTSLOT_ON;
0f0881b0
GKH
5834 shortslot_restrict = true;
5835 ofdm_basic = true;
7c783cef 5836 preamble = BRCMS_PLCP_SHORT;
0f0881b0 5837 preamble_restrict = true;
a9533e7e
HP
5838 break;
5839
5840 default:
5841 /* Error */
b8f092c9
RV
5842 wiphy_err(wlc->wiphy, "wl%d: %s: invalid gmode %d\n",
5843 wlc->pub->unit, __func__, gmode);
e10d82d4 5844 return -ENOTSUPP;
a9533e7e
HP
5845 }
5846
5847 /*
5848 * If we are switching to gmode == GMODE_LEGACY_B,
5849 * clean up rate info that may refer to OFDM rates.
5850 */
5851 if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
5852 band->gmode = gmode;
5853 if (band->rspec_override && !IS_CCK(band->rspec_override)) {
5854 band->rspec_override = 0;
fe741e5e 5855 brcms_c_reprate_init(wlc);
a9533e7e 5856 }
8ea54c9f 5857 if (band->mrspec_override && !IS_CCK(band->mrspec_override))
a9533e7e 5858 band->mrspec_override = 0;
a9533e7e
HP
5859 }
5860
5861 band->gmode = gmode;
5862
a9533e7e
HP
5863 wlc->shortslot_override = shortslot;
5864
8ea54c9f 5865 if (AP_ENAB(wlc->pub))
a9533e7e
HP
5866 /* wlc->ap->shortslot_restrict = shortslot_restrict; */
5867 wlc->PLCPHdr_override =
5868 (preamble !=
7c783cef 5869 BRCMS_PLCP_LONG) ? BRCMS_PLCP_SHORT : BRCMS_PLCP_AUTO;
a9533e7e 5870
7c783cef
RV
5871 if ((AP_ENAB(wlc->pub) && preamble != BRCMS_PLCP_LONG)
5872 || preamble == BRCMS_PLCP_SHORT)
04795017 5873 wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
a9533e7e 5874 else
04795017 5875 wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
a9533e7e
HP
5876
5877 /* Update shortslot capability bit for AP and IBSS */
7c783cef
RV
5878 if ((AP_ENAB(wlc->pub) && shortslot == BRCMS_SHORTSLOT_AUTO) ||
5879 shortslot == BRCMS_SHORTSLOT_ON)
04795017 5880 wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
a9533e7e 5881 else
04795017
RV
5882 wlc->default_bss->capability &=
5883 ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
a9533e7e
HP
5884
5885 /* Use the default 11g rateset */
5886 if (!rs.count)
f52a0ad0 5887 brcms_c_rateset_copy(&cck_ofdm_rates, &rs);
a9533e7e
HP
5888
5889 if (ofdm_basic) {
5890 for (i = 0; i < rs.count; i++) {
7c783cef
RV
5891 if (rs.rates[i] == BRCM_RATE_6M
5892 || rs.rates[i] == BRCM_RATE_12M
5893 || rs.rates[i] == BRCM_RATE_24M)
5894 rs.rates[i] |= BRCMS_RATE_FLAG;
a9533e7e
HP
5895 }
5896 }
5897
5898 /* Set default bss rateset */
5899 wlc->default_bss->rateset.count = rs.count;
835ef44c 5900 memcpy(wlc->default_bss->rateset.rates, rs.rates,
02160695 5901 sizeof(wlc->default_bss->rateset.rates));
a9533e7e
HP
5902
5903 return ret;
5904}
5905
1c4c54ba 5906static int brcms_c_nmode_validate(struct brcms_c_info *wlc, s32 nmode)
a9533e7e
HP
5907{
5908 int err = 0;
5909
5910 switch (nmode) {
5911
5912 case OFF:
5913 break;
5914
5915 case AUTO:
5916 case WL_11N_2x2:
5917 case WL_11N_3x3:
7c783cef 5918 if (!(BRCMS_PHY_11N_CAP(wlc->band)))
e10d82d4 5919 err = -EINVAL;
a9533e7e
HP
5920 break;
5921
5922 default:
b74ac12e 5923 err = -EINVAL;
a9533e7e
HP
5924 break;
5925 }
5926
5927 return err;
5928}
5929
fe741e5e 5930int brcms_c_set_nmode(struct brcms_c_info *wlc, s32 nmode)
a9533e7e
HP
5931{
5932 uint i;
5933 int err;
5934
1c4c54ba 5935 err = brcms_c_nmode_validate(wlc, nmode);
a9533e7e
HP
5936 if (err)
5937 return err;
5938
5939 switch (nmode) {
5940 case OFF:
5941 wlc->pub->_n_enab = OFF;
7c783cef 5942 wlc->default_bss->flags &= ~BRCMS_BSS_HT;
a9533e7e 5943 /* delete the mcs rates from the default and hw ratesets */
f52a0ad0 5944 brcms_c_rateset_mcs_clear(&wlc->default_bss->rateset);
a9533e7e
HP
5945 for (i = 0; i < NBANDS(wlc); i++) {
5946 memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
5947 MCSSET_LEN);
5948 if (IS_MCS(wlc->band->rspec_override)) {
5949 wlc->bandstate[i]->rspec_override = 0;
fe741e5e 5950 brcms_c_reprate_init(wlc);
a9533e7e
HP
5951 }
5952 if (IS_MCS(wlc->band->mrspec_override))
5953 wlc->bandstate[i]->mrspec_override = 0;
5954 }
5955 break;
5956
5957 case AUTO:
5958 if (wlc->stf->txstreams == WL_11N_3x3)
5959 nmode = WL_11N_3x3;
5960 else
5961 nmode = WL_11N_2x2;
5962 case WL_11N_2x2:
5963 case WL_11N_3x3:
a9533e7e 5964 /* force GMODE_AUTO if NMODE is ON */
fe741e5e 5965 brcms_c_set_gmode(wlc, GMODE_AUTO, true);
a9533e7e
HP
5966 if (nmode == WL_11N_3x3)
5967 wlc->pub->_n_enab = SUPPORT_HT;
5968 else
5969 wlc->pub->_n_enab = SUPPORT_11N;
7c783cef 5970 wlc->default_bss->flags |= BRCMS_BSS_HT;
a9533e7e 5971 /* add the mcs rates to the default and hw ratesets */
f52a0ad0 5972 brcms_c_rateset_mcs_build(&wlc->default_bss->rateset,
a9533e7e
HP
5973 wlc->stf->txstreams);
5974 for (i = 0; i < NBANDS(wlc); i++)
5975 memcpy(wlc->bandstate[i]->hw_rateset.mcs,
5976 wlc->default_bss->rateset.mcs, MCSSET_LEN);
5977 break;
5978
5979 default:
a9533e7e
HP
5980 break;
5981 }
5982
5983 return err;
5984}
5985
fa67ebba
RV
5986static int
5987brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs_arg)
a9533e7e 5988{
fa67ebba 5989 struct brcms_c_rateset rs, new;
a9533e7e
HP
5990 uint bandunit;
5991
fa67ebba 5992 memcpy(&rs, rs_arg, sizeof(struct brcms_c_rateset));
a9533e7e
HP
5993
5994 /* check for bad count value */
7c783cef 5995 if ((rs.count == 0) || (rs.count > BRCMS_NUMRATES))
e10d82d4 5996 return -EINVAL;
a9533e7e
HP
5997
5998 /* try the current band */
5999 bandunit = wlc->band->bandunit;
fa67ebba 6000 memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
f52a0ad0 6001 if (brcms_c_rate_hwrs_filter_sort_validate
0f0881b0 6002 (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
a9533e7e
HP
6003 wlc->stf->txstreams))
6004 goto good;
6005
6006 /* try the other band */
6007 if (IS_MBAND_UNLOCKED(wlc)) {
6008 bandunit = OTHERBANDUNIT(wlc);
fa67ebba 6009 memcpy(&new, &rs, sizeof(struct brcms_c_rateset));
f52a0ad0 6010 if (brcms_c_rate_hwrs_filter_sort_validate(&new,
a9533e7e
HP
6011 &wlc->
6012 bandstate[bandunit]->
0f0881b0 6013 hw_rateset, true,
a9533e7e
HP
6014 wlc->stf->txstreams))
6015 goto good;
6016 }
6017
b74ac12e 6018 return -EBADE;
a9533e7e
HP
6019
6020 good:
6021 /* apply new rateset */
fa67ebba
RV
6022 memcpy(&wlc->default_bss->rateset, &new,
6023 sizeof(struct brcms_c_rateset));
02160695 6024 memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
fa67ebba 6025 sizeof(struct brcms_c_rateset));
90ea2296 6026 return 0;
a9533e7e
HP
6027}
6028
6029/* simplified integer set interface for common ioctl handler */
fe741e5e 6030int brcms_c_set(struct brcms_c_info *wlc, int cmd, int arg)
a9533e7e 6031{
fe741e5e 6032 return brcms_c_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
a9533e7e
HP
6033}
6034
6035/* simplified integer get interface for common ioctl handler */
fe741e5e 6036int brcms_c_get(struct brcms_c_info *wlc, int cmd, int *arg)
a9533e7e 6037{
fe741e5e 6038 return brcms_c_ioctl(wlc, cmd, arg, sizeof(int), NULL);
a9533e7e
HP
6039}
6040
1c4c54ba 6041static void brcms_c_ofdm_rateset_war(struct brcms_c_info *wlc)
a9533e7e 6042{
41feb5ed 6043 u8 r;
0965ae88 6044 bool war = false;
a9533e7e
HP
6045
6046 if (wlc->cfg->associated)
6047 r = wlc->cfg->current_bss->rateset.rates[0];
6048 else
6049 r = wlc->default_bss->rateset.rates[0];
6050
6051 wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
6052
6053 return;
6054}
6055
a9533e7e
HP
6056/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
6057static int
1c4c54ba
RV
6058_brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
6059 struct brcms_c_if *wlcif)
a9533e7e
HP
6060{
6061 int val, *pval;
6062 bool bool_val;
6063 int bcmerror;
a9533e7e
HP
6064 struct scb *nextscb;
6065 bool ta_ok;
6066 uint band;
471f1b51 6067 struct brcms_bss_cfg *bsscfg;
cc87568a 6068 struct brcms_bss_info *current_bss;
a9533e7e
HP
6069
6070 /* update bsscfg pointer */
94da409e
AS
6071 bsscfg = wlc->cfg;
6072 current_bss = bsscfg->current_bss;
a9533e7e
HP
6073
6074 /* initialize the following to get rid of compiler warning */
6075 nextscb = NULL;
0965ae88 6076 ta_ok = false;
a9533e7e 6077 band = 0;
a9533e7e
HP
6078
6079 /* If the device is turned off, then it's not "removed" */
6080 if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
b8f092c9
RV
6081 wiphy_err(wlc->wiphy, "wl%d: %s: dead chip\n", wlc->pub->unit,
6082 __func__);
8817f754 6083 brcms_down(wlc->wl);
b74ac12e 6084 return -EBADE;
a9533e7e
HP
6085 }
6086
a9533e7e 6087 /* default argument is generic integer */
835ef44c 6088 pval = arg ? (int *)arg : NULL;
a9533e7e 6089
49d468f6
RV
6090 /*
6091 * This will prevent misaligned access. The (void *) cast prevents a
6092 * memcpy alignment issue on e.g. Sparc64 platforms.
6093 */
66cbd3ab 6094 if (pval && (u32) len >= sizeof(val))
49d468f6 6095 memcpy((void *)&val, (void *)pval, sizeof(val));
a9533e7e
HP
6096 else
6097 val = 0;
6098
6099 /* bool conversion to avoid duplication below */
6100 bool_val = val != 0;
a9533e7e 6101 bcmerror = 0;
a9533e7e 6102
7306e4e3
RV
6103 if ((arg == NULL) || (len <= 0)) {
6104 wiphy_err(wlc->wiphy, "wl%d: %s: Command %d needs arguments\n",
6105 wlc->pub->unit, __func__, cmd);
6106 bcmerror = -EINVAL;
6107 goto done;
a9533e7e
HP
6108 }
6109
6110 switch (cmd) {
6111
7c783cef 6112 case BRCM_SET_CHANNEL:{
6bd20a1b 6113 u16 chspec = CH20MHZ_CHSPEC(val);
a9533e7e
HP
6114
6115 if (val < 0 || val > MAXCHANNEL) {
e10d82d4 6116 bcmerror = -EINVAL;
a9533e7e
HP
6117 break;
6118 }
6119
f52a0ad0 6120 if (!brcms_c_valid_chanspec_db(wlc->cmi, chspec)) {
e10d82d4 6121 bcmerror = -EINVAL;
a9533e7e
HP
6122 break;
6123 }
6124
6125 if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
6126 if (wlc->band->bandunit !=
7c783cef 6127 CHSPEC_BANDUNIT(chspec))
0f0881b0 6128 wlc->bandinit_pending = true;
a9533e7e 6129 else
0965ae88 6130 wlc->bandinit_pending = false;
a9533e7e
HP
6131 }
6132
6133 wlc->default_bss->chanspec = chspec;
1c4c54ba
RV
6134 /* brcms_c_BSSinit() will sanitize the rateset before
6135 * using it.. */
eff1b99a 6136 if (wlc->pub->up &&
7c783cef 6137 (BRCMS_BAND_PI_RADIO_CHANSPEC != chspec)) {
fe741e5e
RV
6138 brcms_c_set_home_chanspec(wlc, chspec);
6139 brcms_c_suspend_mac_and_wait(wlc);
6140 brcms_c_set_chanspec(wlc, chspec);
6141 brcms_c_enable_mac(wlc);
a9533e7e 6142 }
a9533e7e
HP
6143 break;
6144 }
6145
7c783cef 6146 case BRCM_SET_SRL:
a9533e7e
HP
6147 if (val >= 1 && val <= RETRY_SHORT_MAX) {
6148 int ac;
7d4df48e 6149 wlc->SRL = (u16) val;
a9533e7e 6150
c654fce6 6151 brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
a9533e7e 6152
8ea54c9f 6153 for (ac = 0; ac < AC_COUNT; ac++)
7c783cef 6154 BRCMS_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
8ea54c9f 6155
1c4c54ba 6156 brcms_c_wme_retries_write(wlc);
a9533e7e 6157 } else
b74ac12e 6158 bcmerror = -EINVAL;
a9533e7e
HP
6159 break;
6160
7c783cef 6161 case BRCM_SET_LRL:
a9533e7e
HP
6162 if (val >= 1 && val <= 255) {
6163 int ac;
7d4df48e 6164 wlc->LRL = (u16) val;
a9533e7e 6165
c654fce6 6166 brcms_b_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
a9533e7e 6167
8ea54c9f 6168 for (ac = 0; ac < AC_COUNT; ac++)
7c783cef 6169 BRCMS_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
8ea54c9f 6170
1c4c54ba 6171 brcms_c_wme_retries_write(wlc);
a9533e7e 6172 } else
b74ac12e 6173 bcmerror = -EINVAL;
a9533e7e
HP
6174 break;
6175
7c783cef 6176 case BRCM_GET_CURR_RATESET:{
786d00f7
RV
6177 struct brcm_rateset *ret_rs =
6178 (struct brcm_rateset *) arg;
fa67ebba 6179 struct brcms_c_rateset *rs;
a9533e7e 6180
94da409e 6181 if (wlc->pub->associated)
a9533e7e
HP
6182 rs = &current_bss->rateset;
6183 else
6184 rs = &wlc->default_bss->rateset;
6185
6186 if (len < (int)(rs->count + sizeof(rs->count))) {
e10d82d4 6187 bcmerror = -EOVERFLOW;
a9533e7e
HP
6188 break;
6189 }
6190
6191 /* Copy only legacy rateset section */
6192 ret_rs->count = rs->count;
02160695 6193 memcpy(&ret_rs->rates, &rs->rates, rs->count);
a9533e7e
HP
6194 break;
6195 }
6196
7c783cef 6197 case BRCM_SET_RATESET:{
fa67ebba 6198 struct brcms_c_rateset rs;
786d00f7
RV
6199 struct brcm_rateset *in_rs =
6200 (struct brcm_rateset *) arg;
a9533e7e
HP
6201
6202 if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
e10d82d4 6203 bcmerror = -EOVERFLOW;
a9533e7e
HP
6204 break;
6205 }
6206
7c783cef 6207 if (in_rs->count > BRCMS_NUMRATES) {
b74ac12e 6208 bcmerror = -ENOBUFS;
a9533e7e
HP
6209 break;
6210 }
6211
fa67ebba 6212 memset(&rs, 0, sizeof(struct brcms_c_rateset));
a9533e7e
HP
6213
6214 /* Copy only legacy rateset section */
6215 rs.count = in_rs->count;
02160695 6216 memcpy(&rs.rates, &in_rs->rates, rs.count);
a9533e7e
HP
6217
6218 /* merge rateset coming in with the current mcsset */
6219 if (N_ENAB(wlc->pub)) {
09f882b0 6220 struct brcms_bss_info *mcsset_bss;
a9533e7e 6221 if (bsscfg->associated)
09f882b0 6222 mcsset_bss = current_bss;
a9533e7e 6223 else
09f882b0
AS
6224 mcsset_bss = wlc->default_bss;
6225 memcpy(rs.mcs, &mcsset_bss->rateset.mcs[0],
6226 MCSSET_LEN);
a9533e7e
HP
6227 }
6228
1c4c54ba 6229 bcmerror = brcms_c_set_rateset(wlc, &rs);
a9533e7e
HP
6230
6231 if (!bcmerror)
1c4c54ba 6232 brcms_c_ofdm_rateset_war(wlc);
a9533e7e
HP
6233
6234 break;
6235 }
6236
7c783cef 6237 case BRCM_SET_BCNPRD:
a9533e7e
HP
6238 /* range [1, 0xffff] */
6239 if (val >= DOT11_MIN_BEACON_PERIOD
7c783cef 6240 && val <= DOT11_MAX_BEACON_PERIOD)
7d4df48e 6241 wlc->default_bss->beacon_period = (u16) val;
7c783cef 6242 else
b74ac12e 6243 bcmerror = -EINVAL;
a9533e7e
HP
6244 break;
6245
7c783cef 6246 case BRCM_GET_PHYLIST:
a9533e7e 6247 {
580a0bd9 6248 unsigned char *cp = arg;
a9533e7e 6249 if (len < 3) {
e10d82d4 6250 bcmerror = -EOVERFLOW;
a9533e7e
HP
6251 break;
6252 }
6253
7c783cef 6254 if (BRCMS_ISNPHY(wlc->band))
a9533e7e 6255 *cp++ = 'n';
7c783cef 6256 else if (BRCMS_ISLCNPHY(wlc->band))
a9533e7e 6257 *cp++ = 'c';
7c783cef 6258 else if (BRCMS_ISSSLPNPHY(wlc->band))
a9533e7e 6259 *cp++ = 's';
a9533e7e
HP
6260 *cp = '\0';
6261 break;
6262 }
6263
7c783cef
RV
6264 case BRCMS_SET_SHORTSLOT_OVERRIDE:
6265 if (val != BRCMS_SHORTSLOT_AUTO && val != BRCMS_SHORTSLOT_OFF &&
6266 val != BRCMS_SHORTSLOT_ON) {
b74ac12e 6267 bcmerror = -EINVAL;
a9533e7e
HP
6268 break;
6269 }
6270
562c8850 6271 wlc->shortslot_override = (s8) val;
a9533e7e
HP
6272
6273 /* shortslot is an 11g feature, so no more work if we are
6274 * currently on the 5G band
6275 */
6276 if (BAND_5G(wlc->band->bandtype))
6277 break;
6278
6279 if (wlc->pub->up && wlc->pub->associated) {
6280 /* let watchdog or beacon processing update shortslot */
6281 } else if (wlc->pub->up) {
6282 /* unassociated shortslot is off */
fe741e5e 6283 brcms_c_switch_shortslot(wlc, false);
a9533e7e 6284 } else {
fe741e5e
RV
6285 /* driver is down, so just update the brcms_c_info
6286 * value */
8ea54c9f 6287 if (wlc->shortslot_override == BRCMS_SHORTSLOT_AUTO)
0965ae88 6288 wlc->shortslot = false;
8ea54c9f 6289 else
a9533e7e
HP
6290 wlc->shortslot =
6291 (wlc->shortslot_override ==
7c783cef 6292 BRCMS_SHORTSLOT_ON);
a9533e7e
HP
6293 }
6294
6295 break;
6296
a9533e7e
HP
6297 }
6298 done:
6299
b74ac12e
RV
6300 if (bcmerror)
6301 wlc->pub->bcmerror = bcmerror;
a9533e7e 6302
90ea2296 6303 return bcmerror;
a9533e7e
HP
6304}
6305
2682e2a3
AS
6306int
6307brcms_c_ioctl(struct brcms_c_info *wlc, int cmd, void *arg, int len,
6308 struct brcms_c_if *wlcif)
6309{
6310 return _brcms_c_ioctl(wlc, cmd, arg, len, wlcif);
6311}
6312
a9533e7e 6313/*
c5e7c035 6314 * register watchdog and down handlers.
a9533e7e 6315 */
cc87568a 6316int brcms_c_module_register(struct brcms_pub *pub,
2f6b1dde 6317 const char *name, struct brcms_info *hdl,
1a5f680d 6318 int (*d_fn)(void *handle))
0d2f0724 6319{
fe741e5e 6320 struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
a9533e7e
HP
6321 int i;
6322
a9533e7e 6323 /* find an empty entry and just add, no duplication check! */
7c783cef 6324 for (i = 0; i < BRCMS_MAXMODULES; i++) {
a9533e7e
HP
6325 if (wlc->modulecb[i].name[0] == '\0') {
6326 strncpy(wlc->modulecb[i].name, name,
6327 sizeof(wlc->modulecb[i].name) - 1);
a9533e7e 6328 wlc->modulecb[i].hdl = hdl;
a9533e7e
HP
6329 wlc->modulecb[i].down_fn = d_fn;
6330 return 0;
6331 }
6332 }
6333
e10d82d4 6334 return -ENOSR;
a9533e7e
HP
6335}
6336
6337/* unregister module callbacks */
2f6b1dde
RV
6338int brcms_c_module_unregister(struct brcms_pub *pub, const char *name,
6339 struct brcms_info *hdl)
0d2f0724 6340{
fe741e5e 6341 struct brcms_c_info *wlc = (struct brcms_c_info *) pub->wlc;
a9533e7e
HP
6342 int i;
6343
6344 if (wlc == NULL)
b74ac12e 6345 return -ENODATA;
a9533e7e 6346
7c783cef 6347 for (i = 0; i < BRCMS_MAXMODULES; i++) {
a9533e7e
HP
6348 if (!strcmp(wlc->modulecb[i].name, name) &&
6349 (wlc->modulecb[i].hdl == hdl)) {
12bacc1b 6350 memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
a9533e7e
HP
6351 return 0;
6352 }
6353 }
6354
6355 /* table not found! */
b74ac12e 6356 return -ENODATA;
a9533e7e
HP
6357}
6358
a9533e7e 6359#ifdef BCMDBG
d558dea7 6360static const char * const supr_reason[] = {
a9533e7e
HP
6361 "None", "PMQ Entry", "Flush request",
6362 "Previous frag failure", "Channel mismatch",
6363 "Lifetime Expiry", "Underflow"
6364};
6365
1c4c54ba 6366static void brcms_c_print_txs_status(u16 s)
a9533e7e 6367{
0bef7748
AS
6368 printk(KERN_DEBUG "[15:12] %d frame attempts\n",
6369 (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
6370 printk(KERN_DEBUG " [11:8] %d rts attempts\n",
6371 (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
6372 printk(KERN_DEBUG " [7] %d PM mode indicated\n",
a9533e7e 6373 ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
0bef7748 6374 printk(KERN_DEBUG " [6] %d intermediate status\n",
a9533e7e 6375 ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
0bef7748
AS
6376 printk(KERN_DEBUG " [5] %d AMPDU\n",
6377 (s & TX_STATUS_AMPDU) ? 1 : 0);
6378 printk(KERN_DEBUG " [4:2] %d Frame Suppressed Reason (%s)\n",
a9533e7e
HP
6379 ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
6380 supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
0bef7748
AS
6381 printk(KERN_DEBUG " [1] %d acked\n",
6382 ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
a9533e7e
HP
6383}
6384#endif /* BCMDBG */
6385
cc87568a 6386void brcms_c_print_txstatus(struct tx_status *txs)
a9533e7e
HP
6387{
6388#if defined(BCMDBG)
7d4df48e
GKH
6389 u16 s = txs->status;
6390 u16 ackphyrxsh = txs->ackphyrxsh;
a9533e7e 6391
0bef7748
AS
6392 printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
6393
6394 printk(KERN_DEBUG "FrameID: %04x ", txs->frameid);
6395 printk(KERN_DEBUG "TxStatus: %04x", s);
6396 printk(KERN_DEBUG "\n");
a9533e7e 6397
1c4c54ba 6398 brcms_c_print_txs_status(s);
0bef7748
AS
6399
6400 printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
6401 printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
6402 printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
6403 printk(KERN_DEBUG "RxAckRSSI: %04x ",
a9533e7e 6404 (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
0bef7748
AS
6405 printk(KERN_DEBUG "RxAckSQ: %04x",
6406 (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
6407 printk(KERN_DEBUG "\n");
a9533e7e
HP
6408#endif /* defined(BCMDBG) */
6409}
6410
fe741e5e 6411void brcms_c_statsupd(struct brcms_c_info *wlc)
a9533e7e
HP
6412{
6413 int i;
cc87568a 6414 struct macstat macstats;
a9533e7e 6415#ifdef BCMDBG
7d4df48e
GKH
6416 u16 delta;
6417 u16 rxf0ovfl;
6418 u16 txfunfl[NFIFO];
a9533e7e
HP
6419#endif /* BCMDBG */
6420
6421 /* if driver down, make no sense to update stats */
6422 if (!wlc->pub->up)
6423 return;
6424
6425#ifdef BCMDBG
6426 /* save last rx fifo 0 overflow count */
6427 rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
6428
6429 /* save last tx fifo underflow count */
6430 for (i = 0; i < NFIFO; i++)
6431 txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
6432#endif /* BCMDBG */
6433
e4cf544e 6434 /* Read mac stats from contiguous shared memory */
c654fce6 6435 brcms_b_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
cc87568a 6436 &macstats, sizeof(struct macstat));
e4cf544e 6437
a9533e7e
HP
6438#ifdef BCMDBG
6439 /* check for rx fifo 0 overflow */
7d4df48e 6440 delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
a9533e7e 6441 if (delta)
b8f092c9
RV
6442 wiphy_err(wlc->wiphy, "wl%d: %u rx fifo 0 overflows!\n",
6443 wlc->pub->unit, delta);
a9533e7e
HP
6444
6445 /* check for tx fifo underflows */
6446 for (i = 0; i < NFIFO; i++) {
6447 delta =
7d4df48e 6448 (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
a9533e7e
HP
6449 txfunfl[i]);
6450 if (delta)
b8f092c9
RV
6451 wiphy_err(wlc->wiphy, "wl%d: %u tx fifo %d underflows!"
6452 "\n", wlc->pub->unit, delta, i);
a9533e7e
HP
6453 }
6454#endif /* BCMDBG */
6455
a9533e7e
HP
6456 /* merge counters from dma module */
6457 for (i = 0; i < NFIFO; i++) {
8ea54c9f 6458 if (wlc->hw->di[i])
a9533e7e 6459 dma_counterreset(wlc->hw->di[i]);
a9533e7e 6460 }
a9533e7e
HP
6461}
6462
fe741e5e 6463bool brcms_c_chipmatch(u16 vendor, u16 device)
a9533e7e 6464{
be1c09f9 6465 if (vendor != PCI_VENDOR_ID_BROADCOM) {
1c4c54ba 6466 pr_err("chipmatch: unknown vendor id %04x\n", vendor);
0965ae88 6467 return false;
a9533e7e
HP
6468 }
6469
5d6e3aec
RV
6470 if (device == BCM43224_D11N_ID_VEN1)
6471 return true;
a9533e7e 6472 if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
0f0881b0 6473 return true;
a9533e7e 6474 if (device == BCM4313_D11N2G_ID)
0f0881b0 6475 return true;
a9533e7e 6476 if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
0f0881b0 6477 return true;
a9533e7e 6478
1c4c54ba 6479 pr_err("chipmatch: unknown device id %04x\n", device);
0965ae88 6480 return false;
a9533e7e
HP
6481}
6482
a9533e7e 6483#if defined(BCMDBG)
cc87568a 6484void brcms_c_print_txdesc(struct d11txh *txh)
a9533e7e 6485{
628f10ba
SF
6486 u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
6487 u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
6488 u16 mfc = le16_to_cpu(txh->MacFrameControl);
6489 u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
6490 u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
6491 u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
6492 u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
6493 u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
6494 u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
6495 u16 mainrates = le16_to_cpu(txh->MainRates);
6496 u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
41feb5ed
GKH
6497 u8 *iv = txh->IV;
6498 u8 *ra = txh->TxFrameRA;
628f10ba 6499 u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
41feb5ed 6500 u8 *rtspfb = txh->RTSPLCPFallback;
628f10ba 6501 u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
41feb5ed 6502 u8 *fragpfb = txh->FragPLCPFallback;
628f10ba
SF
6503 u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
6504 u16 mmodelen = le16_to_cpu(txh->MModeLen);
6505 u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
6506 u16 tfid = le16_to_cpu(txh->TxFrameID);
6507 u16 txs = le16_to_cpu(txh->TxStatus);
6508 u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
6509 u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
6510 u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
6511 u16 mmbyte = le16_to_cpu(txh->MinMBytes);
a9533e7e 6512
41feb5ed 6513 u8 *rtsph = txh->RTSPhyHeader;
f3dc3ea4 6514 struct ieee80211_rts rts = txh->rts_frame;
a9533e7e
HP
6515 char hexbuf[256];
6516
6517 /* add plcp header along with txh descriptor */
34227316
AS
6518 printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
6519 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
cc87568a 6520 txh, sizeof(struct d11txh) + 48);
a9533e7e 6521
0bef7748
AS
6522 printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
6523 printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
6524 printk(KERN_DEBUG "FC: %04x ", mfc);
6525 printk(KERN_DEBUG "FES Time: %04x\n", tfest);
6526 printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
a9533e7e 6527 (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
0bef7748
AS
6528 printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
6529 printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
6530 printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
6531 printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
6532 printk(KERN_DEBUG "MainRates: %04x ", mainrates);
6533 printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
6534 printk(KERN_DEBUG "\n");
a9533e7e 6535
67ad48bc 6536 brcmu_format_hex(hexbuf, iv, sizeof(txh->IV));
0bef7748 6537 printk(KERN_DEBUG "SecIV: %s\n", hexbuf);
67ad48bc 6538 brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
0bef7748 6539 printk(KERN_DEBUG "RA: %s\n", hexbuf);
a9533e7e 6540
0bef7748 6541 printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
67ad48bc 6542 brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
0bef7748
AS
6543 printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
6544 printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
67ad48bc 6545 brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
0bef7748
AS
6546 printk(KERN_DEBUG "PLCP: %s ", hexbuf);
6547 printk(KERN_DEBUG "DUR: %04x", fragdfb);
6548 printk(KERN_DEBUG "\n");
a9533e7e 6549
0bef7748
AS
6550 printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
6551 printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
a9533e7e 6552
0bef7748
AS
6553 printk(KERN_DEBUG "FrameID: %04x\n", tfid);
6554 printk(KERN_DEBUG "TxStatus: %04x\n", txs);
a9533e7e 6555
0bef7748
AS
6556 printk(KERN_DEBUG "MaxNumMpdu: %04x\n", mnmpdu);
6557 printk(KERN_DEBUG "MaxAggbyte: %04x\n", mabyte);
6558 printk(KERN_DEBUG "MaxAggbyte_fb: %04x\n", mabyte_f);
6559 printk(KERN_DEBUG "MinByte: %04x\n", mmbyte);
a9533e7e 6560
67ad48bc 6561 brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
0bef7748 6562 printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
67ad48bc 6563 brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
0bef7748
AS
6564 printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
6565 printk(KERN_DEBUG "\n");
a9533e7e
HP
6566}
6567#endif /* defined(BCMDBG) */
6568
6569#if defined(BCMDBG)
cc87568a 6570void brcms_c_print_rxh(struct d11rxhdr *rxh)
a9533e7e 6571{
7d4df48e
GKH
6572 u16 len = rxh->RxFrameSize;
6573 u16 phystatus_0 = rxh->PhyRxStatus_0;
6574 u16 phystatus_1 = rxh->PhyRxStatus_1;
6575 u16 phystatus_2 = rxh->PhyRxStatus_2;
6576 u16 phystatus_3 = rxh->PhyRxStatus_3;
6577 u16 macstatus1 = rxh->RxStatus1;
6578 u16 macstatus2 = rxh->RxStatus2;
a9533e7e
HP
6579 char flagstr[64];
6580 char lenbuf[20];
67ad48bc 6581 static const struct brcmu_bit_desc macstat_flags[] = {
a9533e7e
HP
6582 {RXS_FCSERR, "FCSErr"},
6583 {RXS_RESPFRAMETX, "Reply"},
6584 {RXS_PBPRES, "PADDING"},
6585 {RXS_DECATMPT, "DeCr"},
6586 {RXS_DECERR, "DeCrErr"},
6587 {RXS_BCNSENT, "Bcn"},
6588 {0, NULL}
6589 };
6590
34227316 6591 printk(KERN_DEBUG "Raw RxDesc:\n");
cc87568a
RV
6592 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, rxh,
6593 sizeof(struct d11rxhdr));
a9533e7e 6594
67ad48bc 6595 brcmu_format_flags(macstat_flags, macstatus1, flagstr, 64);
a9533e7e
HP
6596
6597 snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
6598
0bef7748 6599 printk(KERN_DEBUG "RxFrameSize: %6s (%d)%s\n", lenbuf, len,
a9533e7e 6600 (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
0bef7748 6601 printk(KERN_DEBUG "RxPHYStatus: %04x %04x %04x %04x\n",
a9533e7e 6602 phystatus_0, phystatus_1, phystatus_2, phystatus_3);
0bef7748
AS
6603 printk(KERN_DEBUG "RxMACStatus: %x %s\n", macstatus1, flagstr);
6604 printk(KERN_DEBUG "RXMACaggtype: %x\n",
6605 (macstatus2 & RXS_AGGTYPE_MASK));
6606 printk(KERN_DEBUG "RxTSFTime: %04x\n", rxh->RxTSFTime);
a9533e7e 6607}
a9533e7e
HP
6608#endif /* defined(BCMDBG) */
6609
839f9f62
RV
6610u16 brcms_b_rate_shm_offset(struct brcms_hardware *wlc_hw, u8 rate)
6611{
6612 u16 table_ptr;
6613 u8 phy_rate, index;
6614
6615 /* get the phy specific rate encoding for the PLCP SIGNAL field */
6616 if (IS_OFDM(rate))
6617 table_ptr = M_RT_DIRMAP_A;
6618 else
6619 table_ptr = M_RT_DIRMAP_B;
6620
6621 /* for a given rate, the LS-nibble of the PLCP SIGNAL field is
6622 * the index into the rate table.
6623 */
6624 phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
6625 index = phy_rate & 0xf;
6626
6627 /* Find the SHM pointer to the rate table entry by looking in the
6628 * Direct-map Table
6629 */
6630 return 2 * brcms_b_read_shm(wlc_hw, table_ptr + (index * 2));
6631}
6632
1c4c54ba 6633static u16 brcms_c_rate_shm_offset(struct brcms_c_info *wlc, u8 rate)
a9533e7e 6634{
c654fce6 6635 return brcms_b_rate_shm_offset(wlc->hw, rate);
a9533e7e
HP
6636}
6637
6638/* Callback for device removed */
a9533e7e
HP
6639
6640/*
6641 * Attempts to queue a packet onto a multiple-precedence queue,
6642 * if necessary evicting a lower precedence packet from the queue.
6643 *
6644 * 'prec' is the precedence number that has already been mapped
6645 * from the packet priority.
6646 *
0965ae88 6647 * Returns true if packet consumed (queued), false if not.
a9533e7e 6648 */
11431424 6649static bool brcms_c_prec_enq(struct brcms_c_info *wlc, struct pktq *q,
2f6b1dde 6650 struct sk_buff *pkt, int prec)
a9533e7e 6651{
fe741e5e 6652 return brcms_c_prec_enq_head(wlc, q, pkt, prec, false);
a9533e7e
HP
6653}
6654
de91ed29 6655bool
fe741e5e
RV
6656brcms_c_prec_enq_head(struct brcms_c_info *wlc, struct pktq *q,
6657 struct sk_buff *pkt, int prec, bool head)
a9533e7e 6658{
c26b1378 6659 struct sk_buff *p;
a9533e7e
HP
6660 int eprec = -1; /* precedence to evict from */
6661
6662 /* Determine precedence from which to evict packet, if any */
6663 if (pktq_pfull(q, prec))
6664 eprec = prec;
6665 else if (pktq_full(q)) {
67ad48bc 6666 p = brcmu_pktq_peek_tail(q, &eprec);
a9533e7e 6667 if (eprec > prec) {
b8f092c9
RV
6668 wiphy_err(wlc->wiphy, "%s: Failing: eprec %d > prec %d"
6669 "\n", __func__, eprec, prec);
0965ae88 6670 return false;
a9533e7e
HP
6671 }
6672 }
6673
6674 /* Evict if needed */
6675 if (eprec >= 0) {
6676 bool discard_oldest;
6677
a9533e7e
HP
6678 discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
6679
6680 /* Refuse newer packet unless configured to discard oldest */
6681 if (eprec == prec && !discard_oldest) {
b8f092c9
RV
6682 wiphy_err(wlc->wiphy, "%s: No where to go, prec == %d"
6683 "\n", __func__, prec);
0965ae88 6684 return false;
a9533e7e
HP
6685 }
6686
6687 /* Evict packet according to discard policy */
67ad48bc
RV
6688 p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) :
6689 brcmu_pktq_pdeq_tail(q, eprec);
6690 brcmu_pkt_buf_free_skb(p);
a9533e7e
HP
6691 }
6692
6693 /* Enqueue */
6694 if (head)
67ad48bc 6695 p = brcmu_pktq_penq_head(q, prec, pkt);
a9533e7e 6696 else
67ad48bc 6697 p = brcmu_pktq_penq(q, prec, pkt);
a9533e7e 6698
0f0881b0 6699 return true;
a9533e7e
HP
6700}
6701
2f6b1dde
RV
6702void brcms_c_txq_enq(struct brcms_c_info *wlc, struct scb *scb,
6703 struct sk_buff *sdu, uint prec)
a9533e7e 6704{
471f1b51 6705 struct brcms_txq_info *qi = wlc->pkt_queue; /* Check me */
a9533e7e
HP
6706 struct pktq *q = &qi->q;
6707 int prio;
6708
54991ad6 6709 prio = sdu->priority;
a9533e7e 6710
fe741e5e 6711 if (!brcms_c_prec_enq(wlc, q, sdu, prec)) {
a9533e7e
HP
6712 if (!EDCF_ENAB(wlc->pub)
6713 || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
1c4c54ba 6714 wiphy_err(wlc->wiphy, "wl%d: txq_enq: txq overflow"
b8f092c9 6715 "\n", wlc->pub->unit);
a9533e7e 6716
a30825a3 6717 /*
e52d30f2 6718 * we might hit this condtion in case
a30825a3
AS
6719 * packet flooding from mac80211 stack
6720 */
67ad48bc 6721 brcmu_pkt_buf_free_skb(sdu);
a9533e7e
HP
6722 }
6723
419ad34e
AS
6724 /*
6725 * Check if flow control needs to be turned on after enqueuing the
6726 * packet. Don't turn on flow control if EDCF is enabled. Driver
6727 * would make the decision on what to drop instead of relying on
6728 * stack to make the right decision
a9533e7e
HP
6729 */
6730 if (!EDCF_ENAB(wlc->pub)
6731 || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
8ea54c9f 6732 if (pktq_len(q) >= wlc->pub->tunables->datahiwat)
fe741e5e 6733 brcms_c_txflowcontrol(wlc, qi, ON, ALLPRIO);
a9533e7e
HP
6734 } else if (wlc->pub->_priofc) {
6735 if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
8ea54c9f 6736 wlc->pub->tunables->datahiwat)
fe741e5e 6737 brcms_c_txflowcontrol(wlc, qi, ON, prio);
a9533e7e
HP
6738 }
6739}
6740
a9533e7e
HP
6741/*
6742 * bcmc_fid_generate:
6743 * Generate frame ID for a BCMC packet. The frag field is not used
6744 * for MC frames so is used as part of the sequence number.
6745 */
7d4df48e 6746static inline u16
471f1b51 6747bcmc_fid_generate(struct brcms_c_info *wlc, struct brcms_bss_cfg *bsscfg,
cc87568a 6748 struct d11txh *txh)
a9533e7e 6749{
7d4df48e 6750 u16 frameid;
a9533e7e 6751
628f10ba
SF
6752 frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
6753 TXFID_QUEUE_MASK);
a9533e7e
HP
6754 frameid |=
6755 (((wlc->
6756 mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
6757 TX_BCMC_FIFO;
6758
6759 return frameid;
6760}
6761
2682e2a3
AS
6762static uint
6763brcms_c_calc_ack_time(struct brcms_c_info *wlc, u32 rspec,
6764 u8 preamble_type)
a9533e7e 6765{
2682e2a3 6766 uint dur = 0;
a9533e7e 6767
2682e2a3
AS
6768 BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d\n",
6769 wlc->pub->unit, rspec, preamble_type);
419ad34e 6770 /*
2682e2a3
AS
6771 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
6772 * is less than or equal to the rate of the immediately previous
6773 * frame in the FES
a9533e7e 6774 */
2682e2a3
AS
6775 rspec = BRCMS_BASIC_RATE(wlc, rspec);
6776 /* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
6777 dur =
6778 brcms_c_calc_frame_time(wlc, rspec, preamble_type,
6779 (DOT11_ACK_LEN + FCS_LEN));
6780 return dur;
a9533e7e
HP
6781}
6782
2682e2a3
AS
6783static uint
6784brcms_c_calc_cts_time(struct brcms_c_info *wlc, u32 rspec,
6785 u8 preamble_type)
a9533e7e 6786{
2682e2a3
AS
6787 BCMMSG(wlc->wiphy, "wl%d: ratespec 0x%x, preamble_type %d\n",
6788 wlc->pub->unit, rspec, preamble_type);
6789 return brcms_c_calc_ack_time(wlc, rspec, preamble_type);
a9533e7e
HP
6790}
6791
2682e2a3
AS
6792static uint
6793brcms_c_calc_ba_time(struct brcms_c_info *wlc, u32 rspec,
6794 u8 preamble_type)
a9533e7e 6795{
2682e2a3
AS
6796 BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, "
6797 "preamble_type %d\n", wlc->pub->unit, rspec, preamble_type);
6798 /*
6799 * Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that
6800 * is less than or equal to the rate of the immediately previous
6801 * frame in the FES
6802 */
6803 rspec = BRCMS_BASIC_RATE(wlc, rspec);
6804 /* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
6805 return brcms_c_calc_frame_time(wlc, rspec, preamble_type,
6806 (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
6807 FCS_LEN));
a9533e7e
HP
6808}
6809
2682e2a3
AS
6810/* brcms_c_compute_frame_dur()
6811 *
6812 * Calculate the 802.11 MAC header DUR field for MPDU
6813 * DUR for a single frame = 1 SIFS + 1 ACK
6814 * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
6815 *
6816 * rate MPDU rate in unit of 500kbps
6817 * next_frag_len next MPDU length in bytes
6818 * preamble_type use short/GF or long/MM PLCP header
6819 */
6820static u16
6821brcms_c_compute_frame_dur(struct brcms_c_info *wlc, u32 rate,
6822 u8 preamble_type, uint next_frag_len)
a9533e7e 6823{
2682e2a3 6824 u16 dur, sifs;
a9533e7e 6825
2682e2a3 6826 sifs = SIFS(wlc->band);
a9533e7e 6827
2682e2a3
AS
6828 dur = sifs;
6829 dur += (u16) brcms_c_calc_ack_time(wlc, rate, preamble_type);
a9533e7e 6830
2682e2a3
AS
6831 if (next_frag_len) {
6832 /* Double the current DUR to get 2 SIFS + 2 ACKs */
6833 dur *= 2;
6834 /* add another SIFS and the frag time */
6835 dur += sifs;
6836 dur +=
6837 (u16) brcms_c_calc_frame_time(wlc, rate, preamble_type,
6838 next_frag_len);
6839 }
6840 return dur;
a9533e7e
HP
6841}
6842
2682e2a3
AS
6843/* The opposite of brcms_c_calc_frame_time */
6844static uint
6845brcms_c_calc_frame_len(struct brcms_c_info *wlc, u32 ratespec,
6846 u8 preamble_type, uint dur)
a9533e7e 6847{
2682e2a3
AS
6848 uint nsyms, mac_len, Ndps, kNdps;
6849 uint rate = RSPEC2RATE(ratespec);
a9533e7e 6850
2682e2a3
AS
6851 BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, dur %d\n",
6852 wlc->pub->unit, ratespec, preamble_type, dur);
a9533e7e 6853
2682e2a3
AS
6854 if (IS_MCS(ratespec)) {
6855 uint mcs = ratespec & RSPEC_RATE_MASK;
6856 int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
6857 dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
6858 /* payload calculation matches that of regular ofdm */
6859 if (BAND_2G(wlc->band->bandtype))
6860 dur -= DOT11_OFDM_SIGNAL_EXTENSION;
6861 /* kNdbps = kbps * 4 */
6862 kNdps =
6863 MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
6864 RSPEC_ISSGI(ratespec)) * 4;
6865 nsyms = dur / APHY_SYMBOL_TIME;
6866 mac_len =
6867 ((nsyms * kNdps) -
6868 ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
6869 } else if (IS_OFDM(ratespec)) {
6870 dur -= APHY_PREAMBLE_TIME;
6871 dur -= APHY_SIGNAL_TIME;
6872 /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
6873 Ndps = rate * 2;
6874 nsyms = dur / APHY_SYMBOL_TIME;
6875 mac_len =
6876 ((nsyms * Ndps) -
6877 (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
6878 } else {
6879 if (preamble_type & BRCMS_SHORT_PREAMBLE)
6880 dur -= BPHY_PLCP_SHORT_TIME;
6881 else
6882 dur -= BPHY_PLCP_TIME;
6883 mac_len = dur * rate;
6884 /* divide out factor of 2 in rate (1/2 mbps) */
6885 mac_len = mac_len / 8 / 2;
a9533e7e 6886 }
2682e2a3 6887 return mac_len;
a9533e7e
HP
6888}
6889
2682e2a3
AS
6890static u32
6891mac80211_wlc_set_nrate(struct brcms_c_info *wlc, struct brcms_band *cur_band,
6892 u32 int_val)
a9533e7e 6893{
2682e2a3
AS
6894 u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
6895 u8 rate = int_val & NRATE_RATE_MASK;
6896 u32 rspec;
6897 bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
6898 bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
6899 bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
6900 == NRATE_OVERRIDE_MCS_ONLY);
6901 int bcmerror = 0;
a9533e7e 6902
2682e2a3
AS
6903 if (!ismcs)
6904 return (u32) rate;
a9533e7e 6905
2682e2a3
AS
6906 /* validate the combination of rate/mcs/stf is allowed */
6907 if (N_ENAB(wlc->pub) && ismcs) {
6908 /* mcs only allowed when nmode */
6909 if (stf > PHY_TXC1_MODE_SDM) {
6910 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid stf\n",
6911 BRCMS_UNIT(wlc), __func__);
6912 bcmerror = -EINVAL;
6913 goto done;
6914 }
a9533e7e 6915
2682e2a3
AS
6916 /* mcs 32 is a special case, DUP mode 40 only */
6917 if (rate == 32) {
6918 if (!CHSPEC_IS40(wlc->home_chanspec) ||
6919 ((stf != PHY_TXC1_MODE_SISO)
6920 && (stf != PHY_TXC1_MODE_CDD))) {
6921 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid mcs "
6922 "32\n", BRCMS_UNIT(wlc), __func__);
6923 bcmerror = -EINVAL;
6924 goto done;
6925 }
6926 /* mcs > 7 must use stf SDM */
6927 } else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
6928 /* mcs > 7 must use stf SDM */
6929 if (stf != PHY_TXC1_MODE_SDM) {
6930 BCMMSG(wlc->wiphy, "wl%d: enabling "
6931 "SDM mode for mcs %d\n",
6932 BRCMS_UNIT(wlc), rate);
6933 stf = PHY_TXC1_MODE_SDM;
6934 }
6935 } else {
6936 /*
6937 * MCS 0-7 may use SISO, CDD, and for
6938 * phy_rev >= 3 STBC
6939 */
6940 if ((stf > PHY_TXC1_MODE_STBC) ||
6941 (!BRCMS_STBC_CAP_PHY(wlc)
6942 && (stf == PHY_TXC1_MODE_STBC))) {
6943 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid STBC"
6944 "\n", BRCMS_UNIT(wlc), __func__);
6945 bcmerror = -EINVAL;
6946 goto done;
6947 }
6948 }
6949 } else if (IS_OFDM(rate)) {
6950 if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
6951 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid OFDM\n",
6952 BRCMS_UNIT(wlc), __func__);
6953 bcmerror = -EINVAL;
6954 goto done;
6955 }
6956 } else if (IS_CCK(rate)) {
6957 if ((cur_band->bandtype != BRCM_BAND_2G)
6958 || (stf != PHY_TXC1_MODE_SISO)) {
6959 wiphy_err(wlc->wiphy, "wl%d: %s: Invalid CCK\n",
6960 BRCMS_UNIT(wlc), __func__);
6961 bcmerror = -EINVAL;
6962 goto done;
6963 }
6964 } else {
6965 wiphy_err(wlc->wiphy, "wl%d: %s: Unknown rate type\n",
6966 BRCMS_UNIT(wlc), __func__);
6967 bcmerror = -EINVAL;
6968 goto done;
6969 }
6970 /* make sure multiple antennae are available for non-siso rates */
6971 if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
6972 wiphy_err(wlc->wiphy, "wl%d: %s: SISO antenna but !SISO "
6973 "request\n", BRCMS_UNIT(wlc), __func__);
6974 bcmerror = -EINVAL;
6975 goto done;
6976 }
a9533e7e 6977
2682e2a3
AS
6978 rspec = rate;
6979 if (ismcs) {
6980 rspec |= RSPEC_MIMORATE;
6981 /* For STBC populate the STC field of the ratespec */
6982 if (stf == PHY_TXC1_MODE_STBC) {
6983 u8 stc;
6984 stc = 1; /* Nss for single stream is always 1 */
6985 rspec |= (stc << RSPEC_STC_SHIFT);
6986 }
a9533e7e 6987 }
2682e2a3
AS
6988
6989 rspec |= (stf << RSPEC_STF_SHIFT);
6990
6991 if (override_mcs_only)
6992 rspec |= RSPEC_OVERRIDE_MCS_ONLY;
6993
6994 if (issgi)
6995 rspec |= RSPEC_SHORT_GI;
6996
6997 if ((rate != 0)
6998 && !brcms_c_valid_rate(wlc, rspec, cur_band->bandtype, true))
6999 return rate;
7000
7001 return rspec;
7002done:
7003 return rate;
a9533e7e
HP
7004}
7005
2682e2a3
AS
7006/*
7007 * Add struct d11txh, struct cck_phy_hdr.
a9533e7e 7008 *
2682e2a3
AS
7009 * 'p' data must start with 802.11 MAC header
7010 * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
7011 *
7012 * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
a9533e7e 7013 *
a9533e7e 7014 */
2682e2a3
AS
7015static u16
7016brcms_c_d11hdrs_mac80211(struct brcms_c_info *wlc, struct ieee80211_hw *hw,
7017 struct sk_buff *p, struct scb *scb, uint frag,
7018 uint nfrags, uint queue, uint next_frag_len,
7019 struct wsec_key *key, u32 rspec_override)
a9533e7e 7020{
3e9796f9 7021 struct ieee80211_hdr *h;
cc87568a 7022 struct d11txh *txh;
41feb5ed 7023 u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
a9533e7e 7024 int len, phylen, rts_phylen;
9d7326f9
AS
7025 u16 mch, phyctl, xfts, mainrates;
7026 u16 seq = 0, mcl = 0, status = 0, frameid = 0;
6bd20a1b 7027 u32 rspec[2] = { BRCM_RATE_1M, BRCM_RATE_1M }, rts_rspec[2] = {
7c783cef 7028 BRCM_RATE_1M, BRCM_RATE_1M};
0965ae88
GKH
7029 bool use_rts = false;
7030 bool use_cts = false;
7031 bool use_rifs = false;
7032 bool short_preamble[2] = { false, false };
7c783cef
RV
7033 u8 preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
7034 u8 rts_preamble_type[2] = { BRCMS_LONG_PREAMBLE, BRCMS_LONG_PREAMBLE };
41feb5ed 7035 u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
f3dc3ea4 7036 struct ieee80211_rts *rts = NULL;
a9533e7e
HP
7037 bool qos;
7038 uint ac;
66cbd3ab 7039 u32 rate_val[2];
0965ae88 7040 bool hwtkmic = false;
7d4df48e 7041 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
a9533e7e 7042#define ANTCFG_NONE 0xFF
41feb5ed
GKH
7043 u8 antcfg = ANTCFG_NONE;
7044 u8 fbantcfg = ANTCFG_NONE;
a9533e7e 7045 uint phyctl1_stf = 0;
7d4df48e 7046 u16 durid = 0;
a9533e7e
HP
7047 struct ieee80211_tx_rate *txrate[2];
7048 int k;
7049 struct ieee80211_tx_info *tx_info;
7050 bool is_mcs[2];
7d4df48e 7051 u16 mimo_txbw;
41feb5ed 7052 u8 mimo_preamble_type;
a9533e7e 7053
2682e2a3
AS
7054 /* locate 802.11 MAC header */
7055 h = (struct ieee80211_hdr *)(p->data);
7056 qos = ieee80211_is_data_qos(h->frame_control);
7057
7058 /* compute length of frame in bytes for use in PLCP computations */
7059 len = brcmu_pkttotlen(p);
7060 phylen = len + FCS_LEN;
7061
7062 /* If WEP enabled, add room in phylen for the additional bytes of
7063 * ICV which MAC generates. We do NOT add the additional bytes to
7064 * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
7065 * in this case
7066 */
7067 if (key)
7068 phylen += key->icv_len;
7069
7070 /* Get tx_info */
7071 tx_info = IEEE80211_SKB_CB(p);
7072
7073 /* add PLCP */
7074 plcp = skb_push(p, D11_PHY_HDR_LEN);
7075
7076 /* add Broadcom tx descriptor header */
7077 txh = (struct d11txh *) skb_push(p, D11_TXH_LEN);
7078 memset(txh, 0, D11_TXH_LEN);
7079
7080 /* setup frameid */
7081 if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
7082 /* non-AP STA should never use BCMC queue */
7083 if (queue == TX_BCMC_FIFO) {
7084 wiphy_err(wlc->wiphy, "wl%d: %s: ASSERT queue == "
7085 "TX_BCMC!\n", BRCMS_UNIT(wlc), __func__);
7086 frameid = bcmc_fid_generate(wlc, NULL, txh);
7087 } else {
7088 /* Increment the counter for first fragment */
7089 if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
7090 SCB_SEQNUM(scb, p->priority)++;
7091
7092 /* extract fragment number from frame first */
7093 seq = le16_to_cpu(seq) & FRAGNUM_MASK;
7094 seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
7095 h->seq_ctrl = cpu_to_le16(seq);
7096
7097 frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
7098 (queue & TXFID_QUEUE_MASK);
7099 }
7100 }
7101 frameid |= queue & TXFID_QUEUE_MASK;
7102
7103 /* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
7104 if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
7105 mcl |= TXC_IGNOREPMQ;
7106
7107 txrate[0] = tx_info->control.rates;
7108 txrate[1] = txrate[0] + 1;
7109
7110 /*
7111 * if rate control algorithm didn't give us a fallback
7112 * rate, use the primary rate
7113 */
7114 if (txrate[1]->idx < 0)
7115 txrate[1] = txrate[0];
7116
7117 for (k = 0; k < hw->max_rates; k++) {
7118 is_mcs[k] =
7119 txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
7120 if (!is_mcs[k]) {
7121 if ((txrate[k]->idx >= 0)
7122 && (txrate[k]->idx <
7123 hw->wiphy->bands[tx_info->band]->n_bitrates)) {
7124 rate_val[k] =
7125 hw->wiphy->bands[tx_info->band]->
7126 bitrates[txrate[k]->idx].hw_value;
7127 short_preamble[k] =
7128 txrate[k]->
7129 flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
7130 true : false;
7131 } else {
7132 rate_val[k] = BRCM_RATE_1M;
7133 }
7134 } else {
7135 rate_val[k] = txrate[k]->idx;
7136 }
7137
7138 /*
7139 * Currently only support same setting for primay and
7140 * fallback rates. Unify flags for each rate into a
7141 * single value for the frame
7142 */
7143 use_rts |=
7144 txrate[k]->
7145 flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
7146 use_cts |=
7147 txrate[k]->
7148 flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
7149
7150 if (is_mcs[k])
7151 rate_val[k] |= NRATE_MCS_INUSE;
7152
7153 rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
7154
7155 /*
7156 * (1) RATE:
7157 * determine and validate primary rate
7158 * and fallback rates
7159 */
7160 if (!RSPEC_ACTIVE(rspec[k])) {
7161 rspec[k] = BRCM_RATE_1M;
7162 } else {
7163 if (!is_multicast_ether_addr(h->addr1)) {
7164 /* set tx antenna config */
7165 brcms_c_antsel_antcfg_get(wlc->asi, false,
7166 false, 0, 0, &antcfg, &fbantcfg);
7167 }
7168 }
7169 }
7170
7171 phyctl1_stf = wlc->stf->ss_opmode;
7172
7173 if (N_ENAB(wlc->pub)) {
7174 for (k = 0; k < hw->max_rates; k++) {
7175 /*
7176 * apply siso/cdd to single stream mcs's or ofdm
7177 * if rspec is auto selected
7178 */
7179 if (((IS_MCS(rspec[k]) &&
7180 IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
7181 IS_OFDM(rspec[k]))
7182 && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
7183 || !(rspec[k] & RSPEC_OVERRIDE))) {
7184 rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
7185
7186 /* For SISO MCS use STBC if possible */
7187 if (IS_MCS(rspec[k])
7188 && BRCMS_STF_SS_STBC_TX(wlc, scb)) {
7189 u8 stc;
7190
7191 /* Nss for single stream is always 1 */
7192 stc = 1;
7193 rspec[k] |= (PHY_TXC1_MODE_STBC <<
7194 RSPEC_STF_SHIFT) |
7195 (stc << RSPEC_STC_SHIFT);
7196 } else
7197 rspec[k] |=
7198 (phyctl1_stf << RSPEC_STF_SHIFT);
7199 }
7200
7201 /*
7202 * Is the phy configured to use 40MHZ frames? If
7203 * so then pick the desired txbw
7204 */
7205 if (CHSPEC_WLC_BW(wlc->chanspec) == BRCMS_40_MHZ) {
7206 /* default txbw is 20in40 SB */
7207 mimo_ctlchbw = mimo_txbw =
7208 CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
7209 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
7210
7211 if (IS_MCS(rspec[k])) {
7212 /* mcs 32 must be 40b/w DUP */
7213 if ((rspec[k] & RSPEC_RATE_MASK)
7214 == 32) {
7215 mimo_txbw =
7216 PHY_TXC1_BW_40MHZ_DUP;
7217 /* use override */
7218 } else if (wlc->mimo_40txbw != AUTO)
7219 mimo_txbw = wlc->mimo_40txbw;
7220 /* else check if dst is using 40 Mhz */
7221 else if (scb->flags & SCB_IS40)
7222 mimo_txbw = PHY_TXC1_BW_40MHZ;
7223 } else if (IS_OFDM(rspec[k])) {
7224 if (wlc->ofdm_40txbw != AUTO)
7225 mimo_txbw = wlc->ofdm_40txbw;
7226 } else if (wlc->cck_40txbw != AUTO) {
7227 mimo_txbw = wlc->cck_40txbw;
7228 }
7229 } else {
7230 /*
7231 * mcs32 is 40 b/w only.
7232 * This is possible for probe packets on
7233 * a STA during SCAN
7234 */
7235 if ((rspec[k] & RSPEC_RATE_MASK) == 32)
7236 /* mcs 0 */
7237 rspec[k] = RSPEC_MIMORATE;
7238
7239 mimo_txbw = PHY_TXC1_BW_20MHZ;
7240 }
7241
7242 /* Set channel width */
7243 rspec[k] &= ~RSPEC_BW_MASK;
7244 if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
7245 rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
7246 else
7247 rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
7248
7249 /* Disable short GI, not supported yet */
7250 rspec[k] &= ~RSPEC_SHORT_GI;
7251
7252 mimo_preamble_type = BRCMS_MM_PREAMBLE;
7253 if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
7254 mimo_preamble_type = BRCMS_GF_PREAMBLE;
7255
7256 if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
7257 && (!IS_MCS(rspec[k]))) {
7258 wiphy_err(wlc->wiphy, "wl%d: %s: IEEE80211_TX_"
7259 "RC_MCS != IS_MCS(rspec)\n",
7260 BRCMS_UNIT(wlc), __func__);
7261 }
7262
7263 if (IS_MCS(rspec[k])) {
7264 preamble_type[k] = mimo_preamble_type;
7265
7266 /*
7267 * if SGI is selected, then forced mm
7268 * for single stream
7269 */
7270 if ((rspec[k] & RSPEC_SHORT_GI)
7271 && IS_SINGLE_STREAM(rspec[k] &
7272 RSPEC_RATE_MASK))
7273 preamble_type[k] = BRCMS_MM_PREAMBLE;
7274 }
7275
7276 /* should be better conditionalized */
7277 if (!IS_MCS(rspec[0])
7278 && (tx_info->control.rates[0].
7279 flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
7280 preamble_type[k] = BRCMS_SHORT_PREAMBLE;
7281 }
7282 } else {
7283 for (k = 0; k < hw->max_rates; k++) {
7284 /* Set ctrlchbw as 20Mhz */
7285 rspec[k] &= ~RSPEC_BW_MASK;
7286 rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
7287
7288 /* for nphy, stf of ofdm frames must follow policies */
7289 if (BRCMS_ISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
7290 rspec[k] &= ~RSPEC_STF_MASK;
7291 rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
7292 }
7293 }
7294 }
7295
7296 /* Reset these for use with AMPDU's */
7297 txrate[0]->count = 0;
7298 txrate[1]->count = 0;
7299
7300 /* (2) PROTECTION, may change rspec */
7301 if ((ieee80211_is_data(h->frame_control) ||
7302 ieee80211_is_mgmt(h->frame_control)) &&
7303 (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
7304 use_rts = true;
7305
7306 /* (3) PLCP: determine PLCP header and MAC duration,
7307 * fill struct d11txh */
7308 brcms_c_compute_plcp(wlc, rspec[0], phylen, plcp);
7309 brcms_c_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
7310 memcpy(&txh->FragPLCPFallback,
7311 plcp_fallback, sizeof(txh->FragPLCPFallback));
7312
7313 /* Length field now put in CCK FBR CRC field */
7314 if (IS_CCK(rspec[1])) {
7315 txh->FragPLCPFallback[4] = phylen & 0xff;
7316 txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
7317 }
7318
7319 /* MIMO-RATE: need validation ?? */
7320 mainrates = IS_OFDM(rspec[0]) ?
7321 D11A_PHY_HDR_GRATE((struct ofdm_phy_hdr *) plcp) :
7322 plcp[0];
7323
7324 /* DUR field for main rate */
7325 if (!ieee80211_is_pspoll(h->frame_control) &&
7326 !is_multicast_ether_addr(h->addr1) && !use_rifs) {
7327 durid =
7328 brcms_c_compute_frame_dur(wlc, rspec[0], preamble_type[0],
7329 next_frag_len);
7330 h->duration_id = cpu_to_le16(durid);
7331 } else if (use_rifs) {
7332 /* NAV protect to end of next max packet size */
7333 durid =
7334 (u16) brcms_c_calc_frame_time(wlc, rspec[0],
7335 preamble_type[0],
7336 DOT11_MAX_FRAG_LEN);
7337 durid += RIFS_11N_TIME;
7338 h->duration_id = cpu_to_le16(durid);
7339 }
7340
7341 /* DUR field for fallback rate */
7342 if (ieee80211_is_pspoll(h->frame_control))
7343 txh->FragDurFallback = h->duration_id;
7344 else if (is_multicast_ether_addr(h->addr1) || use_rifs)
7345 txh->FragDurFallback = 0;
7346 else {
7347 durid = brcms_c_compute_frame_dur(wlc, rspec[1],
7348 preamble_type[1], next_frag_len);
7349 txh->FragDurFallback = cpu_to_le16(durid);
7350 }
a9533e7e 7351
2682e2a3
AS
7352 /* (4) MAC-HDR: MacTxControlLow */
7353 if (frag == 0)
7354 mcl |= TXC_STARTMSDU;
a9533e7e 7355
2682e2a3
AS
7356 if (!is_multicast_ether_addr(h->addr1))
7357 mcl |= TXC_IMMEDACK;
a9533e7e 7358
2682e2a3
AS
7359 if (BAND_5G(wlc->band->bandtype))
7360 mcl |= TXC_FREQBAND_5G;
a9533e7e 7361
2682e2a3
AS
7362 if (CHSPEC_IS40(BRCMS_BAND_PI_RADIO_CHANSPEC))
7363 mcl |= TXC_BW_40;
a9533e7e 7364
2682e2a3
AS
7365 /* set AMIC bit if using hardware TKIP MIC */
7366 if (hwtkmic)
7367 mcl |= TXC_AMIC;
a9533e7e 7368
2682e2a3 7369 txh->MacTxControlLow = cpu_to_le16(mcl);
a9533e7e 7370
2682e2a3
AS
7371 /* MacTxControlHigh */
7372 mch = 0;
a9533e7e 7373
2682e2a3
AS
7374 /* Set fallback rate preamble type */
7375 if ((preamble_type[1] == BRCMS_SHORT_PREAMBLE) ||
7376 (preamble_type[1] == BRCMS_GF_PREAMBLE)) {
7377 if (RSPEC2RATE(rspec[1]) != BRCM_RATE_1M)
7378 mch |= TXC_PREAMBLE_DATA_FB_SHORT;
a9533e7e 7379 }
a9533e7e 7380
2682e2a3
AS
7381 /* MacFrameControl */
7382 memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
7383 txh->TxFesTimeNormal = cpu_to_le16(0);
a9533e7e 7384
2682e2a3
AS
7385 txh->TxFesTimeFallback = cpu_to_le16(0);
7386
7387 /* TxFrameRA */
7388 memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
7389
7390 /* TxFrameID */
7391 txh->TxFrameID = cpu_to_le16(frameid);
a9533e7e 7392
419ad34e 7393 /*
2682e2a3
AS
7394 * TxStatus, Note the case of recreating the first frag of a suppressed
7395 * frame then we may need to reset the retry cnt's via the status reg
419ad34e 7396 */
2682e2a3 7397 txh->TxStatus = cpu_to_le16(status);
a9533e7e 7398
2682e2a3
AS
7399 /*
7400 * extra fields for ucode AMPDU aggregation, the new fields are added to
7401 * the END of previous structure so that it's compatible in driver.
7402 */
7403 txh->MaxNMpdus = cpu_to_le16(0);
7404 txh->MaxABytes_MRT = cpu_to_le16(0);
7405 txh->MaxABytes_FBR = cpu_to_le16(0);
7406 txh->MinMBytes = cpu_to_le16(0);
8ea54c9f 7407
2682e2a3
AS
7408 /* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration,
7409 * furnish struct d11txh */
7410 /* RTS PLCP header and RTS frame */
7411 if (use_rts || use_cts) {
7412 if (use_rts && use_cts)
7413 use_cts = false;
a9533e7e 7414
2682e2a3
AS
7415 for (k = 0; k < 2; k++) {
7416 rts_rspec[k] = brcms_c_rspec_to_rts_rspec(wlc, rspec[k],
7417 false,
7418 mimo_ctlchbw);
7419 }
a9533e7e 7420
2682e2a3
AS
7421 if (!IS_OFDM(rts_rspec[0]) &&
7422 !((RSPEC2RATE(rts_rspec[0]) == BRCM_RATE_1M) ||
7423 (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
7424 rts_preamble_type[0] = BRCMS_SHORT_PREAMBLE;
7425 mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
7426 }
a9533e7e 7427
2682e2a3
AS
7428 if (!IS_OFDM(rts_rspec[1]) &&
7429 !((RSPEC2RATE(rts_rspec[1]) == BRCM_RATE_1M) ||
7430 (wlc->PLCPHdr_override == BRCMS_PLCP_LONG))) {
7431 rts_preamble_type[1] = BRCMS_SHORT_PREAMBLE;
7432 mch |= TXC_PREAMBLE_RTS_FB_SHORT;
7433 }
7434
7435 /* RTS/CTS additions to MacTxControlLow */
7436 if (use_cts) {
7437 txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
a9533e7e 7438 } else {
2682e2a3
AS
7439 txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
7440 txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
a9533e7e 7441 }
a9533e7e 7442
2682e2a3
AS
7443 /* RTS PLCP header */
7444 rts_plcp = txh->RTSPhyHeader;
7445 if (use_cts)
7446 rts_phylen = DOT11_CTS_LEN + FCS_LEN;
7447 else
7448 rts_phylen = DOT11_RTS_LEN + FCS_LEN;
a9533e7e 7449
2682e2a3 7450 brcms_c_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
a9533e7e 7451
2682e2a3
AS
7452 /* fallback rate version of RTS PLCP header */
7453 brcms_c_compute_plcp(wlc, rts_rspec[1], rts_phylen,
7454 rts_plcp_fallback);
7455 memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
7456 sizeof(txh->RTSPLCPFallback));
a9533e7e 7457
2682e2a3
AS
7458 /* RTS frame fields... */
7459 rts = (struct ieee80211_rts *)&txh->rts_frame;
7460
7461 durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
7462 rspec[0], rts_preamble_type[0],
7463 preamble_type[0], phylen, false);
7464 rts->duration = cpu_to_le16(durid);
7465 /* fallback rate version of RTS DUR field */
7466 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
7467 rts_rspec[1], rspec[1],
7468 rts_preamble_type[1],
7469 preamble_type[1], phylen, false);
7470 txh->RTSDurFallback = cpu_to_le16(durid);
7471
7472 if (use_cts) {
7473 rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
7474 IEEE80211_STYPE_CTS);
7475
7476 memcpy(&rts->ra, &h->addr2, ETH_ALEN);
7477 } else {
7478 rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
7479 IEEE80211_STYPE_RTS);
7480
7481 memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
7482 }
7483
7484 /* mainrate
7485 * low 8 bits: main frag rate/mcs,
7486 * high 8 bits: rts/cts rate/mcs
7487 */
7488 mainrates |= (IS_OFDM(rts_rspec[0]) ?
7489 D11A_PHY_HDR_GRATE(
7490 (struct ofdm_phy_hdr *) rts_plcp) :
7491 rts_plcp[0]) << 8;
7492 } else {
7493 memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
7494 memset((char *)&txh->rts_frame, 0,
7495 sizeof(struct ieee80211_rts));
7496 memset((char *)txh->RTSPLCPFallback, 0,
7497 sizeof(txh->RTSPLCPFallback));
7498 txh->RTSDurFallback = 0;
7499 }
a9533e7e 7500
2682e2a3
AS
7501#ifdef SUPPORT_40MHZ
7502 /* add null delimiter count */
7503 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec))
7504 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
7505 brcm_c_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
a9533e7e 7506
2682e2a3 7507#endif
8ea54c9f 7508
2682e2a3
AS
7509 /*
7510 * Now that RTS/RTS FB preamble types are updated, write
7511 * the final value
7512 */
7513 txh->MacTxControlHigh = cpu_to_le16(mch);
a9533e7e 7514
2682e2a3
AS
7515 /*
7516 * MainRates (both the rts and frag plcp rates have
7517 * been calculated now)
7518 */
7519 txh->MainRates = cpu_to_le16(mainrates);
a9533e7e 7520
2682e2a3
AS
7521 /* XtraFrameTypes */
7522 xfts = FRAMETYPE(rspec[1], wlc->mimoft);
7523 xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
7524 xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
7525 xfts |=
7526 CHSPEC_CHANNEL(BRCMS_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
7527 txh->XtraFrameTypes = cpu_to_le16(xfts);
a9533e7e 7528
2682e2a3
AS
7529 /* PhyTxControlWord */
7530 phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
7531 if ((preamble_type[0] == BRCMS_SHORT_PREAMBLE) ||
7532 (preamble_type[0] == BRCMS_GF_PREAMBLE)) {
7533 if (RSPEC2RATE(rspec[0]) != BRCM_RATE_1M)
7534 phyctl |= PHY_TXC_SHORT_HDR;
7535 }
a9533e7e 7536
2682e2a3
AS
7537 /* phytxant is properly bit shifted */
7538 phyctl |= brcms_c_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
7539 txh->PhyTxControlWord = cpu_to_le16(phyctl);
a9533e7e 7540
2682e2a3
AS
7541 /* PhyTxControlWord_1 */
7542 if (BRCMS_PHY_11N_CAP(wlc->band)) {
7543 u16 phyctl1 = 0;
a9533e7e 7544
2682e2a3
AS
7545 phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[0]);
7546 txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
7547 phyctl1 = brcms_c_phytxctl1_calc(wlc, rspec[1]);
7548 txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
a9533e7e 7549
2682e2a3
AS
7550 if (use_rts || use_cts) {
7551 phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[0]);
7552 txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
7553 phyctl1 = brcms_c_phytxctl1_calc(wlc, rts_rspec[1]);
7554 txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
a9533e7e 7555 }
a9533e7e 7556
2682e2a3
AS
7557 /*
7558 * For mcs frames, if mixedmode(overloaded with long preamble)
7559 * is going to be set, fill in non-zero MModeLen and/or
7560 * MModeFbrLen it will be unnecessary if they are separated
7561 */
7562 if (IS_MCS(rspec[0]) &&
7563 (preamble_type[0] == BRCMS_MM_PREAMBLE)) {
7564 u16 mmodelen =
7565 brcms_c_calc_lsig_len(wlc, rspec[0], phylen);
7566 txh->MModeLen = cpu_to_le16(mmodelen);
7567 }
7568
7569 if (IS_MCS(rspec[1]) &&
7570 (preamble_type[1] == BRCMS_MM_PREAMBLE)) {
7571 u16 mmodefbrlen =
7572 brcms_c_calc_lsig_len(wlc, rspec[1], phylen);
7573 txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
a9533e7e
HP
7574 }
7575 }
7576
2682e2a3
AS
7577 ac = skb_get_queue_mapping(p);
7578 if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
7579 uint frag_dur, dur, dur_fallback;
a9533e7e 7580
2682e2a3
AS
7581 /* WME: Update TXOP threshold */
7582 if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) && frag == 0) {
7583 frag_dur =
7584 brcms_c_calc_frame_time(wlc, rspec[0],
7585 preamble_type[0], phylen);
fd821d1e 7586
2682e2a3
AS
7587 if (rts) {
7588 /* 1 RTS or CTS-to-self frame */
7589 dur =
7590 brcms_c_calc_cts_time(wlc, rts_rspec[0],
7591 rts_preamble_type[0]);
7592 dur_fallback =
7593 brcms_c_calc_cts_time(wlc, rts_rspec[1],
7594 rts_preamble_type[1]);
7595 /* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
7596 dur += le16_to_cpu(rts->duration);
7597 dur_fallback +=
7598 le16_to_cpu(txh->RTSDurFallback);
7599 } else if (use_rifs) {
7600 dur = frag_dur;
7601 dur_fallback = 0;
7602 } else {
7603 /* frame + SIFS + ACK */
7604 dur = frag_dur;
7605 dur +=
7606 brcms_c_compute_frame_dur(wlc, rspec[0],
7607 preamble_type[0], 0);
a9533e7e 7608
2682e2a3
AS
7609 dur_fallback =
7610 brcms_c_calc_frame_time(wlc, rspec[1],
7611 preamble_type[1],
7612 phylen);
7613 dur_fallback +=
7614 brcms_c_compute_frame_dur(wlc, rspec[1],
7615 preamble_type[1], 0);
7616 }
7617 /* NEED to set TxFesTimeNormal (hard) */
7618 txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
7619 /*
7620 * NEED to set fallback rate version of
7621 * TxFesTimeNormal (hard)
7622 */
7623 txh->TxFesTimeFallback =
7624 cpu_to_le16((u16) dur_fallback);
a9533e7e 7625
2682e2a3
AS
7626 /*
7627 * update txop byte threshold (txop minus intraframe
7628 * overhead)
7629 */
7630 if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
7631 uint newfragthresh;
a9533e7e 7632
2682e2a3
AS
7633 newfragthresh =
7634 brcms_c_calc_frame_len(wlc,
7635 rspec[0], preamble_type[0],
7636 (wlc->edcf_txop[ac] -
7637 (dur - frag_dur)));
7638 /* range bound the fragthreshold */
7639 if (newfragthresh < DOT11_MIN_FRAG_LEN)
7640 newfragthresh =
7641 DOT11_MIN_FRAG_LEN;
7642 else if (newfragthresh >
7643 wlc->usr_fragthresh)
7644 newfragthresh =
7645 wlc->usr_fragthresh;
7646 /* update the fragthresh and do txc update */
7647 if (wlc->fragthresh[queue] !=
7648 (u16) newfragthresh)
7649 wlc->fragthresh[queue] =
7650 (u16) newfragthresh;
7651 } else {
7652 wiphy_err(wlc->wiphy, "wl%d: %s txop invalid "
7653 "for rate %d\n",
7654 wlc->pub->unit, fifo_names[queue],
7655 RSPEC2RATE(rspec[0]));
7656 }
a9533e7e 7657
2682e2a3
AS
7658 if (dur > wlc->edcf_txop[ac])
7659 wiphy_err(wlc->wiphy, "wl%d: %s: %s txop "
7660 "exceeded phylen %d/%d dur %d/%d\n",
7661 wlc->pub->unit, __func__,
7662 fifo_names[queue],
7663 phylen, wlc->fragthresh[queue],
7664 dur, wlc->edcf_txop[ac]);
7665 }
a9533e7e
HP
7666 }
7667
2682e2a3
AS
7668 return 0;
7669}
a9533e7e 7670
2682e2a3
AS
7671bool
7672brcms_c_sendpkt_mac80211(struct brcms_c_info *wlc, struct sk_buff *sdu,
7673 struct ieee80211_hw *hw)
7674{
7675 u8 prio;
7676 uint fifo;
7677 struct scb *scb = &global_scb;
7678 struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
a9533e7e 7679
2682e2a3
AS
7680 /*
7681 * 802.11 standard requires management traffic
7682 * to go at highest priority
7683 */
7684 prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
7685 MAXPRIO;
7686 fifo = prio2fifo[prio];
7687 if (unlikely
7688 (brcms_c_d11hdrs_mac80211(
7689 wlc, hw, sdu, scb, 0, 1, fifo, 0, NULL, 0)))
7690 return -EINVAL;
7691 brcms_c_txq_enq(wlc, scb, sdu, BRCMS_PRIO_TO_PREC(prio));
7692 brcms_c_send_q(wlc);
7693 return 0;
7694}
a9533e7e 7695
2682e2a3
AS
7696void brcms_c_send_q(struct brcms_c_info *wlc)
7697{
7698 struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
7699 int prec;
7700 u16 prec_map;
7701 int err = 0, i, count;
7702 uint fifo;
7703 struct brcms_txq_info *qi = wlc->pkt_queue;
7704 struct pktq *q = &qi->q;
7705 struct ieee80211_tx_info *tx_info;
a9533e7e 7706
2682e2a3
AS
7707 if (in_send_q)
7708 return;
7709 else
7710 in_send_q = true;
a9533e7e 7711
2682e2a3 7712 prec_map = wlc->tx_prec_map;
a9533e7e 7713
2682e2a3
AS
7714 /* Send all the enq'd pkts that we can.
7715 * Dequeue packets with precedence with empty HW fifo only
7716 */
7717 while (prec_map && (pkt[0] = brcmu_pktq_mdeq(q, prec_map, &prec))) {
7718 tx_info = IEEE80211_SKB_CB(pkt[0]);
7719 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
7720 err = brcms_c_sendampdu(wlc->ampdu, qi, pkt, prec);
7721 } else {
7722 count = 1;
7723 err = brcms_c_prep_pdu(wlc, pkt[0], &fifo);
7724 if (!err) {
7725 for (i = 0; i < count; i++)
7726 brcms_c_txfifo(wlc, fifo, pkt[i], true,
7727 1);
7728 }
7729 }
a9533e7e 7730
2682e2a3
AS
7731 if (err == -EBUSY) {
7732 brcmu_pktq_penq_head(q, prec, pkt[0]);
7733 /*
7734 * If send failed due to any other reason than a
7735 * change in HW FIFO condition, quit. Otherwise,
7736 * read the new prec_map!
7737 */
7738 if (prec_map == wlc->tx_prec_map)
7739 break;
7740 prec_map = wlc->tx_prec_map;
7741 }
a9533e7e
HP
7742 }
7743
419ad34e 7744 /*
2682e2a3
AS
7745 * Check if flow control needs to be turned off after
7746 * sending the packet
72345923 7747 */
2682e2a3
AS
7748 if (!EDCF_ENAB(wlc->pub)
7749 || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
7750 if (brcms_c_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
7751 && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2))
7752 brcms_c_txflowcontrol(wlc, qi, OFF, ALLPRIO);
7753 } else if (wlc->pub->_priofc) {
7754 int prio;
7755 for (prio = MAXPRIO; prio >= 0; prio--) {
7756 if (brcms_c_txflowcontrol_prio_isset(wlc, qi, prio) &&
7757 (pktq_plen(q, wlc_prio2prec_map[prio]) <
7758 wlc->pub->tunables->datahiwat / 2))
7759 brcms_c_txflowcontrol(wlc, qi, OFF, prio);
a9533e7e 7760 }
2682e2a3
AS
7761 }
7762 in_send_q = false;
7763}
a9533e7e 7764
2682e2a3
AS
7765static void brcms_c_war16165(struct brcms_c_info *wlc, bool tx)
7766{
7767 if (tx) {
7768 /* the post-increment is used in STAY_AWAKE macro */
7769 if (wlc->txpend16165war++ == 0)
7770 brcms_c_set_ps_ctrl(wlc);
7771 } else {
7772 wlc->txpend16165war--;
7773 if (wlc->txpend16165war == 0)
7774 brcms_c_set_ps_ctrl(wlc);
7775 }
7776}
a9533e7e 7777
2682e2a3
AS
7778void
7779brcms_c_txfifo(struct brcms_c_info *wlc, uint fifo, struct sk_buff *p,
7780 bool commit, s8 txpktpend)
7781{
7782 u16 frameid = INVALIDFID;
7783 struct d11txh *txh;
a9533e7e 7784
2682e2a3 7785 txh = (struct d11txh *) (p->data);
a9533e7e 7786
2682e2a3
AS
7787 /* When a BC/MC frame is being committed to the BCMC fifo
7788 * via DMA (NOT PIO), update ucode or BSS info as appropriate.
7789 */
7790 if (fifo == TX_BCMC_FIFO)
7791 frameid = le16_to_cpu(txh->TxFrameID);
a9533e7e 7792
2682e2a3
AS
7793 if (BRCMS_WAR16165(wlc))
7794 brcms_c_war16165(wlc, true);
a9533e7e 7795
a9533e7e 7796
2682e2a3
AS
7797 /*
7798 * Bump up pending count for if not using rpc. If rpc is
7799 * used, this will be handled in brcms_b_txfifo()
7800 */
7801 if (commit) {
7802 TXPKTPENDINC(wlc, fifo, txpktpend);
7803 BCMMSG(wlc->wiphy, "pktpend inc %d to %d\n",
7804 txpktpend, TXPKTPENDGET(wlc, fifo));
7805 }
a9533e7e 7806
2682e2a3
AS
7807 /* Commit BCMC sequence number in the SHM frame ID location */
7808 if (frameid != INVALIDFID)
7809 BCMCFID(wlc, frameid);
a9533e7e 7810
2682e2a3
AS
7811 if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0)
7812 wiphy_err(wlc->wiphy, "txfifo: fatal, toss frames !!!\n");
7813}
2fbd6b37 7814
2682e2a3
AS
7815/*
7816 * Compute PLCP, but only requires actual rate and length of pkt.
7817 * Rate is given in the driver standard multiple of 500 kbps.
7818 * le is set for 11 Mbps rate if necessary.
7819 * Broken out for PRQ.
7820 */
7821
7822static void brcms_c_cck_plcp_set(struct brcms_c_info *wlc, int rate_500,
7823 uint length, u8 *plcp)
7824{
7825 u16 usec = 0;
7826 u8 le = 0;
2fbd6b37 7827
2682e2a3
AS
7828 switch (rate_500) {
7829 case BRCM_RATE_1M:
7830 usec = length << 3;
7831 break;
7832 case BRCM_RATE_2M:
7833 usec = length << 2;
7834 break;
7835 case BRCM_RATE_5M5:
7836 usec = (length << 4) / 11;
7837 if ((length << 4) - (usec * 11) > 0)
7838 usec++;
7839 break;
7840 case BRCM_RATE_11M:
7841 usec = (length << 3) / 11;
7842 if ((length << 3) - (usec * 11) > 0) {
7843 usec++;
7844 if ((usec * 11) - (length << 3) >= 8)
7845 le = D11B_PLCP_SIGNAL_LE;
a9533e7e 7846 }
2682e2a3 7847 break;
a9533e7e 7848
2682e2a3
AS
7849 default:
7850 wiphy_err(wlc->wiphy,
7851 "brcms_c_cck_plcp_set: unsupported rate %d\n",
7852 rate_500);
7853 rate_500 = BRCM_RATE_1M;
7854 usec = length << 3;
7855 break;
a9533e7e 7856 }
2682e2a3
AS
7857 /* PLCP signal byte */
7858 plcp[0] = rate_500 * 5; /* r (500kbps) * 5 == r (100kbps) */
7859 /* PLCP service byte */
7860 plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
7861 /* PLCP length u16, little endian */
7862 plcp[2] = usec & 0xff;
7863 plcp[3] = (usec >> 8) & 0xff;
7864 /* PLCP CRC16 */
7865 plcp[4] = 0;
7866 plcp[5] = 0;
7867}
a9533e7e 7868
2682e2a3
AS
7869/* Rate: 802.11 rate code, length: PSDU length in octets */
7870static void brcms_c_compute_mimo_plcp(u32 rspec, uint length, u8 *plcp)
7871{
7872 u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
7873 plcp[0] = mcs;
7874 if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
7875 plcp[0] |= MIMO_PLCP_40MHZ;
7876 BRCMS_SET_MIMO_PLCP_LEN(plcp, length);
7877 plcp[3] = RSPEC_MIMOPLCP3(rspec); /* rspec already holds this byte */
7878 plcp[3] |= 0x7; /* set smoothing, not sounding ppdu & reserved */
7879 plcp[4] = 0; /* number of extension spatial streams bit 0 & 1 */
7880 plcp[5] = 0;
7881}
8ea54c9f 7882
2682e2a3
AS
7883/* Rate: 802.11 rate code, length: PSDU length in octets */
7884static void
7885brcms_c_compute_ofdm_plcp(u32 rspec, u32 length, u8 *plcp)
7886{
7887 u8 rate_signal;
7888 u32 tmp = 0;
7889 int rate = RSPEC2RATE(rspec);
a9533e7e 7890
419ad34e 7891 /*
2682e2a3
AS
7892 * encode rate per 802.11a-1999 sec 17.3.4.1, with lsb
7893 * transmitted first
419ad34e 7894 */
2682e2a3
AS
7895 rate_signal = rate_info[rate] & BRCMS_RATE_MASK;
7896 memset(plcp, 0, D11_PHY_HDR_LEN);
7897 D11A_PHY_HDR_SRATE((struct ofdm_phy_hdr *) plcp, rate_signal);
a9533e7e 7898
2682e2a3
AS
7899 tmp = (length & 0xfff) << 5;
7900 plcp[2] |= (tmp >> 16) & 0xff;
7901 plcp[1] |= (tmp >> 8) & 0xff;
7902 plcp[0] |= tmp & 0xff;
a9533e7e 7903
2682e2a3
AS
7904 return;
7905}
a9533e7e 7906
2682e2a3
AS
7907/* Rate: 802.11 rate code, length: PSDU length in octets */
7908static void brcms_c_compute_cck_plcp(struct brcms_c_info *wlc, u32 rspec,
7909 uint length, u8 *plcp)
7910{
7911 int rate = RSPEC2RATE(rspec);
a9533e7e 7912
2682e2a3
AS
7913 brcms_c_cck_plcp_set(wlc, rate, length, plcp);
7914}
a9533e7e 7915
2682e2a3
AS
7916void
7917brcms_c_compute_plcp(struct brcms_c_info *wlc, u32 rspec,
7918 uint length, u8 *plcp)
7919{
7920 if (IS_MCS(rspec))
7921 brcms_c_compute_mimo_plcp(rspec, length, plcp);
7922 else if (IS_OFDM(rspec))
7923 brcms_c_compute_ofdm_plcp(rspec, length, plcp);
7924 else
7925 brcms_c_compute_cck_plcp(wlc, rspec, length, plcp);
7926 return;
7927}
a9533e7e 7928
2682e2a3
AS
7929/* brcms_c_compute_rtscts_dur()
7930 *
7931 * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
7932 * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
7933 * DUR for CTS-TO-SELF w/ frame = 2 SIFS + next frame time + 1 ACK
7934 *
7935 * cts cts-to-self or rts/cts
7936 * rts_rate rts or cts rate in unit of 500kbps
7937 * rate next MPDU rate in unit of 500kbps
7938 * frame_len next MPDU frame length in bytes
7939 */
7940u16
7941brcms_c_compute_rtscts_dur(struct brcms_c_info *wlc, bool cts_only,
7942 u32 rts_rate,
7943 u32 frame_rate, u8 rts_preamble_type,
7944 u8 frame_preamble_type, uint frame_len, bool ba)
7945{
7946 u16 dur, sifs;
a9533e7e 7947
2682e2a3 7948 sifs = SIFS(wlc->band);
a9533e7e 7949
2682e2a3
AS
7950 if (!cts_only) {
7951 /* RTS/CTS */
7952 dur = 3 * sifs;
7953 dur +=
7954 (u16) brcms_c_calc_cts_time(wlc, rts_rate,
7955 rts_preamble_type);
7956 } else {
7957 /* CTS-TO-SELF */
7958 dur = 2 * sifs;
7959 }
a9533e7e 7960
2682e2a3
AS
7961 dur +=
7962 (u16) brcms_c_calc_frame_time(wlc, frame_rate, frame_preamble_type,
7963 frame_len);
7964 if (ba)
7965 dur +=
7966 (u16) brcms_c_calc_ba_time(wlc, frame_rate,
7967 BRCMS_SHORT_PREAMBLE);
7968 else
7969 dur +=
7970 (u16) brcms_c_calc_ack_time(wlc, frame_rate,
7971 frame_preamble_type);
7972 return dur;
7973}
7974
7975u16 brcms_c_phytxctl1_calc(struct brcms_c_info *wlc, u32 rspec)
7976{
7977 u16 phyctl1 = 0;
7978 u16 bw;
7979
7980 if (BRCMS_ISLCNPHY(wlc->band)) {
7981 bw = PHY_TXC1_BW_20MHZ;
7982 } else {
7983 bw = RSPEC_GET_BW(rspec);
7984 /* 10Mhz is not supported yet */
7985 if (bw < PHY_TXC1_BW_20MHZ) {
7986 wiphy_err(wlc->wiphy, "phytxctl1_calc: bw %d is "
7987 "not supported yet, set to 20L\n", bw);
7988 bw = PHY_TXC1_BW_20MHZ;
a9533e7e
HP
7989 }
7990 }
7991
2682e2a3
AS
7992 if (IS_MCS(rspec)) {
7993 uint mcs = rspec & RSPEC_RATE_MASK;
a9533e7e 7994
2682e2a3
AS
7995 /* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
7996 phyctl1 = RSPEC_PHYTXBYTE2(rspec);
7997 /* set the upper byte of phyctl1 */
7998 phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
7999 } else if (IS_CCK(rspec) && !BRCMS_ISLCNPHY(wlc->band)
8000 && !BRCMS_ISSSLPNPHY(wlc->band)) {
8001 /*
8002 * In CCK mode LPPHY overloads OFDM Modulation bits with CCK
8003 * Data Rate. Eventually MIMOPHY would also be converted to
8004 * this format
8005 */
8006 /* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
8007 phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
8008 } else { /* legacy OFDM/CCK */
8009 s16 phycfg;
8010 /* get the phyctl byte from rate phycfg table */
8011 phycfg = brcms_c_rate_legacy_phyctl(RSPEC2RATE(rspec));
8012 if (phycfg == -1) {
8013 wiphy_err(wlc->wiphy, "phytxctl1_calc: wrong "
8014 "legacy OFDM/CCK rate\n");
8015 phycfg = 0;
8016 }
8017 /* set the upper byte of phyctl1 */
8018 phyctl1 =
8019 (bw | (phycfg << 8) |
8020 (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
8021 }
8022 return phyctl1;
8023}
a9533e7e 8024
2682e2a3
AS
8025u32
8026brcms_c_rspec_to_rts_rspec(struct brcms_c_info *wlc, u32 rspec,
8027 bool use_rspec, u16 mimo_ctlchbw)
8028{
8029 u32 rts_rspec = 0;
a9533e7e 8030
2682e2a3
AS
8031 if (use_rspec)
8032 /* use frame rate as rts rate */
8033 rts_rspec = rspec;
8034 else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec))
8035 /* Use 11Mbps as the g protection RTS target rate and fallback.
8036 * Use the BRCMS_BASIC_RATE() lookup to find the best basic rate
8037 * under the target in case 11 Mbps is not Basic.
8038 * 6 and 9 Mbps are not usually selected by rate selection, but
8039 * even if the OFDM rate we are protecting is 6 or 9 Mbps, 11
8040 * is more robust.
8041 */
8042 rts_rspec = BRCMS_BASIC_RATE(wlc, BRCM_RATE_11M);
8043 else
8044 /* calculate RTS rate and fallback rate based on the frame rate
8045 * RTS must be sent at a basic rate since it is a
8046 * control frame, sec 9.6 of 802.11 spec
8047 */
8048 rts_rspec = BRCMS_BASIC_RATE(wlc, rspec);
a9533e7e 8049
2682e2a3
AS
8050 if (BRCMS_PHY_11N_CAP(wlc->band)) {
8051 /* set rts txbw to correct side band */
8052 rts_rspec &= ~RSPEC_BW_MASK;
8ea54c9f 8053
2682e2a3
AS
8054 /*
8055 * if rspec/rspec_fallback is 40MHz, then send RTS on both
8056 * 20MHz channel (DUP), otherwise send RTS on control channel
8057 */
8058 if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
8059 rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
8060 else
8061 rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
a9533e7e 8062
2682e2a3
AS
8063 /* pick siso/cdd as default for ofdm */
8064 if (IS_OFDM(rts_rspec)) {
8065 rts_rspec &= ~RSPEC_STF_MASK;
8066 rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
a9533e7e
HP
8067 }
8068 }
2682e2a3 8069 return rts_rspec;
a9533e7e
HP
8070}
8071
fe741e5e 8072void brcms_c_tbtt(struct brcms_c_info *wlc)
a9533e7e 8073{
471f1b51 8074 struct brcms_bss_cfg *cfg = wlc->cfg;
a9533e7e 8075
8ea54c9f 8076 if (!cfg->BSS)
419ad34e
AS
8077 /*
8078 * DirFrmQ is now valid...defer setting until end
8079 * of ATIM window
8080 */
a9533e7e 8081 wlc->qvalid |= MCMD_DIRFRMQVAL;
a9533e7e
HP
8082}
8083
cc87568a 8084/* process an individual struct tx_status */
de91ed29 8085bool
cc87568a 8086brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs, u32 frm_tx2)
a9533e7e 8087{
c26b1378 8088 struct sk_buff *p;
a9533e7e 8089 uint queue;
cc87568a 8090 struct d11txh *txh;
a9533e7e
HP
8091 struct scb *scb = NULL;
8092 bool free_pdu;
a9533e7e
HP
8093 int tx_rts, tx_frame_count, tx_rts_count;
8094 uint totlen, supr_status;
8095 bool lastframe;
3e9796f9 8096 struct ieee80211_hdr *h;
7d4df48e 8097 u16 mcl;
a9533e7e
HP
8098 struct ieee80211_tx_info *tx_info;
8099 struct ieee80211_tx_rate *txrate;
8100 int i;
8101
419ad34e
AS
8102 /* Compiler reference to avoid unused variable warning */
8103 (void)(frm_tx2);
a9533e7e
HP
8104
8105 /* discard intermediate indications for ucode with one legitimate case:
419ad34e
AS
8106 * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange,
8107 * but the subsequent tx of DATA failed. so it will start rts/cts
8108 * from the beginning (resetting the rts transmission count)
a9533e7e
HP
8109 */
8110 if (!(txs->status & TX_STATUS_AMPDU)
8111 && (txs->status & TX_STATUS_INTERMEDIATE)) {
b8f092c9
RV
8112 wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
8113 __func__);
0965ae88 8114 return false;
a9533e7e
HP
8115 }
8116
a9533e7e 8117 queue = txs->frameid & TXFID_QUEUE_MASK;
a9533e7e
HP
8118 if (queue >= NFIFO) {
8119 p = NULL;
8120 goto fatal;
8121 }
8122
8123 p = GETNEXTTXP(wlc, queue);
7c783cef 8124 if (BRCMS_WAR16165(wlc))
1c4c54ba 8125 brcms_c_war16165(wlc, false);
a9533e7e
HP
8126 if (p == NULL)
8127 goto fatal;
8128
cc87568a 8129 txh = (struct d11txh *) (p->data);
628f10ba 8130 mcl = le16_to_cpu(txh->MacTxControlLow);
a9533e7e
HP
8131
8132 if (txs->phyerr) {
bc042b67 8133 if (WL_ERROR_ON()) {
b8f092c9
RV
8134 wiphy_err(wlc->wiphy, "phyerr 0x%x, rate 0x%x\n",
8135 txs->phyerr, txh->MainRates);
fe741e5e 8136 brcms_c_print_txdesc(txh);
bc042b67 8137 }
fe741e5e 8138 brcms_c_print_txstatus(txs);
a9533e7e
HP
8139 }
8140
628f10ba 8141 if (txs->frameid != cpu_to_le16(txh->TxFrameID))
a9533e7e 8142 goto fatal;
a9533e7e 8143 tx_info = IEEE80211_SKB_CB(p);
3e9796f9 8144 h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
a9533e7e 8145
8ada0be3
RV
8146 if (tx_info->control.sta)
8147 scb = (struct scb *)tx_info->control.sta->drv_priv;
a9533e7e 8148
a9533e7e 8149 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
f52a0ad0 8150 brcms_c_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
0965ae88 8151 return false;
a9533e7e
HP
8152 }
8153
8154 supr_status = txs->status & TX_STATUS_SUPR_MASK;
8155 if (supr_status == TX_STATUS_SUPR_BADCH)
222508d7
RV
8156 BCMMSG(wlc->wiphy,
8157 "%s: Pkt tx suppressed, possibly channel %d\n",
8158 __func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
a9533e7e 8159
628f10ba 8160 tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
a9533e7e
HP
8161 tx_frame_count =
8162 (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
8163 tx_rts_count =
8164 (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
8165
2fbd6b37 8166 lastframe = !ieee80211_has_morefrags(h->frame_control);
a9533e7e
HP
8167
8168 if (!lastframe) {
b8f092c9 8169 wiphy_err(wlc->wiphy, "Not last frame!\n");
a9533e7e 8170 } else {
94daaf70
RV
8171 /*
8172 * Set information to be consumed by Minstrel ht.
8173 *
8174 * The "fallback limit" is the number of tx attempts a given
8175 * MPDU is sent at the "primary" rate. Tx attempts beyond that
8176 * limit are sent at the "secondary" rate.
8177 * A 'short frame' does not exceed RTS treshold.
8178 */
8179 u16 sfbl, /* Short Frame Rate Fallback Limit */
8180 lfbl, /* Long Frame Rate Fallback Limit */
8181 fbl;
8182
a9533e7e 8183 if (queue < AC_COUNT) {
7c783cef
RV
8184 sfbl = BRCMS_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
8185 lfbl = BRCMS_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
a9533e7e
HP
8186 } else {
8187 sfbl = wlc->SFBL;
8188 lfbl = wlc->LFBL;
8189 }
8190
8191 txrate = tx_info->status.rates;
94daaf70
RV
8192 if (txrate[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
8193 fbl = lfbl;
8194 else
8195 fbl = sfbl;
8196
8197 ieee80211_tx_info_clear_status(tx_info);
8198
8199 if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) {
419ad34e
AS
8200 /*
8201 * rate selection requested a fallback rate
8202 * and we used it
8203 */
94daaf70
RV
8204 txrate[0].count = fbl;
8205 txrate[1].count = tx_frame_count - fbl;
a9533e7e 8206 } else {
419ad34e
AS
8207 /*
8208 * rate selection did not request fallback rate, or
8209 * we didn't need it
8210 */
94daaf70 8211 txrate[0].count = tx_frame_count;
419ad34e
AS
8212 /*
8213 * rc80211_minstrel.c:minstrel_tx_status() expects
8214 * unused rates to be marked with idx = -1
8215 */
a9533e7e
HP
8216 txrate[1].idx = -1;
8217 txrate[1].count = 0;
8218 }
8219
8220 /* clear the rest of the rates */
8221 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
8222 txrate[i].idx = -1;
8223 txrate[i].count = 0;
8224 }
8225
8226 if (txs->status & TX_STATUS_ACK_RCV)
8227 tx_info->flags |= IEEE80211_TX_STAT_ACK;
8228 }
8229
67ad48bc 8230 totlen = brcmu_pkttotlen(p);
0f0881b0 8231 free_pdu = true;
a9533e7e 8232
fe741e5e 8233 brcms_c_txfifo_complete(wlc, queue, 1);
a9533e7e
HP
8234
8235 if (lastframe) {
54991ad6
AS
8236 p->next = NULL;
8237 p->prev = NULL;
a9533e7e 8238 /* remove PLCP & Broadcom tx descriptor header */
c303ecbd
AS
8239 skb_pull(p, D11_PHY_HDR_LEN);
8240 skb_pull(p, D11_TXH_LEN);
a9533e7e 8241 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
a9533e7e 8242 } else {
b8f092c9
RV
8243 wiphy_err(wlc->wiphy, "%s: Not last frame => not calling "
8244 "tx_status\n", __func__);
a9533e7e
HP
8245 }
8246
0965ae88 8247 return false;
a9533e7e
HP
8248
8249 fatal:
a9533e7e 8250 if (p)
67ad48bc 8251 brcmu_pkt_buf_free_skb(p);
a9533e7e 8252
0f0881b0 8253 return true;
a9533e7e
HP
8254
8255}
8256
de91ed29 8257void
fe741e5e 8258brcms_c_txfifo_complete(struct brcms_c_info *wlc, uint fifo, s8 txpktpend)
a9533e7e
HP
8259{
8260 TXPKTPENDDEC(wlc, fifo, txpktpend);
792aa408
RV
8261 BCMMSG(wlc->wiphy, "pktpend dec %d to %d\n", txpktpend,
8262 TXPKTPENDGET(wlc, fifo));
a9533e7e
HP
8263
8264 /* There is more room; mark precedences related to this FIFO sendable */
7c783cef 8265 BRCMS_TX_FIFO_ENAB(wlc, fifo);
a9533e7e 8266
a9533e7e
HP
8267 /* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
8268 if (AP_ENAB(wlc->pub) &&
8ea54c9f 8269 !TXPKTPENDGET(wlc, TX_BCMC_FIFO))
7c783cef 8270 brcms_c_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, BRCM_BAND_AUTO);
a9533e7e
HP
8271
8272 /* figure out which bsscfg is being worked on... */
8273}
8274
a9533e7e 8275/* Update beacon listen interval in shared memory */
fe741e5e 8276void brcms_c_bcn_li_upd(struct brcms_c_info *wlc)
a9533e7e
HP
8277{
8278 if (AP_ENAB(wlc->pub))
8279 return;
8280
8281 /* wake up every DTIM is the default */
8282 if (wlc->bcn_li_dtim == 1)
fe741e5e 8283 brcms_c_write_shm(wlc, M_BCN_LI, 0);
a9533e7e 8284 else
fe741e5e 8285 brcms_c_write_shm(wlc, M_BCN_LI,
a9533e7e
HP
8286 (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
8287}
8288
11431424 8289static void
839f9f62
RV
8290brcms_b_read_tsf(struct brcms_hardware *wlc_hw, u32 *tsf_l_ptr,
8291 u32 *tsf_h_ptr)
8292{
0da64910 8293 struct d11regs *regs = wlc_hw->regs;
839f9f62
RV
8294
8295 /* read the tsf timer low, then high to get an atomic read */
8296 *tsf_l_ptr = R_REG(&regs->tsf_timerlow);
8297 *tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
8298
8299 return;
8300}
8301
88ddf0c9
AS
8302/*
8303 * recover 64bit TSF value from the 16bit TSF value in the rx header
8304 * given the assumption that the TSF passed in header is within 65ms
8305 * of the current tsf.
8306 *
8307 * 6 5 4 4 3 2 1
8308 * 3.......6.......8.......0.......2.......4.......6.......8......0
8309 * |<---------- tsf_h ----------->||<--- tsf_l -->||<-RxTSFTime ->|
8310 *
8311 * The RxTSFTime are the lowest 16 bits and provided by the ucode. The
c654fce6 8312 * tsf_l is filled in by brcms_b_recv, which is done earlier in the
88ddf0c9
AS
8313 * receive call sequence after rx interrupt. Only the higher 16 bits
8314 * are used. Finally, the tsf_h is read from the tsf register.
8315 */
1c4c54ba 8316static u64 brcms_c_recover_tsf64(struct brcms_c_info *wlc,
cc87568a 8317 struct brcms_d11rxhdr *rxh)
88ddf0c9
AS
8318{
8319 u32 tsf_h, tsf_l;
8320 u16 rx_tsf_0_15, rx_tsf_16_31;
8321
c654fce6 8322 brcms_b_read_tsf(wlc->hw, &tsf_l, &tsf_h);
88ddf0c9
AS
8323
8324 rx_tsf_16_31 = (u16)(tsf_l >> 16);
8325 rx_tsf_0_15 = rxh->rxhdr.RxTSFTime;
8326
8327 /*
8328 * a greater tsf time indicates the low 16 bits of
8329 * tsf_l wrapped, so decrement the high 16 bits.
8330 */
8331 if ((u16)tsf_l < rx_tsf_0_15) {
8332 rx_tsf_16_31 -= 1;
8333 if (rx_tsf_16_31 == 0xffff)
8334 tsf_h -= 1;
8335 }
8336
8337 return ((u64)tsf_h << 32) | (((u32)rx_tsf_16_31 << 16) + rx_tsf_0_15);
8338}
8339
a9533e7e 8340static void
cc87568a 8341prep_mac80211_status(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
fe741e5e 8342 struct sk_buff *p,
a9533e7e
HP
8343 struct ieee80211_rx_status *rx_status)
8344{
cc87568a 8345 struct brcms_d11rxhdr *wlc_rxh = (struct brcms_d11rxhdr *) rxh;
a9533e7e
HP
8346 int preamble;
8347 int channel;
6bd20a1b 8348 u32 rspec;
580a0bd9 8349 unsigned char *plcp;
a9533e7e 8350
88ddf0c9 8351 /* fill in TSF and flag its presence */
1c4c54ba 8352 rx_status->mactime = brcms_c_recover_tsf64(wlc, wlc_rxh);
88ddf0c9 8353 rx_status->flag |= RX_FLAG_MACTIME_MPDU;
a9533e7e 8354
7c783cef 8355 channel = BRCMS_CHAN_CHANNEL(rxh->RxChan);
a9533e7e 8356
a9533e7e
HP
8357 if (channel > 14) {
8358 rx_status->band = IEEE80211_BAND_5GHZ;
d69a1358
RV
8359 rx_status->freq = ieee80211_ofdm_chan_to_freq(
8360 WF_CHAN_FACTOR_5_G/2, channel);
8361
a9533e7e
HP
8362 } else {
8363 rx_status->band = IEEE80211_BAND_2GHZ;
1b1d36b6 8364 rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
a9533e7e
HP
8365 }
8366
419ad34e 8367 rx_status->signal = wlc_rxh->rssi;
a9533e7e
HP
8368
8369 /* noise */
8370 /* qual */
419ad34e
AS
8371 rx_status->antenna =
8372 (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
a9533e7e 8373
54991ad6 8374 plcp = p->data;
a9533e7e 8375
f52a0ad0 8376 rspec = brcms_c_compute_rspec(rxh, plcp);
a9533e7e
HP
8377 if (IS_MCS(rspec)) {
8378 rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
8379 rx_status->flag |= RX_FLAG_HT;
8380 if (RSPEC_IS40MHZ(rspec))
8381 rx_status->flag |= RX_FLAG_40MHZ;
8382 } else {
8383 switch (RSPEC2RATE(rspec)) {
7c783cef 8384 case BRCM_RATE_1M:
a9533e7e
HP
8385 rx_status->rate_idx = 0;
8386 break;
7c783cef 8387 case BRCM_RATE_2M:
a9533e7e
HP
8388 rx_status->rate_idx = 1;
8389 break;
7c783cef 8390 case BRCM_RATE_5M5:
a9533e7e
HP
8391 rx_status->rate_idx = 2;
8392 break;
7c783cef 8393 case BRCM_RATE_11M:
a9533e7e
HP
8394 rx_status->rate_idx = 3;
8395 break;
7c783cef 8396 case BRCM_RATE_6M:
a9533e7e
HP
8397 rx_status->rate_idx = 4;
8398 break;
7c783cef 8399 case BRCM_RATE_9M:
a9533e7e
HP
8400 rx_status->rate_idx = 5;
8401 break;
7c783cef 8402 case BRCM_RATE_12M:
a9533e7e
HP
8403 rx_status->rate_idx = 6;
8404 break;
7c783cef 8405 case BRCM_RATE_18M:
a9533e7e
HP
8406 rx_status->rate_idx = 7;
8407 break;
7c783cef 8408 case BRCM_RATE_24M:
a9533e7e
HP
8409 rx_status->rate_idx = 8;
8410 break;
7c783cef 8411 case BRCM_RATE_36M:
a9533e7e
HP
8412 rx_status->rate_idx = 9;
8413 break;
7c783cef 8414 case BRCM_RATE_48M:
a9533e7e
HP
8415 rx_status->rate_idx = 10;
8416 break;
7c783cef 8417 case BRCM_RATE_54M:
a9533e7e
HP
8418 rx_status->rate_idx = 11;
8419 break;
8420 default:
b8f092c9 8421 wiphy_err(wlc->wiphy, "%s: Unknown rate\n", __func__);
a9533e7e
HP
8422 }
8423
5a84d6ad
AS
8424 /*
8425 * For 5GHz, we should decrease the index as it is
8426 * a subset of the 2.4G rates. See bitrates field
8427 * of brcms_band_5GHz_nphy (in mac80211_if.c).
8428 */
8429 if (rx_status->band == IEEE80211_BAND_5GHZ)
8430 rx_status->rate_idx -= BRCMS_LEGACY_5G_RATE_OFFSET;
8431
a9533e7e
HP
8432 /* Determine short preamble and rate_idx */
8433 preamble = 0;
8434 if (IS_CCK(rspec)) {
8435 if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
e5b95845 8436 rx_status->flag |= RX_FLAG_SHORTPRE;
a9533e7e
HP
8437 } else if (IS_OFDM(rspec)) {
8438 rx_status->flag |= RX_FLAG_SHORTPRE;
8439 } else {
b8f092c9
RV
8440 wiphy_err(wlc->wiphy, "%s: Unknown modulation\n",
8441 __func__);
a9533e7e
HP
8442 }
8443 }
8444
8445 if (PLCP3_ISSGI(plcp[3]))
8446 rx_status->flag |= RX_FLAG_SHORT_GI;
8447
8448 if (rxh->RxStatus1 & RXS_DECERR) {
8449 rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
b8f092c9
RV
8450 wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_PLCP_CRC\n",
8451 __func__);
a9533e7e
HP
8452 }
8453 if (rxh->RxStatus1 & RXS_FCSERR) {
8454 rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
b8f092c9
RV
8455 wiphy_err(wlc->wiphy, "%s: RX_FLAG_FAILED_FCS_CRC\n",
8456 __func__);
a9533e7e
HP
8457 }
8458}
8459
a9533e7e 8460static void
cc87568a
RV
8461brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh,
8462 struct sk_buff *p)
a9533e7e
HP
8463{
8464 int len_mpdu;
8465 struct ieee80211_rx_status rx_status;
a9533e7e
HP
8466
8467 memset(&rx_status, 0, sizeof(rx_status));
8468 prep_mac80211_status(wlc, rxh, p, &rx_status);
8469
8470 /* mac header+body length, exclude CRC and plcp header */
3726ed4d 8471 len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
c303ecbd 8472 skb_pull(p, D11_PHY_HDR_LEN);
2cb8ada6 8473 __skb_trim(p, len_mpdu);
a9533e7e 8474
a9533e7e
HP
8475 memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
8476 ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
a9533e7e
HP
8477 return;
8478}
8479
a9533e7e
HP
8480/* Process received frames */
8481/*
0965ae88 8482 * Return true if more frames need to be processed. false otherwise.
a9533e7e
HP
8483 * Param 'bound' indicates max. # frames to process before break out.
8484 */
fe741e5e 8485void brcms_c_recv(struct brcms_c_info *wlc, struct sk_buff *p)
a9533e7e 8486{
cc87568a 8487 struct d11rxhdr *rxh;
3e9796f9 8488 struct ieee80211_hdr *h;
a9533e7e
HP
8489 uint len;
8490 bool is_amsdu;
a9533e7e 8491
792aa408 8492 BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
a9533e7e 8493
a9533e7e 8494 /* frame starts with rxhdr */
cc87568a 8495 rxh = (struct d11rxhdr *) (p->data);
a9533e7e
HP
8496
8497 /* strip off rxhdr */
7c783cef 8498 skb_pull(p, BRCMS_HWRXOFF);
a9533e7e
HP
8499
8500 /* fixup rx header endianness */
f3171549
SF
8501 rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
8502 rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
8503 rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
8504 rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
8505 rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
8506 rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
8507 rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
8508 rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
8509 rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
8510 rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
8511 rxh->RxChan = le16_to_cpu(rxh->RxChan);
a9533e7e
HP
8512
8513 /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
8514 if (rxh->RxStatus1 & RXS_PBPRES) {
54991ad6 8515 if (p->len < 2) {
1c4c54ba 8516 wiphy_err(wlc->wiphy, "wl%d: recv: rcvd runt of "
b8f092c9 8517 "len %d\n", wlc->pub->unit, p->len);
a9533e7e
HP
8518 goto toss;
8519 }
c303ecbd 8520 skb_pull(p, 2);
a9533e7e
HP
8521 }
8522
3e9796f9 8523 h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
54991ad6 8524 len = p->len;
a9533e7e
HP
8525
8526 if (rxh->RxStatus1 & RXS_FCSERR) {
8527 if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
b8f092c9
RV
8528 wiphy_err(wlc->wiphy, "FCSERR while scanning******* -"
8529 " tossing\n");
a9533e7e
HP
8530 goto toss;
8531 } else {
b8f092c9 8532 wiphy_err(wlc->wiphy, "RCSERR!!!\n");
a9533e7e
HP
8533 goto toss;
8534 }
8535 }
8536
8537 /* check received pkt has at least frame control field */
8ea54c9f 8538 if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control))
a9533e7e 8539 goto toss;
a9533e7e
HP
8540
8541 is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
8542
8543 /* explicitly test bad src address to avoid sending bad deauth */
8544 if (!is_amsdu) {
8545 /* CTS and ACK CTL frames are w/o a2 */
2fbd6b37
SF
8546
8547 if (ieee80211_is_data(h->frame_control) ||
8548 ieee80211_is_mgmt(h->frame_control)) {
3e9796f9
RV
8549 if ((is_zero_ether_addr(h->addr2) ||
8550 is_multicast_ether_addr(h->addr2))) {
b8f092c9
RV
8551 wiphy_err(wlc->wiphy, "wl%d: %s: dropping a "
8552 "frame with invalid src mac address,"
8553 " a2: %pM\n",
d83b2a8a 8554 wlc->pub->unit, __func__, h->addr2);
a9533e7e
HP
8555 goto toss;
8556 }
a9533e7e
HP
8557 }
8558 }
8559
8560 /* due to sheer numbers, toss out probe reqs for now */
2fbd6b37
SF
8561 if (ieee80211_is_probe_req(h->frame_control))
8562 goto toss;
a9533e7e 8563
d571a566 8564 if (is_amsdu)
a9533e7e 8565 goto toss;
a9533e7e 8566
1c4c54ba 8567 brcms_c_recvctl(wlc, rxh, p);
a9533e7e
HP
8568 return;
8569
8570 toss:
67ad48bc 8571 brcmu_pkt_buf_free_skb(p);
a9533e7e
HP
8572}
8573
8574/* calculate frame duration for Mixed-mode L-SIG spoofing, return
8575 * number of bytes goes in the length field
8576 *
8577 * Formula given by HT PHY Spec v 1.13
8578 * len = 3(nsyms + nstream + 3) - 3
8579 */
de91ed29 8580u16
6bd20a1b 8581brcms_c_calc_lsig_len(struct brcms_c_info *wlc, u32 ratespec,
fe741e5e 8582 uint mac_len)
a9533e7e
HP
8583{
8584 uint nsyms, len = 0, kNdps;
8585
792aa408 8586 BCMMSG(wlc->wiphy, "wl%d: rate %d, len%d\n",
f4528696 8587 wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
a9533e7e
HP
8588
8589 if (IS_MCS(ratespec)) {
8590 uint mcs = ratespec & RSPEC_RATE_MASK;
8591 /* MCS_TXS(mcs) returns num tx streams - 1 */
8592 int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
8593
419ad34e
AS
8594 /*
8595 * the payload duration calculation matches that
8596 * of regular ofdm
8597 */
a9533e7e
HP
8598 /* 1000Ndbps = kbps * 4 */
8599 kNdps =
8600 MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
8601 RSPEC_ISSGI(ratespec)) * 4;
8602
8603 if (RSPEC_STC(ratespec) == 0)
a9533e7e
HP
8604 nsyms =
8605 CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
8606 APHY_TAIL_NBITS) * 1000, kNdps);
8607 else
8608 /* STBC needs to have even number of symbols */
8609 nsyms =
8610 2 *
8611 CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
8612 APHY_TAIL_NBITS) * 1000, 2 * kNdps);
8613
419ad34e
AS
8614 /* (+3) account for HT-SIG(2) and HT-STF(1) */
8615 nsyms += (tot_streams + 3);
8616 /*
8617 * 3 bytes/symbol @ legacy 6Mbps rate
8618 * (-3) excluding service bits and tail bits
8619 */
8620 len = (3 * nsyms) - 3;
a9533e7e
HP
8621 }
8622
7d4df48e 8623 return (u16) len;
a9533e7e
HP
8624}
8625
419ad34e
AS
8626/*
8627 * calculate frame duration of a given rate and length, return
8628 * time in usec unit
8629 */
de91ed29 8630uint
6bd20a1b 8631brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
fe741e5e 8632 u8 preamble_type, uint mac_len)
a9533e7e
HP
8633{
8634 uint nsyms, dur = 0, Ndps, kNdps;
8635 uint rate = RSPEC2RATE(ratespec);
8636
8637 if (rate == 0) {
b8f092c9
RV
8638 wiphy_err(wlc->wiphy, "wl%d: WAR: using rate of 1 mbps\n",
8639 wlc->pub->unit);
7c783cef 8640 rate = BRCM_RATE_1M;
a9533e7e
HP
8641 }
8642
792aa408 8643 BCMMSG(wlc->wiphy, "wl%d: rspec 0x%x, preamble_type %d, len%d\n",
f4528696 8644 wlc->pub->unit, ratespec, preamble_type, mac_len);
a9533e7e
HP
8645
8646 if (IS_MCS(ratespec)) {
8647 uint mcs = ratespec & RSPEC_RATE_MASK;
8648 int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
a9533e7e
HP
8649
8650 dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
7c783cef 8651 if (preamble_type == BRCMS_MM_PREAMBLE)
a9533e7e
HP
8652 dur += PREN_MM_EXT;
8653 /* 1000Ndbps = kbps * 4 */
8654 kNdps =
8655 MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
8656 RSPEC_ISSGI(ratespec)) * 4;
8657
8658 if (RSPEC_STC(ratespec) == 0)
a9533e7e
HP
8659 nsyms =
8660 CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
8661 APHY_TAIL_NBITS) * 1000, kNdps);
8662 else
8663 /* STBC needs to have even number of symbols */
8664 nsyms =
8665 2 *
8666 CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
8667 APHY_TAIL_NBITS) * 1000, 2 * kNdps);
8668
8669 dur += APHY_SYMBOL_TIME * nsyms;
8670 if (BAND_2G(wlc->band->bandtype))
8671 dur += DOT11_OFDM_SIGNAL_EXTENSION;
8672 } else if (IS_OFDM(rate)) {
8673 dur = APHY_PREAMBLE_TIME;
8674 dur += APHY_SIGNAL_TIME;
8675 /* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
8676 Ndps = rate * 2;
8677 /* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
8678 nsyms =
8679 CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
8680 Ndps);
8681 dur += APHY_SYMBOL_TIME * nsyms;
8682 if (BAND_2G(wlc->band->bandtype))
8683 dur += DOT11_OFDM_SIGNAL_EXTENSION;
8684 } else {
419ad34e
AS
8685 /*
8686 * calc # bits * 2 so factor of 2 in rate (1/2 mbps)
8687 * will divide out
8688 */
a9533e7e
HP
8689 mac_len = mac_len * 8 * 2;
8690 /* calc ceiling of bits/rate = microseconds of air time */
8691 dur = (mac_len + rate - 1) / rate;
7c783cef 8692 if (preamble_type & BRCMS_SHORT_PREAMBLE)
a9533e7e
HP
8693 dur += BPHY_PLCP_SHORT_TIME;
8694 else
8695 dur += BPHY_PLCP_TIME;
8696 }
8697 return dur;
8698}
8699
a9533e7e 8700/* derive wlc->band->basic_rate[] table from 'rateset' */
fa67ebba
RV
8701void brcms_c_rate_lookup_init(struct brcms_c_info *wlc,
8702 struct brcms_c_rateset *rateset)
a9533e7e 8703{
41feb5ed
GKH
8704 u8 rate;
8705 u8 mandatory;
8706 u8 cck_basic = 0;
8707 u8 ofdm_basic = 0;
8708 u8 *br = wlc->band->basic_rate;
a9533e7e
HP
8709 uint i;
8710
8711 /* incoming rates are in 500kbps units as in 802.11 Supported Rates */
7c783cef 8712 memset(br, 0, BRCM_MAXRATE + 1);
a9533e7e
HP
8713
8714 /* For each basic rate in the rates list, make an entry in the
8715 * best basic lookup.
8716 */
8717 for (i = 0; i < rateset->count; i++) {
8718 /* only make an entry for a basic rate */
7c783cef 8719 if (!(rateset->rates[i] & BRCMS_RATE_FLAG))
a9533e7e
HP
8720 continue;
8721
8722 /* mask off basic bit */
7c783cef 8723 rate = (rateset->rates[i] & BRCMS_RATE_MASK);
a9533e7e 8724
7c783cef 8725 if (rate > BRCM_MAXRATE) {
f52a0ad0
RV
8726 wiphy_err(wlc->wiphy, "brcms_c_rate_lookup_init: "
8727 "invalid rate 0x%X in rate set\n",
b8f092c9 8728 rateset->rates[i]);
a9533e7e
HP
8729 continue;
8730 }
8731
8732 br[rate] = rate;
8733 }
8734
8735 /* The rate lookup table now has non-zero entries for each
8736 * basic rate, equal to the basic rate: br[basicN] = basicN
8737 *
8738 * To look up the best basic rate corresponding to any
8739 * particular rate, code can use the basic_rate table
8740 * like this
8741 *
8742 * basic_rate = wlc->band->basic_rate[tx_rate]
8743 *
8744 * Make sure there is a best basic rate entry for
8745 * every rate by walking up the table from low rates
8746 * to high, filling in holes in the lookup table
8747 */
8748
8749 for (i = 0; i < wlc->band->hw_rateset.count; i++) {
8750 rate = wlc->band->hw_rateset.rates[i];
a9533e7e
HP
8751
8752 if (br[rate] != 0) {
8753 /* This rate is a basic rate.
8754 * Keep track of the best basic rate so far by
8755 * modulation type.
8756 */
8757 if (IS_OFDM(rate))
8758 ofdm_basic = rate;
8759 else
8760 cck_basic = rate;
8761
8762 continue;
8763 }
8764
8765 /* This rate is not a basic rate so figure out the
8766 * best basic rate less than this rate and fill in
8767 * the hole in the table
8768 */
8769
8770 br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
8771
8772 if (br[rate] != 0)
8773 continue;
8774
8775 if (IS_OFDM(rate)) {
419ad34e
AS
8776 /*
8777 * In 11g and 11a, the OFDM mandatory rates
8778 * are 6, 12, and 24 Mbps
8779 */
7c783cef
RV
8780 if (rate >= BRCM_RATE_24M)
8781 mandatory = BRCM_RATE_24M;
8782 else if (rate >= BRCM_RATE_12M)
8783 mandatory = BRCM_RATE_12M;
a9533e7e 8784 else
7c783cef 8785 mandatory = BRCM_RATE_6M;
a9533e7e 8786 } else {
419ad34e 8787 /* In 11b, all CCK rates are mandatory 1 - 11 Mbps */
a9533e7e
HP
8788 mandatory = rate;
8789 }
8790
8791 br[rate] = mandatory;
8792 }
8793}
8794
1c4c54ba
RV
8795static void brcms_c_write_rate_shm(struct brcms_c_info *wlc, u8 rate,
8796 u8 basic_rate)
a9533e7e 8797{
41feb5ed
GKH
8798 u8 phy_rate, index;
8799 u8 basic_phy_rate, basic_index;
7d4df48e
GKH
8800 u16 dir_table, basic_table;
8801 u16 basic_ptr;
a9533e7e
HP
8802
8803 /* Shared memory address for the table we are reading */
8804 dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
8805
8806 /* Shared memory address for the table we are writing */
8807 basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
8808
8809 /*
8810 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
8811 * the index into the rate table.
8812 */
7c783cef
RV
8813 phy_rate = rate_info[rate] & BRCMS_RATE_MASK;
8814 basic_phy_rate = rate_info[basic_rate] & BRCMS_RATE_MASK;
a9533e7e
HP
8815 index = phy_rate & 0xf;
8816 basic_index = basic_phy_rate & 0xf;
8817
8818 /* Find the SHM pointer to the ACK rate entry by looking in the
8819 * Direct-map Table
8820 */
fe741e5e 8821 basic_ptr = brcms_c_read_shm(wlc, (dir_table + basic_index * 2));
a9533e7e
HP
8822
8823 /* Update the SHM BSS-basic-rate-set mapping table with the pointer
8824 * to the correct basic rate for the given incoming rate
8825 */
fe741e5e 8826 brcms_c_write_shm(wlc, (basic_table + index * 2), basic_ptr);
a9533e7e
HP
8827}
8828
fa67ebba
RV
8829static const struct brcms_c_rateset *
8830brcms_c_rateset_get_hwrs(struct brcms_c_info *wlc)
a9533e7e 8831{
fa67ebba 8832 const struct brcms_c_rateset *rs_dflt;
a9533e7e 8833
7c783cef 8834 if (BRCMS_PHY_11N_CAP(wlc->band)) {
a9533e7e
HP
8835 if (BAND_5G(wlc->band->bandtype))
8836 rs_dflt = &ofdm_mimo_rates;
8837 else
8838 rs_dflt = &cck_ofdm_mimo_rates;
8839 } else if (wlc->band->gmode)
8840 rs_dflt = &cck_ofdm_rates;
8841 else
8842 rs_dflt = &cck_rates;
8843
8844 return rs_dflt;
8845}
8846
fe741e5e 8847void brcms_c_set_ratetable(struct brcms_c_info *wlc)
a9533e7e 8848{
fa67ebba
RV
8849 const struct brcms_c_rateset *rs_dflt;
8850 struct brcms_c_rateset rs;
41feb5ed 8851 u8 rate, basic_rate;
a9533e7e
HP
8852 uint i;
8853
1c4c54ba 8854 rs_dflt = brcms_c_rateset_get_hwrs(wlc);
a9533e7e 8855
f52a0ad0
RV
8856 brcms_c_rateset_copy(rs_dflt, &rs);
8857 brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
a9533e7e
HP
8858
8859 /* walk the phy rate table and update SHM basic rate lookup table */
8860 for (i = 0; i < rs.count; i++) {
7c783cef 8861 rate = rs.rates[i] & BRCMS_RATE_MASK;
a9533e7e 8862
7c783cef 8863 /* for a given rate BRCMS_BASIC_RATE returns the rate at
a9533e7e
HP
8864 * which a response ACK/CTS should be sent.
8865 */
7c783cef 8866 basic_rate = BRCMS_BASIC_RATE(wlc, rate);
8ea54c9f 8867 if (basic_rate == 0)
a9533e7e
HP
8868 /* This should only happen if we are using a
8869 * restricted rateset.
8870 */
7c783cef 8871 basic_rate = rs.rates[0] & BRCMS_RATE_MASK;
a9533e7e 8872
1c4c54ba 8873 brcms_c_write_rate_shm(wlc, rate, basic_rate);
a9533e7e
HP
8874 }
8875}
8876
8877/*
8878 * Return true if the specified rate is supported by the specified band.
7c783cef 8879 * BRCM_BAND_AUTO indicates the current band.
a9533e7e 8880 */
6bd20a1b 8881bool brcms_c_valid_rate(struct brcms_c_info *wlc, u32 rspec, int band,
c6a9e1fc 8882 bool verbose)
a9533e7e 8883{
fa67ebba 8884 struct brcms_c_rateset *hw_rateset;
a9533e7e
HP
8885 uint i;
8886
8ea54c9f 8887 if ((band == BRCM_BAND_AUTO) || (band == wlc->band->bandtype))
a9533e7e 8888 hw_rateset = &wlc->band->hw_rateset;
8ea54c9f 8889 else if (NBANDS(wlc) > 1)
a9533e7e 8890 hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
8ea54c9f 8891 else
a9533e7e 8892 /* other band specified and we are a single band device */
0965ae88 8893 return false;
a9533e7e
HP
8894
8895 /* check if this is a mimo rate */
8896 if (IS_MCS(rspec)) {
8897 if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
8898 goto error;
8899
8900 return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
8901 }
8902
8903 for (i = 0; i < hw_rateset->count; i++)
8904 if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
0f0881b0 8905 return true;
a9533e7e 8906 error:
8ea54c9f 8907 if (verbose)
1c4c54ba 8908 wiphy_err(wlc->wiphy, "wl%d: valid_rate: rate spec 0x%x "
b8f092c9 8909 "not in hw_rateset\n", wlc->pub->unit, rspec);
a9533e7e 8910
0965ae88 8911 return false;
a9533e7e
HP
8912}
8913
fe741e5e 8914void brcms_c_mod_prb_rsp_rate_table(struct brcms_c_info *wlc, uint frame_len)
a9533e7e 8915{
fa67ebba
RV
8916 const struct brcms_c_rateset *rs_dflt;
8917 struct brcms_c_rateset rs;
41feb5ed 8918 u8 rate;
7d4df48e 8919 u16 entry_ptr;
41feb5ed 8920 u8 plcp[D11_PHY_HDR_LEN];
7d4df48e 8921 u16 dur, sifs;
a9533e7e
HP
8922 uint i;
8923
8924 sifs = SIFS(wlc->band);
8925
1c4c54ba 8926 rs_dflt = brcms_c_rateset_get_hwrs(wlc);
a9533e7e 8927
f52a0ad0
RV
8928 brcms_c_rateset_copy(rs_dflt, &rs);
8929 brcms_c_rateset_mcs_upd(&rs, wlc->stf->txstreams);
a9533e7e 8930
419ad34e
AS
8931 /*
8932 * walk the phy rate table and update MAC core SHM
8933 * basic rate table entries
8934 */
a9533e7e 8935 for (i = 0; i < rs.count; i++) {
7c783cef 8936 rate = rs.rates[i] & BRCMS_RATE_MASK;
a9533e7e 8937
1c4c54ba 8938 entry_ptr = brcms_c_rate_shm_offset(wlc, rate);
a9533e7e
HP
8939
8940 /* Calculate the Probe Response PLCP for the given rate */
fe741e5e 8941 brcms_c_compute_plcp(wlc, rate, frame_len, plcp);
a9533e7e 8942
419ad34e
AS
8943 /*
8944 * Calculate the duration of the Probe Response
8945 * frame plus SIFS for the MAC
8946 */
7c783cef
RV
8947 dur = (u16) brcms_c_calc_frame_time(wlc, rate,
8948 BRCMS_LONG_PREAMBLE, frame_len);
a9533e7e
HP
8949 dur += sifs;
8950
8951 /* Update the SHM Rate Table entry Probe Response values */
fe741e5e 8952 brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
7d4df48e 8953 (u16) (plcp[0] + (plcp[1] << 8)));
fe741e5e 8954 brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
7d4df48e 8955 (u16) (plcp[2] + (plcp[3] << 8)));
fe741e5e 8956 brcms_c_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
a9533e7e
HP
8957 }
8958}
8959
a9533e7e
HP
8960/* Max buffering needed for beacon template/prb resp template is 142 bytes.
8961 *
8962 * PLCP header is 6 bytes.
8963 * 802.11 A3 header is 24 bytes.
8964 * Max beacon frame body template length is 112 bytes.
8965 * Max probe resp frame body template length is 110 bytes.
8966 *
8967 * *len on input contains the max length of the packet available.
8968 *
419ad34e
AS
8969 * The *len value is set to the number of bytes in buf used, and starts
8970 * with the PLCP and included up to, but not including, the 4 byte FCS.
a9533e7e
HP
8971 */
8972static void
1c4c54ba 8973brcms_c_bcn_prb_template(struct brcms_c_info *wlc, u16 type,
6bd20a1b 8974 u32 bcn_rspec,
471f1b51 8975 struct brcms_bss_cfg *cfg, u16 *buf, int *len)
a9533e7e 8976{
a44d4236 8977 static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
cc87568a 8978 struct cck_phy_hdr *plcp;
392308d0 8979 struct ieee80211_mgmt *h;
a9533e7e
HP
8980 int hdr_len, body_len;
8981
2fbd6b37 8982 if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
a9533e7e
HP
8983 hdr_len = DOT11_MAC_HDR_LEN;
8984 else
8985 hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
a9533e7e 8986
419ad34e
AS
8987 /* calc buffer size provided for frame body */
8988 body_len = *len - hdr_len;
8989 /* return actual size */
8990 *len = hdr_len + body_len;
a9533e7e
HP
8991
8992 /* format PHY and MAC headers */
9249ede9 8993 memset((char *)buf, 0, hdr_len);
a9533e7e 8994
cc87568a 8995 plcp = (struct cck_phy_hdr *) buf;
a9533e7e 8996
419ad34e
AS
8997 /*
8998 * PLCP for Probe Response frames are filled in from
8999 * core's rate table
9000 */
8ea54c9f 9001 if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg))
a9533e7e 9002 /* fill in PLCP */
fe741e5e 9003 brcms_c_compute_plcp(wlc, bcn_rspec,
3726ed4d 9004 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
41feb5ed 9005 (u8 *) plcp);
a9533e7e 9006
a9533e7e
HP
9007 /* "Regular" and 16 MBSS but not for 4 MBSS */
9008 /* Update the phytxctl for the beacon based on the rspec */
9009 if (!SOFTBCN_ENAB(cfg))
fe741e5e 9010 brcms_c_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
a9533e7e 9011
2fbd6b37 9012 if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
392308d0 9013 h = (struct ieee80211_mgmt *)&plcp[0];
a9533e7e 9014 else
392308d0 9015 h = (struct ieee80211_mgmt *)&plcp[1];
a9533e7e
HP
9016
9017 /* fill in 802.11 header */
2fbd6b37 9018 h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
a9533e7e
HP
9019
9020 /* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
9021 /* A1 filled in by MAC for prb resp, broadcast for bcn */
2fbd6b37 9022 if (type == IEEE80211_STYPE_BEACON)
02160695
SF
9023 memcpy(&h->da, &ether_bcast, ETH_ALEN);
9024 memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
9025 memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
a9533e7e
HP
9026
9027 /* SEQ filled in by MAC */
9028
9029 return;
9030}
9031
fe741e5e 9032int brcms_c_get_header_len()
a9533e7e
HP
9033{
9034 return TXOFF;
9035}
9036
839f9f62 9037/* mac is assumed to be suspended at this point */
11431424 9038static void
2f6b1dde 9039brcms_b_write_hw_bcntemplates(struct brcms_hardware *wlc_hw, u16 bcn[],
839f9f62
RV
9040 int len, bool both)
9041{
0da64910 9042 struct d11regs *regs = wlc_hw->regs;
839f9f62
RV
9043
9044 if (both) {
9045 brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
9046 brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
9047 } else {
9048 /* bcn 0 */
9049 if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
9050 brcms_c_write_hw_bcntemplate0(wlc_hw, bcn, len);
9051 /* bcn 1 */
9052 else if (!
9053 (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
9054 brcms_c_write_hw_bcntemplate1(wlc_hw, bcn, len);
9055 }
9056}
9057
11431424
AS
9058static void brcms_c_write_hw_bcntemplates(struct brcms_c_info *wlc, u16 bcn[],
9059 int len, bool both)
2682e2a3
AS
9060{
9061 brcms_b_write_hw_bcntemplates(wlc->hw, bcn, len, both);
9062}
9063
419ad34e
AS
9064/*
9065 * Update a beacon for a particular BSS
9066 * For MBSS, this updates the software template and sets "latest" to
9067 * the index of the template updated. Otherwise, it updates the hardware
9068 * template.
a9533e7e 9069 */
fe741e5e 9070void brcms_c_bss_update_beacon(struct brcms_c_info *wlc,
471f1b51 9071 struct brcms_bss_cfg *cfg)
a9533e7e
HP
9072{
9073 int len = BCN_TMPL_LEN;
9074
9075 /* Clear the soft intmask */
9076 wlc->defmacintmask &= ~MI_BCNTPL;
9077
8ea54c9f
HP
9078 if (!cfg->up)
9079 /* Only allow updates on an UP bss */
a9533e7e 9080 return;
a9533e7e 9081
ff31c54c
AS
9082 /* Optimize: Some of if/else could be combined */
9083 if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
9084 /* Hardware beaconing for this config */
7d4df48e 9085 u16 bcn[BCN_TMPL_LEN / 2];
66cbd3ab 9086 u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
0da64910 9087 struct d11regs *regs = wlc->regs;
a9533e7e
HP
9088
9089 /* Check if both templates are in use, if so sched. an interrupt
9090 * that will call back into this routine
9091 */
8ea54c9f 9092 if ((R_REG(&regs->maccommand) & both_valid) == both_valid)
a9533e7e 9093 /* clear any previous status */
ff31c54c 9094 W_REG(&regs->macintstatus, MI_BCNTPL);
8ea54c9f 9095
a9533e7e
HP
9096 /* Check that after scheduling the interrupt both of the
9097 * templates are still busy. if not clear the int. & remask
9098 */
ff31c54c 9099 if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
a9533e7e
HP
9100 wlc->defmacintmask |= MI_BCNTPL;
9101 return;
9102 }
9103
9104 wlc->bcn_rspec =
fe741e5e 9105 brcms_c_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
a9533e7e 9106 /* update the template and ucode shm */
1c4c54ba 9107 brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
2fbd6b37 9108 wlc->bcn_rspec, cfg, bcn, &len);
fe741e5e 9109 brcms_c_write_hw_bcntemplates(wlc, bcn, len, false);
a9533e7e
HP
9110 }
9111}
9112
9113/*
9114 * Update all beacons for the system.
9115 */
fe741e5e 9116void brcms_c_update_beacon(struct brcms_c_info *wlc)
a9533e7e
HP
9117{
9118 int idx;
471f1b51 9119 struct brcms_bss_cfg *bsscfg;
a9533e7e
HP
9120
9121 /* update AP or IBSS beacons */
49552d33 9122 FOREACH_BSS(wlc, idx, bsscfg)
a9533e7e 9123 if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
fe741e5e 9124 brcms_c_bss_update_beacon(wlc, bsscfg);
49552d33 9125 END_FOREACH_BSS()
a9533e7e
HP
9126}
9127
9128/* Write ssid into shared memory */
471f1b51 9129void brcms_c_shm_ssid_upd(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg)
a9533e7e 9130{
41feb5ed 9131 u8 *ssidptr = cfg->SSID;
7d4df48e 9132 u16 base = M_SSID;
3726ed4d 9133 u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
a9533e7e
HP
9134
9135 /* padding the ssid with zero and copy it into shm */
3726ed4d 9136 memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
02160695 9137 memcpy(ssidbuf, ssidptr, cfg->SSID_len);
a9533e7e 9138
fe741e5e 9139 brcms_c_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
a9533e7e
HP
9140
9141 if (!MBSS_BCN_ENAB(cfg))
fe741e5e 9142 brcms_c_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
a9533e7e
HP
9143}
9144
fe741e5e 9145void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend)
a9533e7e
HP
9146{
9147 int idx;
471f1b51 9148 struct brcms_bss_cfg *bsscfg;
a9533e7e
HP
9149
9150 /* update AP or IBSS probe responses */
49552d33 9151 FOREACH_BSS(wlc, idx, bsscfg)
a9533e7e 9152 if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
fe741e5e 9153 brcms_c_bss_update_probe_resp(wlc, bsscfg, suspend);
49552d33 9154 END_FOREACH_BSS()
a9533e7e
HP
9155}
9156
9157void
fe741e5e 9158brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc,
471f1b51 9159 struct brcms_bss_cfg *cfg,
fe741e5e 9160 bool suspend)
a9533e7e 9161{
7d4df48e 9162 u16 prb_resp[BCN_TMPL_LEN / 2];
a9533e7e
HP
9163 int len = BCN_TMPL_LEN;
9164
419ad34e
AS
9165 /*
9166 * write the probe response to hardware, or save in
9167 * the config structure
9168 */
a9533e7e
HP
9169 if (!MBSS_PRB_ENAB(cfg)) {
9170
9171 /* create the probe response template */
1c4c54ba
RV
9172 brcms_c_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0,
9173 cfg, prb_resp, &len);
a9533e7e
HP
9174
9175 if (suspend)
fe741e5e 9176 brcms_c_suspend_mac_and_wait(wlc);
a9533e7e
HP
9177
9178 /* write the probe response into the template region */
c654fce6 9179 brcms_b_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
a9533e7e
HP
9180 (len + 3) & ~3, prb_resp);
9181
9182 /* write the length of the probe response frame (+PLCP/-FCS) */
fe741e5e 9183 brcms_c_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
a9533e7e
HP
9184
9185 /* write the SSID and SSID length */
fe741e5e 9186 brcms_c_shm_ssid_upd(wlc, cfg);
a9533e7e
HP
9187
9188 /*
419ad34e
AS
9189 * Write PLCP headers and durations for probe response frames
9190 * at all rates. Use the actual frame length covered by the
9191 * PLCP header for the call to brcms_c_mod_prb_rsp_rate_table()
9192 * by subtracting the PLCP len and adding the FCS.
a9533e7e 9193 */
3726ed4d 9194 len += (-D11_PHY_HDR_LEN + FCS_LEN);
fe741e5e 9195 brcms_c_mod_prb_rsp_rate_table(wlc, (u16) len);
a9533e7e
HP
9196
9197 if (suspend)
fe741e5e 9198 brcms_c_enable_mac(wlc);
419ad34e
AS
9199 } else {
9200 /* Generating probe resp in sw; update local template */
af4e9c09 9201 /* error: No software probe response support without MBSS */
a9533e7e
HP
9202 }
9203}
9204
9205/* prepares pdu for transmission. returns BCM error codes */
fe741e5e 9206int brcms_c_prep_pdu(struct brcms_c_info *wlc, struct sk_buff *pdu, uint *fifop)
a9533e7e 9207{
a9533e7e 9208 uint fifo;
cc87568a 9209 struct d11txh *txh;
3e9796f9 9210 struct ieee80211_hdr *h;
a9533e7e 9211 struct scb *scb;
a9533e7e 9212
cc87568a 9213 txh = (struct d11txh *) (pdu->data);
3e9796f9 9214 h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
a9533e7e 9215
1c4c54ba
RV
9216 /* get the pkt queue info. This was put at brcms_c_sendctl or
9217 * brcms_c_send for PDU */
628f10ba 9218 fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
a9533e7e
HP
9219
9220 scb = NULL;
9221
9222 *fifop = fifo;
9223
9224 /* return if insufficient dma resources */
9225 if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
9226 /* Mark precedences related to this FIFO, unsendable */
7c783cef 9227 BRCMS_TX_FIFO_CLEAR(wlc, fifo);
e10d82d4 9228 return -EBUSY;
a9533e7e 9229 }
a9533e7e
HP
9230 return 0;
9231}
9232
9233/* init tx reported rate mechanism */
fe741e5e 9234void brcms_c_reprate_init(struct brcms_c_info *wlc)
a9533e7e
HP
9235{
9236 int i;
471f1b51 9237 struct brcms_bss_cfg *bsscfg;
a9533e7e 9238
49552d33 9239 FOREACH_BSS(wlc, i, bsscfg)
fe741e5e 9240 brcms_c_bsscfg_reprate_init(bsscfg);
49552d33 9241 END_FOREACH_BSS()
a9533e7e
HP
9242}
9243
9244/* per bsscfg init tx reported rate mechanism */
471f1b51 9245void brcms_c_bsscfg_reprate_init(struct brcms_bss_cfg *bsscfg)
a9533e7e
HP
9246{
9247 bsscfg->txrspecidx = 0;
9249ede9 9248 memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
a9533e7e
HP
9249}
9250
fa67ebba 9251void brcms_default_rateset(struct brcms_c_info *wlc, struct brcms_c_rateset *rs)
a9533e7e 9252{
f52a0ad0 9253 brcms_c_rateset_default(rs, NULL, wlc->band->phytype,
7c783cef 9254 wlc->band->bandtype, false, BRCMS_RATE_MASK_FULL,
f52a0ad0
RV
9255 (bool) N_ENAB(wlc->pub),
9256 CHSPEC_WLC_BW(wlc->default_bss->chanspec),
9257 wlc->stf->txstreams);
a9533e7e
HP
9258}
9259
7d4df48e 9260/* Read a single u16 from shared memory.
a9533e7e
HP
9261 * SHM 'offset' needs to be an even address
9262 */
fe741e5e 9263u16 brcms_c_read_shm(struct brcms_c_info *wlc, uint offset)
a9533e7e 9264{
c654fce6 9265 return brcms_b_read_shm(wlc->hw, offset);
a9533e7e
HP
9266}
9267
7d4df48e 9268/* Write a single u16 to shared memory.
a9533e7e
HP
9269 * SHM 'offset' needs to be an even address
9270 */
fe741e5e 9271void brcms_c_write_shm(struct brcms_c_info *wlc, uint offset, u16 v)
a9533e7e 9272{
c654fce6 9273 brcms_b_write_shm(wlc->hw, offset, v);
a9533e7e
HP
9274}
9275
a9533e7e
HP
9276/* Copy a buffer to shared memory.
9277 * SHM 'offset' needs to be an even address and
9278 * Buffer length 'len' must be an even number of bytes
9279 */
fe741e5e
RV
9280void brcms_c_copyto_shm(struct brcms_c_info *wlc, uint offset, const void *buf,
9281 int len)
a9533e7e
HP
9282{
9283 /* offset and len need to be even */
af4e9c09 9284 if (len <= 0 || (offset & 1) || (len & 1))
a9533e7e 9285 return;
af4e9c09 9286
c654fce6 9287 brcms_b_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
a9533e7e
HP
9288
9289}
9290
a9533e7e 9291/* wrapper BMAC functions to for HIGH driver access */
fe741e5e 9292void brcms_c_mctrl(struct brcms_c_info *wlc, u32 mask, u32 val)
a9533e7e 9293{
c654fce6 9294 brcms_b_mctrl(wlc->hw, mask, val);
a9533e7e
HP
9295}
9296
fe741e5e 9297void brcms_c_mhf(struct brcms_c_info *wlc, u8 idx, u16 mask, u16 val, int bands)
a9533e7e 9298{
c654fce6 9299 brcms_b_mhf(wlc->hw, idx, mask, val, bands);
a9533e7e
HP
9300}
9301
11431424 9302static int brcms_b_xmtfifo_sz_get(struct brcms_hardware *wlc_hw, uint fifo,
839f9f62
RV
9303 uint *blocks)
9304{
9305 if (fifo >= NFIFO)
9306 return -EINVAL;
9307
9308 *blocks = wlc_hw->xmtfifo_sz[fifo];
9309
9310 return 0;
9311}
9312
fe741e5e 9313int brcms_c_xmtfifo_sz_get(struct brcms_c_info *wlc, uint fifo, uint *blocks)
a9533e7e 9314{
c654fce6 9315 return brcms_b_xmtfifo_sz_get(wlc->hw, fifo, blocks);
a9533e7e
HP
9316}
9317
fe741e5e 9318void brcms_c_write_template_ram(struct brcms_c_info *wlc, int offset, int len,
c6a9e1fc 9319 void *buf)
a9533e7e 9320{
c654fce6 9321 brcms_b_write_template_ram(wlc->hw, offset, len, buf);
a9533e7e
HP
9322}
9323
a9533e7e 9324void
fe741e5e 9325brcms_c_set_addrmatch(struct brcms_c_info *wlc, int match_reg_offset,
a44d4236 9326 const u8 *addr)
a9533e7e 9327{
c654fce6 9328 brcms_b_set_addrmatch(wlc->hw, match_reg_offset, addr);
6677eaa3
AS
9329 if (match_reg_offset == RCM_BSSID_OFFSET)
9330 memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
a9533e7e
HP
9331}
9332
6bd20a1b 9333void brcms_c_pllreq(struct brcms_c_info *wlc, bool set, u32 req_bit)
a9533e7e 9334{
c654fce6 9335 brcms_b_pllreq(wlc->hw, set, req_bit);
a9533e7e
HP
9336}
9337
fe741e5e 9338void brcms_c_reset_bmac_done(struct brcms_c_info *wlc)
a9533e7e 9339{
a9533e7e
HP
9340}
9341
a9533e7e
HP
9342/* check for the particular priority flow control bit being set */
9343bool
fe741e5e 9344brcms_c_txflowcontrol_prio_isset(struct brcms_c_info *wlc,
471f1b51 9345 struct brcms_txq_info *q,
fe741e5e 9346 int prio)
a9533e7e
HP
9347{
9348 uint prio_mask;
9349
8ea54c9f 9350 if (prio == ALLPRIO)
a9533e7e 9351 prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
8ea54c9f 9352 else
a9533e7e 9353 prio_mask = NBITVAL(prio);
a9533e7e
HP
9354
9355 return (q->stopped & prio_mask) == prio_mask;
9356}
9357
25985edc 9358/* propagate the flow control to all interfaces using the given tx queue */
fe741e5e 9359void brcms_c_txflowcontrol(struct brcms_c_info *wlc,
471f1b51 9360 struct brcms_txq_info *qi,
fe741e5e 9361 bool on, int prio)
a9533e7e
HP
9362{
9363 uint prio_bits;
9364 uint cur_bits;
9365
792aa408 9366 BCMMSG(wlc->wiphy, "flow control kicks in\n");
a9533e7e 9367
8ea54c9f 9368 if (prio == ALLPRIO)
a9533e7e 9369 prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
8ea54c9f 9370 else
a9533e7e 9371 prio_bits = NBITVAL(prio);
a9533e7e
HP
9372
9373 cur_bits = qi->stopped & prio_bits;
9374
9375 /* Check for the case of no change and return early
9376 * Otherwise update the bit and continue
9377 */
9378 if (on) {
8ea54c9f 9379 if (cur_bits == prio_bits)
a9533e7e 9380 return;
8ea54c9f 9381
a9533e7e
HP
9382 mboolset(qi->stopped, prio_bits);
9383 } else {
8ea54c9f 9384 if (cur_bits == 0)
a9533e7e 9385 return;
8ea54c9f 9386
a9533e7e
HP
9387 mboolclr(qi->stopped, prio_bits);
9388 }
9389
9390 /* If there is a flow control override we will not change the external
9391 * flow control state.
9392 */
8ea54c9f 9393 if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK)
a9533e7e 9394 return;
a9533e7e 9395
1c4c54ba 9396 brcms_c_txflowcontrol_signal(wlc, qi, on, prio);
a9533e7e
HP
9397}
9398
9399void
fe741e5e 9400brcms_c_txflowcontrol_override(struct brcms_c_info *wlc,
471f1b51 9401 struct brcms_txq_info *qi,
fe741e5e 9402 bool on, uint override)
a9533e7e
HP
9403{
9404 uint prev_override;
9405
a9533e7e
HP
9406 prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
9407
9408 /* Update the flow control bits and do an early return if there is
9409 * no change in the external flow control state.
9410 */
9411 if (on) {
9412 mboolset(qi->stopped, override);
9413 /* if there was a previous override bit on, then setting this
9414 * makes no difference.
9415 */
8ea54c9f 9416 if (prev_override)
a9533e7e 9417 return;
a9533e7e 9418
1c4c54ba 9419 brcms_c_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
a9533e7e
HP
9420 } else {
9421 mboolclr(qi->stopped, override);
9422 /* clearing an override bit will only make a difference for
9423 * flow control if it was the only bit set. For any other
9424 * override setting, just return
9425 */
8ea54c9f 9426 if (prev_override != override)
a9533e7e 9427 return;
a9533e7e
HP
9428
9429 if (qi->stopped == 0) {
1c4c54ba 9430 brcms_c_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
a9533e7e
HP
9431 } else {
9432 int prio;
9433
9434 for (prio = MAXPRIO; prio >= 0; prio--) {
9435 if (!mboolisset(qi->stopped, NBITVAL(prio)))
1c4c54ba
RV
9436 brcms_c_txflowcontrol_signal(
9437 wlc, qi, OFF, prio);
a9533e7e
HP
9438 }
9439 }
9440 }
9441}
9442
6a3be6e6 9443/*
25985edc 9444 * Flag 'scan in progress' to withhold dynamic phy calibration
6a3be6e6 9445 */
fe741e5e 9446void brcms_c_scan_start(struct brcms_c_info *wlc)
6a3be6e6
RV
9447{
9448 wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
9449}
9450
fe741e5e 9451void brcms_c_scan_stop(struct brcms_c_info *wlc)
6a3be6e6
RV
9452{
9453 wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
9454}
d8a1fb44 9455
fe741e5e 9456void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state)
d8a1fb44
AS
9457{
9458 wlc->pub->associated = state;
9459 wlc->cfg->associated = state;
9460}
9ee63c6a
RV
9461
9462/*
9463 * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
9464 * AMPDU traffic, packets pending in hardware have to be invalidated so that
9465 * when later on hardware releases them, they can be handled appropriately.
9466 */
471f1b51 9467void brcms_c_inval_dma_pkts(struct brcms_hardware *hw,
9ee63c6a
RV
9468 struct ieee80211_sta *sta,
9469 void (*dma_callback_fn))
9470{
70963f98 9471 struct dma_pub *dmah;
9ee63c6a
RV
9472 int i;
9473 for (i = 0; i < NFIFO; i++) {
9474 dmah = hw->di[i];
9475 if (dmah != NULL)
9476 dma_walk_packets(dmah, dma_callback_fn, sta);
9477 }
9478}
94da409e 9479
fe741e5e 9480int brcms_c_get_curband(struct brcms_c_info *wlc)
94da409e
AS
9481{
9482 return wlc->band->bandunit;
9483}
12392c6d 9484
fe741e5e 9485void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
12392c6d
AS
9486{
9487 /* flush packet queue when requested */
9488 if (drop)
67ad48bc 9489 brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
12392c6d
AS
9490
9491 /* wait for queue and DMA fifos to run dry */
3a730500 9492 while (!pktq_empty(&wlc->pkt_queue->q) ||
8ea54c9f 9493 TXPKTPENDTOT(wlc) > 0)
8817f754 9494 brcms_msleep(wlc->wl, 1);
12392c6d 9495}
c5e7c035 9496
fe741e5e
RV
9497int brcms_c_set_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
9498 int int_val)
c5e7c035
RV
9499{
9500 int err = 0;
9501
9502 switch (par_id) {
9503 case IOV_BCN_LI_BCN:
9504 wlc->bcn_li_bcn = (u8) int_val;
9505 if (wlc->pub->up)
fe741e5e 9506 brcms_c_bcn_li_upd(wlc);
c5e7c035
RV
9507 break;
9508 /* As long as override is false, this only sets the *user*
9509 targets. User can twiddle this all he wants with no harm.
9510 wlc_phy_txpower_set() explicitly sets override to false if
9511 not internal or test.
9512 */
9513 case IOV_QTXPOWER:{
9514 u8 qdbm;
9515 bool override;
9516
9517 /* Remove override bit and clip to max qdbm value */
9518 qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
9519 /* Extract override setting */
9520 override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
9521 err =
9522 wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
9523 break;
9524 }
9525 case IOV_MPC:
9526 wlc->mpc = (bool)int_val;
fe741e5e 9527 brcms_c_radio_mpc_upd(wlc);
c5e7c035
RV
9528 break;
9529 default:
9530 err = -ENOTSUPP;
9531 }
9532 return err;
9533}
9534
fe741e5e
RV
9535int brcms_c_get_par(struct brcms_c_info *wlc, enum wlc_par_id par_id,
9536 int *ret_int_ptr)
c5e7c035
RV
9537{
9538 int err = 0;
9539
9540 switch (par_id) {
9541 case IOV_BCN_LI_BCN:
9542 *ret_int_ptr = wlc->bcn_li_bcn;
9543 break;
9544 case IOV_QTXPOWER: {
9545 uint qdbm;
9546 bool override;
9547
9548 err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
9549 &override);
9550 if (err != 0)
9551 return err;
9552
9553 /* Return qdbm units */
9554 *ret_int_ptr =
9555 qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
9556 break;
9557 }
9558 case IOV_MPC:
9559 *ret_int_ptr = (s32) wlc->mpc;
9560 break;
9561 default:
9562 err = -ENOTSUPP;
9563 }
9564 return err;
9565}
d794fec0
AS
9566
9567/*
9568 * Search the name=value vars for a specific one and return its value.
9569 * Returns NULL if not found.
9570 */
9571char *getvar(char *vars, const char *name)
9572{
9573 char *s;
9574 int len;
9575
9576 if (!name)
9577 return NULL;
9578
9579 len = strlen(name);
9580 if (len == 0)
9581 return NULL;
9582
9583 /* first look in vars[] */
9584 for (s = vars; s && *s;) {
9585 if ((memcmp(s, name, len) == 0) && (s[len] == '='))
9586 return &s[len + 1];
9587
9588 while (*s++)
9589 ;
9590 }
9591 /* nothing found */
9592 return NULL;
9593}
9594
9595/*
9596 * Search the vars for a specific one and return its value as
9597 * an integer. Returns 0 if not found.
9598 */
9599int getintvar(char *vars, const char *name)
9600{
9601 char *val;
3f7e0c5d 9602 unsigned long res;
d794fec0
AS
9603
9604 val = getvar(vars, name);
3f7e0c5d
AS
9605 if (val && !kstrtoul(val, 0, &res))
9606 return res;
d794fec0 9607
3f7e0c5d 9608 return 0;
d794fec0 9609}