/* * Copyright (c) 2010 Broadcom Corporation * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* watchdog timer, in unit of ms */ #define TIMER_INTERVAL_WATCHDOG 1000 /* radio monitor timer, in unit of ms */ #define TIMER_INTERVAL_RADIOCHK 800
/* beacon interval, in unit of 1024TU */ #define BEACON_INTERVAL_DEFAULT 100
/* n-mode support capability */ /* 2x2 includes both 1x1 & 2x2 devices * reserved #define 2 for future when we want to separate 1x1 & 2x2 and * control it independently
*/ #define WL_11N_2x2 1 #define WL_11N_3x3 3 #define WL_11N_4x4 4
/* # of entries in Tx FIFO */ #define NTXD 64 /* Max # of entries in Rx FIFO based on 4kb page size */ #define NRXD 256
/* Amount of headroom to leave in Tx FIFO */ #define TX_HEADROOM 4
/* try to keep this # rbufs posted to the chip */ #define NRXBUFPOST 32
/* max # frames to process in brcms_c_recv() */ #define RXBND 8 /* max # tx status to process in wlc_txstatus() */ #define TXSBND 8
/* * The following table lists the buffer memory allocated to xmt fifos in HW. * the size is in units of 256bytes(one block), total size is HW dependent * ucode has default fifo partition, sw can overwrite if necessary * * This is documented in twiki under the topic UcodeTxFifo. Please ensure * the twiki is updated before making changes.
*/
/* Starting corerev for the fifo size table */ #define XMTFIFOTBL_STARTREV 17
/* currently the best mechanism for determining SIFS is the band in use */ static u16 get_sifs(struct brcms_band *band)
{ return band->bandtype == BRCM_BAND_5G ? APHY_SIFS_TIME :
BPHY_SIFS_TIME;
}
/* * Detect Card removed. * Even checking an sbconfig register read will not false trigger when the core * is in reset it breaks CF address mechanism. Accessing gphy phyversion will * cause SB error if aphy is in reset on 4306B0-DB. Need a simple accessible * reg with fixed 0/1 pattern (some platforms return all 0). * If clocks are present, call the sb routine which will figure out if the * device is removed.
*/ staticbool brcms_deviceremoved(struct brcms_c_info *wlc)
{
u32 macctrl;
/* * Update the slot timing for standard 11b/g (20us slots) * or shortslot 11g (9us slots) * The PSM needs to be suspended for this call.
*/ staticvoid brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw, bool shortslot)
{ struct bcma_device *core = wlc_hw->d11core;
/* discard intermediate indications for ucode with one legitimate case: * e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, * but the subsequent tx of DATA failed. so it will start rts/cts * from the beginning (resetting the rts transmission count)
*/ if (!(txs->status & TX_STATUS_AMPDU)
&& (txs->status & TX_STATUS_INTERMEDIATE)) {
brcms_dbg_tx(wlc->hw->d11core, "INTERMEDIATE but not AMPDU\n");
fatal = false; goto out;
}
/* * brcms_c_ampdu_dotxstatus() will trace tx descriptors for AMPDU * frames; this traces them for the rest.
*/
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
supr_status = txs->status & TX_STATUS_SUPR_MASK; if (supr_status == TX_STATUS_SUPR_BADCH) { unsigned xfts = le16_to_cpu(txh->XtraFrameTypes);
brcms_dbg_tx(wlc->hw->d11core, "Pkt tx suppressed, dest chan %u, current %d\n",
(xfts >> XFTS_CHANNEL_SHIFT) & 0xff,
CHSPEC_CHANNEL(wlc->default_bss->chanspec));
}
if (!lastframe) {
brcms_err(wlc->hw->d11core, "Not last frame!\n");
} else { /* * Set information to be consumed by Minstrel ht. * * The "fallback limit" is the number of tx attempts a given * MPDU is sent at the "primary" rate. Tx attempts beyond that * limit are sent at the "secondary" rate. * A 'short frame' does not exceed RTS threshold.
*/
u16 sfbl, /* Short Frame Rate Fallback Limit */
lfbl, /* Long Frame Rate Fallback Limit */
fbl;
if ((tx_frame_count > fbl) && (txrate[1].idx >= 0)) { /* * rate selection requested a fallback rate * and we used it
*/
txrate[0].count = fbl;
txrate[1].count = tx_frame_count - fbl;
} else { /* * rate selection did not request fallback rate, or * we didn't need it
*/
txrate[0].count = tx_frame_count; /* * rc80211_minstrel.c:minstrel_tx_status() expects * unused rates to be marked with idx = -1
*/
txrate[1].idx = -1;
txrate[1].count = 0;
}
/* clear the rest of the rates */ for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
txrate[i].idx = -1;
txrate[i].count = 0;
}
if (txs->status & TX_STATUS_ACK_RCV)
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}
if (lastframe) { /* remove PLCP & Broadcom tx descriptor header */
skb_pull(p, D11_PHY_HDR_LEN);
skb_pull(p, D11_TXH_LEN);
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
} else {
brcms_err(wlc->hw->d11core, "%s: Not last frame => not calling tx_status\n",
__func__);
}
fatal = false;
out: if (fatal) { if (txh)
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
brcmu_pkt_buf_free_skb(p);
}
*fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); if (*fatal) returnfalse;
n++;
}
return n >= max_tx_num;
}
staticvoid brcms_c_tbtt(struct brcms_c_info *wlc)
{ if (wlc->bsscfg->type == BRCMS_TYPE_ADHOC) /* * DirFrmQ is now valid...defer setting until end * of ATIM window
*/
wlc->qvalid |= MCMD_DIRFRMQVAL;
}
/* get pointer to dma engine tx flow control variable */ for (i = 0; i < NFIFO; i++) if (wlc_hw->di[i])
wlc_hw->txavail[i] =
(uint *) dma_getvar(wlc_hw->di[i], "&txavail");
}
for (j = 0; j < NFIFO; j++) { if (wlc_hw->di[j]) {
dma_detach(wlc_hw->di[j]);
wlc_hw->di[j] = NULL;
}
}
}
/* * Initialize brcms_c_info default values ... * may get overrides later in this function * BMAC_NOTES, move low out and resolve the dangling ones
*/ staticvoid brcms_b_info_init(struct brcms_hardware *wlc_hw)
{ struct brcms_c_info *wlc = wlc_hw->wlc;
/* set default sw macintmask value */
wlc->defmacintmask = DEF_MACINTMASK;
/* various 802.11g modes */
wlc_hw->shortslot = false;
staticvoid brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw)
{ /* delay before first read of ucode state */
udelay(40);
/* wait until ucode is no longer asleep */
SPINWAIT((brcms_b_read_shm(wlc_hw, M_UCODE_DBGST) ==
DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
}
/* control chip clock to save power, enable dynamic clock or force fast clock */ staticvoid brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, enum bcma_clkmode mode)
{ if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { /* new chips with PMU, CCS_FORCEHT will distribute the HT clock * on backplane, but mac core will still run on ALP(not HT) when * it enters powersave mode, which means the FCA bit may not be * set. Should wakeup mac if driver wants it to run on HT.
*/
if (wlc_hw->clk) { if (mode == BCMA_CLKMODE_FAST) {
bcma_set32(wlc_hw->d11core,
D11REGOFFS(clk_ctl_st),
CCS_FORCEHT);
/* check fast clock is available (if core is not in reset) */ if (wlc_hw->forcefastclk && wlc_hw->clk)
WARN_ON(!(bcma_aread32(wlc_hw->d11core, BCMA_IOST) &
SISF_FCLKA));
/* * keep the ucode wake bit on if forcefastclk is on since we * do not want ucode to put us back to slow clock when it dozes * for PM mode. Code below matches the wake override bit with * current forcefastclk state. Only setting bit in wake_override * instead of waking ucode immediately since old code had this * behavior. Older code set wlc->forcefastclk but only had the * wake happen if the wakup_ucode work (protected by an up * check) was executed just below.
*/ if (wlc_hw->forcefastclk)
mboolset(wlc_hw->wake_override,
BRCMS_WAKE_OVERRIDE_FORCEFAST); else
mboolclr(wlc_hw->wake_override,
BRCMS_WAKE_OVERRIDE_FORCEFAST);
}
}
/* set or clear ucode host flag bits * it has an optimization for no-change write * it only writes through shared memory when the core has clock; * pre-CLK changes should use wlc_write_mhf to get around the optimization * * * bands values are: BRCM_BAND_AUTO <--- Current band only * BRCM_BAND_5G <--- 5G band only * BRCM_BAND_2G <--- 2G band only * BRCM_BAND_ALL <--- All bands
*/ void
brcms_b_mhf(struct brcms_hardware *wlc_hw, u8 idx, u16 mask, u16 val, int bands)
{
u16 save;
u16 addr[MHFMAX] = {
M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
M_HOST_FLAGS5
}; struct brcms_hw_band *band;
switch (bands) { /* Current band only or all bands, * then set the band to current band
*/ case BRCM_BAND_AUTO: case BRCM_BAND_ALL:
band = wlc_hw->band; break; case BRCM_BAND_5G:
band = wlc_hw->bandstate[BAND_5G_INDEX]; break; case BRCM_BAND_2G:
band = wlc_hw->bandstate[BAND_2G_INDEX]; break; default:
band = NULL; /* error condition */
}
if (band) {
save = band->mhfs[idx];
band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
/* optimization: only write through if changed, and * changed band is the current band
*/ if (wlc_hw->clk && (band->mhfs[idx] != save)
&& (band == wlc_hw->band))
brcms_b_write_shm(wlc_hw, addr[idx],
(u16) band->mhfs[idx]);
}
/* set the maccontrol register to desired reset state and * initialize the sw cache of the register
*/ staticvoid brcms_c_mctrl_reset(struct brcms_hardware *wlc_hw)
{ /* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
wlc_hw->maccontrol = 0;
wlc_hw->suspended_fifos = 0;
wlc_hw->wake_override = 0;
wlc_hw->mute_override = 0;
brcms_b_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
}
/* * write the software state of maccontrol and * overrides to the maccontrol register
*/ staticvoid brcms_c_mctrl_write(struct brcms_hardware *wlc_hw)
{
u32 maccontrol = wlc_hw->maccontrol;
/* OR in the wake bit if overridden */ if (wlc_hw->wake_override)
maccontrol |= MCTL_WAKE;
/* set AP and INFRA bits for mute if needed */ if (wlc_hw->mute_override) {
maccontrol &= ~(MCTL_AP);
maccontrol |= MCTL_INFRA;
}
if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) return;
brcms_c_mctrl_write(wlc_hw);
}
/* When driver needs ucode to stop beaconing, it has to make sure that * MCTL_AP is clear and MCTL_INFRA is set * Mode MCTL_AP MCTL_INFRA * AP 1 1 * STA 0 1 <--- This will ensure no beacons * IBSS 0 0
*/ staticvoid brcms_c_ucode_mute_override_set(struct brcms_hardware *wlc_hw)
{
wlc_hw->mute_override = 1;
/* if maccontrol already has AP == 0 and INFRA == 1 without this * override, then there is no change to write
*/ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) return;
brcms_c_mctrl_write(wlc_hw);
}
/* Clear the override on AP and INFRA bits */ staticvoid brcms_c_ucode_mute_override_clear(struct brcms_hardware *wlc_hw)
{ if (wlc_hw->mute_override == 0) return;
wlc_hw->mute_override = 0;
/* if maccontrol already has AP == 0 and INFRA == 1 without this * override, then there is no change to write
*/ if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA) return;
brcms_c_mctrl_write(wlc_hw);
}
/* * Write a MAC address to the given match reg offset in the RXE match engine.
*/ staticvoid
brcms_b_set_addrmatch(struct brcms_hardware *wlc_hw, int match_reg_offset, const u8 *addr)
{ struct bcma_device *core = wlc_hw->d11core;
u16 mac_l;
u16 mac_m;
u16 mac_h;
/* enter the MAC addr into the RXE match registers */
bcma_write16(core, D11REGOFFS(rcm_ctl),
RCM_INC_DATA | match_reg_offset);
bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_l);
bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_m);
bcma_write16(core, D11REGOFFS(rcm_mat_data), mac_h);
}
/* if MCTL_BIGEND bit set in mac control register, * the chip swaps data in fifo, as well as data in * template ram
*/
be_bit = (bcma_read32(core, D11REGOFFS(maccontrol)) & MCTL_BIGEND) != 0;
while (len > 0) {
memcpy(&word, buf, sizeof(u32));
if (be_bit) {
word_be = cpu_to_be32(word);
word = *(u32 *)&word_be;
} else {
word_le = cpu_to_le32(word);
word = *(u32 *)&word_le;
}
if (BRCMS_ISLCNPHY(wlc->band))
v = SYNTHPU_DLY_LPPHY_US; elseif (BRCMS_ISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3)))
v = SYNTHPU_DLY_NPHY_US; else
v = SYNTHPU_DLY_BPHY_US;
for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) { if (rate == rate_lookup[i].rate) {
plcp_rate = rate_lookup[i].signal_rate; break;
}
}
/* Find the SHM pointer to the rate table entry by looking in the * Direct-map Table
*/ return 2 * brcms_b_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
}
/* * cwmin is band-specific, update hardware * with value for current band
*/
brcms_b_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
brcms_b_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
/* light way to turn on phy clock without reset for NPHY only * refer to brcms_b_core_phy_clk for full version
*/ void brcms_b_phyclk_fgc(struct brcms_hardware *wlc_hw, bool clk)
{ /* support(necessary for NPHY and HYPHY) only */ if (!BRCMS_ISNPHY(wlc_hw->band)) return;
if (ON == clk)
brcms_b_core_ioctl(wlc_hw, SICF_FGC, SICF_FGC); else
brcms_b_core_ioctl(wlc_hw, SICF_FGC, 0);
}
void brcms_b_macphyclk_set(struct brcms_hardware *wlc_hw, bool clk)
{ if (ON == clk)
brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, SICF_MPCLKE); else
brcms_b_core_ioctl(wlc_hw, SICF_MPCLKE, 0);
}
/* Specific reset sequence required for NPHY rev 3 and 4 */ if (BRCMS_ISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
NREV_LE(wlc_hw->band->phyrev, 4)) { /* Set the PHY bandwidth */
brcms_b_core_ioctl(wlc_hw, SICF_BWMASK, phy_bw_clkbits);
udelay(1);
/* Perform a soft reset of the PHY PLL */
brcms_b_core_phypll_reset(wlc_hw);
/* switch to and initialize new band */ staticvoid brcms_b_setband(struct brcms_hardware *wlc_hw, uint bandunit,
u16 chanspec) { struct brcms_c_info *wlc = wlc_hw->wlc;
u32 macintmask;
/* Enable the d11 core before accessing it */ if (!bcma_core_is_enabled(wlc_hw->d11core)) {
bcma_core_enable(wlc_hw->d11core, 0);
brcms_c_mctrl_reset(wlc_hw);
}
/* * If there are any pending software interrupt bits, * then replace these with a harmless nonzero value * so brcms_c_dpc() will re-enable interrupts when done.
*/ if (wlc->macintstatus)
wlc->macintstatus = MI_DMAINT;
/* power both the pll and external oscillator on/off */ staticvoid brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want)
{
brcms_dbg_info(wlc_hw->d11core, "wl%d: want %d\n", wlc_hw->unit, want);
/* * dont power down if plldown is false or * we must poll hw radio disable
*/ if (!want && wlc_hw->pllreq) return;
wlc_hw->sbclk = want; if (!wlc_hw->sbclk) {
wlc_hw->clk = false; if (wlc_hw->band && wlc_hw->band->pi)
wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
}
}
/* * Return true if radio is disabled, otherwise false. * hw radio disable signal is an external pin, users activate it asynchronously * this function could be called when driver is down and w/o clock * it operates on different registers depending on corerev and boardflag.
*/ staticbool brcms_b_radio_read_hwdisabled(struct brcms_hardware *wlc_hw)
{ bool v, clk, xtal;
u32 flags = 0;
xtal = wlc_hw->sbclk; if (!xtal)
brcms_b_xtal(wlc_hw, ON);
/* may need to take core out of reset first */
clk = wlc_hw->clk; if (!clk) { /* * mac no longer enables phyclk automatically when driver * accesses phyreg throughput mac. This can be skipped since * only mac reg is accessed below
*/ if (D11REV_GE(wlc_hw->corerev, 18))
flags |= SICF_PCLKE;
/* * TODO: test suspend/resume * * AI chip doesn't restore bar0win2 on * hibernation/resume, need sw fixup
*/
/* request FAST clock if not on */
fastclk = wlc_hw->forcefastclk; if (!fastclk)
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
/* reset the dma engines except first time thru */ if (bcma_core_is_enabled(wlc_hw->d11core)) { for (i = 0; i < NFIFO; i++) if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i])))
brcms_err(wlc_hw->d11core, "wl%d: %s: " "dma_txreset[%d]: cannot stop dma\n",
wlc_hw->unit, __func__, i);
if ((wlc_hw->di[RX_FIFO])
&& (!wlc_dma_rxreset(wlc_hw, RX_FIFO)))
brcms_err(wlc_hw->d11core, "wl%d: %s: dma_rxreset" "[%d]: cannot stop dma\n",
wlc_hw->unit, __func__, RX_FIFO);
} /* if noreset, just stop the psm and return */ if (wlc_hw->noreset) {
wlc_hw->wlc->macintstatus = 0; /* skip wl_dpc after down */
brcms_b_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0); return;
}
/* * mac no longer enables phyclk automatically when driver accesses * phyreg throughput mac, AND phy_reset is skipped at early stage when * band->pi is invalid. need to enable PHY CLK
*/ if (D11REV_GE(wlc_hw->corerev, 18))
flags |= SICF_PCLKE;
/* * reset the core * In chips with PMU, the fastclk request goes through d11 core * reg 0x1e0, which is cleared by the core_reset. have to re-request it. * * This adds some delay and we can optimize it by also requesting * fastclk through chipcommon during this period if necessary. But * that has to work coordinate with other driver like mips/arm since * they may touch chipcommon as well.
*/
wlc_hw->clk = false;
bcma_core_enable(wlc_hw->d11core, flags);
wlc_hw->clk = true; if (wlc_hw->band && wlc_hw->band->pi)
wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
brcms_c_mctrl_reset(wlc_hw);
if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU)
brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST);
brcms_b_phy_reset(wlc_hw);
/* turn on PHY_PLL */
brcms_b_core_phypll_ctl(wlc_hw, true);
txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
} /* * need to propagate to shm location to be in sync since ucode/hw won't * do this
*/
brcms_b_write_shm(wlc_hw, M_FIFOSIZE0,
wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
brcms_b_write_shm(wlc_hw, M_FIFOSIZE1,
wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
brcms_b_write_shm(wlc_hw, M_FIFOSIZE2,
((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
xmtfifo_sz[TX_AC_BK_FIFO]));
brcms_b_write_shm(wlc_hw, M_FIFOSIZE3,
((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
xmtfifo_sz[TX_BCMC_FIFO]));
}
/* This function is used for changing the tsf frac register * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz * HTPHY Formula is 2^26/freq(MHz) e.g. * For spuron2 - 126MHz -> 2^26/126 = 532610.0 * - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082 * For spuron: 123MHz -> 2^26/123 = 545600.5 * - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341 * For spur off: 120MHz -> 2^26/120 = 559240.5 * - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
*/
/* Initialize GPIOs that are controlled by D11 core */ staticvoid brcms_c_gpio_init(struct brcms_c_info *wlc)
{ struct brcms_hardware *wlc_hw = wlc->hw;
u32 gc, gm;
/* use GPIO select 0 to get all gpio signals from the gpio out reg */
brcms_b_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
/* * Common GPIO setup: * G0 = LED 0 = WLAN Activity * G1 = LED 1 = WLAN 2.4 GHz Radio State * G2 = LED 2 = WLAN 5 GHz Radio State * G4 = radio disable input (HI enabled, LO disabled)
*/
gc = gm = 0;
/* Allocate GPIOs for mimo antenna diversity feature */ if (wlc_hw->antsel_type == ANTSEL_2x3) { /* Enable antenna diversity, use 2x3 mode */
brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
MHF3_ANTSEL_EN, BRCM_BAND_ALL);
brcms_b_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
MHF3_ANTSEL_MODE, BRCM_BAND_ALL);
/* init superswitch control */
wlc_phy_antsel_init(wlc_hw->band->pi, false);
} elseif (wlc_hw->antsel_type == ANTSEL_2x4) {
gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13); /* * The board itself is powered by these GPIOs * (when not sending pattern) so set them high
*/
bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_oe),
(BOARD_GPIO_12 | BOARD_GPIO_13));
bcma_set16(wlc_hw->d11core, D11REGOFFS(psm_gpio_out),
(BOARD_GPIO_12 | BOARD_GPIO_13));
macintmask = wlc->macintmask; /* isr can still happen */
bcma_write32(wlc_hw->d11core, D11REGOFFS(macintmask), 0);
(void)bcma_read32(wlc_hw->d11core, D11REGOFFS(macintmask));
udelay(1); /* ensure int line is no longer driven */
wlc->macintmask = 0;
/* return previous macintmask; resolve race between us and our isr */ return wlc->macintstatus ? 0 : macintmask;
}
/* assumes that the d11 MAC is enabled */ staticvoid brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
uint tx_fifo)
{
u8 fifo = 1 << tx_fifo;
/* Two clients of this code, 11h Quiet period and scanning. */
/* only suspend if not already suspended */ if ((wlc_hw->suspended_fifos & fifo) == fifo) return;
/* force the core awake only if not already */ if (wlc_hw->suspended_fifos == 0)
brcms_c_ucode_wake_override_set(wlc_hw,
BRCMS_WAKE_OVERRIDE_TXFIFO);
wlc_hw->suspended_fifos |= fifo;
if (wlc_hw->di[tx_fifo]) { /* * Suspending AMPDU transmissions in the middle can cause * underflow which may result in mismatch between ucode and
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.68 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.